This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

STM32F0 uint32_t access across boundary

Hi

I am using MDK5.11a on STM32F050. I come across a hard fault, which I eventually find out it is the following construct that causes the problem.

The following is just to demonstrate the fault.

uint8_t array[30] ;
uint32_t *intptr ;
uint8_t i ;
.....
.....
for(i = 0 ; i <= 10 ; i++)
{ intptr = *(uint32_t*)&array[i]) ;

// then access via the integer pointer if(*intptr == 0) {.... }
}

sure, sooner or later, it crashes with hard fault.

My problem in using this approach to access 32 bit is that I received a stream of data from the USART, and put into the array. Depending on the header bytes, somewhere down the stream, the data bytes can either be interpreted as uint16_t or uint32_t, so accessing the 1st byte of the uint32_t by casting its address to uint32_t* and accessing it as 32 bit may bear the problem if the 4 bytes are not aligned correctly, which in my case, is very likely.

The easy way is copy byte by byte (memcpy) into a uint32_t variable and then further processing the variable. But is there any easy way (compiler directives)? As the construct is C compliant, I would have thought that it is the work of the compiler to deal with this automatically without user knowledge about this cross boundary problem?

Rgds

Calvin

Parents
  • "As the construct is C compliant, I would have thought that it is the work of the compiler to deal with this automatically without user knowledge about this cross boundary problem?"

    Take a closer look at the C language standard, and you'll notice that it is the developer who is responsible for making sure that a type-cast pointer points to a memory block of the required alignmnet for the intended use.

    The compiler+linker are just responsible for making sure that all fields in a struct has the proper align, and that the size of the struct and align of the struct fulfills the hardest requirement of any member of the struct.

    A number of compilers have methods for using packed data, where the compiler is forced to assume the data is not aligned and so perform multiple shorter memory accesses to overcom alignment errors. But this gives larger and slower code, so is not something that should be generally used.

    PC programmers often gets hurt by align, since the Intel memory controller chips has hardware-accelerated handling of unaligned ata - i.e. the memory controller will automatically detect if a 32-bit read/write is unaligned and will then convert the 32-bit read into two 32-bit reads and a merge of the two valus read into the 32-bit value that was originally requested.

    Personally, I prefer to implement get16(), get32(), put16() and put32() instead of having the compiler pack/unpack - that makes it clearly visible where packed data is being used.

Reply
  • "As the construct is C compliant, I would have thought that it is the work of the compiler to deal with this automatically without user knowledge about this cross boundary problem?"

    Take a closer look at the C language standard, and you'll notice that it is the developer who is responsible for making sure that a type-cast pointer points to a memory block of the required alignmnet for the intended use.

    The compiler+linker are just responsible for making sure that all fields in a struct has the proper align, and that the size of the struct and align of the struct fulfills the hardest requirement of any member of the struct.

    A number of compilers have methods for using packed data, where the compiler is forced to assume the data is not aligned and so perform multiple shorter memory accesses to overcom alignment errors. But this gives larger and slower code, so is not something that should be generally used.

    PC programmers often gets hurt by align, since the Intel memory controller chips has hardware-accelerated handling of unaligned ata - i.e. the memory controller will automatically detect if a 32-bit read/write is unaligned and will then convert the 32-bit read into two 32-bit reads and a merge of the two valus read into the 32-bit value that was originally requested.

    Personally, I prefer to implement get16(), get32(), put16() and put32() instead of having the compiler pack/unpack - that makes it clearly visible where packed data is being used.

Children
No data