Вытесняющая многозадачная ОС. Практика AVR
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3577656#p3577656"]я уже довольно много написал о том, как сделано сейчас.
в итоге приходится каждый чих окружать всякими мьютексами, семаформаи и т.п. "блокировками", и в итоге получается, что вместо ПАРАЛЛЕЛЬНОГО исполнения код исполняется ПОСЛЕДОВАТЕЛЬНО, т.е. КООПЕРАТИВНО.[/uquote]
Я, честно, не очень представляю, как устроен протокол обмена с модемом. Только в общих чертах. Поэтому, сейчас говорю исходя из своего понимания.
Пока мне непонятны Выши проблемы. Скажем при работе по TCP/IP ровно те же проблемы. Задача (*) посылает данные по TCP сокету, эти данные должны быть подтверждены удаленной строной, когда придет подтверждение не известно. Да задача (*) посылающая данные в TCP сокет может быть заблокирована, но задача принимающая данные из IP интерфейса (и все остальные) при этом, естественно работает. Когда придет подтверждение, то и разблокируется и продожит работать задача (*).
в итоге приходится каждый чих окружать всякими мьютексами, семаформаи и т.п. "блокировками", и в итоге получается, что вместо ПАРАЛЛЕЛЬНОГО исполнения код исполняется ПОСЛЕДОВАТЕЛЬНО, т.е. КООПЕРАТИВНО.[/uquote]
Я, честно, не очень представляю, как устроен протокол обмена с модемом. Только в общих чертах. Поэтому, сейчас говорю исходя из своего понимания.
Пока мне непонятны Выши проблемы. Скажем при работе по TCP/IP ровно те же проблемы. Задача (*) посылает данные по TCP сокету, эти данные должны быть подтверждены удаленной строной, когда придет подтверждение не известно. Да задача (*) посылающая данные в TCP сокет может быть заблокирована, но задача принимающая данные из IP интерфейса (и все остальные) при этом, естественно работает. Когда придет подтверждение, то и разблокируется и продожит работать задача (*).
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
проблема у меня только одна: код получается не красивый. не знаю, как там в TCP/IP... может, там и красиво все, но то, что получается у меня, мне не нравится. причины и описание того, что не нравится, я уже изложил ранее.viiv писал(а):Пока мне непонятны Выши проблемы.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
Если с ресурсами МК (ОЗУ в частности) проблем нет, то описанная задача с модемом решается просто.
Один процесс парсит принятую строку (посимвольно, буфером, поллингом, ... пофиг) и, в зависимости от принятой команды "дёргает" другие процессы. Естественно, с выделением под них памяти из кучи.
И по-барабану ему, ждёт ли там тот процесс уже чего-либо, не ждёт. Принял команду "отправить СМС", запустил соответствующий процесс (повторно, потройно, почетверно, ...). Одну задачу(процесс) в вытесняющей ОС можно вызывать сколь угодно раз, если приняты все меры предосторожности, типа реентерабельности. Всё упирается в одно - ОЗУ под каждый поток.
И если с ним (ОЗУ) нет никаких проблем - то и код будет достаточно прозрачен. Соответственно, наоборот, жыдим памяти - получи "макароны".
"И конфетку съесть и на ... сесть " не всегда получается
Один процесс парсит принятую строку (посимвольно, буфером, поллингом, ... пофиг) и, в зависимости от принятой команды "дёргает" другие процессы. Естественно, с выделением под них памяти из кучи.
И по-барабану ему, ждёт ли там тот процесс уже чего-либо, не ждёт. Принял команду "отправить СМС", запустил соответствующий процесс (повторно, потройно, почетверно, ...). Одну задачу(процесс) в вытесняющей ОС можно вызывать сколь угодно раз, если приняты все меры предосторожности, типа реентерабельности. Всё упирается в одно - ОЗУ под каждый поток.
И если с ним (ОЗУ) нет никаких проблем - то и код будет достаточно прозрачен. Соответственно, наоборот, жыдим памяти - получи "макароны".
"И конфетку съесть и на ... сесть " не всегда получается
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
в том-то и дело, что так хорошо в теории, а на практике с ОЗУ всегда есть проблемы. оттого и тоска-печаль...Аlex писал(а):И если с ним (ОЗУ) нет никаких проблем - то и код будет достаточно прозрачен
главная беда в том, что нельзя заранее узнать, какого размера пришла СМС, чтобы выделить под нее памяти ровно столько, сколько надо. из-за этого приходится выделять всегда максимум, что уже для работы с двумя СМС очень накладно становится.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3577762#p3577762"]главная беда в том, что нельзя заранее узнать, какого размера пришла СМС, чтобы выделить под нее памяти ровно столько, сколько надо. из-за этого приходится выделять всегда максимум[/uquote]
А кто мешает выделять память страницами фиксированного размера, связывая их в список? И фрагментацию уменьшите, и лишняя память будет всегда меньше, чем размер одной страницы.
А кто мешает выделять память страницами фиксированного размера, связывая их в список? И фрагментацию уменьшите, и лишняя память будет всегда меньше, чем размер одной страницы.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3577762#p3577762"]главная беда в том, что нельзя заранее узнать, какого размера пришла СМС, чтобы выделить под нее памяти ровно столько, сколько надо. из-за этого приходится выделять всегда максимум, что уже для работы с двумя СМС очень накладно становится.[/uquote]
Не знаю как в других вытеснялках, не работал, но FreeRTOS есть сервисы, переключающие незамедлительно контекст из прерывания в приоритетную задачу. Это как раз тот случай, когда нужно прерывание обработать максимально быстро, но задерживаться в нём нельзя.
По этому, можно обойтись минимально коротки кольцевым буфером, за счёт использования высокого приоритета для процесса, принимающего/обрабатывающего его.
Отсюда, функция приёма символа будет выглядеть обычным ожиданием сообщения в очереди. Что-то типа :
А прозрачность будет максимальной - как будто модуль сам пихает в эту функцию байтики.
Не знаю как в других вытеснялках, не работал, но FreeRTOS есть сервисы, переключающие незамедлительно контекст из прерывания в приоритетную задачу. Это как раз тот случай, когда нужно прерывание обработать максимально быстро, но задерживаться в нём нельзя.
По этому, можно обойтись минимально коротки кольцевым буфером, за счёт использования высокого приоритета для процесса, принимающего/обрабатывающего его.
Отсюда, функция приёма символа будет выглядеть обычным ожиданием сообщения в очереди. Что-то типа :
Код: Выделить всё
char getchar(){
char ret;
xQueueReceive(UartQueue, &ret);
return ret;
}
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
возможно, это могло бы помочь... если бы я сумел разобраться с портированием freeRTOS на свою платформу... если бы кто-то своевременно подсказал эту идею... если бы... да кабы...
Добавлено after 1 minute 29 seconds:
Добавлено after 1 minute 29 seconds:
ничего не понял, о чем это вы?ПростоНуб писал(а):А кто мешает выделять память страницами фиксированного размера, связывая их в список? И фрагментацию уменьшите, и лишняя память будет всегда меньше, чем размер одной страницы.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
Вопросы:
Коды DTMF равнозначны кодам кнопок? Уточняю. Равнозначны, или любой первый принятый код DTMF - особый режим?
В вашем описании уже вижу недостаток. Сообщение нажатия и параметр код кнопки. Должно быть так: событие нажатия кнопок. И отдельный буфер для кодов кнопок. Размер буфера зависит от проекта. Поясняю. Проверка статичного или в очереди сообщения нажатия кнопок, после этого считываем буфер. Здесь тоже ветвление, одиночное считывание (навигация по меню, какие либо действия) либо считывание всего буфера кодов кнопок (ввод). Это определяется состоянием, по другому никак. Флаги или автомат, решать вам.
Коды DTMF равнозначны кодам кнопок? Уточняю. Равнозначны, или любой первый принятый код DTMF - особый режим?
В вашем описании уже вижу недостаток. Сообщение нажатия и параметр код кнопки. Должно быть так: событие нажатия кнопок. И отдельный буфер для кодов кнопок. Размер буфера зависит от проекта. Поясняю. Проверка статичного или в очереди сообщения нажатия кнопок, после этого считываем буфер. Здесь тоже ветвление, одиночное считывание (навигация по меню, какие либо действия) либо считывание всего буфера кодов кнопок (ввод). Это определяется состоянием, по другому никак. Флаги или автомат, решать вам.
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3577798#p3577798"]ничего не понял, о чем это вы?[/uquote]
Может я Вас не правильно понял? Вы сказали, что не знаете размер SMS и вынуждены выделять память сразу по максимуму. Я так понял, что речь идет о чтении в символьной шестнадцатиричке того, что возвращает, например, M590 по команде AT+CMGR=n.
Для примера, пусть страница у нас 32 байта. Всего 255 страниц (8К-32). В каждой странице в 0-ом байте указываем номер следующей страницы, если она есть, или 255, если таковой нет. Еще 1 байт на длину данных в странице. При желании, можно еще битики на свои флаги выделить, или номера потоков.
Как только с модема мы получаем больше 30 байт, то выделяем новую страницу и номер ее записываем в заголовок старой страницы. После чего первые 30 байт уходят в обработку в другую нить, а то, что приходит из модема пишем в новую страницу. И так далее. Если обработка в параллельной нити не сложная, то, с большой вероятностью, она будет успевать освобождать нам старую страницу, как только получит очередную.
Размер страницы подбирается под задачу и под объем доступной памяти.
Может я Вас не правильно понял? Вы сказали, что не знаете размер SMS и вынуждены выделять память сразу по максимуму. Я так понял, что речь идет о чтении в символьной шестнадцатиричке того, что возвращает, например, M590 по команде AT+CMGR=n.
Для примера, пусть страница у нас 32 байта. Всего 255 страниц (8К-32). В каждой странице в 0-ом байте указываем номер следующей страницы, если она есть, или 255, если таковой нет. Еще 1 байт на длину данных в странице. При желании, можно еще битики на свои флаги выделить, или номера потоков.
Как только с модема мы получаем больше 30 байт, то выделяем новую страницу и номер ее записываем в заголовок старой страницы. После чего первые 30 байт уходят в обработку в другую нить, а то, что приходит из модема пишем в новую страницу. И так далее. Если обработка в параллельной нити не сложная, то, с большой вероятностью, она будет успевать освобождать нам старую страницу, как только получит очередную.
Размер страницы подбирается под задачу и под объем доступной памяти.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
Во-первых, 8К - это ровно в 2 раза больше, чем есть в atmega128
Во-вторых, вы описали один из известных алгоритмов менеджера кучи, далеко не самый оптимальный.
В-третьих, как мне это может помочь? Проблема-то в том, что СМС может занимать от примерно 30 до примерно 360 байт, и заранее я не знаю и не могу узнать, сколько байт надо для очередной СМСки. И приходится всегда выделять по 360, хотя там на самом деле может быть только два слова, и хватило бы 36 байт...
Добавлено after 4 minutes 52 seconds:
гм. интересная мысль. я подумаю. на первый взгляд слабость принципа как раз в отсутствие единообразия в подходах... но, возможно, это окажется наоборот, сильной стороной...
Во-вторых, вы описали один из известных алгоритмов менеджера кучи, далеко не самый оптимальный.
В-третьих, как мне это может помочь? Проблема-то в том, что СМС может занимать от примерно 30 до примерно 360 байт, и заранее я не знаю и не могу узнать, сколько байт надо для очередной СМСки. И приходится всегда выделять по 360, хотя там на самом деле может быть только два слова, и хватило бы 36 байт...
Добавлено after 4 minutes 52 seconds:
С точки зрения извлечени сообщений из очереди нет никакой разницы, попало туда сообщение MSG_KEY с клавиатуры или через DTMF. То есть источник символа никакой роли не играет.Demiurg писал(а):Коды DTMF равнозначны кодам кнопок? Уточняю. Равнозначны, или любой первый принятый код DTMF - особый режим?
то есть вы предлагаете отказаться от общей очереди сообщений и выделить "кнопочные" сообщения в поток символов, обрабатываемых по мере надобности?Demiurg писал(а):И отдельный буфер для кодов кнопок.
гм. интересная мысль. я подумаю. на первый взгляд слабость принципа как раз в отсутствие единообразия в подходах... но, возможно, это окажется наоборот, сильной стороной...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
Я со смарта пишу, редактировать объёмный текст не получается. Разделяй и властвуй. Одно из ваших затруднений как раз в том, что у вас свалены в кучу люди, кони. Как то так:
Это вариант одиночной обработки кодов. Когда требуется обработка ввода, тут уже посложнее будет.
Код: Выделить всё
if (Get_Event (EV_ID_KEY_PRESSED))
{
switch (Get_Key_Code ())
{
case KEY_ESC_COD: break;
case KEY_ENTER_COD: break;
case KEY_PLUS_COD: break;
case KEY_MINUS_COD: break;
}
}
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3577862#p3577862"]Во-первых, 8К - это ровно в 2 раза больше, чем есть в atmega128
Во-вторых, вы описали один из известных алгоритмов менеджера кучи, далеко не самый оптимальный.
В-третьих, как мне это может помочь? Проблема-то в том, что СМС может занимать от примерно 30 до примерно 360 байт, и заранее я не знаю и не могу узнать, сколько байт надо для очередной СМСки. И приходится всегда выделять по 360, хотя там на самом деле может быть только два слова, и хватило бы 36 байт...[/uquote]
Во-первых, никто Вас не заставляет выделять все 255 буферов. Выделите ровно столько, сколько Вам нужно, понимая, что если буферов не хватит, то данные будут утеряны. Для одного последовательного канала и одного парсера, обычно, достаточно 2-4 буфера.
Во-вторых, это не механизм управления пулом буферов, а вовсе не кучи. Подобным образом работает, например, буферизированный ввод-вывод. Куча работает несколько иначе, так как она должна уметь выделять произвольный объем памяти непрерывным экстентом. Если не трогать системы с виртуальной памятью, для кучи страничный подход не применим.
В-третьих, я же описал как. Принимаете первые 30 байт, отдаете фоновому парсеру на обработку. Пока парсер разбирается с этими 30 байтами, заполняете следующий буфер. Парсер же, как только завершит обработку очередного буфера, освободит его, запомнив только номер следующего буфера.
Если же парсинг тривиален, то мне Ваши проблемы вообще не понятны. Ведь тогда можно парсить текст сразу во время его приема не записывая вообще его в память.
Во-вторых, вы описали один из известных алгоритмов менеджера кучи, далеко не самый оптимальный.
В-третьих, как мне это может помочь? Проблема-то в том, что СМС может занимать от примерно 30 до примерно 360 байт, и заранее я не знаю и не могу узнать, сколько байт надо для очередной СМСки. И приходится всегда выделять по 360, хотя там на самом деле может быть только два слова, и хватило бы 36 байт...[/uquote]
Во-первых, никто Вас не заставляет выделять все 255 буферов. Выделите ровно столько, сколько Вам нужно, понимая, что если буферов не хватит, то данные будут утеряны. Для одного последовательного канала и одного парсера, обычно, достаточно 2-4 буфера.
Во-вторых, это не механизм управления пулом буферов, а вовсе не кучи. Подобным образом работает, например, буферизированный ввод-вывод. Куча работает несколько иначе, так как она должна уметь выделять произвольный объем памяти непрерывным экстентом. Если не трогать системы с виртуальной памятью, для кучи страничный подход не применим.
В-третьих, я же описал как. Принимаете первые 30 байт, отдаете фоновому парсеру на обработку. Пока парсер разбирается с этими 30 байтами, заполняете следующий буфер. Парсер же, как только завершит обработку очередного буфера, освободит его, запомнив только номер следующего буфера.
Если же парсинг тривиален, то мне Ваши проблемы вообще не понятны. Ведь тогда можно парсить текст сразу во время его приема не записывая вообще его в память.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
Можете набросать пример кода, который на лету будет выбирать совпадение потока байтов с массивом строк из, предположим, 10 элементов по 5 символов каждая строка?ПростоНуб писал(а):тогда можно парсить текст сразу во время его приема не записывая вообще его в память
я стремлюсь сделать код проще и понятнее, а вы предлагаете чуть ли не ассоциативную память реализовать... боюсь, проще код от этого явно не станет.
как и в случае с предлагаемым вами разбором строки по частям.
вы продолжаете вспоминать свои предыдущие менюшки... и не желаете взглянуть на мою проблему, как на свежую проблему.Demiurg писал(а):Как то так
голосовое меню заключается в работе такого кода:
Код: Выделить всё
m1:
Say("Нажмите 1 для установки часов, нажмите 2 для установки календаря, нажмите 3 для запуска ракеты, нажмите # для отмены или * для повторного прослушивания меню");
do{
timer_start(T1, TIME_LIMIT_MENU);
msg = get_mesage(MAIN_QUEUE);
switch(msg){
case MSG_KEY:
switch(msg.key){
case K_1: setup_time(); break;
case K_2: setup_calender(); break;
case K_3: start_rocket(); break;
case K_#: return;
case K_*: goto m1;
} // key switch
break;
default:
default_process_messages(msg);
} // msg switch
} while(!timer_timeout(T1));
соответственно, представьте себе, если в этом меню будет что-то типа "чтобы ввести пароль, нажмите 5", как все будет выглядеть? в моей реализации это примерно так выглядит:
Код: Выделить всё
case K_5: {
char tmp[8];
if(get_password(tmp, 7)){
strcpy(password, tmp);
}
}
break;
как-то так вот...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- GoldenAndy
- Поставщик валерьянки для Кота
- Сообщения: 1925
- Зарегистрирован: Чт июл 28, 2016 07:58:37
- Откуда: Kyiv, UA
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
ARV, так на лету - это было предложено как пример.
А походу, ГСМ модем отдается на скорости 9600. Или около одного символа в миллисекунду.
За миллисекунду МК у вас отмолотит 16 тысяч операций.
Неужто вы не сможете прочитать 10-15 наборов по 5 байт из прогмема и сравнить их с буфером еще в процессе считывания ? У вас на это целая миллисекунда!
(я надеюсь, прием данных от модема на прерываниях сделан ?)
А походу, ГСМ модем отдается на скорости 9600. Или около одного символа в миллисекунду.
За миллисекунду МК у вас отмолотит 16 тысяч операций.
Неужто вы не сможете прочитать 10-15 наборов по 5 байт из прогмема и сравнить их с буфером еще в процессе считывания ? У вас на это целая миллисекунда!
(я надеюсь, прием данных от модема на прерываниях сделан ?)
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3577935#p3577935"]Можете набросать пример кода, который на лету будет выбирать совпадение потока байтов с массивом строк из, предположим, 10 элементов по 5 символов каждая строка?[/uquote]
Не сейчас, сейчас мне еще по пробкам час тащиться.
Но идея следующая. Список элементов делаем отсортированным. Дубли не допускаются. Таким образом, до первого символа у нас кандидаты все элементы. После первого символа запоминаем номер первого и последнего подходящего элемента. На втором символе проверяем на равенство только вторые символы между запомненными элементами включительно и снова запоминаем номер первого и последнего подходящего элемента. И так далее.
В итоге, или у нас не совпадет символ ни с одним из элементов - значит мы не знаем такого слова. Или останется только одно слово.
Не сейчас, сейчас мне еще по пробкам час тащиться.
Но идея следующая. Список элементов делаем отсортированным. Дубли не допускаются. Таким образом, до первого символа у нас кандидаты все элементы. После первого символа запоминаем номер первого и последнего подходящего элемента. На втором символе проверяем на равенство только вторые символы между запомненными элементами включительно и снова запоминаем номер первого и последнего подходящего элемента. И так далее.
В итоге, или у нас не совпадет символ ни с одним из элементов - значит мы не знаем такого слова. Или останется только одно слово.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
и вы на самом деле считаете, что это просто?ПростоНуб писал(а):Но идея следующая.
8000, но не сутьgoldenandy писал(а):За миллисекунду МК у вас отмолотит 16 тысяч операций
ощущение, что вы не читаете, что я пишуgoldenandy писал(а):Неужто вы не сможете
именно что я все смог. вчера обработчик принятого уведомления от модема вызывался через 105 микросекунд после того, как был принят символ '\r', являющийся завершающим строку символом. т.е. мне понадобилось 105 микросекунд на то, чтобы отправить сообщение в главную очередь, выйти из обработчика прерываний, дойти в главном цикле до очереднго опроса очереди, извлечь сообщение, проанализировать его и просканировать список строк в PROGMEM на предмет совпадения с принтой строкой, и вызвать нужный обработчик.
Код: Выделить всё
// прием по прерываниям
ISR(_VECTOR_RX){
static char *rx_ptr = (void*)rx_buf;
char d = _UDR;
switch(d){
case '\n': break; // игнорируем
case '\r':
if(*rx_begin) put_message(MAIN_MSG_QUEUE, MSG_GSM, 0, (uint16_t)rx_begin);
rx_begin = (void*)rx_ptr+1;
d = 0;
default:
// принятый символ сохраняем
*rx_ptr++ = d;
// закольцовываем указатель
if(rx_ptr >= (rx_buf + RING_SZ)) rx_ptr = (void*)rx_buf;
}
}
в принципе, вообще нет проблемы с работоспособностью кода. проблема есть только в плане красоты кода, как я уже писал. меньше всего мне нравится рекурсивное обращение к обработчику сообщений во многих местах моего кода. но пока что я не придумал, как это обойти. и, не смотря на некоторые занятные советы, пока и помощи в идеях не получил. ну, если, конечно, не считать проблемой мой отказ от RTOS...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3578006#p3578006"]и вы на самом деле считаете, что это просто?[/uquote]
Все в мире относительно. Для меня функция на полэкрана всегда проста.
Вот пример для GCC на компе:
Просьба сильно не пинать, так как писалось слету, да еще поздно вечером после рабочего дня.
Все в мире относительно. Для меня функция на полэкрана всегда проста.
Вот пример для GCC на компе:
Код: Выделить всё
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
uint8_t *words[] = { "Abcd","So","Zero","R","Alpa","Breaking","Top","Unit","Boat","So","R","Abcd","Abcde","Breaking" };
uint8_t *keys[] = { "Abcd","Alpha","Boat","Breaking","R","So","Top","Unit","Zero" };
// Returns:
// 0..n - index of founded key
// -1 - awaiting next symbol
// -2 - key not found
short parse_symbols(uint8_t symbol)
{
static uint8_t level = 0;
static uint8_t from_idx = 0;
static uint8_t to_idx = sizeof(keys)/sizeof(uint8_t *)-1;
short found = -2;
if ( symbol==' ' ) symbol=0;
for (uint8_t i=from_idx;i<=to_idx;i++ ) {
if ( keys[i][level]<symbol ) {
from_idx++;
} else if ( keys[i][level]>symbol ) {
if ( found==-2 ) break;
to_idx=i-1;
level++;
return(-1);
break;
} else {
found=i;
if ( symbol==0 ) break;
}
}
if ( found>=0 && symbol!=0 ) {
level++;
return(-1);
}
level=from_idx=0;
to_idx=sizeof(keys)/sizeof(uint8_t *)-1;
return(found);
}
int main(void)
{
uint8_t *ptr;
short rc;
printf("Begin test with %d words by %d elements in dictionary\n",
sizeof(words)/sizeof(uint8_t *),sizeof(keys)/sizeof(uint8_t *));
for (uint8_t w=0;w<sizeof(words)/sizeof(uint8_t *);w++) {
ptr=words[w];
do {
rc=parse_symbols(*(ptr));
} while ( (*ptr++)!=0 && rc==-1 );
if (rc<0) {
printf("Word %s not found. rc=%d\n",words[w],rc);
} else {
printf("Word %s found at index %d\n",words[w],rc);
}
}
exit(0);
}
Re: Вытесняющая многозадачная ОС. Практика AVR
Почти всегда всё накрученное можно оформить функцией (если надо положить отдельным файлом), расписать и забыть.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Вытесняющая многозадачная ОС. Практика AVR
а мусор можно под ковёр замести... и забыть. не мой подход, хотя, чего там скрывать - приходится так делать порой...OKF писал(а):Почти всегда всё накрученное можно оформить функцией (если надо положить отдельным файлом), расписать и забыть
да когда ж такое было, чтобы за попытку помочь пинали?!ПростоНуб писал(а):Просьба сильно не пинать
вот смотрите, как сделал сейчас я (не в плане критики вашего варианта, а вообще в плане поедлиться опытом).
слегка подправил скрипт линкера так, чтобы он обрабатывал секцию ".my_table", размещая её в PROGMEM, и заодно определил два символа - начало этой секции и конец. сделал макрос, который по заданному шаблону генерирует объявление строковой константы (в секции .my_table), задающей принятое уведомление, и функции для обработки этого уведомления. в коде написал небольшую функцию с циклом, который от адреса "начало секции my_table" до ареса "конец секции my_table" перебирает строки и сравнивает их с принятой строкой от модема, и, если совпадение обнаружено, вызывает соответствующую функцию обработки.
а теперь - внимание! что это мне дает: в любом месте своего кода при помощи макроса я объявляю функцию-обработчик уведомления, и не забочусь ни о том, чтобы править какие-то массивы строк, контролировать размерность этих массивов и т.п. - все делается автоматически! не нужен более обработчик - удаляю его в том месте, где объявил, и снова ни о чем не переживаю.
кстати, аналогично сделал и программные таймеры. в плане удобства - просто очень шикарно, рекомендую всем!
вот так это выглядит в коде:
Код: Выделить всё
/// определение функции обработки команды s
#define CMD_HOOK(s) static const __flash char s [] = "+" # s ; \
static void CONCAT(hook_, s)(FUNC_PARAM); \
static const tbl_item_t __attribute__((used, section(".my_table"))) CONCAT(item_, s) = {.cmd = s, .func = CONCAT(hook_, s)}; \
static void CONCAT(hook_, s)(FUNC_PARAM)
Код: Выделить всё
void gsm_str_process(char *str){
extern const int __my_tbl_start;
extern const int __my_tbl_end;
const __flash tbl_item_t *item = (void*)&__my_tbl_start;
// начиная с первого зарегистрированного обработчика и до последнего
for(; item != (void*)&__my_tbl_end; item++){
// если зарегистрирован обработчик-пустышка - игнорируем его
if(item->func == NULL) continue;
// если команда найдена
if(respcmp(item->cmd, str)){
// вызываем обработчик и завершаем перебор
item->func(str, item);
return;
}
}
debug_prn(PSTR("Unknown EVENT: \"%s\""), str);
}Код: Выделить всё
CMD_HOOK(CMTI){
uint16_t n;
// str = +CMTI: "SM", N
char *begin = find_chr(str,',',1);
if(begin){
n = atoi(begin);
put_message(MAIN_MSG_QUEUE, MSG_SYS, SYS_SMS, n);
}
}наконец, вот такой кусочек добавлен в скрипт линкера, чтобы все это заработало:
Код: Выделить всё
/* Внедрение моих секций для таблиц */
__my_tbl_start = . ;
*(.my_table)
*(.my_table*)
KEEP (*(.my_table))
__my_tbl_end = . ;
KEEP (SORT(*)(.my_table))
/* Конец моих секций для таблиц */
/* From this point on, we don't bother about wether the insns are
below or above the 16 bits boundary. */
*(.init0) /* Start here after reset. */
KEEP (*(.init0))
*(.init1)
возможно, кто-нибудь возьмёт на вооружение
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Вытесняющая многозадачная ОС. Практика AVR
[uquote="ARV",url="/forum/viewtopic.php?p=3578137#p3578137"]в вашем подходе, помимо относительной сложности и некоторой загадочности, есть еще одна проблема: сортировка "образцов". это затрудняет процесс модификации списка вручную.[/uquote]
О сложности и, тем более, загадочности, предлагаю вопрос замять по причине его явной субъективности. А сортировать список вручную никто не заставляет.
Вынесите список в отдельный включаемый файл
Указывайте в этом файле по одному ключевому слову на строку и сортируйте его при сборке проекта своей любимой утилитой сортировки. Хоть обычным sort.exe под Windows.
Ну МК я предпочитаю частый обмен короткими сообщениями длиной 1-4 байта, но по каждому прерыванию, чем редкий обмен длинными сообщениями после накопления информации в буфере.
Ваш проект, как хотите, так и поступайте. Я просто ответил на вопрос и показал, как парсить строки на лету.
О сложности и, тем более, загадочности, предлагаю вопрос замять по причине его явной субъективности. А сортировать список вручную никто не заставляет.
Вынесите список в отдельный включаемый файл
Код: Выделить всё
uint8_t *keys[] = {
#include "keys_incl.h"
};
Интересный вариант, но он как раз не для обработки "на лету". Объем кода, выполняемого между двумя полученными символами у Вас всяко больше, чем в моем примере.вот смотрите, как сделал сейчас я (не в плане критики вашего варианта, а вообще в плане поедлиться опытом).
Ну МК я предпочитаю частый обмен короткими сообщениями длиной 1-4 байта, но по каждому прерыванию, чем редкий обмен длинными сообщениями после накопления информации в буфере.
Вы лукавите. Добавлять новые ключевые слова Вам так же требуется, как и их обработчики. В моем случае, номер обработчика так же можно считать совпадающим с номером найденного ключевого слова. А размерность массивов (не строк, а указателей на строки) контролирует компилятор, а не я.не забочусь ни о том, чтобы править какие-то массивы строк, контролировать размерность этих массивов
Ваш проект, как хотите, так и поступайте. Я просто ответил на вопрос и показал, как парсить строки на лету.


