近期白嫖君在使用GD32這款芯片時候,發現了一個大概率是芯片設計上的BUG,貼出來和大家分享一下。
我們在使用串口發送數據時,無非是使用兩種方法,一種是逐字節發送,另一種是DMA發送。

一般串口發送數據前,我們需要先查看TBE標志位,判斷緩存區內是不是已經空了,如果空了我們才會往里填數據。
但是當發送緩存區為空時,并不代表我們的數據已經實際發完了,只是代表緩存區內的數據空了,這時物理意義上的發送可能還在進行中,如果你使用RS485器件,這時候把發送使能關斷的話,就會丟失一個字節的數據。
因此,一般發送完成后,需要檢查TC標志是不是已經被拉高了,以此來判斷數據線上的數據是不是確實已經發結束了。
void usart_sendbuf(uint32_t usart_periph, uint8_t *Buffer , uint16_t ucSend_num)
{
unsigned int i;
usart_flag_clear(usart_periph, USART_FLAG_TC); //在發送前要先清除TC
for(i = 0; i < ucSend_num; i++)
{
while(usart_flag_get(usart_periph, USART_FLAG_TBE) == RESET);
usart_data_transmit(usart_periph, Buffer[i]);
}
while(usart_flag_get(usart_periph,USART_FLAG_TC)==RESET);
}
這次白嫖君的程序就是還按照這個套路來寫的,串口發送數據量比較大,在運行一段時間后,程序突然就死機了,查看一下,是死在了最后一行等待TC標志位這里。查看寄存器列表,TC始終為0。
下面是官方庫函數手冊上給出的說明:
TC標識是受單片機硬件控制的,并不受程序影響,這里無法拉高九成九就是芯片BUG了,于是白嫖君谷歌了一下,發現也有人遇到類似問題:
針對這種情況,硬件上無法做出改善,只能從軟件上規避了:
void usart_sendbuf(uint32_t usart_periph, uint8_t *Buffer , uint16_t ucSend_num)
{
uint32_t i;
uint32_t j = 0;
usart_flag_clear(usart_periph, USART_FLAG_TC); //為了使用TC,在發送前要先清除TC
for(i = 0; i< ucSend_num; i++)
{
while(usart_flag_get(usart_periph, USART_FLAG_TBE) == RESET);
usart_data_transmit(usart_periph, Buffer[i]);
}
while(usart_flag_get(usart_periph, USART_FLAG_TC) == RESET)
{
if(j++ >= 0xFFFF) //在這里加超時機制
{
break;
}
}
}
引入超時機制,當等待時間超過設定閾值,則不再等待TC置位,以此來避免程序阻塞假死。
特別注意:出現這種情況目前來說可能GD全系都有可能存在這個問題,且不區分是USART0還是USARTx,同時似乎只在數據量較大時會出現此種情況。我以前用GD的片子也不少,從沒遇見過這種情況。特此說明,避免抬杠嘛~
審核編輯 :李倩
-
芯片
+關注
關注
459文章
52481瀏覽量
440591 -
單片機
+關注
關注
6067文章
44982瀏覽量
650298
原文標題:國產單片機GD32 串口發送再現BUG?
文章出處:【微信號:嵌入式電子創客街,微信公眾號:嵌入式電子創客街】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
如何在Android設備上安裝Cyusb3014芯片驅動?
Gui Guiderv1.9.0使用下拉框控件問題,出現bug不顯示list選項怎么解決?
AI在芯片上的應用:革新設計與功能
移動端設備上稀奇古怪的前端問題收集(一)
使用SIGMA STUDIO PLUS對連接在ADAU1452 SPI上的FLASH進行編程時,程序并不能成功的寫入flash怎么解決?
KiCon 演講回顧(十五):提交 Kicad Bug



eeprom芯片用在什么上
TAS5630B芯片的12V和地短路了,芯片不在板子上,為什么?怎么解除?
引腳封裝HotRod和FC-SOT上倒裝芯片的降額和壽命計算

一般ram芯片上的引腳有哪些
stm32H7 HAL庫中存在的bug
底部填充工藝在倒裝芯片上的應用

評論