[SOLVED] Difference between AVR sketch and Arduino sketch in Arduino IDE

Hello,

I want to change my project sketch from AVR to Arduino.

I'm running all my AVR codes on Arduino IDE.

But, one weird thing is that the same code doesn't work on Arduino sketch!! I don't know why??

I'm using TMR0 interrupt to run the code.

I think Arduino is using this timer to run its millis function, is that right? So this way I can't control timer0.

These are the sketches:

AVR sketch:

#include "multitasking.h"

int  main(){
  cli();
  TMR0_init();
  pins_init();  
  task_set(0);  
  task_set(1);
   sei();
  while(1){
    task_scan();
  }

}

Arduino sketch:

#include "multitasking.h"

void setup() {
  // put your setup code here, to run once:
  cli();
  TMR0_init();
  pins_init();  
  task_set(0);  
  task_set(1);
   sei();
}

void loop() {
    task_scan();
}

They are the same, I just replaced int main() and while(1) with void setup and void loop.

As soon as you switch from using main/while to setup/loop, that is the signal for the IDE to attach all the 'Arduino' background configuration files which include pin/port descriptors, setup for PWM and configuration of timer0 for millis() and delay() and others. You can still use the IDE with main/while and should be able to port code directly. I do most of my work with Notepad++ and a separate avr-gcc compiler, only to copy it into the IDE for the convenience of bootloading and final tweaking. I never use setup/loop.

That's the answer I want to get :slight_smile:

I also do all my libraries with Note++ and upload the application code with Arduino IDE.

Thank you so much for the answer.

  TMR0_init();

Differences in operation are likely to be inside your TMR0_init() function.
Instead of just configure the timer from its system-reset state, your code will also have to "undo" any of the configuration that the Arduino core has already applied.

There is a main() function tucked away in the Arduino core library:

int main(void)
{
 init();

 initVariant();

#if defined(USBCON)
 USBDevice.attach();
#endif
 
 setup();
    
 for (;;) {
 loop();
 if (serialEventRun) serialEventRun();
 }
        
 return 0;
}

When you define your own main(), it overrides the core library's main. In this case, the important thing about that is init() never gets called.

When you define your own main(), it overrides the core library's main. In this case, the important thing about that is init() never gets called.

Very important point.

The importance of init() however, is subject to the users' desire to gain control over system resources. In a beginner/learning mode it makes perfect sense as many of the peripherals would be unavailable without being otherwise configured. If you want complete control though, you would need to undo what init() does and/or reconfigure each peripheral independently. This means actually having to learn how to program the chip as opposed to simply attaching a cart-load of libraries and abstracting the low-level functionality. Depends really, on just what it is you want to learn. For many, the abstraction is sufficient. For others its a nuisance.

First of all I found this dude controlling all 3 timers in Arduino sketch, I ran his code and it's working perfectly, except at very high speed there's little timing not very accurate. Anyway this is the code:

//timer interrupts
//by Amanda Ghassaei
//June 2012
//https://www.instructables.com/id/Arduino-Timer-Interrupts/

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/

//timer setup for timer0, timer1, and timer2.
//For arduino uno or any board with ATMEL 328/168.. diecimila, duemilanove, lilypad, nano, mini...

//this code will enable all three arduino timer interrupts.
//timer0 will interrupt at 2kHz
//timer1 will interrupt at 1Hz
//timer2 will interrupt at 8kHz

//storage variables
boolean toggle0 = 0;
boolean toggle1 = 0;
boolean toggle2 = 0;

void setup(){
  
  //set pins as outputs

  pinMode(11, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  
cli();//stop interrupts

//set timer0 interrupt at 2kHz
  TCCR0A = 0;// set entire TCCR2A register to 0
  TCCR0B = 0;// same for TCCR2B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 2khz increments
  OCR0A = 255;// = (16*10^6) / (2000*64) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS01 and CS00 bits for 64 prescaler
  TCCR0B |= (1 << CS02)/*|(1 << CS01)*/|(1 << CS00);   
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);

//set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 1564;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) /*|(1 << CS10)*/;  
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

//set timer2 interrupt at 8kHz
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 8khz increments
  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS21 bit for 8 prescaler
  TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20);   
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);


