AVR-GCC bug? - static vs non static functions

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

Can someone please assist by compiling this snippet and try running it on another ATMega324P. I'm tearing (what I have left of) my hair out, after 2x Megas, 2x 232 drivers, 3.3V and 5V supplies, UART0 and 1, multiple PCs, different COM ports, different terminals, different BAUDs plus other divide and conquer tests - still same problem.

A simple stream of chars into a terminal window connnected to UART0 and I get multiple reboots if it is compiled with -DFAIL. Ie.

void Test1(void) - lots of reboots
static void Test1(void) - works fine

I just don't understand why / how I can go forward.

Carl

#include  
#include  

#define UART0_BAUD 115200L 

#define UART0_RXFIFO_SIZE    8               		// Bytes in the RX FIFO 
#define UART0_RXFIFO_MASK    (UART0_RXFIFO_SIZE-1)      // Mask (hence why size needs to be ^2) 

static volatile    uint8_t   idx_w; 
static volatile    uint8_t   idx_r; 
static volatile    uint8_t    buff[UART0_RXFIFO_SIZE]; 

ISR(USART0_RX_vect) { 
    unsigned char c; 

    if (! ( UCSR0A & ( _BV(FE0) | _BV(DOR0)) ) ) {
      buff[idx_w & UART0_RXFIFO_MASK] = UDR0;
    } else {
      c = UDR0; buff[idx_w & UART0_RXFIFO_MASK] = '#';   // Overflow / error
    }
    idx_w++;                  		// RMASK makes it unnecessary to range limit this 
    if (idx_w == idx_r) { PORTD &= ~_BV(6); } // Show write / read ptr wrap
} 

unsigned char UART0_rxtest(void) { return (idx_w - idx_r); } 

unsigned char UART0_getc(void) { 
    unsigned char c; 

    do {} while (UART0_rxtest() == 0);  // wait for data. see also UART0_rxtest() 

    c = buff[idx_r & UART0_RXFIFO_MASK]; 
    cli(); idx_r++; sei(); 
    return(c); 
} 

#ifdef FAIL 
void Test1(void) { 
#else 
static void Test1(void) { 
#endif 
   uint16_t d; 

   while ( UART0_rxtest() > 0 ) { 
      d=UART0_getc(); 
   } 
} 

int main (void) 
{ 
   idx_r = 0; idx_w = 0; 

   UBRR0 = (F_CPU / (16UL * UART0_BAUD)) - 1; 
   UCSR0C = ( 1<<UCSZ01 | 1<<UCSZ00 );    	// 8N1 Bit 
   UCSR0B = _BV(RXEN0)|_BV(RXCIE0)|_BV(TXEN0);  // IO & Interrupts enable

   sei(); 

   UDR0 = '_'; // Initialisation char

   for (;;) { 
      Test1(); 
   } 
} 

// EOF 
Last Edited: Tue. Jul 24, 2007 - 08:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Generated ASM from (LHS) non static / static (RHS) - I don't see any functional difference here - any observations?

The rest of the ASM code is identical between the versions.

.global Test1                   <
        .type   Test1, @function<
Test1:                          <
/* prologue: frame size=0 */    <
/* prologue end (size=0) */     <
        rjmp .L19               <
.L20:                           <
        call UART0_getc         <
.L19:                           <
        lds r25,idx_w           <
        lds r24,idx_r           <
        cp r25,r24              <
        brne .L20               <
/* epilogue: frame size=0 */    <
        ret                     <
/* epilogue end (size=1) */     <
/* function Test1 size 10 (9) */<
        .size   Test1, .-Test1  <
.global main                      .global main
        .type   main, @function           .type   main, @function
main:                             main:
/* prologue: frame size=0 */      /* prologue: frame size=0 */
/* prologue end (size=0) */       /* prologue end (size=0) */
        sts idx_r,__zero_reg__            sts idx_r,__zero_reg__
        sts idx_w,__zero_reg__            sts idx_w,__zero_reg__
        ldi r24,lo8(9)                    ldi r24,lo8(9)
        ldi r25,hi8(9)                    ldi r25,hi8(9)
        sts (196)+1,r25                   sts (196)+1,r25
        sts 196,r24                       sts 196,r24
        ldi r24,lo8(6)                    ldi r24,lo8(6)
        sts 194,r24                       sts 194,r24
        ldi r24,lo8(-104)                 ldi r24,lo8(-104)
        sts 193,r24                       sts 193,r24
/* #APP */                        /* #APP */
        sei                               sei
/* #NOAPP */                      /* #NOAPP */
        ldi r24,lo8(95)                   ldi r24,lo8(95)
        sts 198,r24                       sts 198,r24
.L24:                                     rjmp .L27
        call Test1              | .L20:
        rjmp .L24               |         call UART0_getc
                                > .L27:
                                >         lds r25,idx_w
                                >         lds r24,idx_r
                                >         cp r25,r24
                                >         brne .L20
                                >         rjmp .L27
/* epilogue: frame size=0 */      /* epilogue: frame size=0 */
/* epilogue: noreturn */          /* epilogue: noreturn */
/* epilogue end (size=0) */       /* epilogue end (size=0) */
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well in the static case I think the compiler will inline the Test1 function while in the non-static case it'll be a call/return. As this is the only CALL in the program it maybe suggests that there's some kind of stack setup problem. Are you SURE you are building for the right CPU and that it's SRAM really is at the address that the SP is being set to?

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have a JTAG ICE to debug your setup? As this is a 32 KiB device,
even an AVR Dragon would be fine.

To debug, I'd start filling in all the interrupt vectors, have them
set a global variable, and then jump to a common function where you
can enable a breakpoint on. That way, you could see whether it's a
spurious interrupt that triggers your reboot.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK - I think I've got it right but....

ATMega324P-20PU, command line:

cmorgan@borg ~/coding/AVR/GCCProblem
$  avr-gcc -O3 -Os -Wl,-Map,memory.map -mmcu=atmega324p -o"GCCDemo.elf" GCCDemo.c -DF_CPU=18432000 -DFAIL

cmorgan@borg ~/coding/AVR/GCCProblem
$ avr-objcopy -j .text -j .data -O ihex GCCDemo.elf GCCDemo.hex

cmorgan@borg ~/coding/AVR/GCCProblem
$  avrdude -p m324 -P usb -c avrispmkii -U flash:w:GCCDemo.hex

All my standard test LED blinks etc seem to work, including MMC/Tiny FAT drivers etc....

Hope I got the basics right.... Next idea?

Carl

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry - I only have an AVRISPmkII - I do have a second ATMega324P and happy to breadboard up a solution if it helps. I understand the JTAG stuff needs more processing / hardware - can DebugWire be used?

I'm assuming I can't use AVR Simulator as I don't see a way of using the UART interface with it.

Any other options?

Carl

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> I understand the JTAG stuff needs more processing / hardware - can
> DebugWire be used?

No, AVRs come either with JTAG (ATmegas >= 16 KiB ROM except the
ATmega168 and some old parts), or debugWire (ATmegaX8 and new
ATtinys), but never both. Anyway, you'd need an emulator for both
types of connection.

> I'm assuming I can't use AVR Simulator as I don't see a way of using
> the UART interface with it.

simulavr is too simple for that. AVR Studio might work if you've got
access to a Win32 system.

> Any other options?

I'd really suggest you get an emulator, either the Dragon or a JTAG
ICE. Not sure, there used to be some bundle deals at various Atmel
distributors where the combination of an STK500 with either an AVR
Dragon or a JTAG ICE mkII has been sold for a really good price,
depending on your location and distributor, check whether that would
still apply to you if you're interested.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVR Studio 4.13 I've got installed, but didn't see any way of stuffing a "UART" with chars.

JTAG - yes, if I knew then what I know now, I might have gone a slightly different purchasing route :-). Being in NZ, means shipping will be as much as any purchase (US$50+).

I'll try adding a set of other vectors that just light up an LED.

I need to understand / dig more on something dean suggested with regard to .init control and grabbing state information after a reboot - but haven't found anything obvious yet....

Thanks for the pointers....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, quick update for the record.

Jörg has helped out (many thanks) and tried my code - works fine for him @ 9600 / 16MHz. He sent me the .hex and I've changed my crystal. Same problem. Checked on a different terminal platform (Win98 / HyperTerm vs XP TeraTerm) and still same problem. Changed AVR, MAX232 and other tests still same.

I'm starting to question the -0720 chip - but I'm grabbing at straws..... Any further ideas welcome.

Carl

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Right - final close out.....

After more debugging and learning about MCUSR - it was shown that the program counter was going AWOL and that was the cause of the reboots.

The cause of the AWOL took a bit more investigation, this time with avr@atmel.com - really helpful and over a couple of days found the issue was fuse bits.

I had an external 18.432 MHZ crystal and was using a low fuse of lfuse=EE;

"Ext. Crystal Osc.; Frequency 8.0- MHz; Start-up time: 1K CK + 0 ms; [CKSEL=1110 SUT=10]"

After trying a lfuse=F7:

"Full Swing Oscillator; Start-up time: 16K CK + 65 ms; Crystal Osc.; slowly rising power; [CKSEL=0111 SUT=11]"

Everything springs to life and works as it should. This was fairly subtle, particually as a first AVR project, but I have been educated that if you aren't worried about battery power usage etc, the "F7" option is a good / safe / default for >8 Mhz Crystals.

Thanks to all the assistance, now I can get to some coding / development!

Regards,

Carl

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Glad you solved the problem (and learned a lot on the way). Have fun with the real coding!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, what was happening? Clock going south and causing resets?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As far as I know - just not enough drive of the crystal - I also have 27pf caps (vs the normal 22pf).

I think the take away is:- MCUSR provides guidance on the cause of the reboots (I was getting 0x00s) and the F7 option is good for non-power saving critical projects.

Carl