simulavr-devel
[Top][All Lists]
Advanced

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

Re: [Simulavr-devel] UART Interrupt and Timer problem


From: Jakob Schwendner
Subject: Re: [Simulavr-devel] UART Interrupt and Timer problem
Date: Sat, 14 May 2005 23:45:52 +1000

Hi Klaus, 

oops, I am sorry I should have read the avr-libc section on interrupts
properly before posting the report. However, in the current state,
there still seems to be some problems with the UARTs (it could be me
again ofcourse). I have changed the INTERRUPT to a SIGNAL. The test is
meant to transmit 2 characters to the UART using interrupts.
The interrupt gets raised correctly when I enable the UDRIE in the
UCSRnB register.
What doesn't seem to work is the clearing of that same flag in the
interrupt code (using UCSR1B ^= _BV(UDRIE)). Even though the trace
states that the UDRIE is not set anymore, the interrupt keeps getting
raised again once the handler has finished.
Here is my code:

//----- Include Files ---------------------------------------------------------
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

#define F_CPU 16000000
#define UART1_BAUD  19200

typedef unsigned char  u08;

//----- Begin Code ------------------------------------------------------------

void io_init(void);
void uart1_send(char *s, int size);

int main(void)
{
        io_init();

        while(1) {

                char *s = "this is a test";
                uart1_send( s, 2 );

                // delay
                int m = 20000;
                while( m-- );
        }

        return 0;
}

void io_init() {
        // set LED pins for output
    DDRA = _BV(DDA2) | _BV(DDA4);       

        // set BAUD rate for UART1
        UBRR1L = ((F_CPU+(UART1_BAUD * 8L))/(UART1_BAUD * 16L)-1);
        UBRR1H = 0;

        // init UART1
        UCSR1B = _BV(TXEN); 

        // enable all interupts
        sei();
}

char *tx_buf;
u08 tx_index;
u08 tx_size;

void uart1_send(char *s, int size) {
        tx_buf = s;
        tx_size = size;
        tx_index = 0;

        // enable UART data ready interrupt
        UCSR1B |= _BV(UDRIE); 
}

SIGNAL(SIG_UART1_DATA)      
{        
        // send new data
        UDR1 = tx_buf[tx_index++];
        
        if( tx_index >= tx_size ) {
                // disable data ready interrupt
                UCSR1B ^= _BV(UDRIE);
        }
}


