STM32F4 SPI прерывает прекращение стрельбы с FreeRTOS - PullRequest
0 голосов
/ 23 ноября 2018

Я пытаюсь установить связь 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 / обработка прерываний?

Любая помощь будет с радостью принята!

1 Ответ

0 голосов
/ 24 ноября 2018

Вы звоните NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );, как описано в красном тексте на этой странице: https://www.freertos.org/RTOS-Cortex-M3-M4.html?

Если вы используете STM32 с библиотекой драйвера STM32, убедитесь, что всеприоритетные биты назначаются как приоритетные приоритетные биты путем вызова NVIC_PriorityGroupConfig (NVIC_PriorityGroup_4);до запуска ОСРВ.

...