|
LPC_UART (550-совместимый) |
|
|
|
Sep 16 2012, 22:02
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Вечер добрый. Пытаюсь посылать данные через UART, использую fifo. Непонятно как правильно это делать. Код extern "C" void UART_IRQ_Handler() { LedBlink(); }
volatile uint16_t index; const uint8_t TestStr[]="0123456789\n"; void main() { InitUART(); LPC_UART->IER=1<<LPC_UART_IER_THRE; NVIC_EnableIRQ(UART_IRQn); for (index=0; TestStr[index]; index++) LPC_UART->THR=TestStr[index]; while (1); } Поставил breakpoint в UART_IRQ_Handler, программа попала в него, когда данные уже пришли в терминал. Получается, что нужно в основной программе послать хотя бы один байт в THR, чтобы возникло прерывание по опустошению буфера передачи? Попытка записывать данные в THR и проверять состояние флага LSR.THRE приводит к тому, что посылается только 1 байт - буфер не пуст, если в нём есть хотя бы 1 байт. Получается нет нормальной индикации, того что есть ещё место в буфере? Нет ли у кого-нибудь примера передачи с использованием FIFO и прерываний? Спасибо.
|
|
|
|
|
 |
Ответов
|
Sep 17 2012, 15:10
|
Знающий
   
Группа: Свой
Сообщений: 549
Регистрация: 13-07-10
Из: Солнечногорск-7
Пользователь №: 58 414

|
Цитата(_Артём_ @ Sep 17 2012, 02:02)  Получается, что нужно в основной программе послать хотя бы один байт в THR, чтобы возникло прерывание по опустошению буфера передачи? По моему опыту выходит так, что запрос прерывания по наличию места в буфере передачи выдаётся не по самому факту наличия свободного места, а лишь по факту завершения передачи очередного байта из буфера. Таким образом, если разрешить прерывания при заведомо пустом буфере, прерывание так и не произойдёт -- передачи-то не было; однако, если разрешить прерывание и после этого пихнуть в буфер хотя бы один байт -- произойдёт, когда он будет передан (или когда будет переписан из буфера в сдвиговый регистр передатчика). Лично у меня впечатление, что изначальной причиной такого странного поведения послужила аппаратная ошибка, которую не заметили и растиражировали, а дальше тянут из-за совместимости. Ведь куда логичней, если прерывание по наличию места будет "висеть" постоянно, пока в буфере есть хотя бы один свободный байт и само это прерывание разрешено.
|
|
|
|
|
Sep 17 2012, 19:08
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(SII @ Sep 17 2012, 18:10)  По моему опыту выходит так, что запрос прерывания по наличию места в буфере передачи выдаётся не по самому факту наличия свободного места, а лишь по факту завершения передачи очередного байта из буфера. Похоже так, только не очередного, а последнего байта. И байт при этом уже передался в RS (программно можно RS485 делать). Цитата(SII @ Sep 17 2012, 18:10)  Таким образом, если разрешить прерывания при заведомо пустом буфере, прерывание так и не произойдёт -- передачи-то не было; Выглядит именно так. Цитата(SII @ Sep 17 2012, 18:10)  По моему опыту выходит так, что запрос прерывания по наличию места в буфере передачи выдаётся не Лично у меня впечатление, что изначальной причиной такого странного поведения послужила аппаратная ошибка, которую не заметили и растиражировали Может быть. Цитата(haker_fox @ Sep 17 2012, 18:56)  В AVR, например, так и сделано. Нужно что-то передать - подготовил буфер, разрешил прерывание "по пустому FIFO", и все. Буфер передался. А по завершению передачи последнего байта прерывание можно выключить... Не только в АВР так сделано, думаю. Но в общем работает, зато писать можно не байт как в АВР, а аж 16.
|
|
|
|
|
Sep 17 2012, 23:39
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (_Артём_ @ Sep 18 2012, 04:08)  Но в общем работает, зато писать можно не байт как в АВР, а аж 16. В AVR FIFO двухуровневый) Кстати, Вы так и делаете (я имею ввиду по прерыванию THRE сразу 16 байт отправляете)?  Работает?  Я пока машинально на каждый байт прерывание дергаю, на скорую руку писал обработчик) Обработчик в контексте scmRTOS, но думаю, не суть важно... CODE OS_INTERRUPT void uart0ISRHandler() { OS::TISRW ISRW; uint32_t iir;
// While there are pending interrupts while( !( ( iir = U0IIR ) & 1 ) ) { switch( ( iir >> 1 ) & 7UL ) { case 2: // Receive data available case 6: // CTI rx_isr_byte = U0RBR; getPacketEF.signal_isr(); break;
case 1: // THRE Interrupt U0THR = *pOutBuffer++; if( pOutBuffer == pEndBuffer ) { // Disable THRE Interrupt U0IER &= ~THRE_IE; pOutBuffer = outBuffer; sendFinishedEF.signal_isr(); } break; } }
IRQ_DONE(); } Но это, конечно, у меня не оптимальный вариант. Создавался как тестовый вариант разбора полетов с USART ISR...
--------------------
Выбор.
|
|
|
|
|
Sep 18 2012, 12:30
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(haker_fox @ Sep 18 2012, 02:39)  В AVR FIFO двухуровневый) Ну, это он двухуровневый, пока в него не пишешь долго, а потом всё равно в прерывании по одному байту пишешь. Цитата(haker_fox @ Sep 18 2012, 02:39)  Кстати, Вы так и делаете (я имею ввиду по прерыванию THRE сразу 16 байт отправляете)?  Работает?  Я пока машинально на каждый байт прерывание дергаю, на скорую руку писал обработчик) Работоспособность буфера сомнений не вызывает. Цитата(haker_fox @ Sep 18 2012, 02:39)  IRQ_DONE(); P.S. А это кто? IRQ_DONE в смысле. Цитата(Сергей Борщ @ Sep 18 2012, 10:05)  Да, использую FIFO. Но насколько все это можно было бы написать проще, если бы был флаг "FIFO не полное"... Спасибо за пример. Да уж, трёхэтажно получилось, а всего лишь бит незаполненности фифо зажали.
|
|
|
|
|
Sep 18 2012, 13:40
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (_Артём_ @ Sep 18 2012, 21:30)  P.S. А это кто? IRQ_DONE в смысле. А это VICVectAddr = 0 в данном случае. Просто инлайн-функция операционной системы. А отправка и прием организованы примерно так CODE void sendBuffer() { pEndBuffer = pOutBuffer; pOutBuffer = outBuffer;
U0THR = *pOutBuffer++; sendFinishedEF.clear(); // Enable THRE interrupt U0IER |= THRE_IE; sendFinishedEF.wait();
getPacketEF.clear(); }
bool wakePHYGet( uint8_t* byte ) { if( !getPacketEF.wait( FWAKE_ONE_BYTE_RX_TIMEOUT ) ) return false;
*byte = rx_isr_byte; return true; }
--------------------
Выбор.
|
|
|
|
|
Sep 18 2012, 14:35
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (_Артём_ @ Sep 18 2012, 22:50)  Оно на выходе каждого прерывания вызывается? Если так, то что бы его не запихнуть в ~TISRW? Да, на выходе каждого. Наверно можно. Это нужно у авторов операционной системы консультироваться) Поскольку у меня полудуплекс, и более, чем 16 байт за раз не передается, то сделал в прерывании совсем просто CODE case 1: // THRE Interrupt while( pOutBuffer < pEndBuffer ) U0THR = *pOutBuffer++;
// Disable THRE Interrupt U0IER &= ~THRE_IE; pOutBuffer = outBuffer; sendFinishedEF.signal_isr(); break; Вроде полет нормальный)
--------------------
Выбор.
|
|
|
|
|
Oct 21 2012, 18:31
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(pitt @ Oct 21 2012, 19:23)  ожидаю ту же проблему (прерывание по фронту, а не поуровню) с CAN  . Не знаю, как там с lpc17 с CAN, но с UART-ом проблема не в прерываниях, а в некотором неудобстве работы с ним из-за отсутствия флага, показывающего что FIFO не до конца заполнено. Это решается добавлением в программу пары десятков строк (ну может чуть больше). Цитата(pitt @ Oct 21 2012, 19:23)  Похоже это ТМ Phillips. Думаете у других производителей будет качественно лучше? Скажите тогда кто эти производители.
|
|
|
|
|
Oct 21 2012, 20:46
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(_Артём_ @ Oct 21 2012, 14:31)  Не знаю, как там с lpc17 с CAN, но с UART-ом проблема не в прерываниях, а в некотором неудобстве работы с ним из-за отсутствия флага, показывающего что FIFO не до конца заполнено. Это решается добавлением в программу пары десятков строк (ну может чуть больше).
Думаете у других производителей будет качественно лучше? Скажите тогда кто эти производители. Кроме как у Phillips прерывания по фронту для флага стстус-регистра ни у кого не встречал. Если приложению надо мютекс с обработчиком прерывания, прерывание по фронту ликвидирует возмоцность маскирования и требует более сложных и вязких методов. Мне в корне непонятна сама идея такого прерывания. Подчеркиваю, не внешнего, а именно для флага стстус-регистра. Проблему с FIFO я решил достаточно просто: обработчик из HAL, освободив FIFO перезагружает его до завершения сообщения, а если и оно завершено, находит следующее ожидающее своей очереди, а если и очередь пустая, то упираюсь в проблему как инициировать прерывание из приложения, которой бы не было если бы не прерывание по фронту...
--------------------
|
|
|
|
|
Oct 21 2012, 21:21
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(pitt @ Oct 21 2012, 23:46)  Кроме как у Phillips прерывания по фронту для флага стстус-регистра ни у кого не встречал. Возможно есть у кого-нибудь, кто сделал совместимый с 550 UART. А может и нет. Цитата(pitt @ Oct 21 2012, 23:46)  Мне в корне непонятна сама идея такого прерывания. Подчеркиваю, не внешнего, а именно для флага стстус-регистра. Несколькими сообщениями выше было высказано предположение, что это ошибка, ставшая стандартом. Цитата(pitt @ Oct 21 2012, 23:46)  Проблему с FIFO я решил достаточно просто: обработчик из HAL, освободив FIFO перезагружает его до завершения сообщения, а если и оно завершено, находит следующее ожидающее своей очереди, а если и очередь пустая, то упираюсь в проблему как инициировать прерывание из приложения, которой бы не было если бы не прерывание по фронту... Не буду утверждать ничего насчёт типа прерывания THRE, потому что нет под рукой платы с LPC - проверить не могу. Алгоритм проверки простой: Код InitUart(); __disable_irq(); LPC_UART->IER=0; LPC_UART->THR='1'; Delay1s(); LPC_UART->IER=(1<<LPC_UART_IER_THRE_EN); NVIC_EnableIRQ(UART_IRQn); __enable_irq(); THRE станет равным 1 когда буфер опустеет. Если прерывание не возникнет, значит оно по фронту. Почему-то кажется что возникнет...В любом случае никто не мешает разрешать прерывание по THRE перед посылкой байта.
|
|
|
|
|
Oct 21 2012, 21:57
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(pitt @ Oct 22 2012, 00:27)  мне не нужен тест, я уже убедился Мне нужен - я не убедился.  Спасибо, что указали мне на этот новый нюанс. Цитата(pitt @ Oct 22 2012, 00:27)  С CAN еще не убедился, но с большой уверенностью предполагаю. CAN и UART, как мне кажется имеют очень мало общего между собой - бессмысленно обобщать. Цитата(pitt @ Oct 22 2012, 00:27)  С прерываниями по фронту, прерывания маскировать нельзя вообще, Можно запрещать прерывания только UART-а. Цитата(pitt @ Oct 22 2012, 00:27)  а запрещать глобально очень дурная манера. Или понижать его приоритет. И мало ли ещё что можно придумать...
|
|
|
|
|
Oct 21 2012, 22:35
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(_Артём_ @ Oct 21 2012, 17:57)  Мне нужен - я не убедился.  Спасибо, что указали мне на этот новый нюанс. CAN и UART, как мне кажется имеют очень мало общего между собой - бессмысленно обобщать. Можно запрещать прерывания только UART-а. Или понижать его приоритет. И мало ли ещё что можно придумать... Общее между CAN и UART производитель и его концепт. Я работал с CAN IP для FPGA от Phillips и там столкнулся с их, простите, идиотским прерыванием по фронту...Когда сейчас тот же концепт от того же производителя в другом месте - это становится системой. Если доберусь(в смысле не переключимся на другой MCU) сообщу результат. Запрещать все прерывания опасно: в RTOS могут вытеснить, чтобы не приходится включать критическую секцию и прочиее прочее прочее и все из-за непонятно чего... Обидно.
--------------------
|
|
|
|
|
Oct 21 2012, 23:12
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(pitt @ Oct 22 2012, 01:35)  Общее между CAN и UART производитель и его концепт. Производитель - NXP, да. Но ядро от ARM, UART - чей-то стандарт (не от NXP). Цитата(pitt @ Oct 22 2012, 01:35)  Я работал с CAN IP для FPGA от Phillips и там столкнулся с их, простите, идиотским прерыванием по фронту...Когда сейчас тот же концепт от того же производителя в другом месте - это становится системой. Если доберусь(в смысле не переключимся на другой MCU) сообщу результат. Не знаю, кокой процент прерываний у NXP от edge, какой от level... пишут, что есть и те и другие. Цитата(pitt @ Oct 22 2012, 01:35)  Запрещать все прерывания опасно: Запрещайте не все прерывания, а только от UART (NVIC_DisableIRQ). Или скажите, что может не сработать?
|
|
|
|
|
Oct 21 2012, 23:24
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(_Артём_ @ Oct 21 2012, 19:12)  Производитель - NXP, да. Но ядро от ARM, UART - чей-то стандарт (не от NXP). Не знаю, кокой процент прерываний у NXP от edge, какой от level... пишут, что есть и те и другие. Запрещайте не все прерывания, а только от UART (NVIC_DisableIRQ). Или скажите, что может не сработать? Ядро ядром, а периферия у всех своя и в этом главная разница. Я в данном конкретном случае про UART. Я об'яснил почему запрещать прерывания в реальном времени очень плохо, даже если только UART: application task is preemptable, locking could cause priority inversion and as a result - data loss. Я в предыдущем посте писал по-русски, но видимо, непонятно.
--------------------
|
|
|
|
|
Oct 22 2012, 23:06
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(pitt @ Oct 22 2012, 02:24)  Я об'яснил почему запрещать прерывания в реальном времени очень плохо, даже если только UART: Да, в запрете прерываний ничего хорошего. Цитата(pitt @ Oct 22 2012, 02:24)  application task is preemptable, locking could cause priority inversion and as a result - data loss. То есть ни FIFO, на DMA (у вас LPC17, кажется) не спасают? А нельзя тогда не запрещать прерывания от UART?
|
|
|
|
Сообщений в этой теме
_Артём_ LPC_UART (550-совместимый) Sep 16 2012, 22:02 Сергей Борщ Ну вот такой этот УАСПП загадочный, хотя zltigo нр... Sep 17 2012, 06:12 haker_fox QUOTE (Сергей Борщ @ Sep 17 2012, 14:12) ... Sep 17 2012, 06:31  _Артём_ Спасиба за ссылки.
В первом приближении получился... Sep 17 2012, 14:42 haker_fox QUOTE (SII @ Sep 18 2012, 00:10) Ведь куд... Sep 17 2012, 15:56   Сергей Борщ Вот мои страх и ужас (которые, как известно, всего... Sep 18 2012, 07:05                 pitt Цитата(_Артём_ @ Oct 22 2012, 19:06) Да, ... Oct 22 2012, 23:36                  _Артём_ Цитата(pitt @ Oct 23 2012, 02:36) Артем, ... Oct 23 2012, 12:25                   pitt Цитата(_Артём_ @ Oct 23 2012, 08:25) Отве... Oct 24 2012, 00:35           _Артём_ Цитата(_Артём_ @ Oct 22 2012, 00:21) Алго... Oct 22 2012, 12:01
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|