# AVR ATmega32 - C - Gets stuck in function call

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)

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();

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! • Codewise, there's nothing wrong with what you've done. I can't see any obvious problem, a single function called once shouldn't be a problem unless you have zero size for the stack. If I understood your question correctly and it works on one board but not on another, I would suspect hardware rather than software. Dec 28, 2016 at 11:00 • Might be incorrect stack setup. Triple-check that the correct part ist used when linking the project. Dec 28, 2016 at 11:56 • @RogerRowland I haven't actually tried compiling and programming the board that is already working with my updated code for fear of bricking it. What I have done is read the hex file off that board and program the board I'm working on with it, and it doesn't work. I suspect hardware problems as well, but I can't for the life of me find any... Maybe the chip is damaged. I just wanted to get a second opinion on the coding aspect. Dec 28, 2016 at 12:02 • @TurboJ : The linker options: -Wl,-Map="$(OutputFileName).map" -Wl,--start-group -Wl,-lm -Wl,--end-group -Wl,--gc-sections -mmcu=atmega32 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.1.130\gcc\dev\atmega32"  It's the correct part number at least, but for the other parameters I'm not so familiar with them. Dec 28, 2016 at 12:03
• @SnorreO. - the resolution of your question should not be edited into your question, as a question here is not "resolved" until an answer is accepted. If none of the existing answers contain your solution, you can post your own answer explaining it. Your theory, while not impossible does seem rather unlikely however. Jan 9, 2017 at 7:25

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);
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: