avr-chat
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-chat] HELP! mega128 USART receive restarts execution


From: Ned Konz
Subject: Re: [avr-chat] HELP! mega128 USART receive restarts execution
Date: Sun, 12 Feb 2006 08:57:15 -0800


On Feb 12, 2006, at 12:20 AM, Rick Mann wrote:

I have a very simple program, which was working great on an ATmega32. But I've ported it to an ATmega128, and I'm having lots of trouble. Aside from the changes required to get the single UART on the '32 working on UART 0 on the '128, I also stripped it down a bit to try to figure out what's going wrong.

My code does this. It sets up the UART to interrupt when a byte comes in. The main code just twiddles some LEDs. The interrupt handler is here:

ISR(SIG_UART0_RECV)
{
        unsigned char c1;
        c1 = UDR0;
        
#if 0
        usart_putc(c1);
        
        unsigned char c = c1 - '0';
        
        if (c == 1)
        {
                PORTC = _BV(kPinBlueLED);
        }
        else if (c == 2)
        {
                PORTC = _BV(kPinRedLED);
        }
        else if (c == 3)
        {
                PORTC = _BV(kPinGreenLED);
        }
#endif
}

In my hardware, RTS is connected to CTS.

Note that I've commented out most of it. When uncommented, the code sends the received byte back out, then sets one of the three LEDs on, depending on what value was received (the main loop eventually changes that, but that's okay). On the '32, this worked just fine. In particular, each character that was sent back to my terminal program would show up and cause the cursor to shift one to the right.

One the '128, if the character is sent back, it stays in the same position (the cursor doesn't advance). Worse, every time a character is received, the RX ISR gets called (I've verified this in gdb and I can see the byte echoed), then appears to return, and then execution continues from the start of main, rather than wherever execution left off.

Have you tried commenting out just the LED setting part (just to rule out electrical glitches)?

Also, have you made sure that your link is happening using the right crtm128 file and linker script?

And have you tried running your program without the JTAGICE connected (just in case)?

And, have you made sure that you're not in Mega103 compatibility mode?
Remember that 128s are shipped in Mega103 compatibility mode by default.

I know you were changing the fuses.
Make sure that bit 1 of the extended fuse byte is set (i.e. unprogrammed).

Also make sure that the watchdog isn't biting you. If you set the extended fuse byte to 0xff the watchdog timer should be off, and you should be in 128 mode.

Also make sure that your clock frequency is at least 4x your JTAG bitrate (can be set in avarice with the -B or --jtag-bitrate flag; it's 1 MHz by default).


Here's main:

int
main()
{
        //      Set LED output pins…
        
        DDRC = _BV(kPinGreenLED) | _BV(kPinBlueLED) | _BV(kPinRedLED);
        PORTC = 0;
        
#if 1
        init(); // init USART
        sei();  // enable interrupts
        
        // send initial character
        //usart_putc('C');
        //usart_putc(0x0D);
        
        while(!(UCSR0A & (1 << UDRE0)));
        UDR0 = 0x43; // "C"
        while(!(UCSR0A & (1 << UDRE0)));
        UDR0 = 0x0d;
#endif
        
        //      Show initialization complete…
        
        unsigned long d;
        const unsigned long kD = 3000000;
        
        while (1)
        {
                PORTC = _BV(kPinRedLED);
                d = kD; while (d--);
                PORTC = _BV(kPinBlueLED);
                d = kD; while (d--);
                PORTC = _BV(kPinGreenLED);
                d = kD; while (d--);
                PORTC = _BV(kPinBlueLED);
                d = kD; while (d--);
        }
        return 0;
}


Here's init() (sorry about the formatting):

void
init()
{
        // set baud rate
        UBRR0H = (uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) >> 8);
        UBRR0L = (uint8_t) UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);

        // Enable receiver and transmitter; enable RX interrupt
// RX int enable TX int disable dtareg intdis RX enable TX enable 8-bit chars
        //                              1                               0       
                        0                               1                       
        1                               0
        
        UCSR0B =        _BV(RXCIE0)
                |       !_BV(TXCIE0)
                |       !_BV(UDRIE0)
                |       _BV(RXEN0)
                |       _BV(TXEN0)
                |       !_BV(UCSZ02);

// asynchronous --- no parity --- 1 stop bit --- 8-bit chars --- unused, write 0
        //                              0                               0       
                        0                               0                       
        1                               1                               1
        
        UCSR0C =        !_BV(UMSEL0)
                |       !_BV(UPM01)
                |       !_BV(UPM00)
                |       !_BV(USBS0)
                |       _BV(UCSZ01)
                |       _BV(UCSZ00)
                |       _BV(UCPOL0);
}

I'm at my wits' end here. I don't know how to use gdb well enough to figure out why main starts from the top each time the RX handler returns from interrupt. Any suggestions would be most appreciated. Thanks!


--
Rick




_______________________________________________
AVR-chat mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/avr-chat

--
Ned Konz
address@hidden






reply via email to

[Prev in Thread] Current Thread [Next in Thread]