Project

General

Profile

Statistics
| Revision:

root / trunk / bootloader / bootloader.c @ 193

History | View | Annotate | Download (3.51 KB)

1
#include "bootloader.h"
2

    
3

    
4
// Error thresholds
5
#define MAX_RETRIES 5       // Number of times to retry before giving up
6

    
7
//Status LED
8
#define LED_DDR  DDRB
9
#define LED_PORT PORTB
10
#define LED      PORTB1
11

    
12
//Function prototypes
13
void (*main_start)(void) = BOOT_START/2 - 1;
14
int main(void) __attribute__ ((naked));
15

    
16
typedef union {
17
    uint8_t bytes[2];
18
    int16_t sword;
19
} rjump_t;
20

    
21

    
22
// SPM_PAGESIZE is set to 32 bytes
23
void onboard_program_write(uint16_t page, uint8_t *buf) {
24
  uint16_t i;
25

    
26
  boot_page_erase (page);
27
  boot_spm_busy_wait ();      // Wait until the memory is erased.
28

    
29
  for (i=0; i < SPM_PAGESIZE; i+=2){
30
    // Set up little-endian word.
31
    boot_page_fill (page + i, buf[i] | (buf[i+1] <<8));
32
  }
33

    
34
  boot_page_write (page);     // Store buffer in flash page.
35
  boot_spm_busy_wait();       // Wait until the memory is written.
36
}
37

    
38
int main(void) {
39
  uint8_t mbuf[PROGD_PACKET_SIZE];
40
  rjump_t jbuf;
41
  uint16_t caddr = MAIN_ADDR;
42
  uint8_t iteration;
43
  uint8_t resp;
44
  uint16_t prog_len;
45
  uint8_t i;
46
  uint8_t retries;
47

    
48
retry_jpnt:
49
  iteration = 0;
50
  retries = 0;
51
  
52
  // Clear the watchdog timer
53
  MCUSR &= ~_BV(WDRF);
54
  wdt_disable();
55
  WDTCSR = 0;
56

    
57

    
58
  rs485_init(51); //MAGIC NUMBER??
59

    
60
  //set LED pin as output
61
  LED_DDR |= 0x07;
62
  PORTB = 0x07;
63

    
64
  //Start bootloading process
65
  send_packet(TT_BOOT);
66

    
67
  resp = parse_packet(mbuf);
68

    
69
  // Enter programming mode 
70
  if (resp == TT_PROGM) {
71
    prog_len = mbuf[0];
72
    prog_len |= mbuf[1] << 8;
73

    
74
    // This will insert a NOP into the user code jump in case
75
    // the programming fails
76
    for (i = 0; i < PROGD_PACKET_SIZE; i++) {
77
      mbuf[i]= 0;
78
    }
79
    onboard_program_write(BOOT_START - SPM_PAGESIZE, mbuf);
80

    
81
  // Run user code
82
  } else {
83
      main_start();
84
  }
85

    
86
  send_packet(TT_ACK);
87

    
88
  while(1) {
89
      resp = parse_packet(mbuf);
90

    
91
      if (resp == TT_PROGD) {
92
          // We need to muck with the reset vector jump in the first page
93
          if (iteration == 0) {
94
              // Store the jump to user code
95
              jbuf.bytes[0] = mbuf[0];
96
              jbuf.bytes[1] = mbuf[1];
97
             
98
              // Rewrite the user code jump to be correct since we are
99
              // using relative jumps (rjmp)
100
              jbuf.sword &= 0x0FFF;
101
              jbuf.sword -= (BOOT_START >> 1) - 1;
102
              jbuf.sword &= 0x0FFF;
103
              jbuf.sword |= 0xC000;
104

    
105
              // Rewrite the reset vector to jump to the bootloader
106
              mbuf[0] = (BOOT_START/2 - 1) & 0xFF;
107
              mbuf[1] = 0xC0 | (((BOOT_START/2 - 1) >> 8) & 0x0F);
108

    
109
              iteration = 1;
110
          }
111

    
112
          // Write the page to the flash
113
          onboard_program_write(caddr, mbuf);
114
          caddr += PROGD_PACKET_SIZE;
115
          retries = 0;
116
      } else {
117
          send_packet(TT_NACK);
118
          retries++;
119

    
120
          // If we failed too many times, reset. This goes to the start
121
          // of the bootloader function
122
          if (retries > MAX_RETRIES) {
123
              goto retry_jpnt;
124
          }
125
      }
126

    
127
      send_packet(TT_ACK);
128

    
129
      // Once we write the last packet we must override the jump to
130
      // user code to point to the correct address
131
      if (prog_len <= PROGD_PACKET_SIZE) {
132
          for (i = 0; i < PROGD_PACKET_SIZE; i++) {
133
              mbuf[i]= 0;
134
          }
135

    
136
          mbuf[PROGD_PACKET_SIZE-2] = jbuf.bytes[0];
137
          mbuf[PROGD_PACKET_SIZE-1] = jbuf.bytes[1];
138

    
139
          onboard_program_write(BOOT_START - SPM_PAGESIZE, mbuf);
140

    
141
          main_start();
142
      } else { 
143
          prog_len -= PROGD_PACKET_SIZE;
144
      }
145
  }
146

    
147
  // Should never get here
148
  return -1;
149
}