2022-01-17 09:12 PM
Hi all.
I am trying to connect 2 STM32F103C8 (blue pill board).
I run a test using just ONE STM32 using SPI1 as Master and SPI2 as Slave, all configurations were working fine (FullDuplex, Master Transmite. receive only Slave....every test was fine (allways using TX and RX with interruption), this test was performed in order to check if conifiguration is ok....
as all test were ok y decide to interconnect 2 STMs and I have an issue in Slave STM:
Master SPI sent only one data (3), in Slave STM HAL_SPI_RxCpltCallback is fire, so I can see the Data received (3), it is save into an array, but HAL_SPI_ErrorCallback is fire too if Master send more than one word (16 bist).
Data from Master is ok, please check the figure below:
Here is Slave configuration:
#include "main.h"
volatile uint16_t SPI_Datos_RX[5000];
volatile uint8_t SPI_NumElementos=1;
volatile uint8_t SPI_RX_Data_Available=0;
volatile uint16_t SPI_INDEX_RXED=0;
volatile uint16_t SPI_DATA_RXed;
volatile uint16_t INT_TMP=0;
SPI_HandleTypeDef hspi2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);
void Pasivar_SPI_SS()
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, 1);
}
void Activar_SPI_SS()
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, 0);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
SPI_Datos_RX[SPI_INDEX_RXED]=SPI_DATA_RXed;
SPI_INDEX_RXED++;
HAL_SPI_Receive_IT(&hspi2, &SPI_DATA_RXed, SPI_NumElementos);
}
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
int a;
a=HAL_SPI_GetError(&hspi2);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI2_Init();
HAL_SPI_MspInit(&hspi2);
__HAL_SPI_ENABLE(&hspi2);
HAL_SPI_Receive_IT(&hspi2, &SPI_DATA_RXed, SPI_NumElementos);
while (1)
{
for (int a=0; a<1000;a++);
if ((SPI_Datos_RX[INT_TMP]!=0) & (SPI_INDEX_RXED!=0) & (INT_TMP!=0) & (SPI_INDEX_RXED>=4999) )
{
SPI_INDEX_RXED=0;
INT_TMP=0;
}
INT_TMP++;
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_HARD_INPUT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */
this is SPI2 Register:
at this point, HAL_SPI_Receive_IT(&hspi2, &SPI_DATA_RXed, SPI_NumElementos);
was executed, Slave SPI Board is waiting for data from master side.
and this is the register when data from master arrived.
After the HAL_SPI_RxCpltCallback was fire and data was saved, as I am suing debuging tool I can see that HardFault_Handler is called......in stm32f1xx_it.c file.
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
int a;
a=HAL_SPI_GetError(&hspi2);
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
when HAL_SPI_GetError is used, ti got 0 value, as there isn´t any error...but for some reason HardFault_Handlerwas called.....
this is SPI2 configuration from CubeIDE:
In few words: Slave recibe SPI data, 16 bits, after move the data to an array, HardFault_Handler is called, after that if Master send data again, Slave can handle (HAL_SPI_RxCpltCallback is not fire any more)
I need your help, any commment/advice is welcome.
br
Alfredo
Solved! Go to Solution.
2022-01-18 07:38 AM
An overrun suggests the code doesn't read the data fast enough. Try slowing down the clock rate by an order of magnitude to see if the problem disappears, or use DMA.
A hard fault is another issue. Debug the hard fault by reading the SCB registers to understand the source of the problem and correct. Not receiving data after a hard fault is expected.
> if ((SPI_Datos_RX[INT_TMP]!=0) & (SPI_INDEX_RXED!=0) & (INT_TMP!=0) & (SPI_INDEX_RXED>=4999) )
You are doing a bitwise and here. You probably want logical and (&&), not &. Although since they're all boolean, this syntax will actually work.
There are some other issues in the code but I can't see what would cause the hard fault.
2022-01-18 07:38 AM
An overrun suggests the code doesn't read the data fast enough. Try slowing down the clock rate by an order of magnitude to see if the problem disappears, or use DMA.
A hard fault is another issue. Debug the hard fault by reading the SCB registers to understand the source of the problem and correct. Not receiving data after a hard fault is expected.
> if ((SPI_Datos_RX[INT_TMP]!=0) & (SPI_INDEX_RXED!=0) & (INT_TMP!=0) & (SPI_INDEX_RXED>=4999) )
You are doing a bitwise and here. You probably want logical and (&&), not &. Although since they're all boolean, this syntax will actually work.
There are some other issues in the code but I can't see what would cause the hard fault.
2022-01-18 07:44 AM
Hi ST community.
I decided to change from 16 bits 8 bits, and now SPI between two STM32F103 is working fine, no more void HardFault_Handler (void) is fired....
Why this fault happens? When I tested SPI1 as Master and SPI2 a Slave using Just one STM32F103, test were useful, and now, using 2 STM32F103´s the fault is there.
I need to send Data in 16 bits between STM32´s, so I will handle it, but If is it possible, could be nice to know why 16 bits is failing..... and how this issue can be fixed.
any comments, advice is welcome.
br
Alfredo
2022-01-18 07:48 AM
Yes, if ((SPI_Datos_RX[INT_TMP]!=0) & (SPI_INDEX_RXED!=0) & (INT_TMP!=0) & (SPI_INDEX_RXED>=4999) ) is faulty, this code is part of the test i run....
but when i asked for help, Master was sending just one data, using 16 bits....
2022-01-18 09:02 AM
TDK, thanks a lot for yopur comments.
I was making some mistakes, In order to see/check if SPI was working between STM32F103 was using debuger:
if i use just one break point....in HAL_SPI_ErrorCallback, the comunitacion work fine, as there is not any error, SPI works normally...
but my mistake was set a breakpoint in HAL_SPI_RXCpltCallback, after i saw the data receved, the Error in Hal_SPI_ErrorCallBack was fire.....so as i was breaking the SPI flow (time, secuency, etc) with the Breakpoint in HAL_SPI_RXCpltCallback, later the error is reported....
So, now I am uing 16 bits between both STMs, and as just have a breakopint in HAL_SPI_Error, everything is working fine.
Thanks a lot for your help (again jajaja)
br
Alfredo