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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Исходники UART with PDC для Atmel ARM, Состряпал от нифиг делать :)
Andrey_Sudnov
сообщение Aug 10 2005, 13:56
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Кому нужны готовые, либо как примеры работы с UART через PDC (т.е. ПДП) смело в юз.
Помучился с ними пару дней. Работает уже пару недель. Без ошибок.
Приемник работает посимвольно, и приемник и передатчик работают через прерывания, у каждого свой кольцевой буфер. Функции передачи не ждут, если данные помещаются в кольцевой буфер. Если надо ждать конца передачи - есть фунция. Поддерживается работа в многопоточной среде. Можно легко интегрировать в операционную систему (если переписать функции работы с сигналами).
Кристалл у меня AT91SAM7S64 и AT91RM9200, но, думаю, любой Atmel подойдет.
В общем, кому интересно, смело смотрим. Public domain.

О как! Тока запостил, сразу ошибку нашел! Исправил. Как расценить сей шаг всевышнего даже не знаю, но что не случается, все к лучшему wink.gif
Прикрепленные файлы
Прикрепленный файл  uartpdc.rar ( 2.3 килобайт ) Кол-во скачиваний: 457
 
Go to the top of the page
 
+Quote Post
xoms
сообщение Aug 10 2005, 15:24
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 124
Регистрация: 20-06-04
Пользователь №: 67



Ну уже можно скачивать или подождать.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Aug 10 2005, 17:44
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(xoms @ Aug 10 2005, 20:24)
Ну уже можно скачивать или подождать.
*

Да, вполне можно. Ошибка была в ветке алгоритма, которую недавно дописал и не тестировал. Проявилась бы при передаче функции PutStr строки длинее, чем внутренний буфер, когда он пуст.

Конечно же возможны и другие ошибки. Но перекачал уже мегов 100 по X modem да и в консоли постоянно работаю - все ОК.
Go to the top of the page
 
+Quote Post
RRRR
сообщение Aug 11 2005, 14:56
Сообщение #4


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 23-06-05
Пользователь №: 6 264



Для Linux драйвер с использованием PDC (AT91RM9200) лежит на www.ipbx.ru/rm9200
Go to the top of the page
 
+Quote Post
bloodden
сообщение Mar 3 2007, 20:04
Сообщение #5


Бывалый
***

Группа: Validating
Сообщений: 375
Регистрация: 19-10-05
Из: Kiev, UA
Пользователь №: 9 853



cheers.gif a14.gif
Полезная вещь. Сенкс.


--------------------
Заходите кому надо на мой сайт
Go to the top of the page
 
+Quote Post
ivstech
сообщение Mar 14 2007, 09:58
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 204
Регистрация: 5-01-06
Пользователь №: 12 860



Круто, особенно примитивы синхронизации понравились
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 20 2007, 07:24
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Глянул на исходники PDC от Linux (древние, правда). Там функция вывода, перед тем как поместить новые данные в буфер и настроить указатели, выключает(!) передатчик. Т.е. если в этот момент произойдет более высокоуровневое прерывание - передатчик будет выключен и данные передаваться не будут. Если же запрещаются все прерывания, значит в течение всего времени копирования выходных данных в буфер нет возможности прерваться на более привелигированную операцию (не помню, запрещаются ли прерывания, но у обоих вариантов есть минусы). К тому же какова цена выключения и включения передатчика? Это просто кажущаяся простота смены значения одного бита, за которой, на самом деле идет много всяких переключений, а это лишняя трата энергии, что иногда немаловажно.

В моем драйвере применяется более сложный алгоритм, который позволяет передатчику продолжать работать в момент копирования буфера, прерывания при этом разрешены. Единственное, что на момент копирования маскируется прерывание самого передатчика.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 20 2007, 12:57
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Andrey Sudnov @ Dec 20 2007, 10:24) *
К тому же какова цена выключения и включения передатчика? Это просто кажущаяся простота смены значения одного бита, за которой, на самом деле идет много всяких переключений, а это лишняя трата энергии, что иногда немаловажно.

smile.gif А какова цена побайтного копирования данных из приемника в прерывании?
Я уж не говорю о том, что это потенциальная причина потери данных при даже не очень длительном (174uS @ 115200) запрещении прерываний.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 20 2007, 18:23
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(aaarrr @ Dec 20 2007, 17:57) *
smile.gif А какова цена побайтного копирования данных из приемника в прерывании?
Я уж не говорю о том, что это потенциальная причина потери данных при даже не очень длительном (174uS @ 115200) запрещении прерываний.

