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

Как правильно объявить extern для typedef?

Обычно для разделения пакетов существует пауза в передаче длиной более одного байта - Break frame, либо состояние Idle. Эта пауза может быть распознана аппаратно приемником и будет служить признаком начала и конца передечию

Изменено пользователем EdgeAligned

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


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

3 minutes ago, EdgeAligned said:

Обычно для разделения пакетов существует пауза в передаче длиной более одного байта - Break frame. Эта пауза даже аппаратно может быть распознана приемником по состоянию Idle line и будет служить признаком начала и конца передечию

Получилось:

        if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET )   //Judging whether it is idle interruption
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart2);                     //Clear idle interrupt sign (otherwise it will continue to enter interrupt)
          

        }

 

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


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

2 часа назад, artemkad сказал:

Разбор входного потока(в данном случае принимаемом UARTом) на лексемы или токены.

И почему этого нельзя делать в ISR? Кто запрещает?

PS: Вы как-нибудь попробуйте заглянуть в примеры например USB-стеков (идущие с компиляторами или от производителей). Получите сюрприз.  :wink: Там вообще весь протокол общения host-device реализован внутри ISR. И ничего. А USB он всё-таки как правило пошустрее UART-а.

36 минут назад, MementoMori сказал:

спор перешел в разряд "с какого конца разбивать яйцо, с острого или тупого".

именно :good:  А теперь ещё и негров неграми называть парсить в ISR запрещают.  :sarcastic:

38 минут назад, MementoMori сказал:

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

Главное - не забыть объявить её пакованной.

38 минут назад, MementoMori сказал:

Там ведь как - если приходит 0x00, то это считается концом строки.  А если в структуре есть байт 0x00? Как быть? Как синхронизировать начало посылки?

1. Почитать про существующие протоколы обмена. 

2. Узнать что такое "кодонезависимость".

 

ЗЫ: Только у тупого чатГПТ не спрашивать.  :sarcastic:

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


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

1 час назад, jcxz сказал:

И почему этого нельзя делать в ISR? Кто запрещает?

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

1 час назад, jcxz сказал:

PS: Вы как-нибудь попробуйте заглянуть в примеры например USB-стеков (идущие с компиляторами или от производителей). Получите сюрприз. 

Че я, индусского кода не видел? А уж с проблемами USB-девайсов не сталкивался разве что полный юзвер.

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


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

2 часа назад, MementoMori сказал:

Там ведь как - если приходит 0x00, то это считается концом строки.  А если в структуре есть байт 0x00? Как быть? Как синхронизировать начало посылки?

Передаешь пакетами. Для начала пакета

1)выделяешь символ(скажем 0x5A) плюс еще управляющий символ для экранирования(скажем, 0xB3). При встрече во входном потоке байта начал потока или экранирующего символа заменяешь их на двухбайтовую последовательность с первым экранирующим символом 0xB3 0x00 и  0xB3 0x01, при приеме операция обратная.

2)делаешь паузу между пакетами(по сути - вызываешь ошибку кадрирования UART)

3)Передаешь данные 9-битными символами один бит из которых говорит о том, что передается управляющий символ(к примеру - начало пакета)

4) Передавай структуру в текстовом виде, а потом разбирай поток парсером.

5)....

В общем - вариантов много.

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


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

1 час назад, artemkad сказал:

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

Такое возможно только когда не хватит быстродействия CPU для обработки этого потока. Но как тут поможет вынос обработки за пределы ISR? Очевидно - никак.

1 час назад, artemkad сказал:

Т.е. это потенциально кривое место которое может приводить к трудноуловимым багам.

И как же здесь поможет вынос парсинга из ISR? Объясните.

И причём тут "индусский код"???  :wacko2:

Валите с больной головы на здоровую..

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


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

5 часов назад, jcxz сказал:

Такое возможно только когда не хватит быстродействия CPU для обработки этого потока.

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

5 часов назад, jcxz сказал:

И причём тут "индусский код"???

У очень  многих производителей в примерах столь жуткий подход к коду, что требует для работы в разы завышать требования к железу. И перенос дурной работы в обработчик  прерывания - из этой категории.

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


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

Есть stdio. Сделай кольцевые буферы, в который пишет-читает UART и пользуйся stdio. Версия для gcc под МК с ARM позволяет подключать к ней до 20 своих потоков.

Если нет требований к скорости обмена и объёму трафика, то проще передавать сложные структуры в текстовом виде, например, используя json.

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


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

