Hello, I'm stuck with hardfault handler.
When I try to execute read value from pointer address:
struct S2E_Packet { uint8_t module_type[3]; uint8_t fw_ver[3]; } __attribute__((packed)) S2E_Packet;
struct S2E_Packet s2e_packet;
AddressSrc=(uint32_t)&s2e_packet; uint32_t test = *(uint32_t*)AddressSrc; HAL_FLASH_Unlock(); HAL_FLASH_Program(TYPEPROGRAM_WORD, AddressDes, test);
program goes to hardfault handler. No errors or warnings during compilation.
I have no idea.....
Processor is STM32F072RB. Fault is connected with instruction: uint32_t test = *(uint32_t*)AddressSrc;
It is strange but it works when I switch to char: AddressSrc=(uint32_t)&s2e_packet; char test = *(uint32_t*)AddressSrc; Now I can read first byte of struct variable.
But I need 4 byte for flash write function.;(
Why I cannot read uint32_t type from pointer? What else can I check?
Note that you are playing with packed data.
Then you type-cast into a pointer that does not know anything about the data being packet. So if AddressSrc isn't a 32-bit-aligned value then you will get into troubles when reading/writing using your pointer.
Be very, very careful when playing with type casts. Especially that you don't strip some volatile, packed or other important attribute.
It is strange but it works when I switch to char Not really. Welcome to the world of a CPU that actually cares about alignment.
Why I cannot read uint32_t type from pointer?
Because there is no uint32_t object at the address you've brutally forced that pointer to point to.
The Cortex-M0 does not permit unaligned 32-bit reads, ie ones where the address is not divisible by 4. It will Hard Fault, so use memcpy() to get data from an unaligned address into a variable.
Thanks for answer. I know that maybe this kind of pointer cast is "brutal" way but I just want to read struct value in memory area and simply doesn't care what is in the struct value.
Pier, Can You tell me where I can find more about Cortex-M0 unaligned 32-bit limit? It is sth new for me.
Thanks everybody for answers.
Just make sure you align the data at an address evenly dividable by 4. Or make use of a uint8_t pointer to extract the four bytes and then combine them into a uint32_t value.
The memory controller on x86 systems is nice and hides issues with unaligned data (except for potential bandwidth loss). But lots of 32-bit processors do not have a nice memory controller that makes two 32-bit accesses to be able to combine some bytes from the first word and some bytes from the second word before handing over to the processor core.
The compiler+linker will normally align the data. When the compiler sees that data is packed, then it knows it can't trust the data to be properly aligned so it will instead produce alternative (larger/slower) code that can handle unaligned accesses. But your type cast throws away that attribute so the compiler assumes the pointer points to aligned data and is safe to use as-is.
View a quick Google infocenter.arm.com/.../index.jsp
__attribute__((packed)) and __packed are very similar, but not the same. struct S2E_Packet { uint8_t module_type[3]; uint8_t fw_ver[3]; uint32_t uint1; // &se2_Packet.uint1 gives you a (uint32_t *) } __attribute__((packed)) S2E_Packet; __packed struct S2E_Packet { uint8_t module_type[3]; uint8_t fw_ver[3]; uint32_t uint1; // &se2_Packet.uint1 gives you a (__packed uint32_t *) } S2E_Packet; If you use the following cast, it works with aligned or un-aligned data. No Hard Fault. uint32_t test = *(__packed uint32_t*)AddressSrc; Google "Cortex-M0 data alignment" and you will get good information
I just want to read struct value in memory area and simply doesn't care what is in the struct value.
If that's what you're trying to do, how did pointers to 32-bit integers even enter the picture? There's nothing related uint32_t in that job description. A uint32_t isn't even big enough to hold all the bytes of the existing struct.
If all you want to do is move sequences of bytes from one place to the another, use (void *) for passing around the pointers, and (uint8_t *) to actually access the data. That's what they exist for. There's no point even thinking about (uint32_t *) for this.
Solution with "__packed uint32_t*" works like a charm;) Now I can read memory area of struct value in 4 byte sequence and use for flash write function.
Many thaks for all advices.