??? Не понял.
В каком месте там теряются данные? В приемнике? Да, приемник работает не через PDC. Но я не вижу там проблем.
Не помню детально работу с UART у SAM. Но по идее потеря произойдет только если не уcпеть считать предыдущей принятый байт. Байты приходят через каждые 2864 такта. Прерывания от UART маскируются для копирования порции данных в выходрой буфер. Если в этот момент поступит байт, обработан он не будет. Сразу же. А только после того, как memcpy скопирует данные, прерывание демаскируются и тут же срабатывает. Размер буфера передатчика всего 128 байт, так что байт не потеряется.
Хотя, конечно надо бы и приемник сделать через PDC. И у вас есть пример.
З.Ы. А то что UART вообще выключается, пока копируется буфер, это как повлияет на возможность потери?
Что за 174uS?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 20 2007, 18:35
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Andrey Sudnov @ Dec 20 2007, 21:23) *
Хотя, конечно надо бы и приемник сделать через PDC. И у вас есть пример.

Надо. У меня и приемник есть, зачем мне пример smile.gif

Цитата(Andrey Sudnov @ Dec 20 2007, 21:23) *
З.Ы. А то что UART вообще выключается, пока копируется буфер, это как повлияет на возможность потери?

Никак, если все уже передано.

Цитата(Andrey Sudnov @ Dec 20 2007, 21:23) *
Что за 174uS?

Это время передачи двух байт на скорости 115200. Очень маленькое время, особенно если процессор занят другими задачами.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 20 2007, 18:49
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(aaarrr @ Dec 20 2007, 23:35) *
Никак, если все уже передано.

Т.е. прием и передача идут сразу из пользовательских буферов. Которые, например, локальные. Ню-ню.
Цитата
Это время передачи двух байт на скорости 115200. Очень маленькое время, особенно если процессор занят другими задачами.

К чему это?
Продолжительнорсть маскировки прерывания не превышает копирования 128 байт функцией memcpy. Это сколько, не помню, 128 тактов (1 копирование за 4-е такта)? Для того чтобы принятый байт потерялся, необходимо чтобы MC был занят более привелигированной задачей (ну там время считал) указаное вами время поделить на 2, т.е. 2871 такт (я указал 2864 smile.gif Это значит ваще каюк пришел реал-тайму.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 20 2007, 18:57
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Andrey Sudnov @ Dec 20 2007, 21:49) *
Т.е. прием и передача идут сразу из пользовательских буферов. Которые, например, локальные. Ню-ню.

Я не говорю, что запрещать правильно и хорошо. Просто это не приведет к катастрофическим последствиям.

Цитата(Andrey Sudnov @ Dec 20 2007, 21:49) *
Для того чтобы принятый байт потерялся, необходимо чтобы MC был занят более привелигированной задачей (ну там время считал) указаное вами время поделить на 2, т.е. 2871 такт (я указал 2864 smile.gif Это значит ваще каюк пришел реал-тайму.

Во-первых, ничего делить не надо - для переполнения нужно два символа. А во-вторых, почему бы процессору не отвлечься на такое время? Реал-тайм реал-тайму рознь smile.gif
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 20 2007, 19:16
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(aaarrr @ Dec 20 2007, 23:57) *
Я не говорю, что запрещать правильно и хорошо. Просто это не приведет к катастрофическим последствиям.

Ну вот выключили мы UART. И отвлеклись. Причем не на 2 байта, а всего на один стартовый бит. Потом включили. Нееет, все нормально, никаких катострофических последствий.
Цитата
Во-первых, ничего делить не надо - для переполнения нужно два символа. А во-вторых, почему бы процессору не отвлечься на такое время? Реал-тайм реал-тайму рознь smile.gif

Принимаю, вроде так. Ну дак значит времени на оброботку есть еще больше.

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

Вспомнил насчет копироавния и внутренних буферов. Они нужны для того чтобы вызвать PutStr и сразу же вернуться из нее. При этом буфер, который указывали PutStr можно использовать по новому. Единственное но. Длина не должна превышать свободный размер внутреннего буфера, иначе PutStr будет ждать его освобождения. Размер буфера 128 байт. Для некоторых применеий может быть мало. Но тут нет идеально варианта, в любом случае в чем-то выигрываем, в чем то проигрываем.
В случае если PDC будет работать прям из переданного буфера, функция PutStr вынуждена ждать завершение передачи, иначе данные могут быть испорчены программой, после возврата из нее.
Как вариант - все время передавать из разных мест. Да, в некоторых случаех надо делать так, но это гораздо сложнее, чем вызвать PutStr и забыть.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 20 2007, 19:28
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Andrey Sudnov @ Dec 20 2007, 22:16) *
Ну вот выключили мы UART. И отвлеклись. Причем не на 2 байта, а всего на один стартовый бит. Потом включили. Нееет, все нормально, никаких катострофических последствий.

