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