|
|
  |
Возможность использования OS::channel в прерываниях |
|
|
|
Sep 4 2013, 21:41
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(сарматъ @ Sep 4 2013, 23:26)  я так и не понял, а функции типа push_isr() не нужны?и если не нужны то почему? Не нужны. Код void OS::TChannel::push(uint8_t x) { TCritSect cs;
while (!Cbuf.get_free_size()) { // channel is full, suspend current process suspend(ProducersProcessMap); }
////..... В случае, если кончилось место для записи в фифо, процесс который пишет в буфер засыпает (channel is full, suspend current process). Если запись происходит в прерывании и место кончилось, то кого усыплять-то? Такая ситуация говорит о том что либо буфер мал, либо данные поступают слишком быстро, либо данные читаются слишком медленно.
|
|
|
|
|
Sep 5 2013, 05:39
|
Частый гость
 
Группа: Участник
Сообщений: 153
Регистрация: 19-11-12
Пользователь №: 74 463

|
там могло бы быть что либо такого плана CODE template<typename T, uint16_t Size, typename S> void OS::channel<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); } }
Сообщение отредактировал сарматъ - Sep 5 2013, 05:41
|
|
|
|
|
Sep 5 2013, 06:10
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (сарматъ @ Sep 5 2013, 07:39)  там могло бы быть что либо такого плана Всего предусмотреть невозможно. Но выход есть: CODE template<typename T, uint16_t Size, typename S = uint8_t> class my_channel_with_isr : public channel<T, Size, S> { public: void push_isr(const T& item); }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 5 2013, 07:37
|
Частый гость
 
Группа: Участник
Сообщений: 153
Регистрация: 19-11-12
Пользователь №: 74 463

|
потому что нужен вот такой вот пул и если я его добавляю в наследника канала то в нем о тпредка еще родной 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 скомпилировал
Сообщение отредактировал сарматъ - Sep 5 2013, 08:12
|
|
|
|
|
Sep 5 2013, 08:25
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (сарматъ @ Sep 5 2013, 09:37)  потому что нужен вот такой вот пул Честно говоря, не понимаю - что вы пытаетесь создать. У нас есть класс канала, который вас устраивает всем, кроме отсутствия функции-члена посылки из прерывания. Я предложил вам создать новый класс, наследник канала в котором реализовать недостающую функцию. То есть все остальные функции канала, а также собственно буфер и прочие необходимые переменные используются от родителя и лишь недостающая добавлена в наследнике. Зачем тут начинать все заново с ring_buffer - совершенно непонятно. QUOTE (сарматъ @ Sep 5 2013, 09:37)  и если я его добавляю в наследника канала то в нем о тпредка еще родной ring_buffer будет сидеть Опять же непонятно - зачем добавлять еще один ring_buffer в наследника? Надо использовать родительский. Или я снова не понял вопроса.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 5 2013, 08:33
|
Частый гость
 
Группа: Участник
Сообщений: 153
Регистрация: 19-11-12
Пользователь №: 74 463

|
да, класс канала отличный класс, плюс ко всем его достоинствам хочется добавить возможность инлайн подстановки кода его функций в прерывание чтобы не тратить время на вызовы в теле прерывания то же самое и с буфером хочется чтобы вот эта функция 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_ */ работает примерно так же как и ивент если судить по количеству потерянных пакетов, теперь вопрос: если исходники все равно ковырял то лучше изменения все в них внести чтобы код не дублировать понапрасну?
Сообщение отредактировал сарматъ - Sep 5 2013, 12:26
|
|
|
|
|
Sep 6 2013, 08:29
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
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 варианты. И это никак бы не повлияло на старые проекты - вот такое изменение вполне можно было бы внести в официальные исходники ОС.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 6 2013, 08:44
|
Частый гость
 
Группа: Участник
Сообщений: 153
Регистрация: 19-11-12
Пользователь №: 74 463

|
ок, так и сделаю и потом выложу сюда что получилось собственно результат в прикрепленном файле все равно наследника сделать не получилось - на что то ругается поэтому функцию push_isr_empty добавил в класс канала, она добавляет в пустой канал задачу внутри тела прерывания (в пустой - у меня то что вызывается из прерывания вызывается всегда когда в канал добавляется задача, поэтому дублировать задачи из прерывания смысла нет)
Сообщение отредактировал сарматъ - Sep 6 2013, 11:41
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|