Ваши слова:
Цитата(Andrey Sudnov @ Dec 20 2007, 10:24) *
выключает(!) передатчик

и причем здесь прием?

Цитата(Andrey Sudnov @ Dec 20 2007, 22:16) *
Я утверждаю, что даже с посимвольным вводом, ситуация, когда потеряется символ - невозможна. Точнее это произойдет только в том случае, если прерывания будут запрещены в течение 5742 такта, а это невозможно. Если же это возможно, значит возможны и другие катастрофы.

Если в системе крутится один драйвер UART, то невозможно. Но обычно крутится еще много чего другого безо всяких катастроф.
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 20 2007, 19:51
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



Если Вы не против, подкину еще одну тему для обсуждения. Есть такое замечательное устройство GSM-модем SIM508. Так вот он при приеме пакета данных сообщает об этом следующим образом "+IPD<размер>:". Есть идея обработки обычных сообщений через обычные прерывания. Т.е. посимвольно. Ибо неизвестно, когда же закончится входящее сообщение. А парсить его на предмет <CR><LF> расточительно. Зато принимать пакеты заранее известной длинны оч. удобно через PDC. Есть вопрос: теоретически возможна ли потеря символов при переключении режимов работы. Что-то я в документации ничего толкового не нашел по этому вопросу...


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 20 2007, 20:31
Сообщение #16


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(aaarrr @ Dec 21 2007, 00:28) *
и причем здесь прием?

Не помню что там выключается. Я рассматривал исходя из передачи, поэтому так написал. Имел ввиду весь UART. Ведь если при передаче выключается передатчик, то при преме должен выключаться приемник. Ведь так? К тому же передача из произвольных буферов я еще представляю, а прием в произвольные - это как? Вызвали GetData, передав указатель, вернулись, что-то делаем, потом каким-то образом узнаем что данные получены. Ну, буфер заполнен. Новые данные принимать некуда. Надо подставлять новый. А в этот момент бабац, и пресловутое запрещение прерываний. А мы ведь в пользовательском коде, ваще самые некотируемые.
Нее. Так не правильно.
Цитата
Если в системе крутится один драйвер UART, то невозможно. Но обычно крутится еще много чего другого безо всяких катастроф.

Обработчик прерываний не должен выполнять никакой длительной работы работы внутри себя. Это даже по Windows (далеко не реал-тайм) - закон! Если же в программе допускаются такие задержки, то ни при каком способе работы с UART нельзя гарантировать, что не произойдет потери принятого байта. Ведь задержка может произойти между переключениями буферов в пользовательском коде (а такое переключение более длительное, чем метод, используемый у меня).


Цитата(Dron_Gus @ Dec 21 2007, 00:51) *
Если Вы не против, подкину еще одну тему для обсуждения. Есть такое замечательное устройство GSM-модем SIM508. Так вот он при приеме пакета данных сообщает об этом следующим образом "+IPD<размер>:". Есть идея обработки обычных сообщений через обычные прерывания. Т.е. посимвольно. Ибо неизвестно, когда же закончится входящее сообщение. А парсить его на предмет <CR><LF> расточительно. Зато принимать пакеты заранее известной длинны оч. удобно через PDC. Есть вопрос: теоретически возможна ли потеря символов при переключении режимов работы. Что-то я в документации ничего толкового не нашел по этому вопросу...

