我正在尝试使用SPI在F410 MCU和RPi之间进行SPI通信。 我在当前有效的代码下面发布(不使用FreeRTOS):
main.c
volatile int tx_done = 0;
volatile int rx_done = 0;
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
tx_done = 1;
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
rx_done = 1;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI5_Init();
MX_USART2_UART_Init();
const uint8_t BUF_SIZE = 16 * sizeof(uint8_t);
uint8_t buf[16];
// For UART debug
uint8_t dbg_buffer[64];
while (1) {
memset(buf, 0, BUF_SIZE);
HAL_StatusTypeDef ret = HAL_SPI_Receive_IT(&hspi5, (uint8_t*)&buf, BUF_SIZE);
while (rx_done == 0) {};
rx_done = 0;
sprintf((char*) dbg_buffer, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d]\r\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
buf[13], buf[14], buf[15]);
HAL_UART_Transmit(&huart2, dbg_buffer, strlen((char const*) dbg_buffer), 50);
HAL_SPI_Transmit_IT(&hspi5, (uint8_t*) &buf, BUF_SIZE);
while (tx_done == 0) {};
tx_done = 0;
}
}
stm32f4xx_it.c
/**
* @brief This function handles TIM1 trigger and commutation interrupts and TIM11 global interrupt.
*/
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim11);
}
/**
* @brief This function handles SPI5 global interrupt.
*/
void SPI5_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi5);
}
spi.c
/* SPI5 init function */
void MX_SPI5_Init(void)
{
hspi5.Instance = SPI5;
hspi5.Init.Mode = SPI_MODE_SLAVE;
hspi5.Init.Direction = SPI_DIRECTION_2LINES;
hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi5.Init.NSS = SPI_NSS_HARD_INPUT;
hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi5.Init.CRCPolynomial = 15;
if (HAL_SPI_Init(&hspi5) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
[...]
HAL_NVIC_SetPriority(SPI5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI5_IRQn);
}
这与我的另一侧(树莓派)的测试代码配合使用,可以每秒发送一个SPI帧,等待100ms并从F410读取答案。
现在,当我激活FreeRTOS时,我将while(1)循环内容移动到任务中,并使用
创建它BaseType_t task1 = xTaskCreate(task_1, "task_1", 512, NULL, tskIDLE_PRIORITY, &xHandle);
和osKernelStart()。我还使用TIM11作为时基源(根据软件本身的建议,在CubeMX的SYS选项卡下)
然后,我有以下行为:如果我在两个Tx / Rx SPI中断中都放置了断点,我发现其中有两对(3-4?)被触发,然后再也不会触发。如果停止我的代码,我会发现自己陷入了
while (rx_done == 0) {};
循环,确认我不再收到SPI RX中断,而SPI总线上仍有帧。
为了深入研究该理论,我在任务中对此进行了另一项测试:
while(1) {
memset(buf, 0, 16);
HAL_StatusTypeDef ret = HAL_SPI_Receive_IT(&hspi5, (uint8_t*)&buf, 16);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
// Wait for RX interrupt, task is suspended to give processing time to (incoming) others tasks
vTaskSuspend(NULL);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
}
在我的Rx中断中,我只需调用
xTaskResumeFromISR(task1Handle);
使用此代码,STM32F4可以正确读取发送的第一个数据包,然后任务将其打印在USART2上并再次挂起。从那时起,(再检查内部是否有断点),再也不会调用Rx中断,因此任务都不会在其中继续执行,并且我的代码被冻结...
真的看起来FreeRTOS和STM32 HAL SPI /中断处理之间是一团糟吗?
任何帮助都会很高兴被接受!
答案 0 :(得分:0)
您是否按照此页面上红色文字所述致电NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
:https://www.freertos.org/RTOS-Cortex-M3-M4.html?
如果将STM32与STM32驱动程序库一起使用,则通过调用NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)确保将所有优先级位分配为可抢占优先级位。在RTOS启动之前。