ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
30 марта
397636 Топик полностью
fk0, легенда (27.03.2013 11:44, просмотров: 796) ответил DragonS на Парсер для GSM модема и работа с ним. Как правильно организовать работу?
Здесь нечего изобретать, нужно просто подсмотреть как оно сделано на "больших компьютерах" (в виндовсе, линуксе и т.п.) Есть драйвер последовательного порта. У него, естесственно, есть FIFO-буфер (скорей кольцевой) куда обработчик прерываний от UART складывает принимаемые данные (такой же буфер есть для передачи). Далее есть уже программа, которая функциями read() и write() читает и пишет данные в этих буферах. Обычно ввод нужен не блокирующий, поэтому функции C-библиотеки для чтения использовать не получится. А вывод может быть и блокирующий, в таком случае можно использовать функции вроде printf, что может быть удобно. Как разбирать ответы модема. Периодически вызывается read() для считывания данных уже в линейный массив размера большего, чем один максимально возможный ответ модема. Либо размер может динамически изменяться. После каждого поступления данных массив анализируется и если там найден ответ или "unsoliscited message", то оно выделяется (из начала массива) и передаётся на обработку, потом необработанный остаток (из конца массива) перемещается в начало и всё продолжается... Как выделяется ответ. Вообще ответ содержится в V.250. Если вкратце, то поток данных по 0D/0A разделяется на строки. Если формально, то тут есть конечный автомат, который и осуществляет "парсинг". Но только до уровня отдельных ответов модема перечисленных в V.250 (NO CARRIER, OK, ERROR и т.п.) Далее существует ещё один автомат, который уже оперирует не символами, а ответами модема (строками) и, фактически, его состояние отражает состояние модема по выполнению команды. Это важно, чтоб понимать, когда команда завершилась и как она завершилась (успешно, с ошибкой, код ошибки из +ERROR). Другие ответы модема, не влияющие на исполнение команд, передаются всем заинтересованным в получении ответов модема разным программным модулям (потому, что разные модули используют разные функции модема) и они их как-то обрабатывают. В виде строк, разумеется. Потому, что на более нижнем уровне невозможно разобрать все ответы сразу: модуль работающий с модемом не знает ни возможных ответов модема во всех возможных случаях, ни точный состав программных модулей их обрабатывающих (используется "динамическое связывание", по сути вызываются callback функции модулей зарегистрированные при старте программы). Модуль работающий с командами и ответами модема о звонках, SMS, интернете и всём таком ничего не знает. Он только умеет передать команду (и связанные с ней данные, если отправка SMS, например) в модем, дождаться ответа или таймаута, сообщить на уровень выше ок или ошибка и код ошибки, а также передать все прочие сообщения на уровень выше, где другие модули уже примут нужные для них сообщения. Эхо не мешает (ответы модема начинающиеся с "AT" откидываются как эхо), но оно не нужно т.к. создаёт лишнюю нагрузку и на процессор и на объём свободной в буфере памяти. К вопросу о флагах -- я их очень недолюбливаю. Потому, что набор из 10 флагов может кодировать уже 2^10 состояний. А реально их там с десяток-два всего. Считаю, нужно выделять единую переменную хранящую состояние в таких случаях и проектировать программу как автомат. Использовать также вложенные или паралельные автоматы (иначе, если всё объединять в один большой автомат, то его трудно понять умом и число состояний там фактически перемножается). Ждать ответа не обязательно. Теоретически команду можно отменить просто послав 0D (V.250 об этом говорит). Практически редкий модем такое позволит. Остаётся ждать. Вопрос, что делать если не дождался. Можно сбрасывать модем. Но для начала можно подать ещё раз "AT", вдруг модем "забыл" ответ (у SIM900 бывает). Про "другие события" не понял. Сообщения от модема, в момент обработки команды, поступают же. Нельзя только дать следующую команду. Это да, проблема, когда SMS по 2 минуты отправляются (практический таймаут ~90 секунд)... Возможно речь о том, не как работать с модемом, а как вообще организовать архитектуру относительно больших программ, чтоб получить параллельную работу отдельных частей программы более менее в "реальном времени"? Практически это всё делается на конечных автоматах, чтоб не было блокирующихся на длительное время функций, т.к. кооперативная многозадачность с единым на всё стеком. Либо какая-либо ОС для многозадачности. Но подход с ОС не так-то прост. ОС позволит завести, например, 10-20 задач. Но не 100-200. Всё равно придётся придти к конечно-автоматному или событийно-ориентированному программированию. Хороший аналог -- GUI в "больших" ОС. Там событийно-ориентированная архитектура. Никто не пытается завести отдельный поток на каждый "виджет" в GUI -- это просто невозможно. Также и с ОС. Отдельные потоки нужны в основном для совсем уж разных задач и к тому же требующих либо вытеснения (долгие вычислительные задачи), либо быстрой реакции (в силу опять же вытеснения, не надо ждать пока там другие автоматы додумают до конца свой очередной шаг). И на этот вопрос хотелось бы ответить "это know how, мы за это зарплату получаем" (C). RTS/CTS не всегда обрабатываются в "командном режиме" модема, бывает только при передаче данных. Понятно почему: в командном режиме есть естесственные причины (нет ответ) по "торможению" потока. Если нет передачи данных в "прозрачном режиме", а работа ведётся только через команды модема, то RTS/CTS возможно и не нужны. Или если используется CMUX, или если принято решения использовать XON/XOFF (но тогда ограничения по содержанию этих XON/XOFF в данных). DCD -- аналогично, нужен в основном если есть передача данных в "прозрачном режиме", иначе не очень. DTR скорей нужен, RI тоже полезен.
[ZX]