
On 08/29/2011 03:12 PM, Anton Staaf wrote:
- Mikes's macro
#define DMA_ALIGN_SIZE(size) \ (((size) + CONFIG_SYS_CACHELINE_SIZE - 1)
#define DMA_DECLARE_BUFFER(type, name, size) \ void __##name[DMA_ALIGN_SIZE(size * sizeof(type))]; \ type * name = __##name & ~(CONFIG_SYS_CACHELINE_SIZE - 1));
DMA_DECLARE_BUFFER(int, buffer, 100);
This doesn't compile, and it tries to round the buffer down below its starting point.
After fixing the more obvious issues, I get "error: initializer element is not constant".
There might be no way to express and-by-constant as a relocation.
You could set the pointer at runtime, though, and remove some of the macrification:
#define DMA_ALIGN_SIZE(size) \ ((size) + CONFIG_SYS_CACHELINE_SIZE - 1) #define DMA_ALIGN_ADDR(addr) \ (DMA_ALIGN_SIZE(addr) & (CONFIG_SYS_CACHELINE_SIZE - 1))
int buffer_unaligned[DMA_ALIGN_SIZE(100)]; int *buffer;
some_init_func() { buffer = (int *)(DMA_ALIGN_ADDR((uintptr_t)buffer_unaligned)); }
- Use GCC specific alignment attribute:
#define CACHLINE_ALIGNED __attribute__ ((aligned (CONFIG_SYS_CACHELINE_SIZE)))
int buffer[100] CACHELINE_ALIGNED;
Pros: The declaration of the buffer is even simpler and more obvious, no use of alloca at all.
Cons: This doesn't work in any version of GCC before October 2010. Meaning that it probably doesn't work in whatever compiler you're using.
It's really too bad that this isn't a usable solution. I suppose that we could switch to it at some point when we expect U-Boot to only be compiled by versions of GCC that support this. By the way, the failure mode here is pretty bad. If you compile the above code with an older GCC it will silently fail to align the variable. :(
If the decision is made to depend on newer compilers, U-Boot could check for it and #error out if the compiler is too old (possibly just in the files that depend on this feature).
-Scott