• 使用中断开关实现全局变量互斥访问


      最近在STM32F429平台上实现一套主从机串口库,在开发过程中,出现偶发性丢帧问题,反复核对关键代码,均未发现任何问题,一筹莫展。按照经验第一反应就是互斥访问导致的脏数据问题,但苦于无法锁定问题,因为只有在串口大量数据收发时,才出现偶发性丢帧,无法采取在线调试锁定问题,极其难以抓取。为了能够尽快找到问题关键采取了最费力的办法:

    1. 锁定问题代码,对所有全局变量互斥访问代码逐一注释,同时检测注释后是否停止丢帧:锁定问题代码位置;
    2. 在问题代码处添加调试代码,通过串口重定向打印相关全局变量;

      虽然方法费时费力,但很快有了突破:打印出来的全局变量仅反复的进行加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);
    }

      结果:在开启互斥访问中断开关后,长时间大量测试下均未发生丢帧。  

      总结:如何锁定和确定问题和解决问题的最终方法一样的重要;其次大胆猜测,用后验逻辑去解决问题也不失为一种解决问题的好思路。

      

      

  • 相关阅读:
    数组按行访问和按列访问的区别
    解决github中图片无法显示问题的策略
    C#验证帮助类(手机号、身份证等)
    WPF圆角按钮样式
    弗洛伊德的本我、自我与超我概念
    KEPServerEX OPCUA服务器地址配置
    C#List的一些操作
    梦、清醒梦、梦魇
    类说明head部格式
    阅读笔记20222
  • 原文地址:https://www.cnblogs.com/randyjang/p/8476043.html
Copyright © 2020-2023  润新知