最近在STM32F429平台上实现一套主从机串口库,在开发过程中,出现偶发性丢帧问题,反复核对关键代码,均未发现任何问题,一筹莫展。按照经验第一反应就是互斥访问导致的脏数据问题,但苦于无法锁定问题,因为只有在串口大量数据收发时,才出现偶发性丢帧,无法采取在线调试锁定问题,极其难以抓取。为了能够尽快找到问题关键采取了最费力的办法:
- 锁定问题代码,对所有全局变量互斥访问代码逐一注释,同时检测注释后是否停止丢帧:锁定问题代码位置;
- 在问题代码处添加调试代码,通过串口重定向打印相关全局变量;
虽然方法费时费力,但很快有了突破:打印出来的全局变量仅反复的进行加0操作,其未做任何改变,但仍发生丢帧,由此推论:串口丢帧是由于全局变量互斥访问引起的可能性极大。
解决方法:1、使用中断开关,在进行互斥访问前关闭中断,完成后再开启中断;2、使用LDREX/STREX指令;
为了最快地解决问题,先暂时采用方法一(以下是部分代码):
void uart_it_sw(FunctionalState state)
{
USART_ITConfig(USART, USART_IT_RXNE, state);
}
void USART1_IRQHandler(void)
{
uint8_t ucTemp;
if(USART_GetITStatus(USART,USART_IT_RXNE)!=RESET)
{
ucTemp = USART_ReceiveData( USART );
push(ucTemp);
}
}
static int front=0;
static int rear=0;
static int count=0;
void push(unsigned char tmp)
{
recv_buf[rear]=tmp;
rear++;
rear%=MAX_QUEUE_LEN;
if (count==MAX_QUEUE_LEN)
{
front++;
front%=MAX_QUEUE_LEN;
}
else
{
count++;
}
}
void pop(int len)
{
// if (len>0)
{
if (len>count)
{
len=count;
}
uart_it_sw(DISABLE); //互斥访问前关闭串口中断
front+=len;
front%=MAX_QUEUE_LEN;
count-=len;
uart_it_sw(ENABLE); //互斥访问结束重新打开串口中断
}
}
void empty(void)
{
uart_it_sw(DISABLE);
front=0;
rear=0;
count=0;
uart_it_sw(ENABLE);
}
结果:在开启互斥访问中断开关后,长时间大量测试下均未发生丢帧。
总结:如何锁定和确定问题和解决问题的最终方法一样的重要;其次大胆猜测,用后验逻辑去解决问题也不失为一种解决问题的好思路。