Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Возможность использования OS::channel в прерываниях
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
Страницы: 1, 2
сарматъ
потому что нужен вот такой вот пул и если я его добавляю в наследника канала то в нем о тпредка еще родной ring_buffer будет сидеть

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


или я что то путаю? (повторюсь я очень не силен в плюсах)

ругается на инлайн(... а это эклипс ругается gcc скомпилировал
Сергей Борщ
QUOTE (сарматъ @ Sep 5 2013, 09:37) *
потому что нужен вот такой вот пул
Честно говоря, не понимаю - что вы пытаетесь создать. У нас есть класс канала, который вас устраивает всем, кроме отсутствия функции-члена посылки из прерывания. Я предложил вам создать новый класс, наследник канала в котором реализовать недостающую функцию. То есть все остальные функции канала, а также собственно буфер и прочие необходимые переменные используются от родителя и лишь недостающая добавлена в наследнике. Зачем тут начинать все заново с ring_buffer - совершенно непонятно.

QUOTE (сарматъ @ Sep 5 2013, 09:37) *
и если я его добавляю в наследника канала то в нем о тпредка еще родной ring_buffer будет сидеть
Опять же непонятно - зачем добавлять еще один ring_buffer в наследника? Надо использовать родительский. Или я снова не понял вопроса.
сарматъ
да, класс канала отличный класс, плюс ко всем его достоинствам хочется добавить возможность инлайн подстановки кода его функций в прерывание чтобы не тратить время на вызовы в теле прерывания

то же самое и с буфером хочется чтобы вот эта функция 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_ */


работает примерно так же как и ивент если судить по количеству потерянных пакетов, теперь вопрос: если исходники все равно ковырял то лучше изменения все в них внести чтобы код не дублировать понапрасну?
Сергей Борщ
QUOTE (сарматъ @ Sep 5 2013, 10:33) *
сделал пока так но без ковыряния исходников все равно не обошлось - в ринг буфере заменил секцию приват на протектед самую последнюю с переменными
Боюсь, вы пошли несколько неправильным путем - вы в своем производном классе практически продублировали весь код функций родителя ради добавления INLINE. Я бы сделал новые inline - функции в родителе и в родителе же используя их же сделал бы не-inline версии:
CODE
template<typename T, uint16_t Size, typename S = uint8_t>
class ring_buffer
{
public:
ring_buffer() : Count(0), First(0), Last(0) { }

//----------------------------------------------------------------
//
// Data transfer functions
//
bool write(const T* data, const S cnt);
void read(T* const data, const S cnt);

INLINE bool push_back_inline(const T item);
INLINE bool push_front_inline(const T item);
bool push_back(const T item);
bool push_front(const T item);
......

template<typename T, uint16_t Size, typename S>
bool usr::ring_buffer<T, Size, S>::push_back_inline(const T item)
{
if(Count == Size)
return false;

push_item(item);
return true;
}

template<typename T, uint16_t Size, typename S>
bool usr::ring_buffer<T, Size, S>::push_back(const T item)
{
return push_back_inline(item);
}
Таким образом полностью исключил бы дублирование кода и получил возможность в наследниках использовать и inline и не-inline варианты. И это никак бы не повлияло на старые проекты - вот такое изменение вполне можно было бы внести в официальные исходники ОС.
сарматъ
ок, так и сделаю и потом выложу сюда что получилось
собственно результат в прикрепленном файле

все равно наследника сделать не получилось - на что то ругается поэтому функцию push_isr_empty добавил в класс канала, она добавляет в пустой канал задачу внутри тела прерывания (в пустой - у меня то что вызывается из прерывания вызывается всегда когда в канал добавляется задача, поэтому дублировать задачи из прерывания смысла нет)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.