Переключаться между режимами может быть и можно, но не правильно. Думаю, в данном случае надо всегда работать через PDC. После "+IPD<размер>:" есть таймаут или сразу данные идут? В любом случае, настраиваем таймаут (ну там, возможны другие команды, URC), указываем буфер, ждем когда он заполнится (полностью или нет, не важно). По любому парсим начиная с начала. Если нашли "+IPD<размер>:", остальную часть буфера рассматриваем как данные. Три варианта: 1) после данных есть еще строковые ответы, 2) данные кончаются в конце буфера, 3) не все данные влезли в буфер. Во третьем случае указываем еще буфер, но после заполнения помним, что там данные вначале. А потом могут быть строки.
Алгоритм не тривиален. Если его делать влоб - не получиться. Но могу псевдокодом расписать, как делать.

Кстати, что насчет URC? У некоторых телефонов возможны такие фишки:
AT+CMGL=0 (запрос списка новых входящих SMS)
+CMGL: 1,0,,24 (ответ: индекс, статус,,длина)
0791xxxxxxxxxxF1040B919720380422F6 (это PDU - закодированная SMS)
+CMTI: "ME",39 (хопа, пришло URC - уведомление - о новом сообщении)
00006001701041130005C8329BFD06 (продолжение PDU)
Как такое обрабатывать?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 20 2007, 22:03
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Dron_Gus @ Dec 20 2007, 22:51) *
Если Вы не против, подкину еще одну тему для обсуждения. Есть такое замечательное устройство GSM-модем SIM508. Так вот он при приеме пакета данных сообщает об этом следующим образом "+IPD<размер>:". Есть идея обработки обычных сообщений через обычные прерывания. Т.е. посимвольно. Ибо неизвестно, когда же закончится входящее сообщение. А парсить его на предмет <CR><LF> расточительно. Зато принимать пакеты заранее известной длинны оч. удобно через PDC. Есть вопрос: теоретически возможна ли потеря символов при переключении режимов работы. Что-то я в документации ничего толкового не нашел по этому вопросу...

В свое время я извращался подобным образом на AT91x40xxx. У них PDC был без двойной буферизации, так что приходилось останавливать прием до окончания буфера и быстренько подключать следующий.
ИМХО, можно, но лучше так не делать. Парсить <CR><LF> будет значительно проще.

Цитата(Andrey Sudnov @ Dec 20 2007, 23:31) *
Ведь если при передаче выключается передатчик, то при преме должен выключаться приемник. Ведь так?

Почему это?

Цитата(Andrey Sudnov @ Dec 20 2007, 23:31) *
К тому же передача из произвольных буферов я еще представляю, а прием в произвольные - это как?

Что Вы понимаете под термином "произвольный буфер"?

Цитата(Andrey Sudnov @ Dec 20 2007, 23:31) *
Обработчик прерываний не должен выполнять никакой длительной работы работы внутри себя. Это даже по Windows (далеко не реал-тайм) - закон! Если же в программе допускаются такие задержки, то ни при каком способе работы с UART нельзя гарантировать, что не произойдет потери принятого байта. Ведь задержка может произойти между переключениями буферов в пользовательском коде (а такое переключение более длительное, чем метод, используемый у меня).

Да кто же спорит? Просто в одном случае допустима задержка в 2 символа, а во втором - в 1 буфер PDC, размер которого можно регулировать. А ОС, пользовательский код и прочее к делу не относится.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 20 2007, 22:53
Сообщение #18


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(aaarrr @ Dec 21 2007, 03:03) *
ИМХО, можно, но лучше так не делать. Парсить <CR><LF> будет значительно проще.

Т.е. делать по моему? Я вспомнил! Сделал побайтно из-за того, что так проще принимать строки.
Цитата
Почему это?
Что Вы понимаете под термином "произвольный буфер"?

Совсем забыл как работает этот PDU. Сейчас глянул. Без отключения приемника не обойтись, так как установить адрес на следующий буфер и счетчик надо одновременно! Это если адрес буфера будет все время разный, "произвольный", для обработчика прерываний, неизвестный ему заранее. Если использовать один и тот же буфер или пару, то без выключения приемника обойтись можно.
Плюс с PDC появляется проблема с приемом строк произвольной длины. Как ее организовать? Ловить прерывание по таймауту, копировать (!) буфер от значения до текущего адреса? Или PDC переходит на следующий буфер по таймауту?
Опишите пожалуйста парой слов Ваш алгоритм, так сказать путь данных от UART до пользовательского буфера. Куда указывает адрес и следующий адрес в PDC (в течение всего цикла)?
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 20 2007, 22:55
Сообщение #19


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



