atxmega32a4, przerwania USART i resetowanie uC...

Witam wszystkich i proszę o pomoc :-) Pytałem na avrfreaks, ale nie dostałem żadnej odpowiedzi...

Podłączyłem xmega32a4 do PCta i mogę wysyłać dane. Dodałem ISR do kodu, i przerwanie odpala się przy wysłaniu danych (TXC). To działa bez problemu. Teraz dodaję ISR dla RX i sprawdzam... i niestety, gdy wysyłam coś do uC to teoretycznie przerwanie się wykonuje... mówię teoretycznie, bo odebranie znaku resetuje się mikrokontroler! A gdy mikrokontroler się zresetuje i program wykonuje się od nowa, to wszystkie przerwania są wyłączone (i nawet TX już nie działa).

Ktoś wie co robię źle? :-(

Oto mój kod:

#define UART_GPS USARTE0

int main (void) { cli(); sei(); /* enable interrupts */

OSC.CTRL |= OSC_RC32MEN_bm; while(!(OSC_STATUS & OSC_RC32MRDY_bm)); CCP = CCP_IOREG_gc; CLK.CTRL = CLK_SCLKSEL_RC32M_gc;

UARTinit(&UART_GPS); // init serial port

while(1) { UARTputs(&UART_GPS, "test string\r\n"); _delay_ms(500); }

}

ISR(USARTE0_RXC_vect) { //UART receive interrupt PORTA.OUTTGL |= (1 <<PIN0); // PA0 is toggled }

ISR(USARTE0_TXC_vect) { //UART receive interrupt PORTA.OUTTGL |= (1 <<PIN1); // PA1 is toggled }

I moje funkcje:

//not finished yet, need to handle PORTE via arg void UARTinit(USART_t *port) { int bsel = 3325; int bscale = -3; // 4800 @ 32MHz

PORTE.OUTSET = PIN3_bm; PORTE.DIRSET = PIN3_bm; // PE3 (TXD0) as output PORTE.DIRCLR = PIN2_bm; // PE2 (RXD0) as input

PORTE.INTCTRL = 0x01; // set interrupt0 low level PORTE.INT0MASK = 0x04; // set pins 3 and 2 for as a source for interrupt

port->BAUDCTRLA = /*(uint8_t)*/ bsel; port->BAUDCTRLB = (bscale << 4) | (bsel >> 8);

PMIC.CTRL = PMIC_LOLVLEN_bm;

// Enable RX and TX low level interrupts port->CTRLA = USART_RXCINTLVL_LO_gc | USART_TXCINTLVL_LO_gc;

// Enable both RX and TX. port->CTRLB = USART_RXEN_bm | USART_TXEN_bm;

// Set USART to 8bit, no parity, 1 stop bit port->CTRLC = USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc;

}

//send a string to UART uint8_t UARTputs(USART_t *port, const char *ptr) {

while(*ptr) { while(!(port->STATUS & USART_DREIF_bm)) // wait for output buffer to clear / send complete / ready to send _delay_us(1);

port->DATA = *ptr++; // send character }

return 1; }

Używam tego z MAX232 (wiem, że jest na 5V). Niestety nic innego na chwilę obecną pod ręką nie mam. TX z xmegi jest podłączony bezpośrednio, i to działa. RX jest podłączony przez dzielnik napięcia (Umax = 3V, zasilanie uC 3.3V).

Reply to
Martin Lukasik
Loading thread data ...

Najprawdopodobniej musisz odczytać dane, które przyszły żeby wyzerować flagę przerwania. Doczytaj w pdfie lub sprawdź.

Reply to
bratsiostry

Miałem cichą nadzieję, że to to, ale jednak nie :/ W ogóle chyba nie trzeba czytać tych danych tak na dobrą sprawę, bo bufor może się bezkarnie przepełnić, ma nawet flagę przepełnienia bufora. Tak czy owak sprobowałem czytać USARTE0.DATA w procedurze ISR(), ale dalej to samo. W PDFie, którego przeczytałem już kilka razy dalej nic nowego nie znalazłem :/

Nie mam pojęcia o co chodzi :-( Jakieś pomysły?

Chyba trzeba będzie w konću wydać kasę na sprzętowy debugger...

m.

Reply to
Martin Lukasik

W atmegach flaga RXC jest zerowana dopiero po odczycie danej. Nie mam pdfa od xmegi, ale może być tak samo. Sprawdź jeszcze w kodzie wynikowym jak skompilowany jest odczyt - może być sytuacja, że kompilator zoptymalizował kod jeśli przypisana wartość nie jest później wykorzystana.

Reply to
bratsiostry

AVR1307:

"When a complete character is received in the shift register, it is copied to the buffer, and the shift register is ready to receive a second (or third) character. Note that, if three characters have been received, without reading the DATA register, a fourth character will cause loss of the character in the shift register, the third byte is lost. In this case the buffer overflow flag will be set (BUFOVF in USARTxn.STATUS)."

więc to potwierdza co mówiłem odnośnie czytania bufora.

A to odnośnie czytania z DATA: "The RXCIF flag is set when there are unread data in the receive buffer, and cleared when the receive buffer is empty. The RXCIF flag is cleared by reading the data, it is not required to clear the flag manually."

Zajrzę jeszcze do kodu asm. Ponoć reset może się pojawić przy skoku (jmp, rjmp) do niezdefiniowanego adresu (ponoć dzieje się tak gdy włączysz przerwanie a nie ma nigdzie procedury do jego obsługi -- wtedy wywołanie przerwania kończy się skokiem "niewiadomogdzie" i uC się resetuje). No nic, powalczę jeszcze...

Dzięki.

m.

Reply to
Martin Lukasik

W dniu 05.06.2011 21:28, Martin Lukasik pisze:

Nie, nie "niewiadomogdzie", ale właśnie pod reset (tam wskazują wszystkie niezdefiniowane przerwania) - możesz za pomocą jakiegoś objdump/gdb zobaczyć jak wygląda reset vector - czy jest jakaś funkcja przypisana.

Reply to
Michoo

Niestety nie ma nic pod tym wektorem. Rozumiem, że wektor resetu to 0. W asmie mam tylko wektory 58 i 60, co jest zgodne z założeniami i moim programem. Nie mam tam nigdzie skoku do wektora 0.

w .lss mam:

00000212 <__vector_58>: }

ISR(USARTE0_RXC_vect) { //UART receive interrupt 212: 1f 92 push r1 214: 0f 92 push r0 216: 0f b6 in r0, 0x3f ; 63 218: 0f 92 push r0 21a: 11 24 eor r1, r1 21c: 8f 93 push r24 21e: ef 93 push r30 220: ff 93 push r31 data = USARTE0.DATA; 222: 80 91 a0 0a lds r24, 0x0AA0 226: 80 93 00 20 sts 0x2000, r24 PORTA.OUTTGL |= (1 <<PIN0); // PA0 is toggled 22a: e0 e0 ldi r30, 0x00 ; 0 22c: f6 e0 ldi r31, 0x06 ; 6 22e: 87 81 ldd r24, Z+7 ; 0x07 230: 81 60 ori r24, 0x01 ; 1 232: 87 83 std Z+7, r24 ; 0x07

/* lcd_puts("INT triggered"); lcd_puts(UARTgetc(&USARTD0)); show_display();

*/ } 234: ff 91 pop r31 236: ef 91 pop r30 238: 8f 91 pop r24 23a: 0f 90 pop r0 23c: 0f be out 0x3f, r0 ; 63 23e: 0f 90 pop r0 240: 1f 90 pop r1 242: 18 95 reti

00000244 <__vector_60>:

ISR(USARTE0_TXC_vect) { //UART receive interrupt 244: 1f 92 push r1 246: 0f 92 push r0 248: 0f b6 in r0, 0x3f ; 63 24a: 0f 92 push r0 24c: 11 24 eor r1, r1 24e: 8f 93 push r24 250: ef 93 push r30 252: ff 93 push r31 PORTA.OUTTGL |= (1 <<PIN1); // PA1 is toggled 254: e0 e0 ldi r30, 0x00 ; 0 256: f6 e0 ldi r31, 0x06 ; 6 258: 87 81 ldd r24, Z+7 ; 0x07 25a: 82 60 ori r24, 0x02 ; 2 25c: 87 83 std Z+7, r24 ; 0x07 } 25e: ff 91 pop r31 260: ef 91 pop r30 262: 8f 91 pop r24 264: 0f 90 pop r0 266: 0f be out 0x3f, r0 ; 63 268: 0f 90 pop r0 26a: 1f 90 pop r1 26c: 18 95 reti

Wygląda ok... Przeoczyłem coś?

Dzieje się magia...

m.

Reply to
Martin Lukasik
Reply to
Marcin Wasilewski

W dniu 2011-06-05 15:45, Martin Lukasik pisze:

[...]

A stos prawidłowo zainicjowany? K.

Reply to
John Smith

[...]

Z reguły kiedy z programem dzieje się magia, to winny jest temu stos. Przypatrz się dokładnie czy nie masz zbyt głębokich odwołań do funkcji, czy stos nie wchodzi na obszar danych albo nie wychodzi poza RAM, czy nie piszesz gdzieś poza obszarem zadeklarowanych zmiennych. Za każdym razem jak miałem do czynienia z "czarną magią" na uP, okazywało się że błąd był związany ze stosem.

pzdr. j.

Reply to
Jacek Radzikowski

Podpiąłem RX i TX na krótko, i problem był dalej.

Później zrobiłem tak jak piszesz -- wpakowałem diody na port, ustawiłem te 93 wektory, żeby zaświecały diody... :-) i doszedłem do problemu!!! Było to nieobsługiwane przerwanie! Jakie? External interrupt on PORTE.

Z UARTinit():

PORTE.INTCTRL = 0x01; // set interrupt0 low level PORTE.INT0MASK = 0x04; // set pins 3 and 2 for as a source for interrupt

Jako, że książek o xmega na oczy nie widziałem, to przenoszę się z mega przy pomocy tutorialów. I w jednym cudownym było właśnie powyższe, co durnie przepisałem, myśląc, że tak ma być.

Tylko ta linia jest za to odpowiedzialna:

port->CTRLA = USART_RXCINTLVL_LO_gc | USART_TXCINTLVL_LO_gc;

Działa teraz przecudownie, zmarnowałem na to 2 dni... ale hej, w sumie czegoś się nauczyłem!

WIELKIE DZIĘKI Marcin za podpowiedź i całej reszcie za pomoc!

Dobranoc, m.

Reply to
Martin Lukasik

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.