Contiki-Inga 3.x
bootloader.c
1 #include "bootloader.h"
2 #include "dev/watchdog.h"
3 #include <util/delay.h>
4 #include <avr/wdt.h>
5 #include <avr/interrupt.h>
6 #include <avr/pgmspace.h>
7 #include "dev/usb/usb_drv.h"
8 #include <avr/pgmspace.h>
9 #include <avr/interrupt.h>
10 #include <avr/eeprom.h>
11 
12 /* Not all AVR toolchains alias MCUSR to the older MSUSCR name */
13 #if !defined (MCUSR) && defined (MCUCSR)
14 #warning *** MCUSR not defined, using MCUCSR instead ***
15 #define MCUSR MCUCSR
16 #endif
17 
18 #ifndef EEPROM_MAGIC_BYTE_ADDR
19 #define EEPROM_MAGIC_BYTE_ADDR (uint8_t*)(E2END-3)
20 #endif
21 
22 volatile uint32_t Boot_Key ATTR_NO_INIT;
23 
24 extern void Bootloader_Jump_Check(void) ATTR_INIT_SECTION(3);
25 
26 bool
27 bootloader_is_present(void)
28 {
29 #if defined(BOOTLOADER_START_ADDRESS)
30  return pgm_read_word_far(BOOTLOADER_START_ADDRESS) != 0xFFFF;
31 #else
32  return false;
33 #endif
34 }
35 
36 void
37 Jump_To_Bootloader(void)
38 {
39  /* Disable all interrupts */
40  cli();
41 
42 #ifdef UDCON
43  /* If USB is used, detach from the bus */
44  Usb_detach();
45 
46  uint8_t i;
47 
48  /* Wait two seconds for the USB detachment to register on the host */
49  for(i = 0; i < 200; i++) {
50  _delay_ms(10);
52  }
53 #endif
54 
55  /* Set the bootloader key to the magic value and force a reset */
56  Boot_Key = MAGIC_BOOT_KEY;
57 
58  eeprom_write_byte(EEPROM_MAGIC_BYTE_ADDR, 0xFF);
59 
60  /* Enable interrupts */
61  sei();
62 
64 }
65 
66 void
67 Bootloader_Jump_Check(void)
68 {
69  /* If the reset source was the bootloader and the key is correct,
70  * clear it and jump to the bootloader
71  */
72  if(MCUSR & (1 << WDRF)) {
73  MCUSR = 0;
74  if(Boot_Key == MAGIC_BOOT_KEY) {
75  Boot_Key = 0;
76  wdt_disable();
77 
78  /* Disable all interrupts */
79  cli();
80 
81  eeprom_write_byte(EEPROM_MAGIC_BYTE_ADDR, 0xFF);
82 
83  /* Enable interrupts */
84  sei();
85 
86  ((void (*)(void))(BOOTLOADER_START_ADDRESS)) ();
87  } else {
88  /* The watchdog fired. Probably means we
89  * crashed. Wait two seconds before continuing.
90  */
91 
92  Boot_Key++;
93  uint8_t i;
94 
95  for(i = 0; i < 200; i++) {
96  _delay_ms(10);
98  }
99  }
100  } else {
101  Boot_Key = MAGIC_BOOT_KEY - 4;
102  }
103 }