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 件のコメント:
コメントを投稿