Перейти к содержанию
    

Кольцевой буфер не успевает себя сдвигать до прихода нового байта..

У вас идеология неверная. Уарт заполняет фифо и только.

Фоновая программа выгребает фифо и парсит фреймы. В таком варианте будет достаточным иметь размер фифо байт на 16-64..

А парсер фреймов (собственно протокол) может иметь свой буфер на максимальный размер пакета.

Как-то так обычно делается.

Благодаря чему выполняется парадигма минимизации времени обработки прерываний...

Более того некоторые протоколы регламентируют максимальный размер фифо канала связи. Так например modbus имеет пожелания на размер фифо в 32 байта...

 

А если пример с NMEA? Там остановить передачу нельзя. В этом случае нужно иметь буфер на максимальную посылку. Ну а как обрабатывать - уже выше описали.

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если пример с NMEA?
Тем более.

В 90% случаев цикл основной программы отрабатывается быстрее чем несколько мс. Только исходя из этого и выбирается размер фифо (чтобы не переполнился за эти пару мс).

Например на скорости 115200 один байт передаётся за ~90мкс, а цикл фоновой программы 2мс.

Следовательно минимальный размер фифо будет 2000мкс/90мкс = 22 байта. Округлим до ближайшего кратного 2 и получим 32.

ЧИТД. Вот такая простая арифметика.

 

А то, что вам написали (ловить старт-стоп) нужно делать в фоновой программе (в модуле протокола NMEA например медленно и печально искать пакеты и сверять crc) а не в ISR уарта.

Тем самым вы рассекаете на независимые логические модули свою программу.

Я вам дельный совет даю - прислушайтесь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При желании разбирать входные данные можно вообще безо всяких буферов, исключительно на конечных автоматах. Объем кода получится приличный, зато без затрат памяти и быстро - можно отрабатывать не выходя из прерывания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При желании разбирать входные данные можно вообще безо всяких буферов, исключительно на конечных автоматах. Объем кода получится приличный, зато без затрат памяти и быстро - можно отрабатывать не выходя из прерывания.
Дилетантский подход в подавляющем большинстве случаев, ИМХО.

Долго сидеть в прерывании - зло.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все относительно и ситуационно.

Дилетантский подход в подавляющем большинстве случае - это возводить в абсолют время сидения в прерывании, ИМХО :)

Часто минимизировать нужно именно время реакции системы, а перекладывание из буфера в буфер скорости не добавит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для простых программ (относительно простых), с крайне малым числом конкурирующих процессов можно вообще всю программу запихать в прерывание. И в этом нет никакого зла.

 

Но такой подход плох только одним. Появляется привычка. И в следующих, настоящих сложных проектах не будет опыта распределять нагрузку, работать с буферами и прочим.

 

В данном же случае, очевидно, что NMEA не имеет никакой возможности загрузить контроллер до упора. Посему можно создавать кучу буферов и сделать программу более понятной для самого себя. Как бэ потренироваться в создании уровней обработки. На простом примере. Ибо также очевидно, что если чел не знаком с кольцевыми буферами, то ему самое время начать тренировки...

 

Времена, когда на IBM PC экономили память и оптимизировали код ассемблером канули в вечность.

 

Времена, когда нечего экономить и в микроконтроллерах - уже наступили. Только еще не все в курсе...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все относительно и ситуационно.

Дилетантский подход в подавляющем большинстве случае - это возводить в абсолют время сидения в прерывании, ИМХО :)

Часто минимизировать нужно именно время реакции системы, а перекладывание из буфера в буфер скорости не добавит.

 

А собственно чего сидеть в прерывании USART, что Вам это даст ? У него самая тупая задача , принял (запихнул в буфер) - передал. На это он и расчитан.

Другую Вы ему даже предложить не сможете.

