Project

General

Profile

Statistics
| Revision:

root / trunk / toolbox / bootloader / bootloader.c @ 162

History | View | Annotate | Download (5.06 KB)

1

    
2

    
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <avr/boot.h>
6

    
7
#include "tooltron.h"
8
#include "uart.h"
9

    
10
#define TRUE        0
11
#define FALSE        1
12

    
13
#define ADDR    18
14

    
15

    
16
#define MAX_WAIT_IN_CYCLES 800000
17
#define MAX_TIMEOUT 60000        // Seconds to wait before exiting bootloader mode
18
#define MAIN_ADDR 0x400
19

    
20
//Status LED
21
#define LED_DDR  DDRB
22
#define LED_PORT PORTB
23
#define LED      PORTB1
24

    
25
//#define PAGE_SIZE 32
26

    
27
//Function prototypes
28
void flash_led(uint8_t);
29
void onboard_program_write(uint16_t page, uint8_t *buf);
30
void (*main_start)(void) = MAIN_ADDR;
31

    
32
//Variables
33
uint8_t incoming_page_data[PAGE_SIZE];
34
uint8_t page_length;
35
uint8_t retransmit_flag = FALSE;
36

    
37
uint8_t sec;
38
uint8_t min;
39

    
40
union page_address_union {
41
  uint16_t word;
42
  uint8_t  byte[2];
43
} page_address;
44

    
45
typedef enum {
46
    sd,
47
    src,
48
    dest,
49
    comd,
50
    read,
51
    cs,
52
    ack
53
} state_t;
54

    
55
void init_timer(void) {
56
    // Clear timmer on OCRA1 Compare match
57
    // No prescale
58
    TCCR1B |= _BV(WGM12) | _BV(CS12);
59
    
60
    // 1 second @ 8MHz clock
61
    OCR1AH =0x7A;
62
    OCR1AL =0x12;
63

    
64
    TIMSK = _BV(OCIE1A);
65

    
66
    sec = 0;
67
    min = 0;
68
}
69

    
70
void reset_timer(void) {
71
    sec = 0;
72
    min = 0;
73
}
74

    
75
ISR(TIMER1_COMPA_vect) {
76
    if (sec == 59) {
77
        sec = 0;
78
        min++;
79
    } else {
80
        sec++;
81
    }
82
}
83

    
84
char parse_packet(uint8_t *mbuf) {
85
  uint8_t r = 0;        // Byte from the network
86
  uint8_t crc = 0;      // Running checksum of the packet
87
  uint8_t cmd = 0;      // The command received
88
  uint8_t pos = 0;      // Position in the message buffer
89
  uint8_t lim = 0;      // Max number of bytes to read into the message buf
90
  state_t state = sd;    // State machine
91
    uint16_t count;
92
  //reset_timer();
93
  count = 0;
94

    
95
  while (1) {
96
    // Wait for the next byte
97
    while ((uart_get_byte(&r)) < 0) {
98
        if (count >= MAX_TIMEOUT) {
99
            return TT_BAD;
100
       }
101
    }
102

    
103
    switch (state) {
104
        case sd:
105
            if (r == DELIM) {
106
                state = src;
107
            }
108
            break;
109

    
110
        case src:
111
            if (r == DELIM) {
112
                state = src;
113
            } else {
114
                crc = r;
115
                state = dest;
116
            }
117
            break;
118

    
119
        case dest:
120
            if (r == DELIM) {
121
                state = src;
122
            } else if (r == ADDR) {
123
                crc ^= r;
124
                state = comd;
125
            } else {
126
                state = sd;
127
            }
128
            break;
129

    
130
        case comd:
131
            cmd = r;
132
            crc ^= r;
133

    
134
            if (r == DELIM) {
135
                state = src;
136
            } else if (r == TT_PROGM) {
137
                lim = PROGM_PACKET_SIZE;
138
                state = read;
139
            } else if (r == TT_PROGD) {
140
                lim = PROGD_PACKET_SIZE;
141
                state = read;
142
            } else {
143
                state = cs;
144
            }
145
            break;
146

    
147
        case read:
148
            mbuf[pos] = r;
149
            crc ^= r;
150
            pos++;
151

    
152
            if (pos == lim) {
153
                state = cs;
154
            }
155

    
156
            break;
157
       
158
        case cs:
159
            if (r == crc) {
160
                return cmd;
161
            } else {
162
                return TT_BAD;
163
            }
164

    
165
            break;
166

    
167
        default:
168
            return TT_BAD;
169
    }
170
  }
171
}
172

    
173
void send_packet(uint8_t cmd) {
174
    uart_send_byte(DELIM);
175
    uart_send_byte(ADDR);
176
    uart_send_byte(SERVER);
177
    uart_send_byte(cmd);
178
    uart_send_byte(ACK_CRC ^ cmd);
179
}
180

    
181
int main(void)
182
{
183
    uint8_t mbuf[PROGD_PACKET_SIZE];
184
  uint16_t caddr = MAIN_ADDR;
185

    
186
  uint8_t resp;
187
  uint16_t prog_len = 0;
188

    
189
  init_uart(51); //MAGIC NUMBER??
190
  init_timer();
191
  sei();
192

    
193
  //set LED pin as output
194
  LED_DDR |= 0x07;
195
  PORTB = 0x07;
196

    
197
  //Start bootloading process
198
  send_packet(TT_BOOT);
199

    
200
  resp = parse_packet(mbuf);
201
  if (resp == TT_PROGM) {
202
    prog_len = mbuf[0];
203
    prog_len |= mbuf[1] << 8;
204
  } else {
205
      //while(1) {
206
      //    flash_led(1);
207
      //}
208
      main_start();
209
  }
210
  send_packet(TT_ACK);
211

    
212
  while(1) {
213
      resp = parse_packet(mbuf);
214

    
215
      if (resp == TT_PROGD) {
216
          onboard_program_write(caddr, mbuf);
217
          caddr += PROGD_PACKET_SIZE;
218
      } else {
219
          while(1) {
220
              flash_led(1);
221
          }
222
      }
223

    
224
      send_packet(TT_ACK);
225

    
226
      if (prog_len <= PROGD_PACKET_SIZE) {
227
          send_packet(TT_ACK);
228
          //while(1) {
229
             PORTB = 0;
230
          //}
231
          main_start();
232
      } else { 
233
          prog_len -= PROGD_PACKET_SIZE;
234
      }
235
  }
236
}
237

    
238
//#define SPM_PAGESIZE 32
239
void onboard_program_write(uint16_t page, uint8_t *buf)
240
{
241
  uint16_t i;
242

    
243
  cli();
244

    
245
  //eeprom_busy_wait();
246

    
247
  boot_page_erase (page);
248
  boot_spm_busy_wait ();      // Wait until the memory is erased.
249

    
250
  for (i=0; i < SPM_PAGESIZE; i+=2){
251
    // Set up little-endian word.
252

    
253
    //uint16_t w = *buf++;
254
    //w += (*buf++) << 8;
255
        
256
    boot_page_fill (i, buf[i] | (buf[i+1] <<8));
257
  }
258

    
259
  boot_page_write (page);     // Store buffer in flash page.
260
  boot_spm_busy_wait();       // Wait until the memory is written.
261

    
262
  sei();
263
}
264

    
265
void flash_led(uint8_t count)
266
{
267
        uint8_t i;
268
        
269
        for (i = 0; i < count; ++i) {
270
                LED_PORT |= _BV(LED);
271
                _delay_ms(100);
272
                LED_PORT &= ~_BV(LED);
273
                _delay_ms(100);
274
        }
275
}