реклама на сайте
подробности

 
 
> Возможность использования OS::channel в прерываниях
abutorin
сообщение Jan 13 2013, 19:25
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Добрый вечер.
Пробую сделать передачу по USART с использование буфера. Для межпроцессорного удобства очень нравится использовать OS::channel. Возможно ли его использовать и в прерываниях? Точнее интересует процедура получения элемента из канала?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
abutorin
сообщение Jan 18 2013, 18:52
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Как обещал ранее выкладываю код который у меня работает.

Код
class usart_transport
{
private:
    usr::ring_buffer<uint8_t, 30, uint8_t> TxPool;
    usr::ring_buffer<uint8_t, 30, uint8_t> RxPool;

    OS::TEventFlag TxNotFull;
    OS::TEventFlag RxNotEmpty;

public:

    USART_TypeDef * PORT;

    bool open (bool)
    {
        USART_ITConfig(this->PORT, USART_IT_RXNE, ENABLE);
        return true;
    }

    INLINE void it_handler ()
    {
        if (USART_GetITStatus(this->PORT,USART_IT_TXE) != RESET)
        {
            if(this->TxPool.get_count())
            {
                USART_SendData(this->PORT,this->TxPool.pop());
                this->TxNotFull.signal_isr();
            }
            else
            {
                USART_ITConfig(this->PORT, USART_IT_TXE, DISABLE);
            }
            USART_ClearITPendingBit(this->PORT,USART_IT_TXE);
        }

        if (USART_GetITStatus(this->PORT,USART_IT_RXNE) != RESET)
        {
            if (this->RxPool.get_free_size())
            {
                this->RxPool.push(USART_ReceiveData(this->PORT));
                this->RxNotEmpty.signal_isr();
            }
            else
            {
                //здесь должна быть обработка переполнения буфера
            }
            USART_ClearITPendingBit(this->PORT,USART_IT_RXNE);
        }

    }

    INLINE bool full ()
    {
        TCritSect cs;

        return !this->TxPool.get_free_size();

    }
    INLINE bool empty ()
    {
        TCritSect cs;

        return !this->RxPool.get_count();
    }

    void send(const uint8_t & data)
    {
        this->TxNotFull.clear();

        while (this->full())
        {
            this->TxNotFull.wait();
        }

        {
            TCritSect cs;
            this->TxPool.push(data);
        }

        USART_ITConfig(this->PORT, USART_IT_TXE, ENABLE);
    }

    uint8_t get ()
    {
        this->RxNotEmpty.clear();

        while (this->empty())
        {
            this->RxNotEmpty.wait();
        }

        TCritSect cs;

        return this->RxPool.pop();
    }
};

Отказ от канала в результате вызван тем, что канал больше предназначен для межпроцессного взаимодействия а не между процессом и прерыванием. Инициализацию порта необходимо выполнять самостоятельно. Сразу хочу заметить что данная реализация сделана на коленке и имеет достаточный потенциал для улучшения, сразу видно что целесообразно сделать данный класс через шаблон со статичными членами, с указанием порта как параметра и использовать данные методы без создания экземпляра класса.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 19 2013, 04:43
Сообщение #3


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



USART_ClearITPendingBit(this->PORT,USART_IT_TXE); - бессмысленная операция. (как я уже писал выше, этот флаг не сбрасывается программно, он read-only).
USART_ClearITPendingBit(this->PORT,USART_IT_RXNE); - лучше перенести в ветку else.
Ну а вообще, OS::channel делает всё то же самое, так что это в некотором роде "закат солнца вручную":)
Цитата(abutorin @ Jan 19 2013, 00:52) *
канал больше предназначен для межпроцессного взаимодействия а не между процессом и прерыванием.

Можете обосновать это утверждение?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 19 2013, 17:19
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(AHTOXA @ Jan 19 2013, 08:43) *
USART_ClearITPendingBit(this->PORT,USART_IT_TXE); - бессмысленная операция. (как я уже писал выше, этот флаг не сбрасывается программно, он read-only).

Возможно, сейчас так сделал для однообразия и нехотелось разбиратся какой флаг сам сбрасывается, а какой нет.

