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

 
 
> Возможность использования 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   Возможность использования 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
|- - abutorin   Цитата(AHTOXA @ Jan 19 2013, 23:36) А по ...   Jan 19 2013, 20:01
|- - AHTOXA   Цитата(abutorin @ Jan 20 2013, 02:01) Есл...   Jan 19 2013, 20:21
|- - abutorin   Цитата(AHTOXA @ Jan 20 2013, 00:21) А уве...   Jan 19 2013, 20:42
|- - AHTOXA   Ну, с тех пор что-то же поменялось. Так что это бы...   Jan 20 2013, 05:31
|- - abutorin   Цитата(AHTOXA @ Jan 20 2013, 09:31) В общ...   Jan 20 2013, 05:57
- - сарматъ   я так и не понял, а функции типа 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 Текстовая версия Сейчас: 25th June 2025 - 14:32
Рейтинг@Mail.ru


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