2025-09-14 6:32 AM
Hi,
I have a struct that looks like the following:
typedef struct {
uint8_t statusbyte;
uint8_t dmaBuffer[32];
} STRUCT_ReceptionBuffer;
The RM0091 instructs that source and destination addresses should be aligned on the data size. What I want to transfer to the buffer are 32-bit words (it is an I2S-to-USB-Audio conversion, and USB deals with bytes).
This means I need to align the struct. I am using the GCC compiler tools but the F0 HAL library also defines the __ALIGN_BEGIN and __ALIGN_END macros.
My question is, how and where should I place these macros in order for them to have the desired effect?
Does this look correct?
typedef __ALIGN_BEGIN struct {
uint8_t statusByte;
__ALIGN_BEGIN uint8_t dmaBuffer[32] __ALIGN_END;
} STRUCT_ReceptionBuffer __ALIGN_END;
Or would this be more correct?
typedef struct __ALIGN_BEGIN {
uint8_t statusByte;
__ALIGN_BEGIN uint8_t __ALIGN_END dmaBuffer[32];
} __ALIGN_END STRUCT_ReceptionBuffer ;
The complier does not seem to care much what I do. Even the following blatantly-wrong looking definition is completely fine?
typedef struct {
uint8_t statusByte; __ALIGN_END
uint8_t __ALIGN_END dmaBuffer[32];
} __ALIGN_END STRUCT_ReceptionBuffer;
Is this just a matter of trial and error? Or is it so that the compiler really doesn't care, and any errors caused by this only pop up during runtime?
2025-09-14 9:40 AM - edited 2025-09-14 9:41 AM
It's not clear what do you actually want:
A. define a structure so that members are properly aligned
B. Unpack byte-packed data to C struct with properly aligned members
C. Define a tightly packed structure (prevent adding pad bytes between struct members) though some struct members won't be aligned.
2025-09-14 11:48 AM - edited 2025-09-14 11:10 PM
Use standard C language feature - _Alignas keyword (in C23 - alignas).
Or - maybe more suitable in your case - declare the buffer as union:
union {
uint32_t buf_as_words[8];
uint8_t buf_as_bytes[32];
};
2025-09-15 12:18 PM - edited 2025-09-15 12:26 PM
@Pavel A. I want to define a structure where the member "dmaBuffer" is 32-bit -aligned, to ensure that using DMA to transfer data to it is safe, regardless of where the beginning of the struct ("statusByte") resides.
This syntax seems to achieve what I want:
typedef struct {
uint8_t statusByte;
__ALIGN_BEGIN uint8_t dmaBuffer[32] __ALIGN_END;
} STRUCT_ReceptionBuffer;
Looking at the memory view, the first member of "dmaBuffer" resides at a 32-bit boundary (in my specific case, at 0x200009b4).
I also tested a scenario where I removed the __ALIGN_* macros. In the memory view, "dmaBuffer" moved to start from 0x200009b1, and the DMA transfer started writing over "statusByte" as well.
So, case closed. If you know the syntax how to align the struct itself, then that'd be appreciated. This latter is just for out of curiosity, not necessity.
2025-09-15 12:24 PM
@gbm Thank you for the suggestion.
Switching to "c23" would require me to modify the "usbd_desc.c" file, and change the __ALIGN_* macros that STM32CubeIDE generated for me, in order for things to be consistent.
I could do that, so I will take this possibility into consideration.
2025-09-15 12:27 PM
You need to align the data buffer being a member of a structure, not the structure as a whole. I suggested two standard ways of doing this without using strange non-standard macros. Since you need to access the buffer as bytes and as words, the union is the way to go, so that you don't need to do the type casts.
_Alignas(uint32_t) uint8_t dmaBufrer;
will work with C11 and above. C23 introduces all-lowercase alignas keyword. GCC13 supplied with CubeIDE supports C23.
2025-09-15 1:51 PM
The structure is uint8_t throughout, so there is nothing to align.
You mentioned you need to transfer 32 bit values to the buffer. Did you mean to define the dmaBuffer as uint32_t and not uint8_t?
2025-09-15 2:12 PM
This will work:
typedef struct {
uint8_t statusbyte;
uint8_t dmaBuffer[32] __attribute__((aligned(4)));
} STRUCT_ReceptionBuffer;
as will this:
typedef struct {
uint8_t statusbyte;
__attribute__((aligned(4))) uint8_t dmaBuffer[32];
} STRUCT_ReceptionBuffer;
The structure itself will always be aligned since one of its members requires 4-bytes alignment. In other words, no need to do this:
__attribute__((aligned(4))) STRUCT_ReceptionBuffer rx;
2025-09-16 1:40 AM - edited 2025-09-16 1:41 AM
@TDK wrote:This will work
As will this, without non-C-standard __attribute__ and with less characters to type. ;)
typedef struct {
uint8_t statusbyte;
_Alignas(uint32_t) uint8_t dmaBuffer[32];
} STRUCT_ReceptionBuffer;
Another side remark - typedef should be avoided here, just for coding style clarity.
2025-09-16 7:24 AM
Do I understand correctly that the placement of the "__attribute__" is not exact science? Considering C-language's strict linguistic rules that seems very bizarre.