[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] re-initialising an ATMega128 as much as possible (sta
From: |
Mudiaga Obada |
Subject: |
Re: [avr-gcc-list] re-initialising an ATMega128 as much as possible (start a bootloader) |
Date: |
Sun, 14 Aug 2005 14:14:44 +0200 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.11) Gecko/20050728 |
If I may ask, why go through such trouble? Instead of trying to
"un-initialise as much of the micro as possible", why not reset and
initial as little of the micro as needed?
On 29.07.2005 I posted a response to you on this list about how you
could pass information between the application and bootloader after
reseting with the WDT. I wonder if you read it...
I am attaching my bootloader entry/exit code with the hope that you
could use it to solve your bootloader issues. The trick is the magic
number thing - which you could extend for other things.
Here's how to use the code:
First you set your fuses so that the microcontroller starts with the
bootloader after each reset.
In your bootloader's main() you do
if (bootloader_disabled()) {
/* run application */
__asm__ volatile("ijmp": : "z" (0));
}
/* switch to bootloader interrupt vector */
MCUCR = _BV(IVCE);
MCUCR = _BV(IVSEL);
/* run bootloader */
To exit your bootloader (after timeout or programmer command), you do
cli();
/* switch to application interrupt vector */
MCUCR = _BV(IVCE);
MCUCR = 0;
bootloader_disable();
reset_now();
To go from application to bootloader
bootloader_start();
Regards,
Mudiaga Obada
Torsten Mohr wrote:
> i program an ATMega128, there's a bootloader at 0x1e000
> and a normal application at 0x00000.
>
> When the application starts the bootloader, it does that
> by directly jumping into it.
>
> In the bootloader i'd like to un-initialise as much of
> the micro as possible, i think it is not possible to
> initialise everything the same way as after a real reset.
>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include "clock.h"
#include "reset.h"
#include "bootloader.h"
#include "leds.h"
#define BOOTLOADER_MAGIC_NUMBER 0xB00D10AD
/*
* use start of ram as noteblock for bootloader state
*/
#define BOOTLOADER_MAGIC_NUMBER_SCRATCHPAD_PTR ((uint32_t *)0x0100)
/*
* used by init0_bootloader()
*/
static uint32_t bootloader_magic_number __attribute__((section(".noinit")));
/*
* enable bootloader for next reset by writing to scratchpad
* happends if magic number not found at magic location
*/
void bootloader_enable()
{
*(BOOTLOADER_MAGIC_NUMBER_SCRATCHPAD_PTR) = 0;
}
/*
* make sure bootloader is not invoked on next reset
*/
void bootloader_disable()
{
*(BOOTLOADER_MAGIC_NUMBER_SCRATCHPAD_PTR) = BOOTLOADER_MAGIC_NUMBER;
}
/*
* was bootloader enaabled before reset?
*/
char bootloader_disabled()
{
return (bootloader_magic_number == BOOTLOADER_MAGIC_NUMBER);
}
/*
* we want complete hardware when we enter bootloader and leave
* bootloader so "ijmp" will not cut it.
*/
void bootloader_start()
{
leds_set(0);
cli();
bootloader_enable();
reset_now();
}
/*
* this detects if magic number was set before the last reset
* this must come after init.c (destructive ramtest)
*/
void init0_bootloader() __attribute__ ((section (".init3"))) __attribute__
((naked));
void init0_bootloader()
{
/*
* transfer bootloader magic number from scratchpad to .noinit
* before crt0 initializes .data section
*/
if (*(BOOTLOADER_MAGIC_NUMBER_SCRATCHPAD_PTR) ==
BOOTLOADER_MAGIC_NUMBER) {
bootloader_magic_number = BOOTLOADER_MAGIC_NUMBER;
} else {
bootloader_magic_number = 0;
}
}
/*
* AVR hardare reset using Watchdog Timer
* (c) 2005, VSI, CS, Universitaet Frankfurt
* Authors: Mudiaga Obada
*/
#include <avr/io.h>
#include <avr/interrupt.h>
/*
* provokes a hardware reset by enabling the watchdog timer
*/
void reset_now() __attribute__((noreturn));
void reset_now()
{
/* say bye-bye to texas... */
cli();
WDTCR = _BV(WDCE) | _BV(WDE);
WDTCR = _BV(WDE);
for (;;);
}