On 5/12/05, Klaus Rudolph <address@hidden> wrote:
> Hi Jakob,
> 
> great that we have found such a good tester!
> 
> > Similar problem,
> I donĀ“t believe :-)
> 
> > different interrupt. UART_DATA_READY is according to
> > the data-sheet meant to stay on until switched off.
> Yes! Thats seems to be your problem :-)
> 
> > However in my
> > sample code (attached below) it seems that the interrupt code body
> > doesn't even get called when an interrupt is raised,
> the irq vector is called! Look at your timestamp: 16058
> you are running in code with symbol __vector_31 which is your INTERRUPT
> routine. That is correct.
> 
> 
> > as a few cycles
> > later another one is raised again. (and so on).
> That seems to be OK. The first thing you do is to enable the interrupt
> again -> SEI instruction, the UDR is still set and also UDRIE is set.
> This three points mean-> start a interrupt. And this is done.
> 
> I think you should not write
> 
> INTERRUPT(SIG_UART1_DATA)
> please use
> SIGNAL(SIG_UART1_DATA)
> instead. This will not activate the interrupts before ending your
> interrupt handler.
> 
> 
> > Also the program
> > generates a "Not allowed to write to Pin! Read-Only!" error. Don't
> > know where that comes from. Here is the trace:
> >
> 
> Thats really simple :-) You are running a interrupt routine and the
> actual PC is saved on stack. After entering the ISR (Interrupt Service
> Routine) you enable the next interrupt but not leave the ISR. You
> pushing a lot of PCs to stack and the lower RAM address space is
> the io register bank. And one of the registers you are writing
> is one of the pin registers. This will throw the message.
> After that you are also crashing the registers and so on.
> 
> Seems that there is only a bug in the test :-). If the behaviour is
> not like the real hardware please send again a mail. But I think
> your testcode is wrong.
> 
> But writing to an reserved register has crashed my simulator!
> Thanks for this, I found a very stupied bug which to fix needs updating
> nearly all files. I will do this the next days and put it together
> with the last changes to CVS. Thanks for that hint!
> 
> Thanks
>     Klaus
> 
> 
> >     15996 ../avrtest/avrtest.elf 0x012a: __vector_31+0x2
> >  IRQ DETECTED: VectorAddr: 62../avrtest/avrtest.elf IrqSystem:
> > IrqHandlerStarted Vec: 31
> > IRAM[0x10fc,,__bss_end,_end+0xfe8]=0x95 SP=0x10fb
> > IRAM[0x10fb,,__bss_end,_end+0xfe7]=0x00 SP=0x10fa
> >     16058 ../avrtest/avrtest.elf 0x007c: __SREG__,__SP_H__+0x1f
> >  CPU-waitstate
> >     16120 ../avrtest/avrtest.elf 0x007c: __SREG__,__SP_H__+0x1f
> >  CPU-waitstate
> >     16182 ../avrtest/avrtest.elf 0x007c: __SREG__,__SP_H__+0x1f
> >  CPU-waitstate
> >     16244 ../avrtest/avrtest.elf 0x007c: __SREG__,__SP_H__+0x1f
> >  JMP 128f0 __stack+0x8bf9
> >     16306 ../avrtest/avrtest.elf 0x0126: __vector_31
> >  CPU-waitstate
> >     16368 ../avrtest/avrtest.elf 0x0126: __vector_31
> >  CPU-waitstate
> >     16430 ../avrtest/avrtest.elf 0x0126: __vector_31
> >  SEI SREG=[I-------]
> >     16492 ../avrtest/avrtest.elf 0x0128: __vector_31+0x1
> >  PUSH R1 IRAM[0x10fa,,__bss_end,_end+0xfe6]=0x00 SP=0x10f9
> >     16554 ../avrtest/avrtest.elf 0x012a: __vector_31+0x2
> >  CPU-waitstate
> >     16616 ../avrtest/avrtest.elf 0x012a: __vector_31+0x2
> >  IRQ DETECTED: VectorAddr: 62../avrtest/avrtest.elf IrqSystem:
> > IrqHandlerStarted Vec: 31
> > IRAM[0x10f9,,__bss_end,_end+0xfe5]=0x95 SP=0x10f8
> > IRAM[0x10f8,,__bss_end,_end+0xfe4]=0x00 SP=0x10f7
> > [...]
> >
> > and the code that produced it:
> >
> > //----- Include Files
> > ---------------------------------------------------------
> > #include <avr/io.h>
> > #include <avr/signal.h>
> > #include <avr/interrupt.h>
> >
> > #define F_CPU 16000000
> > #define UART1_BAUD  19200
> >
> > typedef unsigned char  u08;
> >
> > //----- Begin Code
> > ------------------------------------------------------------
> >
> > void io_init(void);
> > void uart1_send(char *s, int size);
> >
> > int main(void)
> > {
> >       io_init();
> >
> >       while(1) {
> >
> >               char *s = "this is a test";
> >               uart1_send( s, 3 );
> >
> >               // delay
> >               int m = 20000;
> >               while( m-- );
> >       }
> >
> >       return 0;
> > }
> >
> > void io_init() {
> >       // set LED pins for output
> >     DDRA = _BV(DDA2) | _BV(DDA4);
> >
> >       // set BAUD rate for UART1
> >       UBRR1L = ((F_CPU+(UART1_BAUD * 8L))/(UART1_BAUD * 16L)-1);
> >       UBRR1H = 0;
> >
> >       // init UART1
> >       UCSR1B = _BV(TXEN);
> >
> >       // enable all interupts
> >       sei();
> > }
> >
> > char *tx_buf;
> > u08 tx_index;
> > u08 tx_size;
> >
> > void uart1_send(char *s, int size) {
> >       tx_size = size;
> >       tx_buf=s;
> >       tx_index=0;
> >
> >       // enable UART data ready interrupt
> >       UCSR1B |= _BV(UDRIE);
> > }
> >
> > INTERRUPT(SIG_UART1_DATA)
> > {
> >       // disable data ready interrupt
> >       UCSR1B ^= _BV(UDRIE);
> >
> >       // check for more data
> >       if( tx_index < tx_size ) {
> >               // enable data ready interrupt
> >               UDR1 = tx_buf[tx_index++];
> >               UCSR1B |= _BV(UDRIE);
> >       }
> > }
> >
> 
> --
> +++ Lassen Sie Ihren Gedanken freien Lauf... z.B. per FreeSMS +++
> GMX bietet bis zu 100 FreeSMS/Monat: http://www.gmx.net/de/go/mail
>




reply via email to

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