Цитата(AHTOXA @ Jan 19 2013, 08:43) *
USART_ClearITPendingBit(this->PORT,USART_IT_RXNE); - лучше перенести в ветку else.

В какую ветку? Очистка флага нужно всегда когда прерываниеуже обработано.
Цитата(AHTOXA @ Jan 19 2013, 08:43) *
Ну а вообще, OS::channel делает всё то же самое, так что это в некотором роде "закат солнца вручную":)

Можете обосновать это утверждение?


У OS::channel есть дополнительные члены для хранения списка производителей и потребителей, у него более крупная процедура получения первого элемента. Это все годится для межпроцессного взаимодействия, в моем случае все проще и статичнее.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 19 2013, 17:42
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(abutorin @ Jan 19 2013, 23:19) *
В какую ветку? Очистка флага нужно всегда когда прерываниеуже обработано.

Код
            if (this->RxPool.get_free_size())
            {
                this->RxPool.push(USART_ReceiveData(this->PORT)); //  в этой ветке флаг сбрасывается вот этой строчкой
                this->RxNotEmpty.signal_isr();
            }
            else
            {
                //здесь должна быть обработка переполнения буфера
                USART_ClearITPendingBit(this->PORT,USART_IT_RXNE);  // << вот сюда
            }
            // USART_ClearITPendingBit(this->PORT,USART_IT_RXNE); // << отсюда.

Всё же почитайте документацию, использование библиотек не отменяет необходимости её читать. Тогда всё будет работать как надо.
Цитата(abutorin @ Jan 19 2013, 23:19) *
У OS::channel есть дополнительные члены для хранения списка производителей и потребителей, у него более крупная процедура получения первого элемента. Это все годится для межпроцессного взаимодействия, в моем случае все проще и статичнее.

Взамен этих членов вы завели пару штук OS::TEventFlag (TxNotFull, RxNotEmpty). Это явно тяжелее. С остальным тоже не согласен. Но это, конечно, дело вкуса.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 19 2013, 18:42
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(AHTOXA @ Jan 19 2013, 21:42) *
Код
            if (this->RxPool.get_free_size())
            {
                this->RxPool.push(USART_ReceiveData(this->PORT)); //  в этой ветке флаг сбрасывается вот этой строчкой
                this->RxNotEmpty.signal_isr();
            }
            else
            {
                //здесь должна быть обработка переполнения буфера
                USART_ClearITPendingBit(this->PORT,USART_IT_RXNE);  // << вот сюда
            }
            // USART_ClearITPendingBit(this->PORT,USART_IT_RXNE); // << отсюда.

Всё же почитайте документацию, использование библиотек не отменяет необходимости её читать. Тогда всё будет работать как надо.

Взамен этих членов вы завели пару штук OS::TEventFlag (TxNotFull, RxNotEmpty). Это явно тяжелее. С остальным тоже не согласен. Но это, конечно, дело вкуса.

Решил последовать вашим рекомендациям и проверить оба варианта, свой и с использовапние канала

Код
template <typename _Tp,typename BufSizeType,BufSizeType TxbufSize,BufSizeType RxbufSize>
class usart
{
private:
    OS::channel<_Tp, TxbufSize, BufSizeType> TxPool;
    OS::channel<_Tp, RxbufSize, BufSizeType> RxPool;

    bool RxBufferOverflow;

public:

    USART_TypeDef * PORT;

    INLINE bool overflow ()
    {
        return RxBufferOverflow;
    }

    bool open (bool)
    {
        USART_ITConfig(PORT, USART_IT_RXNE, ENABLE);
        return true;
    }

    INLINE void it_handler ()
    {
        OS::TISRW ISRW;

        if (USART_GetITStatus(PORT,USART_IT_TXE) != RESET)
        {
            if(TxPool.get_count())
            {
                _Tp data;
                TxPool.pop(data);
                USART_SendData(PORT,data);
            }
            else
            {
                USART_ITConfig(PORT, USART_IT_TXE, DISABLE);
            }
        }

        if (USART_GetITStatus(PORT,USART_IT_RXNE) != RESET)
        {
            if (RxPool.get_free_size())
            {
                RxPool.push(USART_ReceiveData(PORT));
            }
            else
            {
                RxBufferOverflow = true;
                USART_ClearITPendingBit(PORT,USART_IT_RXNE);
            }
        }

    }