2 Andrey Sudnov. Да уж алгоритм не тривиален. Пауз никаких нет. Иногда модем пакеты выплевывает за раз, иногда бьет на куски и каждый обрамляет <CR><LF>..<CR><LF>. Это еще больше затрудняет разгребание "влоб". Сейчас использую Ваш фифо с некоторыми добавлениями, типа подсчета принятых строк и т.д. Никак не могу понять - на больших обьемах где-то выпадает символ. Overrun я победил, остались свои косяки.

2 aaarrr, убедили. smile.gif Завтра волю в кулак и буду переписывать. Тут только что осознал, что можно запоминать позицию до котрой в прошлый раз парсил и в след раз начинать с нее. Осталось посчитать, как часто надо проверять буфер на наличие новых строк.

З.Ы. ненавижу "равноправные" интерфейсы. Другое дело SPI, пока не спросили слэйв молчит. smile.gif


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 21 2007, 00:36
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Andrey Sudnov @ Dec 21 2007, 01:53) *
Т.е. делать по моему? Я вспомнил! Сделал побайтно из-за того, что так проще принимать строки.

Нет, делать побайтно я не советовал.

Цитата(Andrey Sudnov @ Dec 21 2007, 01:53) *
Совсем забыл как работает этот PDU. Сейчас глянул. Без отключения приемника не обойтись, так как установить адрес на следующий буфер и счетчик надо одновременно! Это если адрес буфера будет все время разный, "произвольный", для обработчика прерываний, неизвестный ему заранее. Если использовать один и тот же буфер или пару, то без выключения приемника обойтись можно.

Объясните мне, какой смысл писать адрес и счетчик в разное время?

Понял Ваше определение "произвольного" буфера. ИМХО, те буферы, с которыми работает PDC должны быть однозначно фиксированными - задача PDC и буферизации состоит прежде всего в разгрузке процессора и обеспечении надежного приема, а дальнейшая судьба данных - дело пользовательского приложения, и обработчик прерывания заботиться о ней не должен.

Цитата(Andrey Sudnov @ Dec 21 2007, 01:53) *
Плюс с PDC появляется проблема с приемом строк произвольной длины. Как ее организовать? Ловить прерывание по таймауту, копировать (!) буфер от значения до текущего адреса? Или PDC переходит на следующий буфер по таймауту?
Опишите пожалуйста парой слов Ваш алгоритм, так сказать путь данных от UART до пользовательского буфера. Куда указывает адрес и следующий адрес в PDC (в течение всего цикла)?

Попробую, парой слов не обойдется, правда. smile.gif
Итак:
1. Заводим два одинаковых буфера.
2. Прописываем в PDC_RPR и PDC_RCR адрес и длину первого буфера, в PDC_RNPR и PDC_RNCR - второго.
3. При поступлении прерывания ENDRX копируем данные из буфера PDC в пользовательский (у меня это обычно FIFO, если принимается поток, или набор фиксированных буферов, если обмен идет в пакетном режиме). Адрес и длину освободившегося буфера записываем в PDC_RNPR и PDC_RNCR.
Наличие места в FIFO или свободного буфера на этом этапе - целиком проблема пользовательского приложения.
4. По TIMEOUT все несколько сложнее:
4.1 Запрещаем - увы - прерывания
4.2 Выключаем PDC
4.3 Запоминаем PDC_RCR
4.4 Если PDC_RNCR != 0, то ставим PDC_RPR = PDC_RNPR, PDC_RCR = PDC_RNCR, PDC_RNCR = 0,
в противном случае игнорируем п.4.6
4.5 Включаем PDC и прерывания
4.6 Копируем данные и прописываем PDC_RNPR и PDC_RNCR аналогично п.3
Время запрета PDC и прерываний получается очень малым.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 21 2007, 05:06
Сообщение #21


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(aaarrr @ Dec 21 2007, 05:36) *
Итак:
1. Заводим два одинаковых буфера.
2. Прописываем в PDC_RPR и PDC_RCR адрес и длину первого буфера, в PDC_RNPR и PDC_RNCR - второго.
3. При поступлении прерывания ENDRX копируем данные из буфера PDC в пользовательский (у меня это обычно FIFO, если принимается поток, или набор фиксированных буферов, если обмен идет в пакетном режиме). Адрес и длину освободившегося буфера записываем в PDC_RNPR и PDC_RNCR.
Наличие места в FIFO или свободного буфера на этом этапе - целиком проблема пользовательского приложения.
4. По TIMEOUT все несколько сложнее:
4.1 Запрещаем - увы - прерывания
4.2 Выключаем PDC
4.3 Запоминаем PDC_RCR
4.4 Если PDC_RNCR != 0, то ставим PDC_RPR = PDC_RNPR, PDC_RCR = PDC_RNCR, PDC_RNCR = 0,
в противном случае игнорируем п.4.6
4.5 Включаем PDC и прерывания
4.6 Копируем данные и прописываем PDC_RNPR и PDC_RNCR аналогично п.3
Время запрета PDC и прерываний получается очень малым.

