Я пытаюсь установить связь SPI между MCU F410 и 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);
}
Это нормально работает с моим тестовым кодом на другой стороне (raspberry pi), посылая кадр SPI каждую секунду, ожидая 100 мс и читая ответ от F410.
Теперь, когда я активируюFreeRTOS, я перемещаю содержимое цикла while (1) в задачу и создаю его с помощью
BaseType_t task1 = xTaskCreate(task_1, "task_1", 512, NULL, tskIDLE_PRIORITY, &xHandle);
и osKernelStart ().Я также использую TIM11 в качестве источника временной базы (на вкладке SYS на CubeMX в соответствии с рекомендациями самого программного обеспечения)
Тогда у меня следующее поведение: если я размещаю точки останова внутри обоих прерываний SPI Tx / Rx, я обнаружил, чтопара (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 / обработка прерываний?
Любая помощь будет с радостью принята!