cancel
Showing results for 
Search instead for 
Did you mean: 

How to reset SPI using HAL functions using Nucleo - L073RZ

JPaz.1
Associate II

I am working on a SPI project (using DMA) as a slave and things seems to work fine but after an hour and maybe more in some cases I see one error and that locks the dma ....I can detect when that happens but I have problems to reset the SPI interface...I tried several things what were posted before like:

HAL_SPI_Abort_IT(&hspi3);

HAL_SPI_Abort(&hspi3);

HAL_SPI_AbortCpltCallback(&hspi3);

HAL_SPIEx_FlushRxFifo(&hspi3);

HAL_SPI_DeInit(&hspi3);

HAL_SPI_Init(&hspi3);

but it does not fix it ...I am using HAL functions ...in a post 2 years ago from from Gone Aug 06 he included the following:

  1. SPIP_SlaveConfigureSpi(pSPIP->hspi);
  2. SPIP_SlaveConfigureDma(pSPIP->hspi);

I do not think these are HAL functions I wonder if you anybody has the code for the functions mentioned above ?

I have been struggling with this for some time ......not sure if it is a noise issue (working with NUCLEO L073RZ ) I am using the highest priority for the SPi and also trying to add pull downs to clock and mosi to try to reduce noise but does not seem to help ....

Thanks for your help.

12 REPLIES 12
Peter BENSCH
ST Employee

You are referring to the very bottom of this thread, but the two lines you mentioned just call the init functions for SPI2 and DMA (for some reason, pasting formatted blocks of code does not currently work):

 /*RCC->AHB1RSTR |= 1<<0; // DMA1

 NOPs(2);

 RCC->AHB1RSTR &= ~(1<<0);*/

 NOPs(2);

 RCC->APB1RSTR1 |= (1<<14);// SPI2

 NOPs(2);

 RCC->APB1RSTR1 &= ~(1<<14);

You will achieve exactly the same result using HAL functions defined in stm32l4xx_hal_rcc.h, but it would still have to be checked whether the NOPs are actually necessary.:

/*

 __HAL_RCC_DMA1_FORCE_RESET(); // see stm32l4xx_hal_rcc.h

 __NOP(); // cmsis_gcc.h

 __NOP();

 __HAL_RCC_DMA1_RELEASE_RESET(); // see stm32l4xx_hal_rcc.h

*/

 __NOP();

 __NOP();

 __HAL_RCC_SPI2_FORCE_RESET(); // see stm32l4xx_hal_rcc.h

 __NOP();

 __NOP();

 __HAL_RCC_SPI2_RELEASE_RESET(); // see stm32l4xx_hal_rcc.h

Regards

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi Peter,

Thanks for your replay ...I did find the dma1_force_reset in stm32l4xx_hal_rcc.h but did not find the SPI2_force_reset (?) .....I am new to STM32 anyways, using SPI2 using  (NUCLEO-L073RZ) and HAL functions I can transmit and receive correct most of the times ...STM processor is the slave and an Aardvark is the master (100Khz - 8 bits) not really creating too much traffic, sporadically mostly I leave the system idle for an hour and maybe more but suddenly i see an error and that is affecting the operation.

In the code I am using basic HAL stuff: (Besides the one SPI Have an ADC also using DMA ( running alone in a thread ) and a UART also TX/and RX using DMA (running also alone in a thread - there is very little traffic in UART almost null it is mostly in receive mode waiting for something that can appear every 20 min or so), I assigned the highest priority to the SPI interrupt. for SPI I have:

SPI_HandleTypeDef hspi2;

DMA_HandleTypeDef hdma_spi2_rx;

DMA_HandleTypeDef hdma_spi2_tx;

 MX_SPI2_Init();

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi2)

{

complete_spi = 1;

}

And in the main program I have a switch to receive and transmit SPI values:

if(HAL_SPI_TransmitReceive_DMA(&hspi2, spi_data_tx, spi_data_rx, 1) != HAL_OK) {

complete_spi = 1;

}

Sometimes the DMA is locked and sometimes I got a wrong value I can detect the wrong value happens ...I wonder if there is some noise (?) I tried to add pull downs to SPI_SCLK, SPI_SS and SPI_MOSI it looks a bit better but the failure is very sporadic and it can happen anytime...problem is when the failure happens only thing I can do is reset the processor to start fresh again so I need to try to implement a mechanism to rest the SPI and continue.. i saw that previous post where some people recommended a method to rest SPI

  1. void SPIP_SlaveReStart(SPIP_t* pSPIP) {
  2. HAL_SPI_DeInit(pSPIP->hspi); // back to original state
  3. // first, we reset the cell (yes!)
  4. /*RCC->AHB1RSTR |= 1<<0; // DMA1
  5. NOPs(2);
  6. RCC->AHB1RSTR &= ~(1<<0);*/
  7. NOPs(2);
  8. RCC->APB1RSTR1 |= (1<<14);// SPI2
  9. NOPs(2);
  10. RCC->APB1RSTR1 &= ~(1<<14);
  11. SPIP_SlaveConfigureSpi(pSPIP->hspi);
  12. SPIP_SlaveConfigureDma(pSPIP->hspi);
  13. }

