cancel
Showing results for 
Search instead for 
Did you mean: 

Bug: STM32F0xx HAL SPI Transmit

stefanoroggerini9175
Associate II
Posted on September 23, 2016 at 11:35

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.
19 REPLIES 19
martin wijk
Associate II
Posted on September 05, 2017 at 15:08

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?

Posted on September 06, 2017 at 17:20

 ,

 ,

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 following

command

:

♯ pragma data_alignment = 4

 ,

uint8_t My_buffer_to_align[Number_Of_Data] ,

Thanks

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Posted on September 14, 2017 at 23:35

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?
Posted on September 15, 2017 at 01:02

Also it is valid with STM32F1,too

Posted on September 15, 2017 at 02:25

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on September 15, 2017 at 02:44

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.

Posted on September 15, 2017 at 03:29

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on September 15, 2017 at 03:37

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];

Posted on September 15, 2017 at 04:24

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_sp

http://www.keil.com/support/man/docs/armasm/armasm_dom1361290002364.htm

 
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on September 15, 2017 at 16:50

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_limit

Clive 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?