    void send(const _Tp & data)
    {
        TxPool.push(data);
        USART_ITConfig(PORT, USART_IT_TXE, ENABLE);
    }

    _Tp get ()
    {
        _Tp data;
        RxPool.pop(data);
        return data;
    }
};

Из того что не делал ранее это добавил в обработчик прерывания OS::TISRW. С таким кодом передача работает нормально, а вот при попытке принять данные камень зависает. Сразу должен заметить что размер кода увеличился на 176 байт. Размер занимаемой RAMна 4 байта.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 19 2013, 19:12
Сообщение #7


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(abutorin @ Jan 20 2013, 00:42) *
С таким кодом передача работает нормально, а вот при попытке принять данные камень зависает.

У меня такой вариант работает нормально. Наверное какая-то мелочь осталась незамеченной. Например, забыли включить приёмsm.gif
Цитата(abutorin @ Jan 20 2013, 00:42) *
Сразу должен заметить что размер кода увеличился на 176 байт. Размер занимаемой RAMна 4 байта.

Ну, это мелочиsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 19 2013, 19:19
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(AHTOXA @ Jan 19 2013, 23:12) *
У меня такой вариант работает нормально. Наверное какая-то мелочь осталась незамеченной. Например, забыли включить приёмsm.gif

Весь остальной код остался неизменный. Менял только код данного класса. Идея использовать готовый код для решения своих задач мне всгда нравится, я потому и поднял эту тему. После того как не смог с вашей помощью решить поставленную задачу попробовал сделать свой вариант. В результате оказалось что мой вариант получается несколько компактнее. Для законченности все же остается понять почему не работает.
Вы какого размера пакеты отправляет и посылает? Я в свое время заметил что такой код работает нормально если посылаешь и принимаешь пакет меньше чем размер буфера то проблем нет. А вот как только объем больше то и происходят зависания.

Сообщение отредактировал abutorin - Jan 19 2013, 19:25
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 19 2013, 19:36
Сообщение #9


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Насчёт компактности - думаю, что случайно так вышло. По ОЗУ должен быть паритет (У каждого EventFlag есть TProcessMap и TValue, а у каждого channel - два TProcessMap). А по коду - если вы будете использовать channel где-то ещё (а вероятность этого ~100%), то этот код всё равно добавится.
С другой стороны, код у channel проверенный в плане межпроцессного взаимодействия (моменты запрещения прерываний, ожидание, и проч.). А с самодельным вариантом может всплыть что-то.
Почему не работает - неясно. Вы как-то не совсем внятно объясняете, что именно не работает. Приём одного байта - работает?
Тот код, который вы показали, содержит только функции записи/чтения одного символа. А вы пишете, что зависает при приёме блока.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 19 2013, 20:01
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(AHTOXA @ Jan 19 2013, 23:36) *
А по коду - если вы будете использовать channel где-то ещё (а вероятность этого ~100%), то этот код всё равно добавится.

Если параметры шаблано отличаются, то код начинает дублироватся. Так что тут код всегда будет больше.

Цитата(AHTOXA @ Jan 19 2013, 23:36) *
С другой стороны, код у channel проверенный в плане межпроцессного взаимодействия (моменты запрещения прерываний, ожидание, и проч.). А с самодельным вариантом может всплыть что-то.

Неверное использование проверенного кода тоже может вызвать проблемы.

Цитата(AHTOXA @ Jan 19 2013, 23:36) *
Почему не работает - неясно. Вы как-то не совсем внятно объясняете, что именно не работает.

Есть некий проект (кода много чтобы выкладывать), пробую использовать оба варианта класса который описывал. Еще раз повторю, для чисторы эксперимента меняю только код данного класса, все остальное остается прежним. Так вот при использовании канала похоже чтокамень на чемто зависает, сказать где не могу, знаю только что процесс с наивысшим приоритетом перестает работать.
Цитата(AHTOXA @ Jan 19 2013, 23:36) *
Приём одного байта - работает?

