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

 
 
> Работа с UART в пакетном режиме и ОС
Pavel V.
сообщение Nov 15 2010, 08:03
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 3-06-06
Пользователь №: 17 742



Как правильно организовать работу с пакетным протоколом (что-то наподобие WAKE в собственной реализации) в условиях использования операционки?

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

Ответный пакет формируется в функции обработки команды и запускается отправка по прерыванию.

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

В этом случае возникает необходимость использования чего-то вроде кольцевого буфера для предотвращения потери данных.

Как правильно реализовать такую схему при наличии операционки?

Пока видится только такая схема работы:
1. Процесс, который занимается отправкой данных в порт, занят только тем, что висит в вечном channel.pop() из кольцевого буфера и в случае появления данных выполняет отправку байта в порт.
2. Процесс, который обрабатывает асинхронные события. Например, нажали кнопку. Процесс в этом случае вызывает некую функцию SendInputAsync() в которой формируется пакет и делается необходимое количество channel.push(). Затем процесс уходит в Sleep() на заданное настройками время.

Возможно, необходимо сделать процесс на каждое асинхронное событие?

Смущает передача управления для отправки каждого байта. Можно, конечно, вызывать channel.pop() с таймаутом и воспользоваться дополнительным событием, которое будет устанавливаться только по добавлению в канал полного пакета. Но как-то громоздко получается.

Прошу помощи у более опытных товарищей smile.gif


--------------------
Good News Everyone!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
dxp
сообщение Nov 17 2010, 04:06
Сообщение #2


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Добавлю свои "пять копеек" к обсуждению.

Поскольку UART - устройство асинхронное, что прием и передача друг на друга не "завязаны" и реализуются независимо.

Мой опыт применения UART'ов следующий. Приемная часть состоит из двух частей - одна в прерывании приемника, вторая - в отдельном процессе. В прерывании приемника осуществляется прием символа и его анализ: если это первый символ в пакете, то в нем закодирована длина пакета - эта величина фиксируется, и ожидающему процессу сигналится флаг событий, по которому процесс переход в ожидание [пакета] с таймаутом (таймаут рассчитывается, исходя из длины пакета, скорости передачи и т.д.). В прерывании теперь в при приеме очередного символа ведется подсчет входящих символов, и когда их количество достигает нужной величины (закодированной в первом символе пакета), код прерывания сигналит флаг события еще раз. Таким образом, получаем две активизации процесса приемника - на старте пакета и в конце. Т.е. процесс приемника не дергается на приеме каждого символа. В конце же и производится собственно обработка пакета (контрольные суммы, требуемые действия).

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

Передатчик собственно на ОС никак не "завязан". У передатчика есть функция send, которая формирует пакет на отправку и инициирует оную (в MSP430 для этого достаточно просто разрешить прерывание UART Tx Data Register Empty). И есть обработчик прерываний, который выпихивает данные из буфера передатчика в UART. Т.к. источников передачи может быть несколько и все они могут работать асинхронно и одновременно, то буфер передатчика реализован в виде кольцевого буфера. Код для MSP430:
Код
#pragma vector = USART1TX_VECTOR
__interrupt void TUART::TxBUF_Empty_ISR()
{
    U1TXBUF = TxBuf.pop();
    if(TxBuf.get_count() == 0) DisableTxInt();
}
//---------------------------------------------------------------------------

Из кода видно, что действия очень простые: извлекли очередной байт из буфера, сунули его в регистр данных передатчика, проверили, есть ли еще данные в буфере. Если их нет, то запретили прерывание от передатчика, чтобы оно не возникало, когда регистр данных TxD опустеет.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 30th June 2025 - 23:35
Рейтинг@Mail.ru


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