В пункте 3 копируем внутри обработчика прерываний?
Мне кажетсе, при приеме необходимости выключать PDC нет (точно PDC? А не UART? А если была задержка перед обработкой прерывания по TIMEOUT и в тот момент, когда выключили PDC как раз поступил новый байт, ну а раз PDC выключен - запомнили и выдали новый запрос на прерывание, но уже без PDC?). Почему необходимо начинать прием в следующий буфер вместо хвоста текущего?
Вот это выключение в пункте 4.2, которое мне совсем не нравится, при передаче необходимо, так как устанавливать адрес и счетчик надо вместе, а вызов PutStr может произойти в любой момент.
При приеме момент смены указателя и значения только один - в прерывании ENDRX, когда вероятность того, что произойдет переключение буферов в PDC очень мала (не успеет просто так много данных поступить).


Цитата(Dron_Gus @ Dec 21 2007, 03:55) *
2 Andrey Sudnov. Да уж алгоритм не тривиален. Пауз никаких нет. Иногда модем пакеты выплевывает за раз, иногда бьет на куски и каждый обрамляет <CR><LF>..<CR><LF>. Это еще больше затрудняет разгребание "влоб". Сейчас использую Ваш фифо с некоторыми добавлениями, типа подсчета принятых строк и т.д. Никак не могу понять - на больших обьемах где-то выпадает символ. Overrun я победил, остались свои косяки.

Символ пропадает в передатчике или приемнике? Вы так спокойно об этом говорите! Ни в коем случае ничего не должно пропадать! Если есть ошибка у меня, а это возможно, о ней надо сообщить, чтобы исправиить ну или отказаться от моего исходника - не исключаю и такой вариант.
Go to the top of the page
 
+Quote Post
vet
сообщение Dec 21 2007, 06:58
Сообщение #22


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



а что за беда от выключения PDC? ну выключили, переставили буферы, снова включили - перенос данных продолжился с того же места.
у меня PDC обычно включен в обе стороны, активны прерывания AT91C_US_RXBUFF | AT91C_US_TXBUFE | AT91C_US_TIMEOUT. Копирования массивов нет, кольцевые буферы заполняются/разгребаются непосредственно функциями putchar/getchar, которые, впрочем, тоже приостанавливают PDC на десяток-другой машинных команд, проблем от этого не испытывал.


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 21 2007, 08:43
Сообщение #23


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(vet @ Dec 21 2007, 11:58) *
а что за беда от выключения PDC? ну выключили, переставили буферы, снова включили - перенос данных продолжился с того же места.
у меня PDC обычно включен в обе стороны, активны прерывания AT91C_US_RXBUFF | AT91C_US_TXBUFE | AT91C_US_TIMEOUT. Копирования массивов нет, кольцевые буферы заполняются/разгребаются непосредственно функциями putchar/getchar, которые, впрочем, тоже приостанавливают PDC на десяток-другой машинных команд, проблем от этого не испытывал.

Допустим PDC выключен. В этот момент приходит новый символ. Устанавливается RXRDY, но так как он замаскирован - прерывания не происходит. Закончили работу с буферами, включили PDC. Скорее всего Вы правы - символ, который уже принят, уйдет в буфер. Это было бы логично. Надо конечно проверить для верности.
Я признаю, что мой драйвер чрезмерно усложнен из-за того что не выключает PDC. В этом нет смысла, поэтому лучше его использовать только в качестве обучающего (ну там все-таки есть некоторые трюки).
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 7 2015, 04:57
Сообщение #24


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Взрыв из прошлогоwink.gif

