|
|
  |
Регистр FCR UART0 не устанавливается должным образом, Не проходит инициализация |
|
|
|
Sep 11 2007, 14:30
|

Частый гость
 
Группа: Validating
Сообщений: 184
Регистрация: 26-06-07
Из: Санкт-Петербург
Пользователь №: 28 714

|
Есть инициализация UART0, в ней есть строка установки FCR, которая задает, кроме всего прочего, длину буфера FIFO, по которой соответственно будут происходить прерывания. Мне нужно установить порог на один байт. Но при пошаговой отладке видно, что в инициализации в RTLS записывается 0х3 (порог в 14байт). Я уже не знаю на что думать. Может контроллер дефектный или есть хитрости работы с FCR? Результат работы UARTa - срабатывание обработчика прерывания по последнему пришедшему символу или полное игнорирование входящих данных. Помогите, только не общими словами, а, если можно, подробнее.
Вот код:
void UARTInit( DWORD baudrate, DWORD IntrPriority ) { DWORD Fdiv; U0LCR = 0x80; Fdiv = ( Fpclk / 16 ) / baudrate ; U0DLM = Fdiv / 256; U0DLL = Fdiv % 256; U0LCR = 0x07; U0FCR = (1<<0) | (1<<1) | (1<<2); U0IER_bit.RDAIE = 1; VIC_SetVectoredIRQ(UART0Interrupt,IntrPriority,VIC_UART0); VICINTENABLE |= 1UL << VIC_UART0; PINSEL0 = 0x00000050; /* RxD0 and TxD0 */ }
Заранее благодарю за дельные советы.
|
|
|
|
|
Sep 11 2007, 14:46
|

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

|
Цитата(Цырен @ Sep 11 2007, 17:30)  Есть инициализация UART0.. Тип контролера, полагаете, несущественнен?  Цитата , в ней есть строка установки FCR, которая задает, кроме всего прочего, длину буфера FIFO, по которой соответственно будут происходить прерывания. Мне нужно установить порог на один байт. Так какого беса Вы тогда АКТИВИЗИРУЕТЕ FIFO??? Код U0FCR = (1<<0) | (1<<1) | (1<<2); -----------^^^^^ Цитата в RTLS И что это за буквы такие "RTLS"???
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Sep 11 2007, 14:48
|
Знающий
   
Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847

|
А на каком процессоре? Попробуйте по аналогии с этим. Код void uart_init(int port_num, int freq, int baudrate) { unsigned short divisor = freq / (baudrate * 16); /* Test for allowable ports */ if ((port_num < 0) || (port_num > 1)) return; /* Test for port is present */ UART[port_num]->SCR = 0x55; if (UART[port_num]->SCR != 0x55) return; UART[port_num]->SCR = 0xAA; if (UART[port_num]->SCR != 0xAA) return; UART[port_num]->SCR = 0; /* Select pin functions */ if (port_num == 0) { PINSEL0 = (PINSEL0 & 0xFFFFFFF0) | 0x5; } else { PINSEL0 = (PINSEL0 & 0xFFF0FFFF) | (0x5 << 16); } /* Disable interrupts */ UART[port_num]->IER = 0; /* Set Divisor for Baud Rate Generator */ UART[port_num]->LCR = 0x80; UART[port_num]->DLL = divisor & 0xFF; UART[port_num]->DLM = (divisor >> 8) & 0xFF; /* Set 8N1 mode */ UART[port_num]->LCR = 0x03; /* Setup Enable Tx & Rx FIFOs, Rx FIFO 8 byte trigger */ UART[port_num]->FCR = 0x06; UART[port_num]->FCR = 0x81; }
--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть. © Lewis Carroll. Alice's adventures in wonderland.
|
|
|
|
|
Sep 11 2007, 23:11
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(zltigo @ Sep 11 2007, 17:46)  Так какого беса Вы тогда АКТИВИЗИРУЕТЕ FIFO??? Чтоб TX fifo работало вестимо. Код // FCR (Fifo control register) bits description #define FCR_FIFO_EN 0 #define FCR_RX_FIFO_RESET 1 #define FCR_TX_FIFO_RESET 2 // RX trigger level bits 7:6 // 0 - trigger level 1 char // 1 - trigger level 4 chars // 2 - trigger level 8 chars // 3 - trigger level 14 chars #define FCR_RX_TRIGGER_LVL0 0x00 #define FCR_RX_TRIGGER_LVL1 0x40 #define FCR_RX_TRIGGER_LVL2 0x80 #define FCR_RX_TRIGGER_LVL3 0xC0 Афтар говорит о RX Trigger Level Select (RTLS) trigger level 0. Работать должно. Ошибка скорее всего в обработчике прерывания. 1. Надо обязательно прочитать UxIIR. 2. надо обязательно записать в конце обработчика прерывания VICVectAddr = 0; //Dummy write to signal end of interrupt
|
|
|
|
|
Sep 12 2007, 05:11
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Цитата(Цырен @ Sep 11 2007, 20:30)  Мне нужно установить порог на один байт. Но при пошаговой отладке видно, что в инициализации в RTLS записывается 0х3 (порог в 14байт). Как уже замечено FCR - регистр только для записи, при попытке его чтения читается IRR. Со сбросом соотв. флагов. К сожалению LPC (как и многие другие) не имеет теневых регистров регистров периферии для чтения по JTAG, поэтому очень внимательно подходите к просмотру содержимого регистров в отладчике. Гдето этим сбрасываются флаги прерываний, а гдето вычитываеются данные из ФИФО....
|
|
|
|
|
Sep 12 2007, 14:26
|

