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

 
 
 
Reply to this topicStart new topic
> Вопрос по usr::ring_buffer, как правильно пользоваться
_Артём_
сообщение Jan 21 2012, 18:54
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Попытался использовать usr::ring_buffer для выдачи отладочного лога в свободный УАРТ.
Алгоритм такой:
1. Задача заполняет его данными
2. В прерывании таймера проверяется не пуст ли буфер, если не пуст, то разрешается прерывание по пустому буферу передачика уарт.
3. В прерывании DRE посылается след.байт и запрещаются прерывания если байтов больше нет.
CODE

class TExtTxBuffer {
usr::ring_buffer<unsigned char, EXTERNAL_UART_TX_BUFFER, unsigned short> fifo;
public:
void WriteByte(unsigned char new_byte)
{
fifo.push(new_byte);
}
unsigned char ReadByte(void)
{
return fifo.pop();
}
void WriteAnsiString(unsigned char __flash *data)
{
while (*data) {
fifo.push(*data++);
}
}
void WriteAnsiString(unsigned char *data)
{
while (*data) {
fifo.push(*data++);
}
}
unsigned char BufferNotEmpty(void)
{
if (fifo.get_count())
return 1;
return 0;
}
};

void StopExtUartTx()
{
UCSR0B&=~(1<<UDRIE0);
}
#pragma vector=USART0_UDRE_vect
__interrupt void ExtUartTx()
{
OS::TISRW_SS ISRW;
unsigned char i=ExtTxPtr.ReadByte();
UDR0=i;
if (ExtTxPtr.BufferNotEmpty()==0)
StopExtUartTx();
}


В какой-то момент обнаружил что передача данных прекратилась. Остановил программу.
Увидел следующее (цифры примерные):
Код
First=10;
Last=9;
Count=0;


B соответственно код
Код
if (ExtTxPtr.BufferNotEmpty())
        StartExtUartTx();

прерывание USART0_UDRE_vect запускать не стал.
Что неправильно делаю?
Неправильно объявил (не использовал volatile)?
Код
usr::ring_buffer<unsigned char, EXTERNAL_UART_TX_BUFFER, unsigned short> fifo;

Нужны ли критические секции перед вызовом BufferNotEmpty и WriteByte?
Спасибо.

Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 21 2012, 19:30
Сообщение #2


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

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



ring_buffer не обеспечивает безопасного многопоточного доступа. Используйте OS::channel, он специально предназначен для таких целей. Это, на самом деле, тот же самый ring_buffer, но с механизмами блокировки.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 21 2012, 21:04
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(AHTOXA @ Jan 21 2012, 21:30) *
ring_buffer не обеспечивает безопасного многопоточного доступа.


Спасибо, AHTOXA.
Чувствовал когда писал что граблю закладываю. Предчуствия меня не обманули.

Попробую выйти из положения пока так:
Код
usr::ring_buffer<unsigned char, EXTERNAL_UART_TX_BUFFER, volatile unsigned short> fifo;
    void WriteByte(unsigned char new_byte)
    {
        TCritSect cs;
        fifo.push(new_byte);
    }
void WriteAnsiString(unsigned char __flash *data)
    {
        TCritSect cs;
        while (*data) {
            fifo.push(*data++);
        }
    }
    void WriteAnsiString(unsigned char *data)
    {
        TCritSect cs;
        while (*data) {
            fifo.push(*data++);
        }
    }


Цитата(AHTOXA @ Jan 21 2012, 21:30) *
Используйте OS::channel, он специально предназначен для таких целей

Понял, channel подходящее будет.

Цитата(AHTOXA @ Jan 21 2012, 21:30) *
Это, на самом деле, тот же самый ring_buffer, но с механизмами блокировки.


Зачем тогда ring_buffer нужен в чистом виде?
Только как основа для того же OS::channel?
Где его использовать?
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jan 22 2012, 11:03
Сообщение #4


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(_Артём_ @ Jan 21 2012, 23:04) *
Попробую выйти из положения пока так:

Вторая и третья функции - плохие, блокируют прерывания и, как следствие, перепланирование процессов на неопределённое время, особенно в случае длинных стрингов. Кроме того, они отличаются только типом параметра, можно было бы сделать шаблоном.
Цитата(_Артём_ @ Jan 21 2012, 23:04) *
Зачем тогда ring_buffer нужен в чистом виде?
Только как основа для того же OS::channel?

В документации и в комментариях сказано, что он нужен для служебных операций, в частности, для OS::channel.
Цитата(_Артём_ @ Jan 21 2012, 23:04) *
Где его использовать?

Его можно применять там, где не критично, т. е. если синхронизация между процессами (наполняющим и выгребающим) делается другими способами.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 22 2012, 14:50
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(IgorKossak @ Jan 22 2012, 13:03) *
Вторая и третья функции - плохие, блокируют прерывания и, как следствие, перепланирование процессов на неопределённое время, особенно в случае длинных стрингов.


Согласен, когда в программу вписывал - понял.
Сделал так:
Код
    void WriteAnsiString(unsigned char *data)
    {
        TCritSect cs;
        while (*data) {
                {
                TCritSect cs;
                 fifo.push(*data++);
                }
        }
    }

Цитата(IgorKossak @ Jan 22 2012, 13:03) *
Кроме того, они отличаются только типом параметра, можно было бы сделать шаблоном.

Хорошая мысль, осталось шаблоны освоить.

Цитата(IgorKossak @ Jan 22 2012, 13:03) *
В документации и в комментариях сказано, что он нужен для служебных операций, в частности, для OS::channel.

Проглядел. Спасибо.

Цитата(IgorKossak @ Jan 22 2012, 13:03) *
Его можно применять там, где не критично, т. е. если синхронизация между процессами (наполняющим и выгребающим) делается другими способами.

Какими? Не представил....



Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jan 22 2012, 17:13
Сообщение #6


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(_Артём_ @ Jan 22 2012, 16:50) *
Сделал так:

Если первую строку с TCritSect cs; выкинуть, то получится ещё лучше.
Цитата(_Артём_ @ Jan 22 2012, 16:50) *
Хорошая мысль, осталось шаблоны освоить.

Это быстрее, чем Вы писали эту фразу. Хотя бы по примерам из той же scmRTOS.
Цитата(_Артём_ @ Jan 22 2012, 16:50) *
Какими? Не представил....

Сигналами, семафорами или, на худой конец, так как в результате у Вас получилось с TCritSect cs. Но это всё не так красиво, как с каналами.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 22 2012, 17:50
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(IgorKossak @ Jan 22 2012, 19:13) *
Если первую строку с TCritSect cs; выкинуть, то получится ещё лучше.

Да, это я хорошо исправил...поспешил.

Цитата(IgorKossak @ Jan 22 2012, 19:13) *
Это быстрее, чем Вы писали эту фразу. Хотя бы по примерам из той же scmRTOS.

Будем посмотреть

Цитата(IgorKossak @ Jan 22 2012, 19:13) *
Сигналами, семафорами или, на худой конец, так как в результате у Вас получилось с TCritSect cs. Но это всё не так красиво, как с каналами.

Ясно. Спасибо.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 29th July 2025 - 10:50
Рейтинг@Mail.ru


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