0

I am writing C code that gets uploaded to arduino uno. It was a simple exercise in learning how to call the ISR in C. Here is the code:

#include<stdio.h>
#include<stdlib.h>
#include<avr/interrupt.h>
#include<avr/io.h>


int main(){

 DDRB        = 0;
 PORTB       = 0;
 DDRB        = (1<<5);
 PORTB       = (0<<5);

 //resetting the Timer/Counter1
 TCNT1H         = 0;
 TCNT1L         = 0;  

 //disabling all global interrupts
 SREG         = 0;

 //defining prescalar

 //TCCR1B: ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
 TCCR1B = 0;
 //TCCR1B_reg = CS11_val; WORKING SETTINGS
 TCCR1B = 0b00000101;//(1<<CS10_val)|(1<<CS12_val);

 //setting up PWM mode

 //TCCR1A: COM1A1 COM1A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
 TCCR1A      = 0; //this is for waveform generation and CTC setting up mode;
 //TCCR1A      = 0b10000000;//(1<<COM1A1_val);
 TCCR1A      = COM1A1;

 OCR1AH      = 0b10011100;//0b00000000;
 OCR1AL      = 0b01000000;//0b01000000;

 TIMSK1      = 0b00100010;//(1<<ICIE1_val)|(1<<OCIE1A_val);//0b00100010;//writing so that output compare A is set up

 //enable global interrupts
 SREG         = (1<<7);
 while(1){}

 return 0;

}

ISR(TIMER1_COMPA_vect){
  PORTB = PORTB^(1<<5);
}

The interesting part is when I get rid of the "while(1){}" the code doesn't seem to work to toggle PinB5 (builtin led on arduino uno). As soon as I added in the while loop I saw PinB5 toggling. The weird part is that when I want to use the timer to make a PWM that outputs directly to a Pin I don't need to use the while loop.

Just in case you guys are curious, here is how I upload to arudino-uno:

avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o ISR_example.o ISR_example.c
avr-gcc -mmcu=atmega328p ISR_example.o -o ISR_example
avr-objcopy -O ihex -R .eeprom ISR_example ISR_example.hex

read -p "Get ready to flash!"
#flashing the Arduino:
avrdude -C/home/ashwini/Downloads/arduino-1.8.3/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:ISR_example.hex:i
ahat
  • 343
  • 3
  • 9
  • 1
    depends on what the bootstrap looks like, one would hope/expect it would just fall into an infinite loop and do the same thing, but perhaps that is not the case here. A quick disassembly around the call to main() would help. – old_timer Aug 07 '17 at 03:43
  • @old_timer "Standard" AVR startup code just does `CLI` end ends in the dead loop. – 0___________ Aug 07 '17 at 22:14

2 Answers2

1

Very simple answer. When main returns on most AVR toolchains it evecutes cli instruction disabling the interrupts and then ends in the infinitive loop. This is the most common epilogue routine in the AVR bare metal toolchains.

This is what is happening when you exit from the main

00000078 <_exit>:
  78:   f8 94           cli

0000007a <__stop_program>:
  7a:   ff cf           rjmp    .-2         ; 0x7a <__stop_program>

You can change it by amending the startup assembly file (it contains the epilogue as well).

0___________
  • 60,014
  • 4
  • 34
  • 74
-1

Without the busy-loop, the program will immediately return 0, and end. While it is in the loop, doing nothing, it can be interrupted by an Interrupt Service Routine.

JGroven
  • 613
  • 1
  • 9
  • 14
  • Why isn't the while loop needed when I created a PWM? Is that functionally different than the Interrupt Service Routine? I am guessing that the "Interrupt" means that it has to interrupt a process and without the while loop there is nothing to interrupt? – ahat Aug 07 '17 at 03:22
  • 2
    PWM is handled by the hardware timers. It isn't driven by code at all. – Delta_G Aug 07 '17 at 04:58
  • @JGroven AVR toolchains do not care about the return value. In the uC something like `end` does not exist. Do some researches before answering questions – 0___________ Aug 07 '17 at 22:12
  • 1
    @ahat unless it is the software PWM & needs the interrupts you do not need the loop in the main as epilogue routines do not change anything except interrupts. But actually it looks horrible and you do not have any contol - if the startup changes and you recompile your code - it might not work if they change something. This dead loop is just the single machine code instruction – 0___________ Aug 07 '17 at 22:17