打印
[STM32F1]

【转】STM32 中断缓存队列的竞态争用问题

[复制链接]
589|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
说书先生|  楼主 | 2016-10-10 22:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
利用STM32 中断进行串口数据读写,由于引入中断机制,串口的读是放在中断回调函数中,由于中断的高速性,很容易引起指定的缓存区满,因此增加串口读缓冲队列,是保证数据高效可靠的保证。
STM32中,没有高级操作系统中的线程调度这一概念,也就无锁的概念,但是中断的优先级高,会不停的打断主程序的执行,当主程序重回中断向量位置时,由于中断对一些数据状态的改变,主程序很容易读到脏数据。因为缓冲队列是作为公共缓冲区的中转场合,势必会造成中断部分与主程序部分的争用问题,为了解决这种竞态争用队列的问题,采用传统的递归扫描队列中的环形数组状态的方法,就不可行了,递归的过程中很容易读到脏数据了。
分析中发现,由于缓冲区较大,读、写部分,是对缓冲区中的不同部分来分开处理的,因此可以把公共竞态的部分,缩小,缩小到状态位的处理,这样争用就少了,但是单独靠状态位,无方向性,因此引入了计数器,只需要比较读、写状态的计数差值,就知道了当前读、写的区间段,为了保证环形数组构造的队列的可循环性,还需要引入游标机制,来确定读、写部分的当前位,游标读、写独立游标,二者唯一需要交互的就是计数器了,利用此方法解决竞态问题。这种机制由于不是高级操作系统的锁那种在CPU上强制做排他处理,因此队列部分无法满足多个输入中断同时进入,多个中断之间的计数会引起竞态。
[objc] view plain copy


  • ReceiveBufferData receiveBufferQueue[20];//½ÓÊÕ¶ÓÁР 
  • int writeBufferQueueCursor=0;//½ÓÊÕ¶ÓÁеÄѹÈëÓαꠠ
  • int writeBufferQueueCount=0;//×ܼÆд¶ÓÁеĴÎÊý  
  • int readBufferQueueCursor=0;//½ÓÊÕ¶ÓÁеĶÁÈ¡Óαꠠ
  • int readBufferQueueCount=0;//×ܼƳɹ¦¶Á¶ÓÁеĴÎÊý  
  • int receiveBufferQueueLen=20;//½ÓÊÕ¶ÓÁг¤¶È  
  • ReceiveBufferData emptyReceiveBufferData;//¿ÕµÄÊý¾Ý£¬ÓÃÓÚ¿ÕÅųöʹÓà 
  • //ѹÈë½ÓÊÕÊý¾Ý°üµ½¶ÓÁР 
  • void PushReceiveBufferData(u8 *tempReceiveBuffer,u8 receiveLen)  
  • {  
  •      int i=0;  
  •    int tempWriteBufferQueueCursor=writeBufferQueueCursor;  
  •      ReceiveBufferData receiveItem;  
  •      writeBufferQueueCursor+=1;  
  •      if(writeBufferQueueCursor==receiveBufferQueueLen)  
  •      {  
  •       writeBufferQueueCursor=0;  
  •    }  
  •      receiveBufferQueue[writeBufferQueueCursor].ReceiveStatus=0x00;  
  •      receiveItem=receiveBufferQueue[tempWriteBufferQueueCursor];  
  •      receiveItem.ReceiveLength=receiveLen;  
  •      for(i=0;i<receiveLen;i++)  
  •      {  
  •          *(receiveItem.ReceiveBuffer+i)=*(tempReceiveBuffer+i);  
  •    }  
  •      receiveItem.ReceiveStatus=0x01;  
  •      receiveBufferQueue[tempWriteBufferQueueCursor]=receiveItem;  
  •      writeBufferQueueCount+=1;  
  • }  
  • //µ¯³öÐèÒª´¦ÀíµÄ½ÓÊÕÊý¾Ý°ü  
  • ReceiveBufferData PopReceiveBufferData()  
  • {  
  •     int tempReadBufferQueueCursor=readBufferQueueCursor;  
  •     ReceiveBufferData receiveItem;  
  •     if(readBufferQueueCount>=writeBufferQueueCount)  
  •     {  
  •      emptyReceiveBufferData.ReceiveStatus=0x00;  
  •        return emptyReceiveBufferData;  
  •   }  
  •     readBufferQueueCursor+=1;  
  •     if(readBufferQueueCursor==receiveBufferQueueLen)  
  •     {  
  •      readBufferQueueCursor=0;  
  •   }  
  •     receiveItem=receiveBufferQueue[tempReadBufferQueueCursor];  
  •     if(receiveItem.ReceiveStatus==0x01)  
  •     {  
  •        receiveItem.ReceiveStatus=0x02;  
  •     }  
  •     receiveBufferQueue[tempReadBufferQueueCursor]=receiveItem;  
  •     readBufferQueueCount+=1;  
  •     return receiveItem;  
  • }  


发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

71

主题

191

帖子

0

粉丝