|
LPC2124 проблема с прерыванием на UART THRE |
|
|
|
Feb 21 2007, 14:51
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
При включении прерывания U0IER_bit.THREIE = 1 не происходит прерывание при этом в U0LSR бит THRE и TEMT установлины. Происходит только после того как что то запишеш в U0THR. Я уже замучялся... Код инициализации: Код ubuff = &u0buff; ubuff->tx_buff = u0_buff_tx; ubuff->rx_buff = u0_buff_rx; ubuff->tx_buff_size = sizeof(u0_buff_tx); ubuff->rx_buff_size = sizeof(u0_buff_rx); PCONP_bit.PCURT0 = 1; //UART power on PINSEL0_bit.P0_0 = 1;//select pin for UART0 PINSEL0_bit.P0_1 = 1; U0FCR = 0xC1; uart_bautrate(UART0,32); U0LCR = 0x03; //1-8-N INT_Plug(UART0_ISR,VIC_UART0,IRQ_int,IRQ_Slot0); VIC_IntEnable(BIT(VIC_UART0)); U0IER_bit.RDAIE = 1; U0IER_bit.RXLSIE = 1; код функции передачи Код int uart_send_str(TUartChanel dev, const char* data) { TUART_BUFF* ubuff; int len,fsize,head,i; unsigned long old_irq; char *ptr; ubuff = &u0buff; fsize = 0; len = strlen(data); ptr = (char*)data; do { do fsize = uart_tx_free(dev); while(fsize == 0); if (fsize > len) fsize = len; head = ubuff->tx_head; for (i=0;i<fsize;i++) { ubuff->tx_buff[head] = *ptr++; if(++head == ubuff->tx_buff_size) head = 0; } ubuff->tx_head = head; old_irq = disable_IRQ(); ubuff->tx_size = ubuff->tx_size+i; restore_IRQ(old_irq); U0IER_bit.THREIE = 1; //<= включаем прерывание и оно не происходит len = len - fsize; } while((*ptr!='\0')&&(len > 0)); return(0); }; код main Код //U0THR = 0x00; //<- если включить эту строку UART начинает генерить прерывания while(1) { uart_send_str(UART0,"HELLO WORD"); } Код обработчика: Код void UART0_ISR (void) { unsigned int tmp; TUART_BUFF* ubuff = &u0buff; switch((U0IIR>>1)&0x7) { case IIR_THRE: // continue sending data if (ubuff->tx_size == 0)U0IER_bit.THREIE = 0; else { U0THR = ubuff->tx_buff[ubuff->tx_tail]; ubuff->tx_size--; if (++ubuff->tx_tail == ubuff->tx_buff_size) ubuff->tx_tail = 0; } break; case IIR_RSL: tmp = U0LSR; ubuff->last_error |= tmp & 0x9E; break; case IIR_RDA: // receive data case IIR_CTI: // time out tmp = U0RBR; if (ubuff->eho_state == ON) { while(!U0LSR_bit.THRE); U0THR = tmp; }; if ((tmp == 0x0D) || (tmp == 0x0A)) ubuff->str_flag = 1; if (ubuff->rx_size == (ubuff->rx_buff_size-1)) { ubuff->last_error |= RC_FIFO_OVERRUN_ERR; } else { ubuff->rx_buff[ubuff->rx_head] = tmp; ubuff->rx_size++; if (++ubuff->rx_head == ubuff->rx_buff_size) ubuff->rx_head = 0; } break; }//switch } //isr
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 25)
|
Feb 21 2007, 15:13
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(MALLOY2 @ Feb 21 2007, 13:51)  При включении прерывания U0IER_bit.THREIE = 1 не происходит прерывание при этом в U0LSR бит THRE и TEMT установлины. Происходит только после того как что то запишеш в U0THR. Я уже замучялся... (разводя руками) Ну вот построен он так. Я тоже огорчен. В параллельной ветке выложил свои исходники с использованием FIFO. В простейшем же случае при входе в функцию отсылки проверяю, взведен ли THREIE и если не взведен - взвожу и кидаю байт сразу в THR, если взведен - складирую в буфер а по прерыванию забираю из буфера и если буфер пуст - сбрасываю THREIE.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 21 2007, 15:56
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(MALLOY2 @ Feb 21 2007, 14:43)  а что их привело к такому кривому решению ? 16550Причем признаки "цельнотянутости" есть в user manual: Цитата 7:6 Rx Trigger Level Select 00: trigger level 0 (default=1 character or 0x01h) 01: trigger level 1 (default=4 characters or 0x04h) 10: trigger level 2 (default=8 characters or 0x08h) 11: trigger level 3 (default=14 characters or 0x0eh) These two bits determine how many receiver UART0 FIFO characters must be written before an interrupt is activated. The four trigger levels are defined by the user at compilation allowing the user to tune the trigger levels to the FIFO depths chosen.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 21 2007, 16:19
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата 7:6 Rx Trigger Level Select 00: trigger level 0 (default=1 character or 0x01h) 01: trigger level 1 (default=4 characters or 0x04h) 10: trigger level 2 (default=8 characters or 0x08h) 11: trigger level 3 (default=14 characters or 0x0eh) These two bits determine how many receiver UART0 FIFO characters must be written before an interrupt is activated. The four trigger levels are defined by the user at compilation allowing the user to tune the trigger levels to the FIFO depths chosen. а это к чему ? речь идет о передатчике.
|
|
|
|
|
Feb 21 2007, 17:19
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Цитата(MALLOY2 @ Feb 21 2007, 17:43)  Вот кривизна, одно растройство, придется драйвер переписывать  , а что их привело к такому кривому решению ? К какому кривому? Мой примерный перевод (ускоренным ПРОМПТом) Цитата UART0 THRE прерывание (U0IIR [3:1] = 001) - прерывание третьего уровня (приоритета), оно активизируется когда UART0 THR FIFO пуст и выполнены определенные условия. Эти условия предназначены, чтобы дать UART0 THR FIFO шанс заполниться данными, чтобы устранить много прерываний THRE при запуске передачи. Прерываний THRE имеет задержку на один символ минус СТОП-бит всякий раз, когда THRE=1 и не было по крайней мере двух символов в U0THR единовременно начиная с последнего THRE = 1 события. Эта задержка создана, чтобы дать время ЦПУ на запись данных в U0THR без прерывания THRE. Прерывание THRE активизируется немедленно, если UART0 THR FIFO содержал как минимум два символа единовременно, а в настоящее время U0THR пуст. Если плюёте пачками (в идеале по 16 байт) то прерывание когда очередь пуста, но ещё передаётся последний байт. Т.е. можно ещё 16 байт в ФИФО загонять. Если шлёте по одному байту то прерывание когда передаётся стоповый бит. Вот отсутствие прерывания по TEMP многие кто реализовывал 485 считают более существенным недостатком. Но... Во времена создания 16550 считали каждый транзистор в чипе.
|
|
|
|
|
Feb 21 2007, 17:30
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Цитата(Alex03 @ Feb 21 2007, 19:19)  Если шлёте по одному байту то прерывание когда передаётся стоповый бит.
Вот отсутствие прерывания по TEMP многие кто реализовывал 485 считают более существенным недостатком. Написал и подумал... А ведь это возможное решение. Т.е. при передаче песледний символ отправлять всегда отдельно. Тогда прерывание будет уже во время передачи СТОП-бита, который единичный. Конечно нехорошо в это время выключать передатчик 485, но в ряде случаев видимо получим приемлимый вариант? Подождать тем же полингом один бит всегда дешевле чем весь символ. Или например физический интерфейс типа к-лайна в авто, там оно видимо покатит. Ктонить пробовал? Раньше я про посимвольную передачу чтото и не думал, ФИФО по максимуму.
|
|
|
|
|
Feb 21 2007, 17:41
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата К какому кривому? Мой примерный перевод (ускоренным ПРОМПТом)
UART0 THRE прерывание (U0IIR [3:1] = 001) - прерывание третьего уровня (приоритета), оно активизируется когда UART0 THR FIFO пуст и выполнены определенные условия. Эти условия предназначены, чтобы дать UART0 THR FIFO шанс заполниться данными, чтобы устранить много прерываний THRE при запуске передачи. Прерываний THRE имеет задержку на один символ минус СТОП-бит всякий раз, когда THRE=1 и не было по крайней мере двух символов в U0THR единовременно начиная с последнего THRE = 1 события. Эта задержка создана, чтобы дать время ЦПУ на запись данных в U0THR без прерывания THRE. Прерывание THRE активизируется немедленно, если UART0 THR FIFO содержал как минимум два символа единовременно, а в настоящее время U0THR пуст. кривизна в том, что при пустом передатчике и включении прерываний THRE прерывание не возникает пока не запишешь в THR хотя бы 1 символ. Не знаю откуда там они что сдирали или делали но у меня лежит плата с ST16C1550 и все он генерирует при включении прерывания.
|
|
|
|
|
Feb 21 2007, 18:25
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(MALLOY2 @ Feb 21 2007, 16:41)  но у меня лежит плата с ST16C1550 и все он генерирует при включении прерывания. Вот именно он и "кривой", если так поступает. У прародителя прерывание генерится при передаче стопового бита. Кроме того наличие "ложного" прерывания ничего не решает - ну разрешили прерывание, ну получили стартовый пинок. Ну а потом пауза в передаче и ..... кто пинок делать будет? 'Проблема' отсутствия прерывания при его первом разрешении просто высосана из пальца. Цитата(Alex03 @ Feb 21 2007, 16:30)  Раньше я про посимвольную передачу чтото и не думал, ФИФО по максимуму.  Так отключите FIFO и посимвольно с полным контролем над передачей.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 21 2007, 18:38
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата Ну а потом пауза в передаче и ..... кто пинок делать будет? 'Проблема' отсутствия прерывания при его первом разрешении просто высосана из пальца. Это как раз и проблема, так я в процедуре отправки скопировал в буфе включил прерывание и он пошел колбасится, а тут еще и пинать надо  , так что это проблема не первого включения а проблема связана с тем что когда нечего передавать надо выключить прерывание, а когда надо что то передать приходится пинки раздавать разве это работа ?
|
|
|
|
|
Feb 21 2007, 20:36
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(MALLOY2 @ Feb 21 2007, 17:38)  Это как раз и проблема Мне бы всегда такие "проблемы". В "идеальном" с Вашей точки зрения железе дергать разрешение прерывания когда есть/нет чего передавать (разбираясь перед этим есть или нет чего)это типа "прямо" и правильно  . А глянуть на один флаг в момент начала передачи порции это "разве это работа". Это гипотетический "идеальный" описанный Вами алгоритм. Код void print_zzz( char *string ) { //"я в процедуре отправки скопировал в буфер" while( *string ) { tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++; tbuf.tail++; } //"включил прерывание" U0IER |= IER_THREIE;
//"и он пошел колбасится" } После того, как отколбасился еще некая процедура должна по каим-то признакам запретить прерывание Это "НЕПРАВИЛЬНЫЙ" Код void print_zzz( char *string ) { U0THR = *string++; while( *string ) { tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++; tbuf.tail++; } } Ну и где "проблема"???
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 21 2007, 22:22
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(zltigo @ Feb 21 2007, 19:36)  После того, как отколбасился еще некая процедура должна по каим-то признакам запретить прерывание само прерывание - если из буфера извлечен последний символ. Цитата(zltigo @ Feb 21 2007, 19:36)  Это "НЕПРАВИЛЬНЫЙ" Код void print_zzz( char *string ) { U0THR = *string++; while( *string ) { tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++; tbuf.tail++; } } Ну и где "проблема"??? print_zzz("Tipa "); print_zzz("test"); В результате "Tt" попало в FIFO а "ipa est" в буфер. Неувязка.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 21 2007, 22:40
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Сергей Борщ @ Feb 21 2007, 21:22)  Неувязка. Читаем внимательно - приводился текст ТОЧНО по предложенному возмущающимся заданию. В задании НЕ ПРЕДУСМОТРЕН вариант, когда вызов функции запонения буфера производится до его опустошения. Какие проблемы? В противном случае - заводится флаг и реальная функция у меня выглядит так: Код void print_str( char *string ) { if( !(status_word & STW_THR_BUSY) ) { status_word |= STW_THR_BUSY; U0THR = *string++; } while( *string ) { tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++; tbuf.tail++; } } Цитата(Сергей Борщ @ Feb 21 2007, 21:22)  само прерывание - если из буфера извлечен последний символ. Само - нет. Для "хорошего" UART придется еще написать: U0ICR |= IER_THREIE; Для "плохого" - ничего лишнего.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 22 2007, 01:08
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата В "идеальном" с Вашей точки зрения железе дергать разрешение прерывания когда есть/нет чего передавать (разбираясь перед этим есть или нет чего)это типа "прямо" и правильно . А глянуть на один флаг в момент начала передачи порции это "разве это работа". ну насчет правильно неправильно тут я судить не буду но код U0IER |= IER_THREIE; куда быстрее выполняется чем код if( !(status_word & STW_THR_BUSY) ) { status_word |= STW_THR_BUSY; U0THR = *string++; } и места меньше потребляет и линейный полностью и конвейер проца не сбрасывает (зависит от компилятора). И флагов дополнительных не надо, одни минусы, так вчем прикол ? я реализовал обмен через разрешение прерываний во многих процах(ATMEGA, ST16C1550+8051, TMS320VC5502 ... ) и намой взгляд это наиболее быстрый и экономический вариант если проц без ДМА, и нигде небыло проблем. Цитата (MALLOY2 @ Feb 21 2007, 16:41)
но у меня лежит плата с ST16C1550 и все он генерирует при включении прерывания.
Вот именно он и "кривой", если так поступает. Он оптимизированный  , просто тогда об этом недогадывались наверное ....
|
|
|
|
|
Feb 22 2007, 01:51
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(MALLOY2 @ Feb 22 2007, 00:08)  но код
U0IER |= IER_THREIE;
куда быстрее выполняется чем код if( !(status_word & STW_THR_BUSY) ) { status_word |= STW_THR_BUSY; U0THR = *string++; } Ну раз речь пошла о быстродействии  1.Знаете сколько наносекунд выполняется у LPC обращение к периферии? Cоветую поинтересоваться на досуге. 2.Приведенная Вам строка совершенно не заменяет приведенный мною код. В своем варианте Вы кроме разрешения прерывания сделаете - лишнее занесение первого байта в буфер в функции передачи - лишнее извлечение первого байта из буфера в обработчике (все это естественно работа с байтами и возня с указателями) - ну и само собой еще одно обращение в обработчике к медленной периферии для запрещения прерывания. Вместо всех этих телодвижений - анализ/сброс бита и прямое без промежуточной буферизации занесение в THR. Цитата и места меньше потребляет Да. Сколько там FLASH у LPC2124 не напомните? Сколько написали кода? Цитата и линейный полностью и конвейер проца не сбрасывает (зависит от компилятора). И флагов дополнительных не надо один бит  в слове где используется дюжина флагов из 32. Кроме того можете работать и по железному флагу TEMT - выиграите 5-6 команд (в сумме с обработчиком прерывния). Цитата одни минусы, так вчем прикол ? Прикол в том, что в Ваших рассуждениях ошибка на ошибке  Цитата я реализовал обмен через разрешение прерываний во многих процах( Ну и что? Из этого следует что всегда и везде надо поступать по этому шаблону? Цитата и нигде небыло проблем. Их нет и в LPC, если чуть-чуть подумать.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 22 2007, 08:38
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Цитата(zltigo @ Feb 21 2007, 20:25)  Цитата(Alex03 @ Feb 21 2007, 16:30)  Раньше я про посимвольную передачу чтото и не думал, ФИФО по максимуму.  Так отключите FIFO и посимвольно с полным контролем над передачей. ИМХО отключение FIFO насовсем не есть гут (накладных расходов на кучу прерываний может быть больше чем выйгрыш, да и шансов создания нежелательных пауз между передаваемыми словами побольше).  А вот отправка последнего символа отдельно от всего пакета, тут можно подумать. Меня и заинтересовало - пользовался ли кто этим для 485 в частности? Ну а применительно к топикосоздателю: Накой все эти игры с разрешениями/запретами прерываний? У меня все нужные прерывания включенны всегда, ну а происходят они тогда когда надо, если это не так, то порой можно отловить глюки, которых иначе не поймать было бы.
|
|
|
|
|
Feb 22 2007, 10:44
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Цитата(zltigo @ Feb 22 2007, 11:22)  Цитата(Alex03 @ Feb 22 2007, 07:38)  ИМХО отключение FIFO насовсем не есть гут (накладных расходов на кучу прерываний может быть больше чем выйгрыш,
Дело не в проигрыше/выигрыше а _необходимости_ выполнить какие-либо действия после передачи, например, байта. Если физический протокол так спроектировал кто-то, то это перечеркивает использование FIFO. Угу. А реализовать эту _необходимость_ можно всякими способами. Вот тут и рассматриваются варианты с плюсами/минусами пройгрышами/выйгрышами. Ну да ладно, думаю мы друг-друга поняли.
|
|
|
|
|
Feb 22 2007, 12:18
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата и нигде небыло проблем.
Их нет и в LPC, если чуть-чуть подумать. да нет никаких проблем в работе, броблема в том что надо переписывать драйвер под этот проц что даже не планировалось. по поводу времени выполнения тут спорный момент. тест 1 Код IO1SET = (1<<16); U0IER_bit.THREIE = 1; IO1CLR = (1<<16); врямя замеряю осцилом ~387нс тест 2 Код volatile unsigned char status_word; //<= volatile т.к. изменяется в прерываниии
IO1SET = (1<<16); status_word |= 1<<0; IO1CLR = (1<<16); врямя замеряю осцилом ~218нс а у вас 2 вызова идет это примено 218*2 что больше 387 Вывод: бесполезный спор который никому не нужен, на этом тему лучше закрыть.
|
|
|
|
|
Feb 22 2007, 12:44
|
Частый гость
 
Группа: Свой
Сообщений: 169
Регистрация: 10-11-05
Из: Воронеж
Пользователь №: 10 687

|
Цитата(MALLOY2 @ Feb 22 2007, 12:18)  врямя замеряю осцилом ~218нс
а у вас 2 вызова идет это примено 218*2 что больше 387
Вывод: бесполезный спор который никому не нужен, на этом тему лучше закрыть. Вы говорите о двух принципиально разных подходах в реализации железа UART. AVR и LPC имеют разные реализации и управлять ими придется по-разному. Для LPC, имхо, zltigo показал более правильный способ. У Вас в функции print, якобы, меньше действий, но в прерывании первый байт вычитывается из буфера и помещается в регистр для отправки. Об этом забываете??? И при чем тут время, затрачиваемое на установку или проверку флага занятости передатчика? Если он занят, а Вы хотите дождаться его освобождения, не все ли равно сколько нс будет затрачено на проверку занятости? Ведь времена проверки флага и передачи бита, который эту занятость вызвал, просто несоизмеримы. Цитата(MALLOY2 @ Feb 22 2007, 12:18)  тест 2 Код volatile unsigned char status_word; //<= volatile т.к. изменяется в прерываниии
IO1SET = (1<<16); status_word |= 1<<0; IO1CLR = (1<<16); тест неправильный. ARM - 32-битная архитектура, которой тяжело работать с байтами. zltigo говорил про 32 флага, а Вы char тестируете. Ради интереса сделайте тест с int и сравните полученный код
|
|
|
|
|
Feb 22 2007, 18:12
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(MALLOY2 @ Feb 22 2007, 11:18)  а у вас 2 вызова идет это примено 218*2 что больше 387 Вывод: бесполезный спор который никому не нужен, на этом тему лучше закрыть. Шлангом прикидываемся? Глупо  Цитата(MALLOY2 @ Feb 22 2007, 12:20)  а я очем !!! это и есть кривизна что он не такой как у других. Из того, что Вы использовали какое-то железо через заднепроходное отверстие, а другое железо, как вдруг оказалось, не "пролезает", не следует, что одно железо кривее другого.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Nov 29 2009, 15:42
|
Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 2-06-08
Из: Москва
Пользователь №: 38 003

|
Цитата(zltigo @ Feb 22 2007, 01:40)  .. реальная функция у меня выглядит так... Извините за тупизну и поднятие старой темы, у меня есть вопросы касающийся кода функци приведнной в сообщении zltigo. Как реализовано "выгребание" буфера tbuf.buf? В прерываниях? Как реализована установка флага STW_THR_BUSY? Интересует конечно не конкретный код а алгоритм. Достаточно долго пытаюсь понять предложенное решение но что-то мозжечка не хватает, если не трудно, поясните пожалуйста. Заранее спасибо.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|