There are some portions commented out (?) not sure what is really needed to rest the SPI but I can do some experiments, I could not find the functions that were not commented out: HAL_RCC_SPI2_FORCE_RESET & HAL_RCC_SPI2_RELEASE_RESET in stm32l4xx_hal_rcc.h and also the last instructions SPIP_SlaveConfigureSpi() and SPIP_SlaveConfigureDma() are they HAL instructions or there are any HAL equivalents to them ? or there is a better way recommended by STM to rest a SPI peripheral and leave it to its initial state ? ..without affecting the rest of the system..

Thanks for your help, time and consideration,

Joe

__HAL_RCC_SPI2_FORCE_RESET() and __HAL_RCC_SPI2_RELEASE_RESET() are defines.

You will find them in stm32l4xx_hal_rcc.h in either the firmware you may have downloaded to your repository (see e.g. STM32CubeIDE settings) or in the Github repository, currently at lines 2470 and 2568.

Regards

/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi Peter,

ok I found them ...my restart sequence is as follows:

void Error_Handler2(){

  status_dma1 = HAL_SPI_Abort_IT(&hspi2);

  osDelay(5);

  status_dma2 = HAL_SPI_Abort(&hspi2);

  osDelay(5);

  HAL_SPI_AbortCpltCallback(&hspi2);

  osDelay(5);

  status_dma4 = HAL_DMA_Abort(&hdma_spi2_rx);

  osDelay(5);

  status_dma5 = HAL_DMA_Abort(&hdma_spi2_tx);

  osDelay(5);

  status_dma6 = HAL_DMA_Abort_IT(&hdma_spi2_rx);

  osDelay(5);

  status_dma7 = HAL_DMA_Abort_IT(&hdma_spi2_tx);

  osDelay(5);

  status_dma8 = HAL_SPI_DeInit(&hspi2);

  osDelay(5);

  status_dma9 = HAL_DMA_DeInit(&hdma_spi2_rx);

  osDelay(5);

  status_dma10 = HAL_DMA_DeInit(&hdma_spi2_tx);

  osDelay(5);

  __HAL_RCC_SPI2_FORCE_RESET();

  osDelay(10);

  __HAL_RCC_SPI2_RELEASE_RESET();

  MX_SPI1_Init();

  osDelay(5);

  status_dma12 = HAL_DMA_Init(&hdma_spi2_rx);

osDelay(5);

  status_dma13 = HAL_DMA_Init(&hdma_spi2_tx);

  osDelay(5);

}

Now I noticed the after 3 hours I got a failure and system was idle I was not doing any spi transaction and suddenly I caught a spi failure so it passed the checked and I detected as a default in a switch case (not expected value in spi) ...

if((status_spitxrx = HAL_SPI_TransmitReceive_DMA(&hspi2, spi_data_tx, spi_data_rx, 1)) != HAL_OK) {

complete_spi = 1;

  Error_Handler2();

}

while (complete_spi != 1){

osDelay(1);

}

complete_spi = 0;

is it some noise (?) ,,,I also started seeing prints that I should not expect in other parts of the system is it possible that system went into the weeds or interrupts got in a weird state ?? ...how can I verify the system is ok ???...I tried to increase the stack as much as I can for t he different tasks but I got the max now 0 available ....

JPaz.1
Associate II

when the spi fails how can I verify the status of the system like if there was a problem with interrupt or if an stack overflow or any other error in the processor happens ? ....are there some instructions to do so ....I can add those checks whenever i detect the spi error and determine if a system error happened too ...

I got it again without doing anything in theory no spi transaction caught something in

if((status_spitxrx = HAL_SPI_TransmitReceive_DMA(&hspi2, spi_data_tx, spi_data_rx, 1)) != HAL_OK) {

complete_spi = 1;

  Error_Handler2();

}

I got HL_OK in the instruction but I detected a wrong spi value (not expected value) ...tested some other portions of the system while in that condition and they look ok at least they responded (so it looks like the rest of the system is ok) ...the print I was getting before was because i was not clearing the print buffer ..it will be a print error instead .......system was idle no spi transaction was it noise ??? how to removed ?? ... I already tried to add pull downs in clock , ss and MOSI line change the speed to slow and it is failing ?? after error in transaction is detected systems goes to try to clean (running abort_spi()) routine to de-init and re-init spi with:

void abort_spi1(){

  status_dma1 = HAL_SPI_Abort_IT(&hspi2);

  osDelay(5);

  status_dma2 = HAL_SPI_Abort(&hspi2);

  osDelay(5);

  HAL_SPI_AbortCpltCallback(&hspi2);

  osDelay(5);

  status_dma4 = HAL_DMA_Abort(&hdma_spi2_rx);

  osDelay(5);

  status_dma5 = HAL_DMA_Abort(&hdma_spi2_tx);

  osDelay(5);

  status_dma6 = HAL_DMA_Abort_IT(&hdma_spi2_rx);

  osDelay(5);

  status_dma7 = HAL_DMA_Abort_IT(&hdma_spi2_tx);

  osDelay(5);

  status_dma8 = HAL_SPI_DeInit(&hspi2);

  osDelay(5);

  status_dma9 = HAL_DMA_DeInit(&hdma_spi2_rx);

  osDelay(5);

  status_dma10 = HAL_DMA_DeInit(&hdma_spi2_tx);

  osDelay(5);

  MX_SPI1_Init();

  osDelay(5);

  status_dma12 = HAL_DMA_Init(&hdma_spi2_rx);

osDelay(5);

  status_dma13 = HAL_DMA_Init(&hdma_spi2_tx);

  osDelay(5);

  printf(MSG, "Wrong value SPI caught ...aborting SPI\n\r");

  HAL_UART_Transmit_IT(&huart2, MSG, sizeof(MSG));

  osDelay(15);

}

but it looks like it not cleaning the spi bus and next transaction HAL_SPI_TransmitReceive_DMA(&hspi2, spi_data_tx, spi_data_rx, 1) gives HAL_BUSY forever .....

Please how can I fix this ????? ...it looks like it is spi related ...just need to clean it and start fresh ...

Here is another updated, included the response of the different operations in spi_abort() routine (system failed in idle state not doing any spi transaction ...can it be noise (?) , other portions of the system look ok), included force and release reset instructions

for some reason after HAL_SPI_AbortCpltCallback the HAL_DMA_Abort() instructions all give HAL_ERROR anyway the de-init and init all got HAL_OK ...but the next transaction after that (it should a normal spi after the cleaning) alwasy give HAL_BUSY ...how to reset that indicator or force it ?

spi_abort()

{

status_dma1 = HAL_SPI_Abort_IT(&hspi2);

  osDelay(5); HAL_OK

  status_dma2 = HAL_SPI_Abort(&hspi2);

  osDelay(5); HAL_OK

  HAL_SPI_AbortCpltCallback(&hspi2);

  osDelay(5); NA

  status_dma4 = HAL_DMA_Abort(&hdma_spi2_rx);

  osDelay(5); HAL_ERROR

  status_dma5 = HAL_DMA_Abort(&hdma_spi2_tx);

  osDelay(5);  HAL_ERROR

  status_dma6 = HAL_DMA_Abort_IT(&hdma_spi2_rx);

  osDelay(5);  HAL_ERROR

  status_dma7 = HAL_DMA_Abort_IT(&hdma_spi2_tx);

  osDelay(5);  HAL_ERROR

  status_dma8 = HAL_SPI_DeInit(&hspi2);

  osDelay(5);  HAL_OK

  status_dma9 = HAL_DMA_DeInit(&hdma_spi2_rx);

  osDelay(5);  HAL_OK

  status_dma10 = HAL_DMA_DeInit(&hdma_spi2_tx);

  osDelay(5);  HAL_OK

  __HAL_RCC_SPI2_FORCE_RESET();

  osDelay(10);

  __HAL_RCC_SPI2_RELEASE_RESET();

  osDelay(10);

  MX_SPI1_Init();

  osDelay(10); HAL_OK

  status_dma12 = HAL_DMA_Init(&hdma_spi2_rx);  

     osDelay(5); HAL_OK

  status_dma13 = HAL_DMA_Init(&hdma_spi2_tx);

  osDelay(5); HAL_OK

 }

Next transaction (it should be a normal one) gives a HAL_BUSY and any subsequent transaction gives HAL_BUSY

if((status_spitxrx = HAL_SPI_TransmitReceive_DMA(&hspi2, spi_data_tx, spi_data_rx, 1)) != HAL_OK) {

complete_spi = 1;

  Error_Handler2();

}

     status_spitxrx = HAL_BUSY

It looks like it did not reset correctly the SPI ??

Thanks for your help, time and consideration,

Joe

In order to recreate the problem I have a breakpoint whenever i see the first error (spi sending a value non-expected - in the tries system was idle and suddenly caught a valid transaction with a wrong value -- noise (?) ) then I followed step by step going to the abort_spi() routine and then starting again another transaction I am the slave the master is not sending so just by trying HAL_SPI_TransmitReceive_DMA(&hspi2, spi_data_tx, spi_data_rx, 1)) I got a HAL_BUSY after the reset ....the sequence to reset spi I have is not completely correct....what is the right sequence?...the rest of the systems looks ok and when spi works fine it does not have any issues ...just need to reset it correctly when a wrong value is received ....what is that sequence ????

Error while parsing Rich Text Content