|
LPC177x UART, использовать FIFO для передачи |
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 33)
|
Sep 24 2013, 14:40
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Два независимых буфера для RX и TX. К примеру, в LPC1768 кажется нет индикатора заполненности TX буфера. Как и в LPC21xx, LPC111x. Так что забиваются по полному освобождению сразу 16 байт. В RX прерывании, если стоит уровень срабатывания 14, то можно вычитывать из RBR сразу 14 раз подряд, анализируя младший бит LSR. Пример обработчика Код void UART0_IRQHandler() { switch(U0IIR & 0x0f) { uInt lsr; default: U0LSR; U0RBR; break; case 0x02: //THRE interrupt proc_tx(&uart0); break; case 0x0C: //timeout case 0x06: //Rx line status error case 0x04: //Receive data available while ((lsr = U0LSR) & 0x01) proc_rx(&uart0, U0RBR, lsr & 0x9e); break; } NVIC_ClearPendingIRQ(UART_IRQn); } //uart0 - структура с данными
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Sep 27 2013, 11:35
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
QUOTE (Golikov A. @ Sep 27 2013, 12:53)  что значит вызывается обработчик при разрешении? Обработчик должен вызывать при возникновении прерывания а не просто при его разрешении... При возникновении прерывания "должен" ставиться флаг запроса на прерывание и ничего более. При разрешении прерывания и установленном флаге запроса контроллер прерывания запускает обработчик. Что курили голландские девелоперы, когда дизайнили уарт известно только им и богу. По факту код передачи по уарту для филипков должен быть продублирован в обработчике прерывания от уарта и в том месте кода, где нужно начать передачу. Для "нормальных" уарт архитектур достаточно разрешить прерывание "передатчик пуст"
|
|
|
|
|
Sep 27 2013, 11:51
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
чего то я не понимаю видать....
у меня это было так.
функция послать данные: если передатчик и доп буфер пусты пихает в передатчик 16 байт данных. Если их меньше и ладно, если их больше пихает 16 остальные кладет в буфер программный. если доп буфер был не пуст, кладет данные в него.
прерывание уарт пуст - если буфер программный пуст и ладно, если нет, то берет данные из него и пихает в передатчик.
я так понимаю что проблема ваша в том что при пустом буфере надо данные в него положить, а не в программный буфер... ну так это добавление одного ифа в функции отправки, зато момент отправки четко обозначен, можно чип селект какой - либо опустить...
вообщем никакой проблемы я не вижу если честно, все мне кажется логично... А вот что делать с прерывание буфер пуст если оно возникает всегда когда буфер пуст для меня как раз вопрос. Ведь большую часть времени если обмена нет, он как раз и пуст, вы прерывание что-ли запрещаете, а когда данные кладете разрешаете? Не уверен, что это прям мего логично...
|
|
|
|
|
Sep 27 2013, 12:04
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
QUOTE (Golikov A. @ Sep 27 2013, 14:51)  вообщем никакой проблемы я не вижу если честно, все мне кажется логично... А вот что делать с прерывание буфер пуст если оно возникает всегда когда буфер пуст для меня как раз вопрос. Ведь большую часть времени если обмена нет, он как раз и пуст, вы прерывание что-ли запрещаете, а когда данные кладете разрешаете? Не уверен, что это прям мего логично... Если вопрос ко мне, то в общем виде картина передачи данных выглядит так: - аппликейшн никогда не работает с уарт прямо. Только через кольцевой буфер. - после получения данных буфер проверяет разрешены ли прерывания на передачу и разрешает их, если запрещены. - обработчик прерывания заполняет выходной регистр (или выходное фифо) данными. Если данные закончились - запрещает преравания на передачу Прерывания разрешаются когда есть данные и запрещаются когда из нет. Просто , логично, компактно и надежно Ну и вы конечно правы, с уарт на лпс нет никаких проблем, одно мелкое неудобство.
|
|
|
|
|
Sep 27 2013, 16:40
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Да, конечно, 16550 уже давно морально устарел и можно сделать гораздо более удобный и современный интерфейс для UART (примеры есть). Но NXP решили для UART реализовать стандартный 16550 (с доп. фичами) и у этого подхода есть и серьёзный '+': UART - это единственная периферия, драйвера для которой я переношу между разными контроллерами практически без изменений, а это серьёзный '+' когда приходится одновременно работать с разными контроллерами. И реализовали они его грамотно - без багов. Цитата(ig_z @ Sep 27 2013, 17:35)  Что курили голландские девелоперы, когда дизайнили уарт известно только им и богу. По факту код передачи по уарту для филипков должен быть продублирован в обработчике прерывания от уарта и в том месте кода, где нужно начать передачу. В си есть такая чудесная вещь как функция(). Попробуйте - вам понравится  Цитата(ig_z @ Sep 27 2013, 17:35)  Для "нормальных" уарт архитектур достаточно разрешить прерывание "передатчик пуст" Это уж не в тех-ли нормальных (типа STM), где забыли добавить FIFO в UART?
|
|
|
|
|
Sep 28 2013, 05:05
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата(Terminator @ Sep 28 2013, 08:52)  это всё конечно красиво, но попробуйте сделать вывод в отладочный порт из разных задач. Останавливать задачу ради вывода отладки нельзя, что влезло в буфер, то влезло. Заводить отдельную задачу для слежения за заполненостью буфера, очень не хочется. Запрещать прерывания перед каждым обращением в uart тоже (тут я конечно несколько лукавлю, т.к. при складывании в буфер прерывания всё равно запрещаются). так в чем проблема то? запрет прерывания надо делать только когда вы кладете данные в буфер, чтобы случайно не возникло прерывание и часть буфер не улетела в уарт, пока вы заполняете хвост. И чтобы по прерыванию вы в середине работы функции добавления данных не попали в другую функцию которая также может добавить данные. в остальном проблем нет. Я же писал функции работают идентично, просто вместо вашей проверки на запрет прерывания и его разрешение, у нас делает проверка на пустоту буфера и его запуск на передачу. Дальше у всех циклический буфер в который кладутся остатки сообщения.
|
|
|
|
|
Sep 30 2013, 02:59
|

Местный
  
Группа: Участник
Сообщений: 209
Регистрация: 7-12-04
Из: Томск
Пользователь №: 1 382

|
Цитата(jcxz @ Sep 28 2013, 18:34)  Возможно товарищи по каким-то причинам (религиозным?) очень хотят писать в FIFO именно из ISR. Непреодолимое желание сиё понять трудно... Но, коли так уж хочется, после разрешения empty-tx IRQ можно программно возбудить прерывание при помощи NVIC. Чем плохо писать в FIFO из ISR? Это позволяет (не в случае с LPC конечно) в коде записать в буфер данные и разрешить прерывание. Всё остальное делается в прерывании. Пинать NVIC не пробовал. При случае попробую. Хотя это чревато лишними вызовами прерываний.
|
|
|
|
|
Sep 30 2013, 07:01
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(jcxz @ Sep 28 2013, 15:34)  Возможно товарищи по каким-то причинам (религиозным?) очень хотят писать в FIFO именно из ISR. Непреодолимое желание сиё понять трудно... Но, коли так уж хочется, после разрешения empty-tx IRQ можно программно возбудить прерывание при помощи NVIC. про первичное наполнение FIFO из ISR это можно охарактеризовать как странность восприятия мира но "докладка" в процессе передачи - вполне обыденное действие. К примеру на RTOS: задача utx_task принимает от других задач task0, taskN то что нужно передать. тогда есть два варианта разруливания: #1 utx_task заполняет FIFO и размещает в глобальной переменной ptr и len чего еще не успело передать и ожидает события завершения ВСЕЙ передачи в прерывании после опустошения FIFO передачи проверяется len и если != 0 то в ISR досылаем в FIFO иначе выставляем признак события чтобы разбудить utx_task задачу для повторения всех циклов #2 utx_task заполняет FIFO и ожидает события завершения передачи FIFO в прерывании после опустошения FIFO выставляем признак события чтобы разбудить utx_task задачу для повторения заполнения FIFO и так по кругу вроде одинаковый результат, но сдается мне что во втором случае будет чаще дергатся шедуллер Цитата(Terminator @ Sep 28 2013, 08:52)  это всё конечно красиво, но попробуйте сделать вывод в отладочный порт из разных задач. Останавливать задачу ради вывода отладки нельзя, что влезло в буфер, то влезло. Заводить отдельную задачу для слежения за заполненостью буфера, очень не хочется. Запрещать прерывания перед каждым обращением в uart тоже (тут я конечно несколько лукавлю, т.к. при складывании в буфер прерывания всё равно запрещаются). тут только отдельная задача, которая: 1. для синхронной отправки ( блокирующая задача ) - выставляет семафор/событие для блокировки текущей задачи 2. для ассинхронной отправки ( неблокирующая задача ) отправка буфера из кучи - сохраняет в своей очереди ptr и len что передать, и по завершению FREE 3. для ассинхронной отправки ( неблокирующая задача ) отправка из стека - свой MALLOC и MEMCPY и предыдущий вариант 2 4. для ассинхронной отправки ( неблокирующая задача ) отправка из const и CODEMEM/FLASH - вариант 2 без FREE
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
|
Sep 30 2013, 20:39
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
По поводу докладывания FIFO 16-тью элементами. Цитата из UM10360 (LPC17xx user manual) Цитата 4.14 UARTn FIFO Level register (U0FIFOLVL - 0x4000 C058, U2FIFOLVL - 0x4009 8058, U3FIFOLVL - 0x4009 C058)
UnFIFOLVL register is a read-only register that allows software to read the current FIFO level status. Both the transmit and receive FIFO levels are present in this register. Так что можно докладывать не заходя в прерывание. Точнее, не дожидаясь полного освобождения Tx FIFO. Жаль, во многих других процах нет этого регистра.
Сообщение отредактировал GetSmart - Sep 30 2013, 20:43
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 1 2013, 03:09
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Terminator @ Sep 30 2013, 16:34)  Отправка выглядела примерно так: уарт не занят, разрешаем прерывание tx_empty, пихаем в фифо первый(или заполняем всё fifo) байт посылки, остальное в очередь которую проверит isr. Если уарт занят, то пихаем всё в очередь. В моём случае заморочка была в том что прерывание tx_empty бывало, что не срабатывало. Что-то вы криво делали - у меня стабильно работает всегда. Например - после разрешения tx_empty и перед пиханием в буфер, вы не забывали запрещать прерывания?  К тому же - по вашему алгоритму придётся запрет прерывания продлить до конца пихания в очередь всех данных. Логичнее делать по-другому: В задаче пишем всё в очередь (с разрешёнными прерываниями). После писания - проверим разрешено-ли прерывание UART (ну или программного флага, если в ISR не запрещаем IRQ TX_EMPTY при опустошении, а просто игнорим его), если запрещено - запрещаем прерывания CPU, вызываем функцию переписывающую из очереди в TX FIFO (эту же функцию вызываем из ISR при TX_EMPTY). Внутри этой функции, если в очереди имеется хотя-бы один байт - она разрешает прерывания TX_EMPTY (ставит программный флаг), заполняет FIFO из очереди. Если на входе в функцию очередь пуста, она запрещает TX_EMPTY (сбрасывает программный флаг). Если всё реализуете аккуратно, в том числе очередь - реерентерабельную для перекрывающихся чтений/записей, то всё будет работать как часы.
|
|
|
|
|
Oct 1 2013, 10:02
|
Участник

Группа: Свой
Сообщений: 69
Регистрация: 22-10-04
Пользователь №: 956

|
Цитата(GetSmart @ Oct 1 2013, 00:39)  По поводу докладывания FIFO 16-тью элементами. Цитата из UM10360 (LPC17xx user manual)
Так что можно докладывать не заходя в прерывание. Точнее, не дожидаясь полного освобождения Tx FIFO.
Жаль, во многих других процах нет этого регистра. UM10360, rev2, 20100819 Modifications: • UART0/1/2/3: FIFOLVL register removed.
|
|
|
|
|
Jan 30 2015, 10:08
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(Golikov A. @ Jan 30 2015, 14:46)  отсутствием FIFO, например.... тем что нельзя пихнуть 16 байт и делать свои дела пока их выдавливает, а надо постоянно отвлекаться и по байту класть. А если у вас ModBus с условием определения конца по паузе между байтами посылки? Да, но так ли это заметно, если процессор работает на частоте под 100 MГц. Ему переложить из регистра в регистр что из fifo, что вручную велика ли разница?
|
|
|
|
|
Jan 30 2015, 12:08
|

Профессионал
    
Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143

|
Цитата(jcxz @ Sep 24 2013, 20:19)  Нет. Там эмуляция стандартного, не самого удачного 16550. хотел высказаться об еще одном неудачном месте в LPC: MultimediaCardIntarface есть три регистра MCI-CLOCK MCI-DATACTRL MCI-COMMAND После записи в которые надо Note: After a data write, data cannot be written to this register for three MCLK clock periods plus two PCLK clock periods.конечно не сложно это сделать, но не нравятся три фактора 1. на этапе иннициализации частота MCLK 200кГц а потом уже и 10МГц может быть, так что эту времянку нужно в рантайме менять 2. PCLK тоже они проекта к проекту может быть разный 3. ладно, записал, подождал указанное время, потом снова записал. Но от предыдущей записи до новой выполнялись же такты, и можно было бы и по меньше ждать времянку. Но не таймер же заводить для этого. Как мне видится аппаратное решение: три бита занятости, clock_busy, datactrl_busy, command_busy перед записью ждешь просто готовность соответствующего бита, и вот она программная независимость от аппаратных заморочек. Ляпота может донести эту мысль инженерам NXP на их форуме ? Но с английским туго. P.S. а как вы красиво решали ожидание на LPC ? P.P.S на других платформах есть такая заморочка с MCI ?
--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|