По одному байту не использую.

Цитата(AHTOXA @ Jan 19 2013, 23:36) *
Тот код, который вы показали, содержит только функции записи/чтения одного символа. А вы пишете, что зависает при приёме блока.


Блок передаю в цикле по одному байту.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 19 2013, 20:21
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(abutorin @ Jan 20 2013, 02:01) *
Если параметры шаблано отличаются, то код начинает дублироватся. Так что тут код всегда будет больше.

А если не отличаются, то не начнёт. Значит - не всегдаsm.gif
Ну да ладно, в любом случае мне плевать на такой прирост кода.
Цитата(abutorin @ Jan 20 2013, 02:01) *
Неверное использование проверенного кода тоже может вызвать проблемы.

Поэтому я и заинтересовался. Если есть проблемы с использованием OS::channel в прерываниях, то я очень хочу знать про них.
Цитата(abutorin @ Jan 20 2013, 02:01) *
Так вот при использовании канала похоже чтокамень на чемто зависает, сказать где не могу, знаю только что процесс с наивысшим приоритетом перестает работать.

А увеличение размера буфера больше размера максимального пакета избавляет от зависаний?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 19 2013, 20:42
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(AHTOXA @ Jan 20 2013, 00:21) *
А увеличение размера буфера больше размера максимального пакета избавляет от зависаний?

Да.
Я писал про это на второй странице помоему.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 20 2013, 05:31
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Ну, с тех пор что-то же поменялось. Так что это было неочевидно.
В общем, я не знаю, чем помочь. Может быть вы сделаете минимальный проект, где проблема проявляется, и выложите его?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 20 2013, 05:57
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(AHTOXA @ Jan 20 2013, 09:31) *
В общем, я не знаю, чем помочь. Может быть вы сделаете минимальный проект, где проблема проявляется, и выложите его?

Тогда пока предлагаю отложить этот вопрос.
Резюме по теме можно сделать такое:
По мнению разработчиков OS:channel можно использовать в прерываниях с некоторыми замечаниями "обязательна проверка на наличие свободного места или данных для для получения из него".
Лично у меня использовать его не получилось по неустановленным причинам. На мой субъективный взгляд использование OS:channel является более накладным (по размеру кода) чем использование собсвтенного кольцевого буфера (из библиотеки usrlib) и двух OS::TEventFlag.

PS. забыл как на форуме можно подправить название темы, чтобы вписать в нее "решено"