sei();//allow interrupts

}//end setup

ISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 8
//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle0){
    digitalWrite(13,HIGH);
    toggle0 = 0;
  }
  else{
    digitalWrite(13,LOW);
    toggle0 = 1;
  }
}

ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle1){
    digitalWrite(12,HIGH);
    toggle1 = 0;
  }
  else{
    digitalWrite(12,LOW);
    toggle1 = 1;
  }
}
  
ISR(TIMER2_COMPA_vect){//timer2 interrupt 8kHz toggles pin 9
//generates pulse wave of frequency 8kHz/2 = 4kHz (takes two cycles for full wave- toggle high then toggle low)
  if (toggle2){
    digitalWrite(11,HIGH);
    toggle2 = 0;
  }
  else{
    digitalWrite(11,LOW);
    toggle2 = 1;
  }
}


void loop(){
  //do other things here
}

This is the logic analyzer testing:

westfw:

  TMR0_init();

Differences in operation are likely to be inside your TMR0_init() function.
Instead of just configure the timer from its system-reset state,

This is my TMR0_init():

void TMR0_init(void){
	// for multitasking timings
	OCR0A=157;								// time: 10ms, PS: 1024, for smooth multitasking
	TCCR0A|=0x02;							// CTC mode WGM01=1, OC0A,OC0B disconnected
	TCCR0B|=0x05;							// 1024 prescaler	
	TIMSK0|=(1<<OCIE0A)/*|(1<<OCIE0B)*/;	// TMR0 COMPA: smooth MT,COMPB: Synch MT Int Enable
}

But what you mean by:

your code will also have to "undo" any of the configuration that the Arduino core has already applied.

Do you mean that anything I do should override any Arduino configurations?

pert:
There is a main() function tucked away in the Arduino core library:
ArduinoCore-avr/cores/arduino/main.cpp at master · arduino/ArduinoCore-avr · GitHub

int main(void)

{
init();

initVariant();

#if defined(USBCON)
USBDevice.attach();
#endif

setup();
   
for (;:wink: {
loop();
if (serialEventRun) serialEventRun();
}
       
return 0;
}



When you define your own main(), it overrides the core library's main. In this case, the important thing about that is init() never gets called.

What I understood is that the first init() should call any Arduino configurations.
Then setup() would call whatever inside void setup() function.

This way anything I put in setup() should overwrite what Arduino did. Am I correct?

wolfrose:
What I understood is that the first init() should call any Arduino configurations.

It calls this:

wolfrose:
This way anything I put in setup() should overwrite what Arduino did. Am I correct?

If by "write", you mean writing to registers, yes. init() is called once when the board first starts up, then setup() is called, then loop() is called over and over again forever.

OK, I discovered the problem is in my TMR0_init():

Arduino is already setting the timers registers, so:

void TMR0_init(void){
	// for multitasking timings
	TCCR0A |= 0x02;							// CTC mode WGM01=1, OC0A,OC0B disconnected
	TCCR0B |= 0x05;							// 1024 prescaler	
	OCR0A = 255;								// time: 10ms, PS: 1024, for smooth multitasking	
	TIMSK0|=(1<<OCIE0A)/*|(1<<OCIE0B)*/;	// TMR0 COMPA: smooth MT,COMPB: Synch MT Int Enable
}

Should be:

void TMR0_init(void){
	// for multitasking timings
	TCCR0A = 0x02;							// CTC mode WGM01=1, OC0A,OC0B disconnected
	TCCR0B = 0x05;							// 1024 prescaler	
	OCR0A = 255;								// time: 10ms, PS: 1024, for smooth multitasking	
	TIMSK0|=(1<<OCIE0A)/*|(1<<OCIE0B)*/;	// TMR0 COMPA: smooth MT,COMPB: Synch MT Int Enable
}

I have to get rid of ORing the registers, because Arduino already set them up.