2016-09-23 02:35 AM
I have found a bug in the STM32F0xx HAL SPI driver, specifically in the HAL_SPI_Transmit andHAL_SPI_TransmitReceive functions. Basically they are converting a pointer to uint8_t into a pointer to uint16_t. The problem with that is that the M0 cannot support unaligned accesses and the uint8_t pointer is not guaranteed to be on a 16 bit boundary. In fact this has happened to me and the software hard faults when the conversion is attempted.
The functions are defined as:HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
They are specifically asking for a pointer to 8 bit data. In the function: /* Transmit and Receive data in 16 Bit mode */
if(hspi->Init.DataSize > SPI_DATASIZE_8BIT)
{
...
}
/* Transmit and Receive data in 8 Bit mode */
else
{
...
hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint16_t);
hspi->TxXferCount -= 2;
It actually checks whether the data being sent is 8 bits and then converts the pointer to the 8 bit data into a pointer to 16 bit data. #stm32f0xx_hal
Note: this post was migrated and contained many threaded conversations, some content may be missing.
2017-09-05 06:08 AM
Very useful and answers the HardFault on my stm32f30 as well. Took me couple of hours to get here. Upgrading to the latest stm32cubemx V4.22.0 did not help unfortunately. Disabled the 16 bits part and went to byte transfer.
Waiting for a patch.... Any news about this?
2017-09-06 10:20 AM
,
,
Hello,
In the last release of CubeF0 v1.8.0, the issue fix consist of adding an assert in case the input param pData address is not 16-bit aligned:
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
,
{,
uint32_t tickstart = 0U,,
HAL_StatusTypeDef errorcode = HAL_OK,if ((hspi->,Init.DataSize >, SPI_DATASIZE_8BIT) || (Size >, 1U))
,
{
,
/* in this case, 16-bit access is performed on Data
,
So, check Data is 16-bit aligned address */
,
assert_param(IS_SPI_16BIT_ALIGNED_ADDRESS(pData)),
,
}
The fix triggers an assert if the input param pData address is not well aligned =>, on M0 core, it is up to the user to ensure pData address is 16-bit aligned.
NOTE: if the user enables USE_FULL_ASSERT, then, assert_param will trigger a fault that inform the user that something is not well configured (user file stm32f0xx_hal_conf.h).
To avoid the reported issue, user must use pre-compilator option to align Rx/Tx buffer on 16bit/32bit.
,
This can be done thanks to followingcommand
:♯ pragma data_alignment = 4
,
uint8_t My_buffer_to_align[Number_Of_Data] ,Thanks
Imen
2017-09-14 04:35 PM
Hi miss,
Could you tell me more please,I couldn't solve this problem yet,I'm little new in STM,What can I do frankly?2017-09-14 06:02 PM
Also it is valid with STM32F1,too
2017-09-14 07:25 PM
https://community.st.com/0D50X00009XkdqISAR
Like the old ARM7 and ARM9 CPU, they do NOT tolerate unaligned read/write operations, ie a 16-bit or 32-bit access to an odd/unaligned address.
The Cortex-M0 will not decompose an access into two bus transactions, it will fault so you can fix your software.
2017-09-14 07:44 PM
it is likely to be a problem in some processors if you don't address it correctly, as Clive says, as best practice.
If you want help,
you have describe what your doing (processor and slave SPI chip is ??)
describe what the processor is not doing correctly, 4 pins to check
and show the problematic code and result.
Clive is suggesting that you stick to 8 or 16 bit transfers, but make sure the code is matched to the hardware configuration.
if you have an oscilloscope, you should check all 4 lines against the data sheet, then come back to us.
2017-09-14 08:29 PM
Using memcpy() to an aligned local buffer is recommended, Keil will optimize
On the M3/M4 you have to watch for aligned 64-bit read/write which use LDRD/STRD, loading an unaligned double with fault, this can be problematic with streams of data bytes or files where things have byte packing.
2017-09-14 08:37 PM
How do you use the ALIGN function in CPP ?
wouldn't that force the buffer into 64bit alignment ?
but the syntax ?
.ALIGN 64
char myBuffer[128];
2017-09-14 09:24 PM
In the LDRD case it is loading a pair of 32-bit words, 4-byte aligned.
A segment with ALIGN=3 allows for 8-byte alignment, likely a similar scheme for describing segments/sections in C/C++, &sharppragma pack(8) for structures.
Stack_Size EQU 0x400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size__initial_sphttp://www.keil.com/support/man/docs/armasm/armasm_dom1361290002364.htm
2017-09-15 09:50 AM
First thanks for helps .
Some codes in my startup.By the way I did stick 8-bit SPI communication
Stack_Size EQU 0x400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size __initial_sp ; <h> Heap Configuration ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h>Heap_Size EQU 0x200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base Heap_Mem SPACE Heap_Size __heap_limitClive One say me to write this
uint16_t data; memcpy(&data, pData, sizeof(uint16_t)); hspi->Instance->DR =data; and now no HardFault error.Now is it ok everything in backround?and I didnt understand some writings like
How do you use the ALIGN function in CPP ?
wouldn't that force the buffer into 64bit alignment ?
but the syntax ?
also
On the M3/M4 you have to watch for aligned 64-bit read/write which use LDRD/STRD
I think I have lack of informations but I'd like to learn more.You guys said me'
A segment with ALIGN=3 allows for 8-byte alignment' what does it mean?