test.c


1
#include <string.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/boot.h>
5
#include <util/delay.h>
6
#include "uart/uart.h"
7
8
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */
9
#define XON                     17       /* XON Zeichen */
10
#define XOFF                    19       /* XOFF Zeichen */
11
#define START_SIGN              ':'      /* Hex-Datei Zeilenstartzeichen */
12
13
/* Zustände des Bootloader-Programms */
14
#define BOOT_STATE_EXIT          0
15
#define BOOT_STATE_PARSER       1
16
17
/* Zustände des Hex-File-Parsers */
18
#define PARSER_STATE_START      0
19
#define PARSER_STATE_SIZE       1
20
#define PARSER_STATE_ADDRESS    2
21
#define PARSER_STATE_TYPE       3
22
#define PARSER_STATE_DATA       4
23
#define PARSER_STATE_CHECKSUM   5
24
#define PARSER_STATE_ERROR      6
25
26
ISR(BADISR_vect) {
27
  
28
}
29
30
void program_page (uint32_t page, uint8_t *buf)
31
{
32
  uint16_t i;
33
  uint8_t sreg;
34
  
35
  /* Disable interrupts */
36
  sreg = SREG;
37
  cli();
38
  
39
  eeprom_busy_wait ();
40
  
41
  boot_page_erase (page);
42
  boot_spm_busy_wait ();      /* Wait until the memory is erased. */
43
  
44
  for (i=0; i<SPM_PAGESIZE; i+=2)
45
  {
46
    /* Set up little-endian word. */
47
    uint16_t w = *buf++;
48
    w += (*buf++) << 8;
49
    
50
    boot_page_fill (page + i, w);
51
  }
52
  
53
  boot_page_write (page);     /* Store buffer in flash page.    */
54
  boot_spm_busy_wait();       /* Wait until the memory is written.*/
55
  
56
  /* Reenable RWW-section again. We need this if we want to jump back */
57
  /* to the application after bootloading. */
58
  boot_rww_enable ();
59
  
60
  /* Re-enable interrupts (if they were ever enabled). */
61
  SREG = sreg;
62
}
63
64
static uint16_t hex2num (const uint8_t * ascii, uint8_t num)
65
{
66
  uint8_t  i;
67
  uint16_t val = 0;
68
  
69
  for (i=0; i<num; i++)
70
  {
71
    uint8_t c = ascii[i];
72
    
73
    /* Hex-Ziffer auf ihren Wert abbilden */
74
    if (c >= '0' && c <= '9')            c -= '0';
75
    else if (c >= 'A' && c <= 'F')       c -= 'A' - 10;
76
    else if (c >= 'a' && c <= 'f')       c -= 'a' - 10;
77
    
78
    val = 16 * val + c;
79
  }
80
  
81
  return val;
82
}
83
84
int main()
85
{
86
          /* Empfangenes Zeichen + Statuscode */
87
  uint16_t        c = 0,
88
          /* Intel-HEX Zieladresse */
89
          hex_addr = 0,
90
          /* Zu schreibende Flash-Page */
91
          flash_page = 0,
92
          /* Intel-HEX Checksumme zum Überprüfen des Daten */
93
          hex_check = 0,
94
          /* Positions zum Schreiben in der Datenpuffer */
95
          flash_cnt = 0;
96
          /* temporäre Variable */
97
  uint8_t         temp,
98
          /* Flag zum steuern des Programmiermodus */
99
          boot_state = BOOT_STATE_EXIT,
100
          /* Empfangszustandssteuerung */
101
          parser_state = PARSER_STATE_START,
102
          /* Flag zum ermitteln einer neuen Flash-Page */
103
          flash_page_flag = 1,
104
          /* Datenpuffer für die Hexdaten*/
105
          flash_data[SPM_PAGESIZE],
106
          /* Position zum Schreiben in den HEX-Puffer */
107
          hex_cnt = 0,
108
          /* Puffer für die Umwandlung der ASCII in Binärdaten */
109
          hex_buffer[5],
110
          /* Intel-HEX Datenlänge */
111
          hex_size = 0,
112
          /* Zähler für die empfangenen HEX-Daten einer Zeile */
113
          hex_data_cnt = 0,
114
          /* Intel-HEX Recordtype */
115
          hex_type = 0,
116
          /* empfangene HEX-Checksumme */
117
          hex_checksum=0;
118
          /* Funktionspointer auf 0x0000 */
119
  void            (*start)( void ) = 0x0000;
120
  
121
  /* Füllen der Puffer mit definierten Werten */
122
  memset(hex_buffer, 0x00, sizeof(hex_buffer));
123
  memset(flash_data, 0xFF, sizeof(flash_data));
124
  
125
  /* Interrupt Vektoren verbiegen */
126
  temp = MCUCR;
127
  MCUCR = temp | (1<<IVCE);
128
  MCUCR = temp | (1<<IVSEL);
129
  
130
  /* Einstellen der Baudrate und aktivieren der Interrupts */
131
  uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) );
