uriy 5 25 июля, 2013 Опубликовано 25 июля, 2013 · Жалоба На BF527 использую оба UART одновременно. Большая часть данных это выдача из процессора и немного прием данных. Есть исходный код который без проблем работал на BF533 (там только один UART). Немного его переделали добавив туда второй UART. Иногда при старте в один из UART не выдаются данные. Но чаще данные перестают идти через десятки секунд на одном из них (на любом) А еще через некоторое время перестают выдаваться и на втором. При этом остальная часть программы работает без каких-либо проблем. Прием по обоим UART также продолжает работать. Через JTAG вижу что перестают возникать прерывания по опустошению регистра THR. Часто бывает так что там даже данные не нулевые. Записал туда а они не ушли. Код прилагаю /** * @brief UART interface initialization * GPIO function set, interrupts enable * @param uartnum uart number 0 or 1 * * @return baudrate uart baudrate bit per second */ int InitUart(u32 uartnum, u32 baudrate) { int ret = 1; register_handler(ik_ivg10, UART_ISR); // UART RX ISR -> IVG 10 register_handler(ik_ivg7, UART_ERR_ISR); // UART Error ISR -> IVG 7 baudrate = GetSCLK()/16/baudrate; if(uartnum == 0) { *pUART0_GCTL |= UCEN; // enable clock *pUART0_LCR |= DLAB; // enable acces to DLL and DLH // *pUART0_DLL = (char)baudrate; // BAUD_RATE = (27MHz*10(MSEL))/(5*16*57600) *pUART0_DLH = (char)(baudrate>>8); // *pUART0_LCR = 0x03; *pPORTG_FER |= (PG7 | PG8); *pPORTG_MUX |= (1<<5); *pPORTG_MUX &= ~(1<<4); *pUART0_IER |= ELSI; //enable UART ERR interrupt *pUART0_IER = ERBFI | ETBEI; // enable rx tx uart interrupt *pSIC_IMASK0 |= IRQ_DMA8 | IRQ_DMA9; // enable UART RX, UART TX interrupt } else if(uartnum == 1) { *pUART1_GCTL |= UCEN; // enable clock *pUART1_LCR |= DLAB; // enable acces to DLL and DLH // *pUART1_DLL = (char)baudrate; // BAUD_RATE = (27MHz*10(MSEL))/(5*16*57600) *pUART1_DLH = (char)(baudrate>>8); // *pUART1_LCR = 0x03; *pPORTF_FER |= 0xC000; *pPORTF_MUX |= 0x0800; *pUART1_IER |= ELSI; //enable UART ERR interrupt *pUART1_IER = ERBFI | ETBEI; // enable rx tx uart interrupt *pSIC_IMASK0 |= IRQ_DMA10 | IRQ_DMA11; // enable UART RX, UART TX interrupt //xdev_out(putchar_UART1); //xdev_in(getchar_UART1); xdev_out(putchar_UART0); xdev_in(getchar_UART0); getchar_argon = getchar_UART1; putchar_argon = putchar_UART1; } else { ret = -1; // uart number doesn't exists } return ret; } void putchar_UART0(char ch) { unsigned int intr_mask; while (tx_counter_0 == TX0_BUFFER_SIZE); intr_mask = cli(); //disable interrupt, save IMASK register into intr_mask if (tx_counter_0 || ((*pUART0_LSR & THRE)==0)) // write into buffer if (tx_counter != 0) or UART is busy { tx_buffer_0[tx_wr_index_0] = ch; tx_wr_index_0++; if (tx_wr_index_0 == TX0_BUFFER_SIZE) tx_wr_index_0=0; tx_counter_0++; } else { *pUART0_THR = ch; } sti(intr_mask); } void putchar_UART1(unsigned char ch) { unsigned int intr_mask; while (tx_counter_1 == TX1_BUFFER_SIZE); intr_mask = cli(); //disable interrupt, save IMASK register into intr_mask if (tx_counter_1 || ((*pUART1_LSR & THRE)==0)) // write into buffer if (tx_counter != 0) or UART is busy { tx_buffer_1[tx_wr_index_1] = ch; tx_wr_index_1++; if (tx_wr_index_1 == TX1_BUFFER_SIZE) tx_wr_index_1=0; tx_counter_1++; } else { *pUART1_THR = ch; } sti(intr_mask); //enable interrupt } EX_INTERRUPT_HANDLER(UART_ISR) { char z,data_0, data_1; unsigned short int_ident_0, int_ident_1; //UART Interrupt identification register ///////////For Interrupt From UART0////////////////////////////////// // *pPORTGIO_TOGGLE = PG_GREEN_LED; int_ident_0 = *pUART0_IIR; int_ident_0 >>= 0x01; switch(int_ident_0) { case 0x00: { break; } // end case 0x00 case 0x01: // UART_THR is empty { if(tx_counter_0) { tx_counter_0--; *pUART0_THR = tx_buffer_0[tx_rd_index_0]; tx_rd_index_0++; if (tx_rd_index_0 == TX0_BUFFER_SIZE) tx_rd_index_0=0; } break; } // end case 0x01 case 0x02: // receive data ready { while (!(*pUART0_LSR & DR)); data_0 = *pUART0_RBR; ssync(); rx_buffer_0[rx_wr_index_0] = data_0; rx_wr_index_0++; if(rx_wr_index_0 == RX0_BUFFER_SIZE) rx_wr_index_0 = 0; rx_counter_0++; if(rx_counter_0 == RX0_BUFFER_SIZE) { rx_counter_0 = 0; printf_UART0("\n\rx_buffer_1 overflow\n\r"); } break; } // end case 0x02 } // end switch(int_ident) ///////////For Interrupt From UART1////////////////////////////////// ///////////////////////////////////////////////////////////////////// int_ident_1 = *pUART1_IIR; int_ident_1 >>= 0x01; switch(int_ident_1) { case 0x00: { break; } // end case 0x00 case 0x01: // UART_THR is empty { if(tx_counter_1) { tx_counter_1--; *pUART1_THR = tx_buffer_1[tx_rd_index_1]; tx_rd_index_1++; if (tx_rd_index_1 == TX1_BUFFER_SIZE) tx_rd_index_1=0; } break; } // end case 0x01 case 0x02: // receive data ready { while (!(*pUART1_LSR & DR)); data_1 = *pUART1_RBR; ssync(); rx_buffer_1[rx_wr_index_1] = data_1; rx_wr_index_1++; if(rx_wr_index_1 == RX1_BUFFER_SIZE) rx_wr_index_1 = 0; rx_counter_1++; if(rx_counter_1 == RX1_BUFFER_SIZE) { rx_counter_1 = 0; debugi("rx_buffer_1 overflow"); } break; } // end case 0x02 } // end switch(int_ident) } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gyga 0 25 июля, 2013 Опубликовано 25 июля, 2013 · Жалоба Может попробовать ДМА? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uriy 5 25 июля, 2013 Опубликовано 25 июля, 2013 · Жалоба На передачу смогу использовать DMA. На прием нет. Мне кажется проблема связана с вложенными прерываниями, только не понимаю что не так. Вложенные прерывания запрещены. Но я не вижу проблем обслужить второе прерывание сразу после первого. Ведь событие все равно должно взвестись, а потом будет обслужено. Из-за моих подозрений на вложенные прерывания проблема может быть и на прием тоже. Просто я ее ни разу не видел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gyga 0 25 июля, 2013 Опубликовано 25 июля, 2013 · Жалоба Может все прерывания поместить на один вектор? И с наибольшим приоритетном Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться