UART絶賛死亡中1~3日目はcloseした.外部HWの処理待ちが廻り廻ってhungupを招いていた.
前回はこちら
本日は4日目、UARTが動かない別のトラブルである.
トラブルシュートのため、ゴテゴテとついてたperipheralを全部そぎ落として、原因箇所を特定したcodeはとてもシンプル.ブルーはMXが吐き出したcodeで、赤のみヒラサカが追加したcode.たったこれだけで何が起こるっていうんだ!?
↓main()
int main(void){
MPU_Config();
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_UART7_Init();
HAL_Delay(100);①
HAL_UART_Receive_IT(&huart7, &ccc, 1);②
while(1){}
}
↓UART受信callback
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);③
HAL_UART_Receive_IT(&huart7, &ccc, 1);④
}
①このdelayを入れると、callbackに飛んでこなくなるというトラブル.
①を削除すると正常にcallbackされる.あまりにも謎すぎて笑う.
②UART1文字受信の初回起動.受信したらcallbackしてくれってな意味
③callbackの確認用LEDチカチカ
④次回のUART1文字受信を起動
なんだよこれ? (笑)
起動時に周辺機器の時間調整でwait入れるのなんかフツーじゃん.
まさかHAL_Delayがキモだったとは思わず、追い詰めるのに苦労したよ.
ちなみに、HAL_Delay(1)→HAL_Delay(10)→HAL_Delay(100)と症状は重くなる.1msだと結構動くが、100msだと全然動かない.
さて、謎の100mSecは何かである.
STM32H743のUART7にはSTM32G030が接続され、G030は10mSec毎に文字を打ち続けている.
H743のUART割込みが動かないケース:
MX_UART7_Init();
HAL_Delay(100);
HAL_UART_Receive_IT(&huart7, &ccc, 1);
H743のUART割込みが動くケース:
MX_UART7_Init();
HAL_UART_Receive_IT(&huart7, &ccc, 1);
仮説:
UART7を初期化してからRecieve_ITを起動するまでの間に、G030がバシバシ打電しているはずである.起動直後のUART7に信号が過剰に入ってくるので、Recieve_ITした時点でUART7がoverrunしているのではないか?
netの情報では、overrun FLAGを消すにはHAL_UART_Abort()ではダメで、フラグを直接消しに行かなくちゃダメなどという書き込みを見かける.
対策:
HAL_Delay(100);①
__HAL_UART_CLEAR_OREFLAG(&huart7); ←これ追加でFLAG消去
HAL_UART_Receive_IT(&huart7, &ccc, 1);②
対策は成功しました.
感想:
これってけっこうおぞましい気がするんだよなぁ.
STM32H743の起動時にUARTをinitするでしょ.init routineはMXが吐き出したcodeで、main()の先頭である.
init後に、外部HWの起動待ちで3秒5秒ぐらいは当たり前でwaitするじゃん.
Recieve_IT()するのはその後である.
だけど、外部HW(この場合はSTM32G030)が早起きクンだったり、寝起きにglitch出したりしたら、UARTがoverrunで止まってしまうと言ってる.
今まで本件で困った経験は無かったが、運が良かっただけだったんだな.
1年後ぐらいに追記:
UARTがヤバイかなと思ったら、こうするようにしています.
__HAL_UART_CLEAR_OREFLAG(UARTcomPORT);
__HAL_UART_FLUSH_DRREGISTER(UARTcomPORT);
HAL_UART_Receive_IT(UARTcomPORT, &uartrxbyte, 1);
UARTの内部bufferをご破算にしてから受信起動する意味です.ロストしますけどhangupよりはマシ.これでfixできましたが、これ以外の逃げ道ってあるのかな?
かしこ