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



利用STM32 中断进行串口数据读写,由于引入中断机制,串口的读是放在中断回调函数中,由于中断的高速性,很容易引起指定的缓存区满,因此增加串口读缓冲队列,是保证数据高效可靠的保证。

STM32中,没有高级操作系统中的线程调度这一概念,也就无锁的概念,但是中断的优先级高,会不停的打断主程序的执行,当主程序重回中断向量位置时,由于中断对一些数据状态的改变,主程序很容易读到脏数据。因为缓冲队列是作为公共缓冲区的中转场合,势必会造成中断部分与主程序部分的争用问题,为了解决这种竞态争用队列的问题,采用传统的递归扫描队列中的环形数组状态的方法,就不可行了,递归的过程中很容易读到脏数据了。

分析中发现,由于缓冲区较大,读、写部分,是对缓冲区中的不同部分来分开处理的,因此可以把公共竞态的部分,缩小,缩小到状态位的处理,这样争用就少了,但是单独靠状态位,无方向性,因此引入了计数器,只需要比较读、写状态的计数差值,就知道了当前读、写的区间段,为了保证环形数组构造的队列的可循环性,还需要引入游标机制,来确定读、写部分的当前位,游标读、写独立游标,二者唯一需要交互的就是计数器了,利用此方法解决竞态问题。这种机制由于不是高级操作系统的锁那种在CPU上强制做排他处理,因此队列部分无法满足多个输入中断同时进入,多个中断之间的计数会引起竞态。

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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值