Skip to content

Commit e561f49

Browse files
committed
Added legacy blog articles
1 parent 7ca8f51 commit e561f49

20 files changed

+1803
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
type: post
3+
categories: code
4+
header_background: /img/atmega32u4_closeup.jpeg
5+
tags: [ bootloader, avr ]
6+
title: "AVR bootloaders: reboot into bootloader"
7+
date: 2014-01-15T10:42:53+02:00
8+
summary: "I needed to tweak the bootloader to get a working reboot into bootloader feature. With help from the AVRFreaks community, I thought it'd be a good idea to share my experience working with AVR bootloaders."
9+
lang: english
10+
logo: "/img/avr.png"
11+
aliases:
12+
- /code/on/avr-for-ble-and-ios/
13+
---
14+
15+
When dealing with firmware updates, you need to make the AVR reboot into bootloader. And
16+
there are lots of solution when you try to do that:
17+
18+
- either you force a reboot using the 'reset' button, and try to launch the avrdude command
19+
just 42ms after hitting the switch, or
20+
- you can use the not always wired up and not always working properly DTR line pushed down, or
21+
- you can wire a pin to the reset button — which is the worst solution, as avr pins are in an undefined state
22+
at startup time) or
23+
- you can use the watchdog reset to reboot.
24+
25+
My preferred solution would be the DTR line pulled down, though it's mostly an electronic
26+
solution and it does not work with newer atmega USB MCUs. So, let's have fun hacking the
27+
bootloader.
28+
29+
As I hacked this on the stk500 bootloader from Peter Fleury, I'm going to show the modifications
30+
based on that bootloader, which is known to work on all AVR from the atmega168 to the 2560. But
31+
that kind of hack could be easily patched on optiboot, the newer smaller (less than 1k) bootloader.
32+
33+
In that latest version of the firmware, patched by Mark Sproul, he fixed an issue with the watchdog
34+
timer, which we can thank him for, as we won't have to do write it. Indeed, when you set up a watchdog
35+
in your firmware for something like 1 second, that for a reason your code gets reboot, and then you
36+
have a 2 seconds timeout in bootloader mode, the watchdog will get triggered during boot time and
37+
won't be reset unless you hard reset the AVR.
38+
39+
So his code in the `_FIX_ISSUE_181_` preprocessor block fixes that:
40+
41+
uint8_t mcuStatusReg;
42+
mcuStatusReg = MCUSR;
43+
44+
__asm__ __volatile__ ("cli");
45+
__asm__ __volatile__ ("wdr");
46+
MCUSR = 0;
47+
WDTCSR |= _BV(WDCE) | _BV(WDE);
48+
WDTCSR = 0;
49+
__asm__ __volatile__ ("sei");
50+
// check if WDT generated the reset, if so, go straight to app
51+
if (mcuStatusReg & _BV(WDRF))
52+
{
53+
app_start();
54+
}
55+
56+
This code stores the reboot status register in `mcuStatusReg`, clears the watchdog reset
57+
registers, and if a watchdog caused the reboot, jump straight to address `0x00` (which
58+
`app_start()` points to).
59+
60+
Though the only minor modification we need to do here is:
61+
62+
if (mcuStatusReg & _BV(WDRF))
63+
{
64+
boot_timeout = 200000; // sixteen LED blinks
65+
} else {
66+
boot_timeout = 50000; // four LED blinks
67+
}
68+
69+
So there's a really long timeout at boot time in order for the flashing to be done.
70+
71+
And voila `\o/`
72+
73+
Don't forget to merge the bootloader with your firmware before uploading using your
74+
favorite flasher and now you can reboot into bootloader using the following code in
75+
your firmware:
76+
77+
#include <avr/wdt.h>
78+
79+
void reboot_into_bootloader(void) {
80+
wdt_enable(WDTO_15MS);
81+
for(;;);
82+
}
83+

0 commit comments

Comments
 (0)