1 | #include <avr/io.h>
|
2 | #include <string.h>
|
3 | #include <avr/boot.h>
|
4 | #include <avr/pgmspace.h>
|
5 | #include <util/crc16.h>
|
6 | #include <util/delay.h>
|
7 | #include "fat1216.h"
|
8 |
|
9 | #define USE_FLASH_LED
|
10 | #define FLASH_LED_PORT PORTG
|
11 | #define FLASH_LED_DDR DDRG
|
12 | #define FLASH_LED_PIN PG0
|
13 | #define FLASH_LED_POLARITY 0
|
14 |
|
15 | #define LEDGRUEN PG0 // Anzeige Bottloader erfolgreich beendet
|
16 | #define LEDROT PG1 // Anzeige Bottloader Fehler in der CRC
|
17 | #define SOUND PA5 // Nur zum Testen
|
18 |
|
19 |
|
20 |
|
21 | typedef struct
|
22 | {
|
23 | uint32_t dev_id;
|
24 | uint16_t app_version;
|
25 | uint16_t crc;
|
26 | } bootldrinfo_t;
|
27 |
|
28 |
|
29 | uint16_t startcluster;
|
30 | uint16_t updatecluster; //is set when update is available
|
31 | bootldrinfo_t current_bootldrinfo;
|
32 |
|
33 | void (*app_start)(void) = 0x0000;
|
34 |
|
35 | static inline void check_file(void)
|
36 | {
|
37 | //Check filesize
|
38 |
|
39 | if (filesize != FLASHEND - BOOTLDRSIZE + 1) return;
|
40 |
|
41 | bootldrinfo_t *file_bootldrinfo;
|
42 | fat1216_readfilesector(startcluster, (FLASHEND - BOOTLDRSIZE + 1) / 512 - 1);
|
43 |
|
44 | file_bootldrinfo = (bootldrinfo_t*) (uint8_t*) (fat_buf + (FLASHEND - BOOTLDRSIZE - sizeof(bootldrinfo_t) + 1) % 512);
|
45 |
|
46 | //Check DEVID
|
47 | if (file_bootldrinfo->dev_id != DEVID) return;
|
48 |
|
49 | //Check application version
|
50 | if (file_bootldrinfo->app_version < current_bootldrinfo.app_version) return;
|
51 |
|
52 | current_bootldrinfo.app_version = file_bootldrinfo->app_version;
|
53 | updatecluster = startcluster;
|
54 | }
|
55 |
|
56 | int main(void)
|
57 | {
|
58 | EIND = 1;
|
59 | uint16_t i;
|
60 |
|
61 | uint16_t filesector, j;
|
62 | uint16_t *lpword;
|
63 | uint32_t adr;
|
64 |
|
65 | DDRG |= (1<<LEDGRUEN); // Port Pin als Ausgang - Bootloader erfolgreich beendet
|
66 | DDRG |= (1<<LEDROT); // Port Pin als Ausgang - Fehlerhafte CRC
|
67 | DDRA |= (1<<SOUND); // Port Pin als Ausgang - Nur zum testen
|
68 |
|
69 | //LED On
|
70 | #ifdef USE_FLASH_LED
|
71 | FLASH_LED_DDR = 1<<FLASH_LED_PIN;
|
72 | #if !FLASH_LED_POLARITY
|
73 | FLASH_LED_PORT |= 1<<FLASH_LED_PIN;
|
74 | #endif
|
75 | #endif
|
76 |
|
77 | // Blinken lassen um den Eintritt in den Bootloader zu erkennen
|
78 | PORTG |= (1<<LEDROT);
|
79 | PORTG ^= 1<<FLASH_LED_PIN;
|
80 | _delay_ms(100);
|
81 | PORTG ^= 1<<FLASH_LED_PIN;
|
82 | _delay_ms(100);
|
83 | PORTG ^= 1<<FLASH_LED_PIN;
|
84 | _delay_ms(100);
|
85 | PORTG ^= 1<<FLASH_LED_PIN;
|
86 | PORTG &= ~ (1<<LEDROT);
|
87 |
|
88 |
|
89 | for (i=0; i<8; i++)
|
90 | ((uint8_t *)¤t_bootldrinfo)[i] = pgm_read_byte_far(FLASHEND - BOOTLDRSIZE - sizeof(bootldrinfo_t) + 1 + i);
|
91 |
|
92 | //memcpy_P(¤t_bootldrinfo, (uint8_t*) FLASHEND - BOOTLDRSIZE - sizeof(bootldrinfo_t) + 1, sizeof(bootldrinfo_t));
|
93 |
|
94 | if (current_bootldrinfo.app_version == 0xFFFF)
|
95 | current_bootldrinfo.app_version = 0; //application not flashed yet
|
96 |
|
97 | if (fat1216_init() == 0)
|
98 | {
|
99 | for (i=0; i<512; i++)
|
100 | {
|
101 | startcluster = fat1216_readRootDirEntry(i);
|
102 |
|
103 | if (startcluster == 0xFFFF)
|
104 | continue;
|
105 |
|
106 | check_file();
|
107 | }
|
108 |
|
109 | if (updatecluster)
|
110 | {
|
111 | for (filesector = 0; filesector < (FLASHEND - BOOTLDRSIZE + 1) / 512; filesector++)
|
112 | {
|
113 | #ifdef USE_FLASH_LED
|
114 | FLASH_LED_PORT ^= 1<<FLASH_LED_PIN;
|
115 | #endif
|
116 |
|
117 | lpword = (uint16_t*) fat_buf;
|
118 | fat1216_readfilesector(updatecluster, filesector);
|
119 |
|
120 | for (i=0; i<(512 / SPM_PAGESIZE); i++)
|
121 | {
|
122 | adr = (filesector * 512) + i * SPM_PAGESIZE;
|
123 | boot_page_erase(adr);
|
124 | while (boot_rww_busy())
|
125 | boot_rww_enable();
|
126 |
|
127 | for (j=0; j<SPM_PAGESIZE; j+=2)
|
128 | boot_page_fill(adr + j, *lpword++);
|
129 |
|
130 | boot_page_write(adr);
|
131 | while (boot_rww_busy())
|
132 | boot_rww_enable();
|
133 | }
|
134 | }
|
135 |
|
136 | //LED on
|
137 | #ifdef USE_FLASH_LED
|
138 | #if FLASH_LED_POLARITY
|
139 | FLASH_LED_PORT &= ~(1<<FLASH_LED_PIN);
|
140 | #else
|
141 | FLASH_LED_PORT |= 1<<FLASH_LED_PIN;
|
142 | #endif
|
143 | #endif
|
144 | }
|
145 | }
|
146 |
|
147 | unsigned short flash_crc = 0xFFFF;
|
148 |
|
149 | for (adr=0; adr<FLASHEND - BOOTLDRSIZE + 1; adr++)
|
150 | flash_crc = _crc_ccitt_update(flash_crc, pgm_read_byte_far(adr));
|
151 |
|
152 | if (flash_crc == 0)
|
153 | {
|
154 | //Led off
|
155 | #ifdef USE_FLASH_LED
|
156 | FLASH_LED_DDR = 0x00;
|
157 | #endif
|
158 | PORTG |= (1<<LEDGRUEN);
|
159 | _delay_ms(1000);
|
160 | PORTG &= ~(1<<LEDGRUEN);
|
161 | //EIND = 1;
|
162 | app_start();
|
163 | //asm volatile("jmp 0000");
|
164 | }
|
165 | else
|
166 | {
|
167 | PORTG |= (1<<LEDROT);
|
168 | _delay_ms(2000);
|
169 |
|
170 | }
|
171 | // Nur zum Testen für den Bestücker
|
172 | PORTA |= (1<<SOUND);
|
173 | _delay_ms(2000);
|
174 | PORTA &= ~(1<<SOUND);
|
175 | while (1);
|
176 | }
|