Кому интересен subj, у мну есть что добавить.
Первое. Это актуально на новом железе Atmel(поменялся ли интерфейс UART и PDC)?
Второе. Появились ли какие новые реализации работы через PDC хорошие?(та, что была в linux kernel времен 2.6 - мне не нравится)
Третье. Теоретически возможно написать поблочный, а не посимвольный алгоритм для приемника, который будет работать в паре с предложенным алгоритмом передатчика БЕЗ ОТКЛЮЧЕНИЯ КОНТРОЛЛЕРОВ UART/PDC(читайте первый и седьмой пост, а также последние несколько).
Этот алгоритм сложнее, чем алгоритм для передатчика(а он сам не прост, по сравнению с linux версией).
И он возможен, так как настройку PDC МОЖНО начинать с установки второй пары указатель-счетчик(которая Next)! Аппаратно значения переносятся сразу в первую пару(текущую) и сразу же начинается прием в этот буфер. Т.е. возможна такая настройка буферов: 1) проверяем свободен ли Next 2) Настраиваем Next 3) переходим к 1. Какбэ не очевидный момент, но выявленный экспериментально на AT91SAM7S64.
В SDK от Atmel же происходит сначала проверка и заполнение первой пары, и только если она не свободна - заполнение пары Next. ЭТО ДЕЛАЕТ НЕВОЗМОЖНЫМ АТОМАРНУЮ УСТАНОВКУ ОБОИХ ПАР И ПРИХОДИТСЯ ОТКЛЮЧАТЬ КОНТРОЛЛЕР.
Да, перенос происходит в момент установки регистра счетчика.
Публиковать пока не буду, но кому интересно, готовый исходник пришлю, так как надо тестить.
Go to the top of the page
 
+Quote Post
MrAlex
сообщение Dec 7 2015, 16:26
Сообщение #25


Частый гость
**

Группа: Свой
Сообщений: 197
Регистрация: 15-10-10
Из: г. Москва
Пользователь №: 60 179



Можно вообще не передергивать контроллер и работать без прерываний.
Достаточно даже одного буфера.
Если next освободился кидаем в него адрес и размер. После заполнения счет начинается сначала. Получается кольцевой буфер.
Остается только сверять текущий указатель и забирать принятое.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 7 2015, 17:28
Сообщение #26


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Согласен насчет того, что можно принимать через один буфер. Сложности с атомарностью и прерываниями начинаются при работе с двумя буферами.
Зачем нужны два буфера?
Они позволяют на HIGHLOAD обрабатывать входящие данные прямо в тех же буферах, которые заполнялись PDC, БЕЗ КОПИРОВАНИЯ!
Насколько все это нужно, каждый решает в меру своей испорченностиwink.gif
Можно сделать как-то эдак хитроватисто, но надо проверять. А зн велком.
Go to the top of the page
 
+Quote Post
MrAlex
сообщение Dec 8 2015, 08:31
Сообщение #27


Частый гость
**

Группа: Свой
Сообщений: 197
Регистрация: 15-10-10
Из: г. Москва
Пользователь №: 60 179



"Правда в том, что никакой ложки нет."
а) не надо теребить текущий буфер, только читать состояние регистров.
и) проверять и обновлять содержимое только next буфера.
q) чтобы еще и работать с данными нужен +1 буфер.
Go to the top of the page
 
+Quote Post
Andrey_Sudnov
сообщение Dec 8 2015, 14:34
Сообщение #28


Частый гость
**

Группа: Свой
Сообщений: 82
Регистрация: 15-03-05
Пользователь №: 3 361



Цитата(MrAlex @ Dec 8 2015, 13:31) *
"Правда в том, что никакой ложки нет."

Ложки нет, ложкодержатели естьwink.gif
Выкладывай что ли свой вариант, а то не очень понятно, что значит "теребить".
Ну или в subj укажи, что можно упростить по твоему. Только когда он делался, я еще не знал про next.
В версию алгоритма с приемником около 100 строк добавляется
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 25th July 2025 - 11:49
Рейтинг@Mail.ru


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