2016-08-03 06:18 AM
Hello,
I've got a project build on custom PCB around STM32F051K6T6. There are a couple of other things on this PCB: ULN2003 driver, CD4511B driver , TLV73333 3.3V regulator and the main ''problem'' NRF24L01+ module, connected through SPI1. Board peripherals and init code are generated with CubeMX software. So far everything worked just well: PWM on gpio, timer 6 for some periodic interrupts, CD4511 7 segment driver... When I tried to connect NRF24L01+ through SPI with custom library (modified tm_nrf library) using SPI HAL drivers, strange things happen. uC halts in Hard Fault Handler after a few SPI transmit and/or receive commands. It halts at in stm32fxx_hal_spi.c file in functionHAL_SPI_Transmit()
at specific line ():
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout){
/*
...other code...
*/
/* Transmit data in 8 Bit mode */
else
{
while
(hspi->TxXferCount > 0){
/* Wait until TXE flag is set to send data */
if
((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE){
if
(hspi->TxXferCount > 1){
/* write on the data register in packing mode */
hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
hspi->pTxBuffPtr +=
sizeof
(uint16_t);
hspi->TxXferCount -= 2;
}
else
{
*((__IO uint8_t*)&hspi->Instance->DR) = (*hspi->pTxBuffPtr++);
hspi->TxXferCount--;
}
}
else
{
/* Timeout management */
if
((Timeout == 0) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout))){
errorcode = HAL_TIMEOUT;
goto
error;
}
}
}
}
/*
...other code...
*/
}
... and than halts at HarFault_Handler.
This is my first HardFault ever, so I don't really know how to handle it. I've google it alot, tried tochange stack size and played with other SPI settings, but with no success. The same NRF24L01 board works with Arduino, so there must be an error somewhere in my code/pcb.
Let me know what additional informations are needed.
Thanks!
#hal #spi #cubemx #hardfault
2016-08-03 07:00 AM
> This is my first HardFault ever, so I don't really know how to handle it.
Breath! Breath! ;) Well I usually examine the disassembly in the vicinity of the offending instruction, plus the state of registers at that moment. We lack that at the moment but if it's true that it's related to this line:hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
then chances are that either
hspi->Instance
points to some funny place or, maybe more probably,
hspi->pTxBuffPtr
is not aligned properly (Cortex-M0 can't perform unaligned accesses).
It may be worth noting that there are more faults than just the hardfault, indicating the nature of the fault further, but most of the time there is a common vector for all of them, so you lose that information.
> works with Arduino,
This word is not to be used in a decent society.
JW
2016-08-07 01:44 PM
Hello. Sorry for late reply, I did see your message, but I was very busy with other things. Anyway. in the mean time I noticed, that almost for sure, this code segment in HAL_SPI_Transmit() function is the problem.
1.
hspi->Instance->DR = *((uint16_t*)hspi->pTxBuffPtr);
2.
hspi->pTxBuffPtr +=
sizeof
(uint16_t);
3.
hspi->TxXferCount -= 2;
I will investigate this problem further tomorrow, but for now, if any of you more experienced guys can take a look at 8-bit mode of thisHAL_SPI_Transmit() function, and check if it is really what it should be. Other functions such asHAL_SPI_TransmitReceive() seems like they don't hardfault microcontroller (so
hspi->Instance
should point to something useful). >> works with Arduino, >This word is not to be used in a decent society. I've read this sentence 300 times and laughed each time :D Thanks!2016-08-07 02:15 PM
8-bit should always be fine, the problem with 16-bit and 32-bit is going to be unaligned addresses, you can't read 16-bit values from ODD addresses. You need to manage carefully the buffers handed to the routines.
2016-08-09 12:36 AM
OK, unaligned address would make sense. Anyway, I'm using HAL libraries, which means I shouldn't even know any of these things :) In fact, I do like CubeMX software, so I just hope (or not :)) that this is my mistake somewhere else in code, I don't want to return back to STD_Peripheral libs.
I'm trying to create communication with nrf24l01+ with custom library. I init SPI with CubeMX, and than passhspi1
handler to this external file (eg. stm32_nrf24lc) like this:
1.
#include ''stm32f0xx_nrf24lh''
2.
extern
SPI_HandleTypeDef hspi1;
... and than use it as I would do it in main.c
1.
void
NRF_SPI_Write(SPI_HandleTypeDef* SPIx, uint8_t* data_out, uint32_t count) {
2.
HAL_SPI_Transmit(SPIx, data_out, count, SPI_TIMEOUT);
3.
}
I call this function as:
1.
NRF_SPI_Write(&hspi1, data, count);
So, if I change HAL_SPI_Transmit() function to something I would say is logical to avoid unaligned acces (delete ''16-bit mode'' out and use only 8-bit way to transfer data), this is:
...
/* Check if the SPI is already enabled */
if
((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){
/* Enable SPI peripheral */
__HAL_SPI_ENABLE(hspi);
}
// EDITED 9.8.2016 ***********************************************
while
(hspi->TxXferCount > 0){
/* Wait until TXE flag is set to send data */
if
((hspi->Instance->SR & SPI_FLAG_TXE) == SPI_FLAG_TXE){
*((__IO uint8_t*)&hspi->Instance->DR) = (*hspi->pTxBuffPtr++);
hspi->TxXferCount--;
}
else
{
/* Timeout management */
if
((Timeout == 0) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout))) {
errorcode = HAL_TIMEOUT;
goto
error;
}
}
}
/* Enable CRC Transmission */
if
(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE){
...
(It is just deleted ''packaging transfer mode'').
Well, this is also not working, but at least uC don't lock in HardFault. Any ideas what I am doing wrong? Is it possible this is some kind of HAL_SPI driver bug? I didn't have any real problems with CubeMX generated code so far. Also, time for my project is running really low, and I can't do anything further without nrf24l01+ communication.
Thanks!
2016-08-09 01:06 AM
> Well, this is also not working
Specify. JW2016-08-09 02:28 AM
I've just figured out that two boards, configured as full duplex master - slave can normally communicate through SPI with default CubeMX software. This means an error must be somewhere in nrf24l01+ library or passed arguments that cause unaligment.
> Well, this is also not workingIt doesn't cause HardFault, and no SPI status error is generated, but other code concerning nrf24l01 is not working - it says 1 byte is always available even with no nrf module attached. Anyway, I will focus now on nrf library and arguments to HAL_SPI functions as mentioned above.