Atmega - Jumping From Firmware App To BootLoader

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

Hi,

 

Right now i have code that start running BootLoader before jumping to the Application. When I Power on  the MCU i can detect the Power On Reset from Status Register correctly (MCUSR). So when I running the Firmware and I decide to jump again to bootLoader (call jump boot_adress) the bootLoader Start correctly but the reset source is still (Power on Reset). 

 

My question is how can detect i am in the bootLoader because I just Restart the System (Power on REset) or i am in bootLoader because i jump it from Firmware Application ?

 

Thanks

Linux Embedded & Firmware Developer

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

In your application, clear the MCUSR flag bits, in the bootloader see if any flags are set, if so see if it was the power on that brought it the bootloader or a call from app (clear flags)

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
https://www.onegold.com/join/7134f67c2b814c5ca8144a458eccfd61

 

 

 

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

Hi,

 

Thank for your fast response.

 

From Firmwarae App I do this :

	// Deactive all active interrupts
	SPCR = 0;

	// Disable interrupt
	cli();

	// Enable change of interrupt vectors
	MCUCR = (1 << IVCE);

	// Move interrupts to boot flash section
	MCUCR = (1 << IVSEL);
		
	// Clear Status REgister
	MCUSR = 0;
	
 	// Jump to the Application
	asm volatile("jmp 0x7000");

From BootLoader I check :

g_power_on_reset = ((MCUSR >> PORF)  == 1);

Aways is a 1. Becasue From Power on Reset we jump to BootLoader, after that we jump to the Firmware and finally we come back to the BootLoader so It is normal that this Flag stay on 1.

 

Some body took about this way also but does not work to meet always to 0:

g_power_on_reset = (WDTCSR & (1 << WDE))

Thanks

Linux Embedded & Firmware Developer

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

It is not so normal, that the POR-flag is still '1' ... Some bootloaders (as 'optiboot' ...) start with clearing the MCUSR

 

int main(void) {

   ch = MCUSR; 

   MCUSR = 0;

   if(!(ch & _BV(EXTRF))) appStart();

...                                                                (from 'optiboot')

 

You do the same in your code, so PORF should be '0'.

 

Shouldn't checking of PORF be done by 'MCUSR & (1<<PORF)' ? Gives you '1' for set and '0' for cleared.

 

What is" (MCUSR >> PORF) == 1" doing ? (Sorry, my C is not so good ... surprise)

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

My questions:

How do you know that you correctly clear status register prior to jump to bootloader and it is set in the bootloader? Have you verified this with debugger? Are you sure that g_power_on_reset is always set to 1? Maybe it is 0 when it should be, but your bootloader code handles it incorrectly?

 

My ideas:

Write the application that contains only MCUSR clear and jump to bootloader. Write the bootloader that contains only MCUSR check and jump to application. Verify what happens with such minimum code. If the issue is still present, post the code here. Give us also information which microcontroller do you use.

 

My suggestions:

g_power_on_reset = ((MCUSR >> PORF)  == 1);

is not a good way to verify state of PORF bit. The value of (MCUSR >> PORF) depends not only on PORF bit state. You should use:

g_power_on_reset = ((MCUSR & (1 << PORF)) != 0);

Despite your issues with MCUSR, switching between application and bootloader by the jmp command is not the best idea. The application uses various microcontroller devices and when it jumps to bootloader, the microcontroller state depends on the application and this can affect operation of the bootloader. You should use reset to transit between application and bootloader. Since there is no software reset in ATMega-s, the most common way to do this is to globally disable interrupts, enable watchdog and enter infinite loop.

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

MarekJ71 wrote:
The value of (MCUSR >> PORF) depends not only on PORF bit state.
while unusual it's an interesting approach but it lacks an & 1

foo = ((MCUSR >> PORF) & 1); // extract PORF state as 0 or 1

Possibly the more "normal" way would be:

foo = !!(MCUSR & (1 << PORF)); // !! converts any non-0 int to 1

 

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

clawson wrote:
The value of (MCUSR >> PORF) depends not only on PORF bit state. while unusual it's an interesting approach but it lacks an & 1

It is unusual and in my opinion it is worse than more usual solutions. It requires right shift of the variable value and it has to be done during runtime. 1 << PORF is a constant expression and is calculated during build. I also don't like !! - there are two operations instead of one and also QAC would probably complain.

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

It's certainly "different"!