I've seen that the subject has been discussed in many other questions, but I can't quite find the answer for my particular case.
I am working with a STM32F0 microcontroller. The top of the SPI reception/transmit FIFO are accessible by a memory access. This particular microcontroller allows me to read/write 8bits or 16bits from the top of the FIFO. More precisely, when a LDRB/STRB instruction is executed, 8bits are popped/pushed from/to the FIFO and when a LDRH/STRH instruction is executed, 16 bits are popped/pushed from/to the FIFO.
The Hardware Abstraction Layer provided by STMicroelectronic proposes this syntax to read the SPI FIFO.
return *(volatile uint8_t*)&_handle->Instance->DR; // Pop 1 byte
return *(volatile uint16_t*)&_handle->Instance->DR; // Pop 2 byte
*(volatile uint8_t*)&_handle->Instance->DR = val; // Push 1 byte
*(volatile uint16_t*)&_handle->Instance->DR = val; // Push 2 bytes
Where DR
is a uint32_t*
pointing on the top of the SPI FIFO
I've built my software using this syntax and it does work fine. The only problem, is that g++ throws a lot of warning about type punning. More precisely:
Inc/drivers/SPI.h:70:50: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
return *(volatile uint16_t*)&_handle->Instance->DR;
After some readings it looks like using union is not a good idea in C++. I did try it anyway but got some problems. Actually accessing the memory through a pointer in a union makes my microcontroller crashes just like an unaligned memory access.
static_cast and reinterpret_cast throws the sames warning as the C-style cast
I cannot use memcpy
with void*
since my final goal is to make the compiler uses a LDRB/STRB and LDRH/STRH instruction.
Others proposed solutions that I found on Stack Overflow were dependent on the use-case.
Any suggestion?