SmartOS/Core/Queue.cpp

209 lines
4.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Queue.h"
extern void EnterCritical();
extern void ExitCritical();
/*// 智能IRQ初始化时备份销毁时还原
// SmartIRQ相当霸道它直接关闭所有中断再也没有别的任务可以跟当前任务争夺MCU
class SmartIRQ
{
public:
SmartIRQ()
{
EnterCritical();
}
~SmartIRQ()
{
ExitCritical();
}
};*/
Queue::Queue(uint len) : _s(len)
{
Clear();
}
void Queue::SetCapacity(uint len)
{
_s.SetLength(len);
}
void Queue::Clear()
{
_s.SetLength(_s.Capacity());
_head = 0;
_tail = 0;
_size = 0;
}
#if !defined(TINY) && defined(STM32F0)
#if defined(__CC_ARM)
#pragma arm section code = "SectionForSys"
#elif defined(__GNUC__)
__attribute__((section("SectionForSys")))
#endif
#endif
void Queue::Push(byte dat)
{
_s[_head++] = dat;
//_head %= _s.Capacity();
// 除法运算是一个超级大祸害,它浪费了大量时间,导致串口中断接收丢数据
if(_head >= _s.Capacity()) _head -= _s.Capacity();
//SmartIRQ irq;
EnterCritical();
_size++;
ExitCritical();
}
byte Queue::Pop()
{
if(_size == 0) return 0;
{
//SmartIRQ irq;
EnterCritical();
_size--;
ExitCritical();
}
/*
昨晚发现串口频繁收发一段数据后出现丢数据现象也即是size为0然后tail比head小刚开始小一个字节然后会逐步拉大。
经过分析得知ARM指令没有递加递减指令更没有原子操作。
size拿出来减一然后再保存回去但是保存回去之前串口接收中断写入拿到了旧的size导致最后的size比原计划要小1。
该问题只能通过关闭中断来解决。为了减少关中断时间以提升性能增加了专门的Read方法。
*/
byte dat = _s[_tail++];
//_tail %= _s.Capacity();
if(_tail >= _s.Capacity()) _tail -= _s.Capacity();
return dat;
}
#if !defined(TINY) && defined(STM32F0)
#if defined(__CC_ARM)
#pragma arm section code
#elif defined(__GNUC__)
__attribute__((section("")))
#endif
#endif
uint Queue::Write(const Buffer& bs)
{
/*
1数据写入队列末尾
2如果还剩有数据则从开头开始写入
3循环处理2
4如果队列过小很有可能后来数据会覆盖前面数据
*/
//byte* buf = (byte*)bs.GetBuffer();
uint len = bs.Length();
uint rs = 0;
while(true)
{
// 计算这一个循环剩下的位置
uint remain = _s.Length() - _head;
// 如果要写入的数据足够存放
if(len <= remain)
{
//_s.Copy(buf, len, _head);
_s.Copy(_head, bs, rs, len);
rs += len;
_head += len;
if(_head >= _s.Length()) _head -= _s.Length();
break;
}
// 否则先写一段,指针回到开头
//_s.Copy(buf, remain, _head);
_s.Copy(_head, bs, rs, remain);
//buf += remain;
len -= remain;
rs += remain;
_head = 0;
}
{
//SmartIRQ irq;
EnterCritical();
_size += rs;
ExitCritical();
}
return rs;
}
uint Queue::Read(Buffer& bs)
{
if(_size == 0) return 0;
/*
1读取当前数据到末尾
2如果还剩有数据则从头开始读取
3循环处理2
4如果队列过小很有可能后来数据会覆盖前面数据
*/
uint len = bs.Length();
if(!len) return 0;
//byte* buf = (byte*)bs.GetBuffer();
if(len > _size) len = _size;
uint rs = 0;
while(true)
{
// 计算这一个循环剩下的位置
uint remain = _s.Capacity() - _tail;
// 如果要读取的数据都在这里
if(len <= remain)
{
//_s.CopyTo(buf, len, _tail);
//_s.CopyTo(_tail, bs, rs, len);
bs.Copy(rs, _s, _tail, len);
rs += len;
_tail += len;
if(_tail >= _s.Capacity()) _tail -= _s.Capacity();
break;
}
// 否则先读一段,指针回到开头
//_s.CopyTo(buf, remain, _tail);
//_s.CopyTo(_tail, bs, rs, remain);
bs.Copy(rs, _s, _tail, remain);
//buf += remain;
len -= remain;
rs += remain;
_tail = 0;
}
//bs.SetLength(rs, false);
{
//SmartIRQ irq;
EnterCritical();
_size -= rs;
ExitCritical();
}
//if(_size == 0) _tail = _head;
return rs;
}
#if defined(__CC_ARM)
__weak void EnterCritical() { }
__weak void ExitCritical() { }
#elif defined(__GNUC__)
void EnterCritical() __attribute__((weak));
void EnterCritical() { }
void ExitCritical() __attribute__((weak));
void ExitCritical() { }
#endif