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 |
} |