Частый гость
 
Группа: Validating
Сообщений: 184
Регистрация: 26-06-07
Из: Санкт-Петербург
Пользователь №: 28 714

|
Верно подметили, я не указал тип контроллера; это LPC2378. Я попробовал все перечисленные советы - без результата  . Видите ли, сегодня я достал другую отладочную плату с другим контроллером, LPC2364, и был неприятно удивлен, что там поведение U0FCR при инициализации подобно. Там тоже после установки в ноль RTLS не устанавливается, а, как прежде принимает значение 0х3. Я много раз слышал, что регистры U0IIR и U0FCR находятся по одному адресу, один из них для чтения другой - для записи, соответственно. Но к чему это? Разве это объясняет, почему прерывание срабатывает не по приходу одного байта, а из очереди байтов выхватывает последний? Помоему прерывание срабатывает на таймаут. А проблема в инициализации. Может там хитрый сиквел инициализации или есть какие-то условия доступа? Кто делал обработчик прерываний по приходу одного байта в UART, отзовитесь!!! Ведь это такая распространенная задача, странно, что никто не сталкивался с подобной проблемой.
|
|
|
|
|
Sep 12 2007, 21:01
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(Цырен @ Sep 12 2007, 17:26)  Там тоже после установки в ноль RTLS не устанавливается, а, как прежде принимает значение 0х3. FCR нельзя прочитать, это Write Only регистр, о чем тут уже 3 раза сказали.. То что вы видете под отладкой 0x3 - взято из другого регистра. Цитата Кто делал обработчик прерываний по приходу одного байта в UART, отзовитесь!!! Ведь это такая распространенная задача, странно, что никто не сталкивался с подобной проблемой. Я делал, TX fifo 14, RX fifo - 1. Никаких проблем не было. Пример: Код #define UART_INTID_RXTH 0x04 #define UART_INTID_TXTH 0x02
void UART0VectoredIRQ (void) __irq { int status = U0IIR & 0xF;
if (status == UART_INTID_RXTH) { int ch = U0RBR; hc_RxFlowControl( ch ); } else if (status == UART_INTID_TXTH) { uart_con.TxQue0.busy = 0; #ifdef UART_INTERRUPT_DRIVEN_DISPATCHER uart_Dispatch(); #endif } VICVectAddr = 0; //Dummy write to signal end of interrupt }
void uart_Init(void) { PINSEL0 |= 0x00050005; // Enable both UARTS RxDx and TxDx
U0LCR = 0x83; // DLAB + 8 bits, no Parity, 1 Stop bit U0DLL = PCLK / (115200 * 16);// 115200 Baud Rate, 16 static divisor U0DLM = 0; U0LCR = 0x03; // DLAB = 0 U0IER = 0x03; // Rx interrupt/Tx interrupt U0FCR = (1 << FCR_FIFO_EN)|(1 << FCR_TX_FIFO_RESET)|(FCR_RX_TRIGGER_LVL0);
VICVectCntl1 = _VICVectEN | isrUART0; //select a priority slot for a given interrupt VICVectAddr1 = (unsigned)UART0VectoredIRQ; //pass the address of the IRQ into the VIC slot
VICIntEnable |= _vUART0; //enable interrupts from UART0 (bit6) }
|
|
|
|
|
Sep 15 2007, 08:18
|

Частый гость
 
Группа: Validating
Сообщений: 184
Регистрация: 26-06-07
Из: Санкт-Петербург
Пользователь №: 28 714

|
Цитата(aaarrr @ Sep 13 2007, 19:45)  Написали бы, в чем было дело, а то столько копий сломано было... С удовольствием отвечу. Инициализировал UART0 так: void MB_UARTInit( DWORD baudrate, DWORD IntrPriority ) { DWORD Fdiv; PINSEL0 = 0x00000050; /* RxD0 and TxD0 */ U0LCR = 0x83; // DLAB + 8 bits, no Parity, 1 Stop bit Fdiv = ( Fpclk / 16 ) / baudrate ; /* baud rate */ U0DLM = Fdiv / 256; U0DLL = Fdiv % 256; U0LCR = 0x03; // DLAB = 0 U0IER = 0x01; // Rx interrupt U0FCR = (1 << 0)|(1 << 1); VIC_SetVectoredIRQ(UART0Interrupt,IntrPriority,VIC_UART0); VICINTENABLE |= 1UL << VIC_UART0; } Прерывания организовал так: static void UART0Interrupt(void) { int status = U0IIR & 0xF; int data = U0RBR; if (status == 0x04) { MB_buf[MB_len+1] = data; MB_len++; } else if (status == 0x0C) { } VICADDRESS = 0; } Прикол в том, что при отладке этот код работает хорошо если не открывать вкладочку view->registers. Думаю, отладчик считывая состояния регистров UART0 "сбивает" логику алгоритма обработки прерывания... Но это лишь предположение, основанное на моем сугубо субъективном эмпирическом опыте.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|