По поводу прерываний. У STM32 - многовекторный приоритетный контроллер с вложенностью прерываний. Поэтому, если разумно управлять приоритетами, то риск блокировок снижается. Во вторых, можно производить прием байтов по DMA, а сигналом разделения будет Idle-состояние. Разбор принятого потока выполнять по этому сигналу разделения. И в-третьих, сам парсинг для убыстрения следует выполнять индексно-табличным методом, а не через if или switch.

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


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

12 часов назад, MementoMori сказал:

А вот как быть с приемом?

Там ведь как - если приходит 0x00, то это считается концом строки.  А если в структуре есть байт 0x00? Как быть? Как синхронизировать начало посылки?

Там сложностей не возникало. А вот со структурами как быть? Там ведь уже не используешь символы конца строки, ибо символы с этим кодом могут быть в структуре.

По UART-у самое простое это SLIP (байт-стаффинг). Чуть сложнее (но не в смысле страшнее) - COBS.

Если в МК есть DMA, то удобнее организовать программный FIFO на его основе, а в каком-то фоновом процессе разгребать.

Таймаутные протоколы софтовой реализации (а-ля Modbus RTU и прочие) считаю мракобесием и применяю только там, где диктуют условия.
 

12 часов назад, EdgeAligned сказал:

Обычно для разделения пакетов существует пауза в передаче длиной более одного байта - Break frame, либо состояние Idle. Эта пауза может быть распознана аппаратно приемником...

Да, в некоторых STM32 есть такое. Но 1) не во всех, и 2) нормально скрестить ужа с ежом DMA с этими паузами не у всякого получится, поэтому использование IDLE надежно только с работой по прерываниям.

А работу с UART по прерываниям я, например, по возможности стараюсь избегать. Тем более на STM32 с его кастрированным UART, не имеющим FIFO.
 

2 часа назад, EdgeAligned сказал:

И в-третьих, сам парсинг для убыстрения следует выполнять индексно-табличным методом, а не через if или switch.

Парсинг, например, SLIP-а индексно-табличным методом... Вы это как себе представляете?

Парсинг индексно-табличным методом оправдан там, где можно гарантировать, что поток данных безопасен для табличного парсера, т.е. заранее известно, что в потоке не будет символов, на основе которых табличный парсер уедет по указателям и получит по башке от контроллера памяти. В случае байтового UART этого принципиально невозможно гарантировать. К тому же нужно выделять границы кадров, переводя автомат приема в специальные промежуточные состояния; а еще нужно как-то разбирать двухбайтовые ESC-последовательности, а еще правильно разбирать стыки этих двухбайтовых последовательностей, когда второй байт еще не пришел, а парсер уже считал из FIFO его первый байт и т.д. Как Вы без if обойдетесь?

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


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

7 часов назад, artemkad сказал:

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

Вопрос повторяю ещё раз: Каким образом "следующие символы могут не успеть прийти" из-за того, что обрабатываем их внутри ISR? При условии, что указанный ISR - это ISR того UART, через который символы и поступают. И условии что быстродействия CPU хватает для обработки потока.

Ясно что такое может быть из-за кривой реализации обработки или построения системы в целом. Но при корректно построенной системе - ...?

7 часов назад, artemkad сказал:

В прерывании достаточно поместить символ в очередь

В прерывании можно делать что угодно. В соответствии со всем алгоритмом работы всего устройства в целом.

Имею несколько проектов, где загрузка CPU внутри ISR может быть > 70-80%. Прекрасно работают и выполняют свои задачи, ничего не переполняется.

7 часов назад, artemkad сказал:

И перенос дурной работы в обработчик  прерывания - из этой категории.

У вас одни штампы в постах. Без какой-либо конкретики....

5 часов назад, EdgeAligned сказал:

многовекторный приоритетный контроллер с вложенностью прерываний. Поэтому, если разумно управлять приоритетами, то риск блокировок снижается. Во вторых, можно производить прием байтов по DMA

Только не говорите об этом artemkad  :wink:

4 часа назад, Arlleex сказал:

Таймаутные протоколы софтовой реализации (а-ля Modbus RTU и прочие) считаю мракобесием

:good:

4 часа назад, Arlleex сказал:

Да, в некоторых STM32 есть такое. Но 1) не во всех, и 2) нормально скрестить ужа с ежом DMA с этими паузами не у всякого получится

......а когда вдруг потребуется перенести проект на другой МК, где DMA такого не умеет, придумавший такой квадратно-колёсный велосипед, огребёт по полной. Вплоть до полной переделки всего алгоритма работы устройства. Или сбежит.  :sarcastic:

Особенности работы DMA и протокольный парсинг не должны быть завязаны между собой. Как разные уровни абстракции.

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


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

8 минут назад, jcxz сказал:

