Project

General

Profile

Statistics
| Revision:

root / trunk / bootloader / bootloader.c @ 194

History | View | Annotate | Download (3.69 KB)

1
#include "bootloader.h"
2

    
3
// Setup the default fuses
4
FUSES = {
5
    .low = (FUSE_SUT0 & FUSE_CKSEL3 & FUSE_CKSEL2 & FUSE_CKSEL0),
6
    .high = (FUSE_EESAVE & FUSE_SPIEN),
7
    .extended = (FUSE_SELFPRGEN),
8
};
9

    
10

    
11

    
12
// Error thresholds
13
#define MAX_RETRIES 5       // Number of times to retry before giving up
14

    
15
//Status LED
16
#define LED_DDR  DDRB
17
#define LED_PORT PORTB
18
#define LED      PORTB1
19

    
20
//Function prototypes
21
void (*main_start)(void) = BOOT_START/2 - 1;
22
int main(void) __attribute__ ((naked));
23

    
24
typedef union {
25
    uint8_t bytes[2];
26
    int16_t sword;
27
} rjump_t;
28

    
29

    
30
// SPM_PAGESIZE is set to 32 bytes
31
void onboard_program_write(uint16_t page, uint8_t *buf) {
32
  uint16_t i;
33

    
34
  boot_page_erase (page);
35
  boot_spm_busy_wait ();      // Wait until the memory is erased.
36

    
37
  for (i=0; i < SPM_PAGESIZE; i+=2){
38
    // Set up little-endian word.
39
    boot_page_fill (page + i, buf[i] | (buf[i+1] <<8));
40
  }
41

    
42
  boot_page_write (page);     // Store buffer in flash page.
43
  boot_spm_busy_wait();       // Wait until the memory is written.
44
}
45

    
46
int main(void) {
47
  uint8_t mbuf[PROGD_PACKET_SIZE];
48
  rjump_t jbuf;
49
  uint16_t caddr = MAIN_ADDR;
50
  uint8_t iteration;
51
  uint8_t resp;
52
  uint16_t prog_len;
53
  uint8_t i;
54
  uint8_t retries;
55

    
56
retry_jpnt:
57
  iteration = 0;
58
  retries = 0;
59
  
60
  // Clear the watchdog timer
61
  MCUSR &= ~_BV(WDRF);
62
  wdt_disable();
63
  WDTCSR = 0;
64

    
65

    
66
  rs485_init(51); //MAGIC NUMBER??
67

    
68
  //set LED pin as output
69
  LED_DDR |= 0x07;
70
  PORTB = 0x07;
71

    
72
  //Start bootloading process
73
  send_packet(TT_BOOT);
74

    
75
  resp = parse_packet(mbuf);
76

    
77
  // Enter programming mode 
78
  if (resp == TT_PROGM) {
79
    prog_len = mbuf[0];
80
    prog_len |= mbuf[1] << 8;
81

    
82
    // This will insert a NOP into the user code jump in case
83
    // the programming fails
84
    for (i = 0; i < PROGD_PACKET_SIZE; i++) {
85
      mbuf[i]= 0;
86
    }
87
    onboard_program_write(BOOT_START - SPM_PAGESIZE, mbuf);
88

    
89
  // Run user code
90
  } else {
91
      main_start();
92
  }
93

    
94
  send_packet(TT_ACK);
95

    
96
  while(1) {
97
      resp = parse_packet(mbuf);
98

    
99
      if (resp == TT_PROGD) {
100
          // We need to muck with the reset vector jump in the first page
101
          if (iteration == 0) {
102
              // Store the jump to user code
103
              jbuf.bytes[0] = mbuf[0];
104
              jbuf.bytes[1] = mbuf[1];
105
             
106
              // Rewrite the user code jump to be correct since we are
107
              // using relative jumps (rjmp)
108
              jbuf.sword &= 0x0FFF;
109
              jbuf.sword -= (BOOT_START >> 1) - 1;
110
              jbuf.sword &= 0x0FFF;
111
              jbuf.sword |= 0xC000;
112

    
113
              // Rewrite the reset vector to jump to the bootloader
114
              mbuf[0] = (BOOT_START/2 - 1) & 0xFF;
115
              mbuf[1] = 0xC0 | (((BOOT_START/2 - 1) >> 8) & 0x0F);
116

    
117
              iteration = 1;
118
          }
119

    
120
          // Write the page to the flash
121
          onboard_program_write(caddr, mbuf);
122
          caddr += PROGD_PACKET_SIZE;
123
          retries = 0;
124
      } else {
125
          send_packet(TT_NACK);
126
          retries++;
127

    
128
          // If we failed too many times, reset. This goes to the start
129
          // of the bootloader function
130
          if (retries > MAX_RETRIES) {
131
              goto retry_jpnt;
132
          }
133
      }
134

    
135
      send_packet(TT_ACK);
136

    
137
      // Once we write the last packet we must override the jump to
138
      // user code to point to the correct address
139
      if (prog_len <= PROGD_PACKET_SIZE) {
140
          for (i = 0; i < PROGD_PACKET_SIZE; i++) {
141
              mbuf[i]= 0;
142
          }
143

    
144
          mbuf[PROGD_PACKET_SIZE-2] = jbuf.bytes[0];
145
          mbuf[PROGD_PACKET_SIZE-1] = jbuf.bytes[1];
146

    
147
          onboard_program_write(BOOT_START - SPM_PAGESIZE, mbuf);
148

    
149
          main_start();
150
      } else { 
151
          prog_len -= PROGD_PACKET_SIZE;
152
      }
153
  }
154

    
155
  // Should never get here
156
  return -1;
157
}