В лучшем случае в прерывании одна команда - вон туда положить. Никаких предворительных ласк делать не надо , как в случае - ВСЁ обрабатывать в прерывании (запихивать в стек регистры ,SREG и прочее, прочее, тратя на эту хрень время) . Вышли и всё остальное время можете тратить на разбор "полётов" .

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Часто минимизировать нужно именно время реакции системы, а перекладывание из буфера в буфер скорости не добавит.
Оценим на пальцах ДОБАВОЧНУЮ латентность, возникающую при использовании фифо.

Максимум один цикл основной программы в случае ТУПОГО суперлупа, а при использовании планировщика или чуть более внятного суперлупа много меньше.

Большая задержка? С Вас примеры где это действительно важно...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Автору уже советовали конечный автомат - так как он

На флажках это дело решать муторно.

упёрся в сложность программы. Если он перенесёт "работу с флажками" во внешнюю (по отношению к прерыванию) программы - не поможет...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но такой подход плох только одним. Появляется привычка. И в следующих, настоящих сложных проектах не будет опыта распределять нагрузку, работать с буферами и прочим.

Как это? Все равно ведь работа по прерываниям получше, чем по триггерам и использует ресурсы идеально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оценим на пальцах ДОБАВОЧНУЮ латентность, возникающую при использовании фифо.

Максимум один цикл основной программы в случае ТУПОГО суперлупа, а при использовании планировщика или чуть более внятного суперлупа много меньше.

Большая задержка? С Вас примеры где это действительно важно...

что, как других дилетантами обзывать так запросто, а как вас, так и обиделись? :)

Примеры, да пожалуста:

1. Принимаем команды по наложению OSD, шина RS485 абонентов много, при получении команды не позже чем через нцать мкс (точное число ен помню больше 100 но меньше 500) следует отправить подтверждение приема. Других задач не выполняем. Формирование картинки работает не быстро - суперлуп длинный. Ну и? ради великой самоцели "малосидения в прерывании" делать еще и планировщик с тиком 100мкс?

2. Резервное устройство на батарейном питании, по команде дергаем клапан. Тут ключевой момент даже не время реакции, а потребление, проц работает ТОЛЬКО в прерывании, остальное время дрыхнет, вынос обработки в суперлуп увеличит потребление на величину отличную от нуля.

Реальные примеры из практики, а не тупые суперлупы в вакууме.

 

PS продолжим холивар или дадим ТСу решать свою задачу?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Размер кольцевого буфера лучше иметь кратным степени 2...

А можно пояснить подробнее - в чём преимущество кольцевого буфера с размером, кратным степени 2 ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

что, как других дилетантами обзывать так запросто, а как вас, так и обиделись? :)
Вовсе нет. Вас лично я и не пытался задеть.

PS продолжим холивар или дадим ТСу решать свою задачу?
Можем продолжить.

1. У ТС протокол без жёских временных ограничений (и таких протоколов несоизмеримо больше).

2. Кто мешает поставить команду sleep в тело суперлупа и просыпаться по тем же прерываниям уарта?

 

Проще закруглять. Одной командой &.
Или % что современные компиляторы хорошо оптимизируют.

#define FIFO_SIZE 32
i = (i+1) % FIFO_SIZE; // никремент индекса fifo

что будет эквивалентно

 i = (i+1) & (FIFO_SIZE-1); // никремент индекса fifo

в случае когда FIFO_SIZE кратно степени 2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обрабатываю NMEA. Сделал следующим образом:

В памяти программ создал таблицу с адресами 25 подпрограмм (из них 16 уникальных), каждая из которых занимается отлавливанием определенного символа или сохранением данных. В прерывании UART запускаем одну из этих подпрограмм по маркеру, который инкрементируется при успешном выполнении подпрограммы, тем самым указывая, что в следующий раз надо будет выполнить другую подпрограмму. Если подпрограмма возвращает ложь, то маркер сбрасывается и в следующий раз будем начинать все сначала.

В итоге SRAM - 2 байта (один маркер, другой счетчик символов при сохранении данных), и скорость максимальная. =)

Изменено пользователем Alt.F4

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...