2018年3月14日水曜日

UARTのHALで直接割り込み

 久しぶりにHALでUSART割り込み使おうとして覚えてなかったのでメモ。

 HALのUSARTではTXE(Transmit Empty)とRXNE(Read Not Empty)のコールバック関数はない。これは、HALではHandleにバッファのポインタを渡し、HALの中でそこに(/から)転送する、という処理になっているため。
 なので、FreeRTOSのQueueとかで転送したい場合は、自分でUSARTx_IRQHandlerの中身を書く必要がある。

if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE))
{
    extern osMessageQId stdin_queueHandle;
    uint8_t data = huart1.Instance->DR;

    xQueueSendFromISR(stdin_queueHandle, &data, 0);

    return;
}

if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE))
{
    extern osMessageQId stdout_queueHandle;
    uint8_t data = 0;
    BaseType_t status = xQueueReceiveFromISR(stdout_queueHandle, &data, 0);

    if (status == pdPASS)
    {
        huart1.Instance->DR = data;
    }
    else
    {
        __HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);
    }

    return;
}

 この処理はおそらくHAL_UART_IRQHandler(&huartx);の前に書く必要がある。
 また、TXEをチェックしてからRXNEをチェックすると、すでにRXNEがクリアされてる、という謎の挙動があるので、RXNEを先にチェックする必要がある。


 送信の場合は、xQueueSendでデータを入れた後に__HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE);でTXEを有効化し、割り込みの中でDRに転送している。TXEが有効でかつDRにデータがない場合、たぶんずーっと割り込みが回り続ける。なのでQueueが空の場合はDISABLEで停止し、QueueSendの後に都度ENABLEする、という手順にしている。

 受信の場合は、適当な箇所で__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);で割り込みを有効化しておく。RXNEは、受信しない限り割り込みが発生することもないので、ずっと有効状態でいい。


 注意点はあまり多くないが、割り込みのチェック(__HAL_UART_GET_FLAG)に渡す値と、割り込みの有効化/無効化(__HAL_UART_ENABLE_IT等)に渡す値は別の値であることに注意する必要がある。

0 件のコメント:

コメントを投稿