Witajcie Zaczynam zabawê z ARM LPC2148. Nie mogê sobie poradziæ z transmisj± przez UART w trybie przerwañ. Do tej pory w 8051 czy AVR robi³em bufor nadawczy i odbiorczy. Wysy³aj±c kilka znaków wpisywa³em do bufora i inicjowa³em transmisjê a w obs³udze przerwania z bufora by³y pobierane kolejne znaki a¿ do opró¿nienia. Analogicznie z odbiorem - przychodzi³o do bufora a w wolnej chwili odczytywa³em to co przysz³o.
W ARM poradzi³em sobie z transmisj± przychodz±c± ale ju¿ drugi dzieñ siedzê i nie mogê uzyskaæ przerwania od wys³ania znaku. Je¿eli pierwszy bajt danych wrzucê "rêcznie" do U0THR to wychodzi na zewn±trz, ale nie jest poprawnie zg³aszane przerwanie.
W U0IER mam w³±czone zezwolenia na przerwania od nadawania i odbioru: UIER_ERB | UIER_THRE
Zainstalowa³em sobie ewaluacyjn± wersjê CrossStudio i debugujê rejestry. Po wys³aniu znaku widzê w U0IIR InterruptPending = 0 (jest przerwanie), Interrupt_Identification = 1 (THRE), czyli niby wszystko OK, ale nie ustawia siê bit przerwania od UARTA w VICIRQStatus (= 0). Doszed³em do etapu ¿e wchodzê do obs³ugi przerwania, dochodzê do makra IS_ENTRY i po przej¶ciu kasuj± mi siê flagi w U0IIR i nie ma ¶ladu po przerwaniu. Oczywi¶cie nie moze byæ poprawnie obs³u¿one. Je¿eli przychodzi znak z zewn±trz, jest odpowiednia flaga w VICIRQStatus, poprawnie wchodzê do obs³ugi przerwania i odczytujê znak.
Próbowa³em debugowaæ ró¿ne przyk³adowe programy z takim samym efektem.
Konfiguracja UARTa wygl±da tak: Uart0Init(B9600, UART_8N1, UART_FIFO_1) //////////////////////////////////////////////////////////////////////////////// uint16_t Uart0Init(uint16_t baud, uint8_t mode, uint8_t fmode) { U0IER = 0x00; // disable all interrupts U0IIR; // clear interrupt ID U0RBR; // clear receive register U0LSR; // clear line status register
// set the baudrate U0LCR = ULCR_DLAB_ENABLE; // select divisor latches U0DLL = (uint8_t)baud; // set for baud low byte U0DLM = (uint8_t)(baud >> 8); // set for baud high byte
// set the number of characters and other // user specified operating parameters U0LCR = (mode & ~ULCR_DLAB_ENABLE); U0FCR = fmode;
//initialize the interrupt vector VICIntSelect &= ~VIC_BIT(UART0_INT); // UART0 selected as IRQ VICVectCntl0 = VIC_ENABLE | UART0_INT; VICVectAddr0 = (uint32_t)Uart0ISR; // address of the ISR VICIntEnable = VIC_BIT(UART0_INT); // UART0 interrupt enabled
//inicjuj zmienne obs³ugi buforów ko³owych wsk_ob0n = 0; wsk_nb0n = 0; wsk_ob0o = 0; wsk_nb0o = 0;
U0FCR = 1;
//w³acz przerwania U0IER = UIER_ERB | UIER_THRE; return (TRUE); }
wysy³anie znaku mam zrobione tak± procedur±: //////////////////////////////////////////////////////////////////////////////// void PutChar0 (uint8_t ch) { unsigned cpsr;
while (buf0_nad_size == UART0_TX_BUFFER_SIZE); // czekaj az bedzie miejsce w buforze
cpsr = disableIRQ(); // disable global interrupts U0IER &= ~UIER_THRE; //wy³±cz przerwanie wysy³ania restoreIRQ(cpsr); // restore global interrupts
//sprawd¼ czy trwa wysy³anie danych if (uart0_tx_running) { uart0_tx_buf[wsk_nb0n++] = ch; if (wsk_nb0n == UART0_TX_BUFFER_SIZE) wsk_nb0n = 0; buf0_nad_size++; } else { // set running flag and write to output register uart0_tx_running = TRUE; U0THR = (uint8_t)ch; }
cpsr = disableIRQ(); // disable global interrupts U0IER |= UIER_THRE; //w³±cz przerwanie wysy³ania restoreIRQ(cpsr); // restore global interrupts }
Je¿eli mo¿ecie wskazaæ jak±¶ ¶cie¿kê, albo podrzuciæ dzia³aj±cy przyk³ad, bêdê wdziêczny.