Electrical – AVR ATmega32 – C – Gets stuck in function call

avrc

I have had lots of problems trying to get a piece of firmware to work which has worked fine earlier, and is working on a copy of the board I'm having problems with. I've narrowed in down to the following (at least to start with):

This piece of code works:

#define F_CPU 8000000

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{   
   // LEDs - initial setting
   DDRC |= 0x03;                // LEDs on pins PC0 and PC1 
   PORTC &= ~(1<<0);             // LED0 OFF
   PORTC |= (1<<1);             // LED1 ON

   DDRD |= 0x30;    // PD4..5 OUT
   TCCR1A = 0xE2;   //0b11100010 (Set OC1A + Clear OC1B on compare match, )
   TCCR1B = 0x19;   //0b00011001 (WGM13:10 = 0b1110 => Fast PWM Mode, TOP = ICR1, CS12:0 = 001 => Use IO clock, no prescaling)
   OCR1A = 18;
   OCR1B = 18;      //  18 / 8000000 =  2.25 us (Output compare match value (OC1A->HIGH, OC1B->LOW)
   ICR1 = 757;      // 757 / 8000000 = 94.625us (TOP value for timer1)

   // Loop blinks LED0..1 alternately
   while(1)
   {
       PORTC = PORTC ^ 0x03;
       _delay_ms(250);
   }
}

It starts the timer and outputs the pulse with the specified timing, and enters the blinking LED loop.

However, this code fails:

#define F_CPU 8000000

#include <avr/io.h>
#include <util/delay.h>

void pulse_init(void)
{   
   DDRD |= 0x30;    // PD4..5 OUT
   TCCR1A = 0xE2;   //0b11100010 (Set OC1A + Clear OC1B on compare match, )
   TCCR1B = 0x19;   //0b00011001 (WGM13:10 = 0b1110 => Fast PWM Mode, TOP = ICR1, CS12:0 = 001 => Use IO clock, no prescaling)
   OCR1A = 18;
   OCR1B = 18;      //  18 / 8000000 =  2.25 us (Output compare match value (OC1A->HIGH, OC1B->LOW)
   ICR1 = 757;      // 757 / 8000000 = 94.625us (TOP value for timer1)
}


int main(void)
{   
   // LEDs - initial setting
   DDRC |= 0x03;                // LEDs on pins PC0 and PC1 
   PORTC &= ~(1<<0);            // LED0 OFF
   PORTC |= (1<<1);         // LED1 ON

   pulse_init();

   // Loop blinks LED0..1 alternately
   while(1)
   {
       PORTC = PORTC ^ 0x03;
       _delay_ms(250);
   }
}

…it's just the same statements as before, moved to the pulse_init() function. When I upload this code the timer is set up correctly and the output pulse is OK, but the program never starts blinking the LEDs on PC0..1.

Any ideas? It's not just this function, this is part of a bigger program with other initalization functions and it seems whenever the program enters a function separate from the main loop it fails to return to main. I am not so familiar with C and how it works on the function block level. I am using Atmel Studio 7 now with the following compiler options:

-x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.1.130\include"  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -Wextra -pedantic -mmcu=atmega32 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.1.130\gcc\dev\atmega32" -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"

but I had the same problems with avrdude. I also tried reading the full binary from the working board and writing it to the board I'm working on. It should communicate with PC over a USB-to-serial but it doesn't work. When I power up the board it spews a few kilobytes on nonsense to the serial (the same nonsense every time, though) and then freezes, i.e. doesn't send the regular "Waiting for command" message or reply to any commands.

The chip is Atmega32L8AU, 8MHz external crystal, LFUSE=0xFF, HFUSE=0x99.

Any ideas?

Edit: SOLVED – The firmware works after changing the AVR chip. Turns out to be a faulty memory area in the SRAM or possibly something wrong with the SRAM/GPR bus. This was suggested by in comments to Maximus' answer below.

Thank you for all your help!

Best Answer

Have you considered the warnings in your compiler (if any) ?

Your problem seems to me like there is an issue with function decleration, perhaps. Can you try to declare the function first on top of main and put function body at the bottom of main.c? Does the issue persists?

Also, have you tried debugger of atmel studio? If you haven't yet, please try and execute step by step. Observe the registers and see how they change.

One more question, can you do a simple error checking/tracking? For example,

#define F_CPU 8000000

#include <avr/io.h>
#include <util/delay.h>

uint8_t PROG_STATE = 0;
void Send_to_PC(uint8_t DATA);

void pulse_init(void)
{   
   PROG_STATE = 3;
   Send_to_PC(PROG_STATE);
   DDRD |= 0x30;    // PD4..5 OUT
   TCCR1A = 0xE2;   //0b11100010 (Set OC1A + Clear OC1B on compare match, )
   TCCR1B = 0x19;   //0b00011001 (WGM13:10 = 0b1110 => Fast PWM Mode, TOP = ICR1, CS12:0 = 001 => Use IO clock, no prescaling)
   OCR1A = 18;
   OCR1B = 18;      //  18 / 8000000 =  2.25 us (Output compare match value (OC1A->HIGH, OC1B->LOW)
   ICR1 = 757;      // 757 / 8000000 = 94.625us (TOP value for timer1)
}


int main(void)
{   
   PROG_STATE = 1;
   Send_to_PC(PROG_STATE);
   // LEDs - initial setting
   DDRC |= 0x03;                // LEDs on pins PC0 and PC1 
   PORTC &= ~(1<<0);            // LED0 OFF
   PORTC |= (1<<1);         // LED1 ON
   PROG_STATE = 2;
   Send_to_PC(PROG_STATE);
   pulse_init();
   PROG_STATE = 4;
   Send_to_PC(PROG_STATE);
   // Loop blinks LED0..1 alternately
   while(1)
   {
       PROG_STATE = 5;
       Send_to_PC(PROG_STATE);
       PORTC = PORTC ^ 0x03;
       _delay_ms(250);
       PROG_STATE = 6;
       Send_to_PC(PROG_STATE);
   }
}

void Send_to_PC(uint8 DATA){
//RS232 OR I2C etc
}

You get the idea. If you do something like this, then you can observe the state of your program live (apart from the debugger).

Edit:

Added Atmega32/32L internal block diagram

enter image description here

enter image description here

enter image description here