Вопрос повторяю ещё раз: Каким образом "следующие символы могут не успеть прийти" из-за того, что обрабатываем их внутри ISR? При условии, что указанный ISR - это ISR того UART, через который символы и поступают.

К примеру, при скорости 115200 межсимвольный интервал примерно 1мс. Если в среднем приходит строка из, 100 символов в которой примерно 5 лексем из 200 возможных, за 1 мс необходимо  сделать 5 раз поиск из 200(помимо всего прочего). К примеру, при одной операции МК за  1мкс, очевидно что в 1000 операций не уложишься, а значит следующий символ(и возможно не один) будет принят при запрещенном прерывании и будет утерян. При том, что если бы в ISR было только заполнение очереди длиной, скажем, 256 байт, на разбор такой строки устанавливался лимит до полного заполнения очереди или иначе говоря за 256мс вместо 1мс.

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


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

Как показывает моя практика, бинарные протоколы проще делать а-ля Модбас. Сам в таких случаях использую Модбас RTU, ибо в этом случае имею аппаратную поддержку со стороны UART. А вот текстовые проще делать как классический терминал.

И да, если предполагается активная работа с UART, то лучше использовать STM32 с полноценным UART, имеющим RTO и прерывание по символу, а не кастрированный UART, где кроме IDLE нет ничего. Ну и приём-передачу вести через DMA, для чего прерывание по заполнению половины буфера и кольцевой режим нам в помощь.

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


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

26 минут назад, artemkad сказал:

К примеру, при скорости 115200 межсимвольный интервал примерно 1мс. Если в среднем приходит строка из, 100 символов в которой примерно 5 лексем из 200 возможных, за 1 мс необходимо  сделать 5 раз поиск из 200(помимо всего прочего). К примеру, при одной операции МК за  1мкс

Что такое "одна операция МК"? 1 такт тактовой частоты или что?

Если это такт тактовой, то объясните - каким именно образом обеспечите 115200 на МК работающем на 1 МГц тактовой??? :shok:

Выполнить 1 раз за 20мс поиск по таблице из 200 элементов - вообще никаких проблем. Даже на МК, работающем на 1 МГц это даст загрузку - доли %. 

Даже в один межсимвольный интервал (указанные вами = 1 мс) это скорее всего уложится. Тем более, что в нормальной реализации алгоритма, будет: или аппаратный FIFO в UART; или такой же FIFO, организованный на базе DMA. Которые не требуют укладываться в 1 мс.

Но даже без аппаратного FIFO или DMA, можно разнести чтение символов из UART и парсинг по разным приоритетам прерываний.

26 минут назад, artemkad сказал:

, очевидно что в 1000 операций не уложишься

Что такое "операция" здесь? Ничего не понятно..... Особенно - как получить UART на 115200 бод на 1 МГц тактовой МК?

 

PS: И при чём тут некие 

7 часов назад, artemkad сказал:

запрета прерываний

26 минут назад, artemkad сказал:

при запрещенном прерывании

о которых всё время пишете? Зачем прерывания запрещать для парсинга строки?

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


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

34 минуты назад, jcxz сказал:

Что такое "одна операция МК"? 1 такт тактовой частоты или что?

Для МК выполняющих 1 операцию за такт = 1 такт тактовой частоты.

34 минуты назад, jcxz сказал:

Если это такт тактовой, то объясните - каким именно образом обеспечите 115200 на МК работающем на 1 МГц тактовой??? 

Вас смущает дробность делителя аппаратного UART? Ну пусть будет 0.92МГц тактовой или скорость 128000.

34 минуты назад, jcxz сказал:

Даже в один межсимвольный интервал (указанные вами = 1 мс) это скорее всего уложится.

 Не уложится. Только организация цикла со счетчиком это примерно в 5 операций или иначе говоря 1мс хватит тупо на 200 проходов пустого цикла. На сравнение и остальную логику - хорошо если поиск за 10мс управится.

34 минуты назад, jcxz сказал:

Что такое "операция" здесь?

1мс/1мкс=1000 Разве не очевидно?

1 час назад, jcxz сказал:

Только не говорите об этом artemkad 

Рассчитывать на вложенность прерываний или более того, на повторное вхождение в процедуру того-же прерывания во время его  исполнения задачка явно не для раздела новичков. Не находите?

34 минуты назад, jcxz сказал:

Тем более, что в нормальной реализации алгоритма, будет: или аппаратный FIFO в UART; или такой же FIFO, организованный на базе DMA.

Это вообще не к нормальной организации алгоритма, а требование к аппаратной части МК. Куча контроллеров на подобное не способны.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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