да, класс канала отличный класс, плюс ко всем его достоинствам хочется добавить возможность инлайн подстановки кода его функций в прерывание чтобы не тратить время на вызовы в теле прерывания
то же самое и с буфером хочется чтобы вот эта функция push_back_isr была бы инлайновой
сделал пока так но без ковыряния исходников все равно не обошлось - в ринг буфере заменил секцию приват на протектед самую последнюю с переменными
CODE
/*
* classes_isr.h
*
* Created on: 05 сент. 2013 г.
*/
#ifndef CLASSES_ISR_H_
#define CLASSES_ISR_H_
#include "usrlib.h"
namespace usr
{
template<typename T, uint16_t Size, typename S = uint8_t>
class ring_buffer_isr : public ring_buffer<T, Size, S>
{
public:
INLINE bool push_back_isr(const T item);
INLINE S get_free_size_isr() const { return Size - this->Count; }
private:
INLINE void push_item_isr(const T item);
};
}
namespace OS
{
template<typename T, uint16_t Size, typename S = uint8_t>
class channel_isr : public TService
{
public:
INLINE channel_isr() : ProducersProcessMap(0)
, ConsumersProcessMap(0)
, pool()
{
}
//----------------------------------------------------------------
//
// Data transfer functions
//
void write(const T* data, const S cnt);
bool read (T* const data, const S cnt, timeout_t timeout = 0);
void push (const T& item);
INLINE void push_isr (const T& item);
void push_front(const T& item);
bool pop (T& item, timeout_t timeout = 0);
bool pop_back(T& item, timeout_t timeout = 0);
//----------------------------------------------------------------
//
// Service functions
//
INLINE S get_count() const { TCritSect cs; return pool.get_count(); }
INLINE S get_free_size() const { TCritSect cs; return pool.get_free_size(); }
void flush();
protected:
volatile TProcessMap ProducersProcessMap;
volatile TProcessMap ConsumersProcessMap;
usr::ring_buffer_isr<T, Size, S> pool;
};
}
template<typename T, uint16_t Size, typename S>
INLINE bool usr::ring_buffer_isr<T, Size, S>::push_back_isr(const T item){
if(this->Count == Size)
return false;
push_item_isr(item);
return true;
}
template<typename T, uint16_t Size, typename S>
INLINE void usr::ring_buffer_isr<T, Size, S>::push_item_isr(const T item){
this->Buf[this->Last] = item;
this->Last++;
this->Count++;
if(this->Last == Size)
this->Last = 0;
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
void OS::channel_isr<T, Size, S>::push(const T& item)
{
TCritSect cs;
while(!pool.get_free_size())
{
// channel is full, suspend current process until data removed
suspend(ProducersProcessMap);
}
pool.push_back(item);
resume_all(ConsumersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
INLINE void OS::channel_isr<T, Size, S>::push_isr(const T& item)
{
TCritSect cs;
if(pool.get_free_size_isr())
{
pool.push_back_isr(item);
resume_all_isr(ConsumersProcessMap);
}
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
void OS::channel_isr<T, Size, S>::push_front(const T& item)
{
TCritSect cs;
while(!pool.get_free_size())
{
// channel is full, suspend current process until data removed
suspend(ProducersProcessMap);
}
pool.push_front(item);
resume_all(ConsumersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
bool OS::channel_isr<T, Size, S>::pop(T& item, timeout_t timeout)
{
TCritSect cs;
if(pool.get_count())
{
item = pool.pop();
resume_all(ProducersProcessMap);
return true;
}
else
{
cur_proc_timeout() = timeout;
for(;;)
{
// channel is empty, suspend current process until data received or timeout
suspend(ConsumersProcessMap);
if(is_timeouted(ConsumersProcessMap))
return false;
if(pool.get_count())
{
cur_proc_timeout() = 0;
item = pool.pop();
resume_all(ProducersProcessMap);
return true;
}
// otherwise another process caught data
}
}
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
bool OS::channel_isr<T, Size, S>::pop_back(T& item, timeout_t timeout)
{
TCritSect cs;
if(pool.get_count())
{
item = pool.pop_back();
resume_all(ProducersProcessMap);
return true;
}
else
{
cur_proc_timeout() = timeout;
for(;;)
{
// channel is empty, suspend current process until data received or timeout
suspend(ConsumersProcessMap);
if(is_timeouted(ConsumersProcessMap))
return false;
if(pool.get_count())
{
cur_proc_timeout() = 0;
item = pool.pop_back();
resume_all(ProducersProcessMap);
return true;
}
// otherwise another process caught data
}
}
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
void OS::channel_isr<T, Size, S>::flush()
{
TCritSect cs;
pool.flush();
resume_all(ProducersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
void OS::channel_isr<T, Size, S>::write(const T* data, const S count)
{
TCritSect cs;
while(pool.get_free_size() < count)
{
// channel does not have enough space, suspend current process until data removed
suspend(ProducersProcessMap);
}
pool.write(data, count);
resume_all(ConsumersProcessMap);
}
//------------------------------------------------------------------------------
template<typename T, uint16_t Size, typename S>
bool OS::channel_isr<T, Size, S>::read(T* const data, const S count, timeout_t timeout)
{
TCritSect cs;
cur_proc_timeout() = timeout;
while(pool.get_count() < count)
{
// channel doesn't contain enough data, suspend current process until data received or timeout
suspend(ConsumersProcessMap);
if(is_timeouted(ConsumersProcessMap))
return false;
}
cur_proc_timeout() = 0;
pool.read(data, count);
resume_all(ProducersProcessMap);
return true;
}
//------------------------------------------------------------------------------
#endif /* CLASSES_ISR_H_ */
работает примерно так же как и ивент если судить по количеству потерянных пакетов, теперь вопрос: если исходники все равно ковырял то лучше изменения все в них внести чтобы код не дублировать понапрасну?