|
|
  |
LPC2148 UART: Постоянный вызов прерывания CTI |
|
|
|
Sep 2 2008, 07:43
|
Местный
  
Группа: Свой
Сообщений: 204
Регистрация: 5-01-06
Пользователь №: 12 860

|
Иногда UART переходит в такое состояние, что вызывается прерывание CTI (U1IIR=0b11001100). Если в обработчике прочитать U1LSR, то там хранится значение 0x60, т.е. младший бит (RDR)=0, якобы в FIFO данных нет. Если не прочитать U1RBR, прерывание вызовется снова. Получется, фрагмент обработчика должен быть такого вида: Код case IIR_CTI: for(;;) { temp = rU1LSR;
data=rU1RBR; // изначально чтение U1RBR было ниже
// Если данных нет (RDR=0), выходим if ((temp&0x11)==0) break;
//data=rU1RBR; // <- здесь
// Если ошибка, продолжаем цикл без обработки принятых данных if (temp&(7<<2)) // PE,FE,BI continue; tn_my_queue_isend_polling(&queue,data); } Странно, что в ERRATA про это ни слова, на форумах тоже
|
|
|
|
|
Sep 2 2008, 08:46
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Странно... у меня вполне работает Код case U0IIR_INT_ID_RX_TIMEOUT: // прерывание по отсутствию данных case U0IIR_INT_ID_RDA: // прерывание по приему
while(U0LSR & U0LSR_RDR) { uchar uc = U0RBR; ... } break; А что в начале/конце обработчика прерывания (главный switch как выглядит)? И не пользуетесь ли отладчиком для просмотра регистров проца в(от) которых сбрасываются флаги по чтению (тот же UхRBR)? О! кстати! Видимо вместо Код if ((temp&0x11)==0) надо Код if (!(temp&0x03)) а то и Код if (!(temp&0x01)) ???
|
|
|
|
|
Sep 2 2008, 09:21
|
Местный
  
Группа: Свой
Сообщений: 204
Регистрация: 5-01-06
Пользователь №: 12 860

|
Цитата(Alex03 @ Sep 2 2008, 14:46)  Странно... у меня вполне работает Код case U0IIR_INT_ID_RX_TIMEOUT: // прерывание по отсутствию данных case U0IIR_INT_ID_RDA: // прерывание по приему
while(U0LSR & U0LSR_RDR) { uchar uc = U0RBR; ... } break; Сначала у меня стояла такая же проверка как у Вас. Потом обнаружилось, что иногда бывает включен бит Break interrupt, а RDR - нет. И нужно считать U1RBR, иначе обработчик постоянно вызывается. Цитата(Alex03 @ Sep 2 2008, 14:46)  А что в начале/конце обработчика прерывания (главный switch как выглядит)? И не пользуетесь ли отладчиком для просмотра регистров проца в(от) которых сбрасываются флаги по чтению (тот же UхRBR)? Код void tn_uart1_int_func(void) { volatile char temp; char data; int i; int rc; temp=rU1IIR; switch((temp>>1)&0x7) //-- and clear int source {
....
}
VICVectAddr = 0xFF; } В отладчике окно с регистрами закрыто. Обычно такой глюк происходит при отладке при перезапуске программы. Помогает только выключение питания. Код инициализации (со сбросом FIFO). Может, проблема именно в сбросе FIFO при старте? Попробую это отключить Код //---- pinout ----- rPINSEL0.....
...
//-- enable access to divisor latch regs rU1LCR = LCR_ENABLE_LATCH_ACCESS; //-- set divisor for desired baud rU1DLM = 0; rU1DLL = 32; // 32; // (60'000'000)/(16*115200) = 32
//-- disable access to divisor latch regs (enable access to xmit/rcv fifos //-- and int enable regs) rU1LCR = LCR_DISABLE_LATCH_ACCESS;
//-- Enable UART1 rx interrupts rU1IER = 0x0F; //-- Enable int //-- setup line control reg - disable break transmittion, even parity, //-- 1 stop bit, 8 bit chars rU1LCR = 0x03; // нет четности rU1FCR = (0x03<<6) | 7; //-- Int Trigger - 14 bytes, Enable FIFO,Reset Tx FIFO & Rx FIFO
// DTR не используется // AutoCTS=1, AutoRTS=1 rU1MCR = (3<<6)|3;
|
|
|
|
|
Sep 2 2008, 11:07
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Цитата(ivstech @ Sep 2 2008, 15:21)  Сначала у меня стояла такая же проверка как у Вас. Потом обнаружилось, что иногда бывает включен бит Break interrupt, а RDR - нет. И нужно считать U1RBR, иначе обработчик постоянно вызывается. Приведите тогда код всего обработчика прерываний... Break interrupt, а также OE/PE/FE - это другой тип прерывания, и проверять их надо не в CTI а в RLS. И читать при Break interrupt надо не U1RBR а U1LSR У меня обработчик начинается так: Код uint register nIIR; while( ((nIIR = U0IIR) & U0IIR_INT_PENDING) == 0 ) { switch(nIIR & U0IIR_INT_ID_MASK) { case U0IIR_INT_ID_RLS: // прерывание по ошибке U0LSR; ... break;
|
|
|
|
|
Sep 2 2008, 11:32
|

Местный
  
Группа: Участник
Сообщений: 219
Регистрация: 20-11-07
Пользователь №: 32 484

|
Цитата(Alex03 @ Sep 2 2008, 15:07)  И читать при Break interrupt надо не U1RBR а U1LSR Мануал: Note: A parity error is associated with the character at the top of the UART1 RBR FIFO. То есть, при возникновении RLS, читать LSR, чтобы определить, какая ошибка и RBR - что принялось с ошибкой. В случае OE - RBR читать не надо (доставать нормальные байты, имхо, следует только в RDA и CIT).
|
|
|
|
|
Sep 2 2008, 11:38
|
Местный
  
Группа: Свой
Сообщений: 204
Регистрация: 5-01-06
Пользователь №: 12 860

|
Не помню, откуда я взял пример обработчика изначально, из IARa или tn_kernel. Затем ввел переменную temp, чтобы можно было посмотреть содержимое U1IIR. Бит PENDING я не проверяю, т.к. прерывание вызвалось. Код void tn_uart1_int_func(void) { volatile char temp; char data; int i; int rc; temp=rU1IIR; switch((temp>>1)&0x7) //-- and clear int source { case IIR_THRE: // continue sending data for (i=0; i<16; i++) { rc = tn_my_queue_ireceive(&queueTX,&data); if(rc != TERR_NO_ERR) { if (i==0) // нет данных на передачу tn_sem_isignal(&semTx1UDRE);
// ^^^ передача 1-го байта после остановки осуществляется из основной программы
// (т.к. прерывание THRE вызывается однократно) break; } rU1THR=data;
} break; case IIR_RLS: // error manage case IIR_RDA: // receive data case IIR_CTI: // time out for(;;) { temp = rU1LSR; // Если данных нет (RDR=0), выходим if ((temp&0x01)==0) break;
// Читаем с вершины FIFO data=rU1RBR; // Если ошибка, продолжаем цикл без обработки принятых данных if (temp&(7<<2)) // PE,FE,BI continue; tn_my_queue_isend_polling(&queueRX,data); } break; case IIR_MODEM_STATUS: // Прерывание CTS or DSR or RI or DCD // CTS автоматический // DSR не используется temp=rU1MSR; // Проверяем только RI и DCD (заглушки) if (temp&(1<<6)); // Звонок if (temp&(1<<7)); // Связи нет
}
VICVectAddr = 0xFF; } Основное подозрение у меня сейчас на инициализацию со сбросом FIFO. Т.к. значение U1LSR привязано к значению на вершине RX FIFO, похоже, при очистке FIFO U1LSR не сбрасывается как при чтении U1RBR
|
|
|
|
|
Sep 2 2008, 11:57
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Лучше разделить Код case IIR_RLS: // error manage temp = rU1LSR; if (temp&(7<<2)) // PE,FE,BI { data=rU1RBR; ... } ... break; case IIR_RDA: // receive data case IIR_CTI: // time out for(;;) { temp = rU1LSR; // Если данных нет (RDR=0), выходим if ((temp&0x01)==0) break;
// Читаем с вершины FIFO data=rU1RBR; tn_my_queue_isend_polling(&queueRX,data); } break; meister Согласен. У меня любая ошибка - это ошибка и далее соответствующие действия не зависимо от типа ошибки. Правда отдельно тикают счётчики разных ошибок, прерываний, принятых/переданных байт и т.д.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|