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