Сообщение отредактировал abutorin - Jan 20 2013, 06:39
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- abutorin   Возможность использования OS::channel в прерываниях   Jan 13 2013, 19:25
- - AHTOXA   Использовать канал в прерывании можно. Учтите толь...   Jan 13 2013, 20:45
|- - abutorin   Спасибо, проверку заполнености, проверку пустоты я...   Jan 14 2013, 02:40
|- - abutorin   Цитата(AHTOXA @ Jan 14 2013, 00:45) Испол...   Jan 15 2013, 19:16
|- - _Артём_   Не знаю почему зависает, наверное что-то неправиль...   Jan 15 2013, 19:26
|- - abutorin   Цитата(_Артём_ @ Jan 15 2013, 23:26) Не з...   Jan 15 2013, 19:31
|- - _Артём_   Цитата(abutorin @ Jan 15 2013, 21:31) Объ...   Jan 15 2013, 20:10
|- - Сергей Борщ   QUOTE (abutorin @ Jan 15 2013, 21:31) Суд...   Jan 15 2013, 22:46
|- - abutorin   Цитата(Сергей Борщ @ Jan 16 2013, 02:46) ...   Jan 16 2013, 03:29
|- - _Артём_   Цитата(abutorin @ Jan 16 2013, 05:29) А в...   Jan 16 2013, 04:45
||- - AHTOXA   TXE очищается записью в DR. Вручную его чистить не...   Jan 16 2013, 05:05
|- - Сергей Борщ   QUOTE (abutorin @ Jan 16 2013, 05:29) USA...   Jan 16 2013, 08:54
|- - AHTOXA   Цитата(Сергей Борщ @ Jan 16 2013, 14:54) ...   Jan 16 2013, 10:18
||- - Сергей Борщ   QUOTE (AHTOXA @ Jan 16 2013, 12:18) А это...   Jan 16 2013, 11:27
||- - AHTOXA   Цитата(Сергей Борщ @ Jan 16 2013, 17:27) ...   Jan 16 2013, 13:52
|- - abutorin   Цитата(Сергей Борщ @ Jan 16 2013, 12:54) ...   Jan 16 2013, 11:33
|- - Сергей Борщ   QUOTE (abutorin @ Jan 16 2013, 13:33) Есл...   Jan 17 2013, 10:15
|- - abutorin   Цитата(Сергей Борщ @ Jan 17 2013, 14:15) ...   Jan 17 2013, 12:25
|- - Сергей Борщ   QUOTE (abutorin @ Jan 17 2013, 14:25) Пло...   Jan 17 2013, 13:12
|- - abutorin   Цитата(Сергей Борщ @ Jan 17 2013, 17:12) ...   Jan 17 2013, 13:20
|- - AHTOXA   Насчёт работы с UART по DMA вот вам три темы: раз...   Jan 17 2013, 18:31
|- - abutorin   Цитата(AHTOXA @ Jan 17 2013, 22:31) Насчё...   Jan 18 2013, 05:37
|- - Сергей Борщ   QUOTE (abutorin @ Jan 18 2013, 07:37) Спа...   Jan 18 2013, 07:41
|- - abutorin   Цитата(Сергей Борщ @ Jan 18 2013, 11:41) ...   Jan 18 2013, 09:14
- - Vasya777   Мне кажется для обмена по интерфейсам связи лучше ...   Jan 15 2013, 15:07
- - abutorin   Проблему решил использовав События: Кодclass usart...   Jan 15 2013, 20:14
|- - _Артём_   Цитата(abutorin @ Jan 15 2013, 22:14) есл...   Jan 15 2013, 20:20
|- - abutorin   Цитата(_Артём_ @ Jan 16 2013, 00:20) На ч...   Jan 15 2013, 20:24
|- - _Артём_   Цитата(abutorin @ Jan 15 2013, 22:24) Вто...   Jan 15 2013, 20:52
|- - abutorin   Цитата(AHTOXA @ Jan 19 2013, 21:42) Код ...   Jan 19 2013, 17:56
||- - _Артём_   Цитата(abutorin @ Jan 19 2013, 19:56) В с...   Jan 19 2013, 18:13
- - сарматъ   я так и не понял, а функции типа push_isr() не нуж...   Sep 4 2013, 20:26
|- - _Артём_   Цитата(сарматъ @ Sep 4 2013, 23:26) я так...   Sep 4 2013, 21:41
|- - сарматъ   там могло бы быть что либо такого плана CODEtempl...   Sep 5 2013, 05:39
|- - Сергей Борщ   QUOTE (сарматъ @ Sep 5 2013, 07:39) там м...   Sep 5 2013, 06:10
- - сарматъ   да я уже подумал над этим правда придется не насле...   Sep 5 2013, 06:24
|- - dxp   QUOTE (сарматъ @ Sep 5 2013, 13:24) да я ...   Sep 5 2013, 07:21
|- - сарматъ   потому что нужен вот такой вот пул и если я его до...   Sep 5 2013, 07:37
|- - Сергей Борщ   QUOTE (сарматъ @ Sep 5 2013, 09:37) потом...   Sep 5 2013, 08:25
- - сарматъ   да, класс канала отличный класс, плюс ко всем его ...   Sep 5 2013, 08:33
|- - Сергей Борщ   QUOTE (сарматъ @ Sep 5 2013, 10:33) сдела...   Sep 6 2013, 08:29
- - сарматъ   ок, так и сделаю и потом выложу сюда что получилос...   Sep 6 2013, 08:44


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th June 2025 - 13:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.02484 секунд с 7
ELECTRONIX ©2004-2016