132
  sei();
133
  
134
  uart_puts("Hallo hier ist der echte Bootloader\r\n");
135
  _delay_ms(2000);
136
  
137
  DDRC |= (1 << PC0);
138
  
139
  do
140
  {
141
    c = uart_getc();
142
    if( !(c & UART_NO_DATA) )
143
    {
144
      /* Programmzustand: Parser */
145
      if(boot_state == BOOT_STATE_PARSER)
146
      {
147
        switch(parser_state)
148
        {
149
          /* Warte auf Zeilen-Startzeichen */
150
          case PARSER_STATE_START:
151
          if((uint8_t)c == START_SIGN)
152
          {
153
            uart_putc(XOFF);
154
            parser_state = PARSER_STATE_SIZE;
155
            hex_cnt = 0;
156
            hex_check = 0;
157
            uart_putc(XON);
158
          }
159
          break;
160
          /* Parse Datengröße */
161
          case PARSER_STATE_SIZE:
162
          hex_buffer[hex_cnt++] = (uint8_t)c;
163
          if(hex_cnt == 2)
164
          {
165
            uart_putc(XOFF);
166
            parser_state = PARSER_STATE_ADDRESS;
167
            hex_cnt = 0;
168
            hex_size = (uint8_t)hex2num(hex_buffer, 2);
169
            hex_check += hex_size;
170
            uart_putc(XON);
171
          }
172
          break;
173
          /* Parse Zieladresse */
174
          case PARSER_STATE_ADDRESS:
175
          hex_buffer[hex_cnt++] = (uint8_t)c;
176
          if(hex_cnt == 4)
177
          {
178
            uart_putc(XOFF);
179
            parser_state = PARSER_STATE_TYPE;
180
            hex_cnt = 0;
181
            hex_addr = hex2num(hex_buffer, 4);
182
            hex_check += (uint8_t) hex_addr;
183
            hex_check += (uint8_t) (hex_addr >> 8);
184
            if(flash_page_flag)
185
            {
186
              flash_page = hex_addr - hex_addr % SPM_PAGESIZE;
187
              flash_page_flag = 0;
188
            }
189
            uart_putc(XON);
190
          }
191
          break;
192
          /* Parse Zeilentyp */
193
          case PARSER_STATE_TYPE:
194
          hex_buffer[hex_cnt++] = (uint8_t)c;
195
          if(hex_cnt == 2)
196
          {
197
            uart_putc(XOFF);
198
            hex_cnt = 0;
199
            hex_data_cnt = 0;
200
            hex_type = (uint8_t)hex2num(hex_buffer, 2);
201
            hex_check += hex_type;
202
            switch(hex_type)
203
            {
204
              case 0: parser_state = PARSER_STATE_DATA; break;
205
              case 1: parser_state = PARSER_STATE_CHECKSUM; break;
206
              default: parser_state = PARSER_STATE_DATA; break;
207
            }
208
            uart_putc(XON);
209
          }
210
          break;
211
          /* Parse Flash-Daten */
212
          case PARSER_STATE_DATA:
213
          hex_buffer[hex_cnt++] = (uint8_t)c;
214
          if(hex_cnt == 2)
215
          {
216
            uart_putc(XOFF);
217
            uart_putc('.');
218
            hex_cnt = 0;
219
            flash_data[flash_cnt] = (uint8_t)hex2num(hex_buffer, 2);
220
            hex_check += flash_data[flash_cnt];
221
            flash_cnt++;
222
            hex_data_cnt++;
223
            if(hex_data_cnt == hex_size)
224
            {
225
              parser_state = PARSER_STATE_CHECKSUM;
226
              hex_data_cnt=0;
227
              hex_cnt = 0;
228
            }
229
            /* Puffer voll -> schreibe Page */
230
            if(flash_cnt == SPM_PAGESIZE)
231
            {
232
              uart_puts("P\r\n");
233
              _delay_ms(100);
234
              program_page((uint16_t)flash_page, flash_data);
235
              memset(flash_data, 0xFF, sizeof(flash_data));
236
              flash_cnt = 0;
237
              flash_page_flag = 1;
238
            }
239
            uart_putc(XON);
240
          }
241
          break;
242
          /* Parse Checksumme */
243
          case PARSER_STATE_CHECKSUM:
244
          hex_buffer[hex_cnt++] = (uint8_t)c;
245
          if(hex_cnt == 2)
246
          {
247
            uart_putc(XOFF);
248
            hex_checksum = (uint8_t)hex2num(hex_buffer, 2);
249
            hex_check += hex_checksum;
250
            hex_check &= 0x00FF;
251
            /* Dateiende -> schreibe Restdaten */
252
            if(hex_type == 1)
253
            {
254
              uart_puts("P\r\n");
255
              _delay_ms(100);
256
              program_page((uint16_t)flash_page, flash_data);
257
              boot_state = BOOT_STATE_EXIT;
258
            }
259
            /* Überprüfe Checksumme -> muss '0' sein */
260
            if(hex_check == 0) parser_state = PARSER_STATE_START;
261
            else parser_state = PARSER_STATE_ERROR;      
262
            uart_putc(XON);
263
          }
264
          break;
265
          /* Parserfehler (falsche Checksumme) */
266
          case PARSER_STATE_ERROR:
267
          uart_putc('#');
268
          break;
269
          default:
270
          break;
271
        }
272
      }
273
      /* Programmzustand: UART Kommunikation */
274
      else if(boot_state != BOOT_STATE_PARSER)
275
      {
276
        switch((uint8_t)c)
277
        {
278
          case 'p':
279
          boot_state = BOOT_STATE_PARSER;
280
          uart_puts("Programmiere den Flash!\r\n");
281
          uart_puts("Kopiere die Hex-Datei und füge sie"
282
          " hier ein (rechte Maustaste)\r\n");
283
          break;
284
          case 'q':
285
          boot_state = BOOT_STATE_EXIT;
286
          uart_puts("Verlasse den Bootloader!\r\n");
287
          break;
288
          case 'x':
289
          do
290
          {
291
            c = uart_getc();
292
            if( !(c & UART_NO_DATA) )
293
            {
294
              if (c == 'o') {
295
                uart_puts("XOFF kommt in 1 Sekunde...\r\n");
296
                _delay_ms(1000);
297
                uart_putc(XOFF);
298
                uart_puts("XON kommt in 1 Sekunde...\r\n");
299
                _delay_ms(1000);
300
                uart_putc(XON);
301
              }
302
              else
303
              {
304
                uart_puts("Du hast folgendes Zeichen gesendet: ");
305
                uart_putc((unsigned char)c);
306
                uart_puts("\r\n");
307
              }
308
            }
309
          } while (c != 'q');
310
          break;
311
          default:
312
          uart_puts("Du hast folgendes Zeichen gesendet: ");
313
          uart_putc((unsigned char)c);
314
          uart_puts("\r\n");
315
          break;
316
        }
317
      }
318
    }
319
  }
320
  while(boot_state!=BOOT_STATE_EXIT);
321
  
322
  uart_puts("Reset AVR!\r\n");
323
  _delay_ms(1000);
324
  
325
  /* Interrupt Vektoren wieder gerade biegen */
326
  temp = MCUCR;
327
  MCUCR = temp | (1<<IVCE);
328
  MCUCR = temp & ~(1<<IVSEL);
329
  
330
  /* Reset */
331
  start();
332
  
333
  return 0;
334
}