33
33
/**********************************************************/
34
34
35
35
#include <inttypes.h>
36
+ #include <string.h>
36
37
#include <avr/io.h>
37
38
#include <avr/pgmspace.h>
38
39
#include <avr/eeprom.h>
@@ -92,13 +93,21 @@ static uint8_t getch(void);
92
93
static void eat (uint8_t );
93
94
94
95
static void byte_response (uint8_t val );
95
- static void stream_response (uint8_t * val , uint8_t len );
96
+ static void stream_response (const uint8_t * val , uint8_t len );
96
97
#define nothing_response () stream_response(0, 0)
97
98
98
99
static void boot_program_page (uint32_t page , uint8_t * buf );
99
100
101
+ static void blink_led (uint8_t led );
100
102
static void launch_app (void );
101
103
104
+ #define IT_LEVEL 0
105
+ #define IT_RAISING_EDGE 1
106
+ #define IT_FALLING_EDGE 2
107
+
108
+ static void enable_interrupt (uint8_t it , uint8_t sence );
109
+ static void disable_interrupt (uint8_t it );
110
+
102
111
union address {
103
112
uint16_t word ;
104
113
struct {
@@ -115,32 +124,48 @@ union length {
115
124
} h ;
116
125
};
117
126
118
- uint8_t buff [256 ];
127
+ static uint8_t buff [256 ];
128
+ static const uint8_t sig [] = {SIG1 , SIG2 , SIG3 };
129
+ static volatile uint8_t loop_forever = 0 ;
130
+
131
+ ISR (INT0_vect , ISR_BLOCK )
132
+ {
133
+ disable_interrupt (0 );
119
134
120
- uint8_t sig [] = {SIG1 , SIG2 , SIG3 };
135
+ loop_forever = 1 ;
136
+
137
+ outb (LED_PORT , inb (LED_PORT ) & ~_BV (LED1 ));
138
+ sbi (LED_DDR , LED1 );
139
+ }
140
+
141
+ ISR (INT1_vect , ISR_BLOCK )
142
+ {
143
+ launch_app ();
144
+ }
121
145
122
146
int main (void )
123
147
{
124
- uint8_t i , ch ;
148
+ uint8_t ch ;
125
149
uint8_t eeprom ;
126
150
union length length ;
127
151
union address address ;
128
152
129
- cli (); // Disable interrupts, just to be sure
130
-
131
- /* initialize UART(s) depending on CPU defined */
153
+ /* initialize UART */
132
154
UBRRH = (((F_CPU /BAUD_RATE )/16 )- 1 )>>8 ; // set baud rate
133
155
UBRRL = (((F_CPU /BAUD_RATE )/16 )- 1 );
134
156
UCSRB = (1 <<RXEN )|(1 <<TXEN ); // enable Rx & Tx
135
157
UCSRC = (1 <<URSEL )|(1 <<UCSZ1 )|(1 <<UCSZ0 ); // config USART; 8N1
136
158
137
- /* blink the LED */
138
- outb (LED_PORT , inb (LED_PORT ) | _BV (LED0 ));
139
- sbi (LED_DDR , LED0 );
140
- for (i = 0 ; i < 16 ; ++ i ) {
141
- outb (LED_PORT , inb (LED_PORT ) ^ _BV (LED0 ));
142
- _delay_loop_2 (0 );
143
- }
159
+ // Move interrupt vectors to the beginning of bootloader section
160
+ GICR = 1 <<IVCE ;
161
+ GICR = 1 <<IVSEL ;
162
+
163
+ enable_interrupt (0 , IT_RAISING_EDGE );
164
+ enable_interrupt (1 , IT_RAISING_EDGE );
165
+
166
+ blink_led (LED0 );
167
+
168
+ sei ();
144
169
145
170
/* forever */
146
171
for (;;) {
@@ -154,7 +179,6 @@ int main(void)
154
179
nothing_response ();
155
180
}
156
181
157
- #if 0
158
182
/* Request programmer ID */
159
183
/* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
160
184
/* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
@@ -171,15 +195,12 @@ int main(void)
171
195
putch (0x10 );
172
196
}
173
197
}
174
- #endif
175
198
176
- #if 0
177
199
/* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
178
200
else if (ch == '@' ) {
179
201
if (getch () > 0x85 ) getch ();
180
202
nothing_response ();
181
203
}
182
- #endif
183
204
184
205
/* AVR ISP/STK500 board requests */
185
206
else if (ch == 'A' ) {
@@ -222,12 +243,10 @@ int main(void)
222
243
launch_app ();
223
244
}
224
245
225
- #if 0
226
246
/* Erase device, don't care as we will erase one page at a time anyway. */
227
247
else if (ch == 'R' ) {
228
248
nothing_response ();
229
249
}
230
- #endif
231
250
232
251
/* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
233
252
else if (ch == 'V' ) {
@@ -280,6 +299,9 @@ int main(void)
280
299
boot_program_page (address .word , b );
281
300
#else
282
301
asm volatile (
302
+ "lds r19,%1 \n" // Save status register and disable interrupts.
303
+ "cli \n"
304
+
283
305
"clr r17 \n" // word count
284
306
285
307
"ldi r18,0x03 \n" // Erase page pointed to by Z ((1<<PGERS) | (1<<SPMEN))
@@ -298,7 +320,7 @@ int main(void)
298
320
"adiw r30,2 \n" // Next word in FLASH
299
321
300
322
"inc r17 \n"
301
- "cpi r17,%1 \n"
323
+ "cpi r17,%2 \n"
302
324
"brlo push \n" // Still same page in FLASH
303
325
"rjmp write \n"
304
326
@@ -308,27 +330,28 @@ int main(void)
308
330
"sbrc r16,0 \n"
309
331
"rjmp wait_spm \n"
310
332
"wait_ee: \n" // Wait for EEPROM writes to complete
311
- "lds r16,%2 \n"
333
+ "lds r16,%3 \n"
312
334
"sbrc r16,1 \n"
313
335
"rjmp wait_ee \n"
314
336
"sts %0,r18 \n"
315
337
"spm \n"
316
338
"ret \n"
317
339
318
340
"write: \n"
319
- "mov r30,%3 \n" // Address of FLASH location (in words)
320
- "mov r31,%4 \n"
341
+ "mov r30,%4 \n" // Address of FLASH location (in words)
342
+ "mov r31,%5 \n"
321
343
322
344
"ldi r18,0x05 \n" // Write page pointed to by Z ((1<<PGWRT) | (1<<SPMEN))
323
345
"rcall do_spm \n"
324
346
325
347
"ldi r18,0x11 \n" // Re-enable RWW section ((1<<RWWSRE) | (1<<SPMEN))
326
348
"rcall do_spm \n"
327
349
328
- "clr __zero_reg__ \n" // restore zero register
350
+ "sts %1,r19 \n" // Re-enable interrupts (if they were ever enabled)
329
351
330
- : "=m" ( SPMCR ) : "M" ( SPM_PAGESIZE >> 1 ), "m" ( EECR ), "r" ( address . h . low ), "r" ( address . h . high ), "z" ( address . word ), "x" ( b ) : "r0" , "r1" , "r16" , "r17" , "r18" );
352
+ "clr __zero_reg__ \n" // restore zero register
331
353
354
+ : "=m" (SPMCR ), "=m" (SREG ) : "M" (SPM_PAGESIZE >>1 ), "m" (EECR ), "r" (address .h .low ), "r" (address .h .high ), "z" (address .word ), "x" (b ) : "r0" ,"r1" ,"r16" ,"r17" ,"r18" ,"r19" );
332
355
#endif
333
356
b += SPM_PAGESIZE ;
334
357
n -= SPM_PAGESIZE ;
@@ -372,12 +395,10 @@ int main(void)
372
395
stream_response (sig , 3 );
373
396
}
374
397
375
- #if 0
376
398
/* Read oscillator calibration byte */
377
399
else if (ch == 'v' ) {
378
400
byte_response (0x00 );
379
401
}
380
- #endif
381
402
} /* end of forever loop */
382
403
}
383
404
@@ -390,12 +411,20 @@ static void putch(uint8_t ch)
390
411
391
412
static uint8_t getch (void )
392
413
{
393
- uint32_t count = MAX_TIME_COUNT ;
414
+ uint32_t count ;
394
415
395
- while (!(inb (UCSRA ) & _BV (RXC )) && -- count );
416
+ for (;;) {
417
+ count = MAX_TIME_COUNT ;
396
418
397
- if (!count )
398
- launch_app ();
419
+ while (!(inb (UCSRA ) & _BV (RXC )) && -- count );
420
+
421
+ if (!count ) {
422
+ if (!loop_forever )
423
+ launch_app ();
424
+ } else {
425
+ break ;
426
+ }
427
+ }
399
428
400
429
return inb (UDR );
401
430
}
@@ -411,7 +440,7 @@ static void byte_response(uint8_t val)
411
440
stream_response (& val , 1 );
412
441
}
413
442
414
- static void stream_response (uint8_t * val , uint8_t len )
443
+ static void stream_response (const uint8_t * val , uint8_t len )
415
444
{
416
445
if (getch () == ' ' ) {
417
446
putch (0x14 );
@@ -426,52 +455,90 @@ static void boot_program_page(uint32_t page, uint8_t *buf)
426
455
uint16_t i , w ;
427
456
uint8_t sreg ;
428
457
429
- #if 0
430
- // Save status register and disable interrupts.
458
+ // Save status register and disable interrupts
431
459
sreg = SREG ;
432
460
cli ();
433
- #endif
434
461
435
462
eeprom_busy_wait ();
436
463
437
464
boot_page_erase (page );
438
- boot_spm_busy_wait (); // Wait until the memory is erased.
465
+ boot_spm_busy_wait (); // Wait until the memory is erased
439
466
440
467
for (i = 0 ; i < SPM_PAGESIZE ; i += 2 ) {
441
- // Set up little-endian word.
468
+ // Set up little-endian word
442
469
w = * buf ++ ;
443
470
w |= (* buf ++ ) << 8 ;
444
471
445
472
boot_page_fill (page + i , w );
446
473
}
447
474
448
- boot_page_write (page ); // Store buffer in flash page.
449
- boot_spm_busy_wait (); // Wait until the memory is written.
475
+ boot_page_write (page ); // Store buffer in flash page
476
+ boot_spm_busy_wait (); // Wait until the memory is written
450
477
451
478
// Reenable RWW-section again. We need this if we want to jump back
452
- // to the application after bootloading.
479
+ // to the application after bootloading
453
480
boot_rww_enable ();
454
481
455
- #if 0
456
- // Re-enable interrupts (if they were ever enabled).
482
+ // Re-enable interrupts (if they were ever enabled)
457
483
SREG = sreg ;
458
- #endif
459
484
}
460
485
461
- static void launch_app ( void )
486
+ static void blink_led ( uint8_t led )
462
487
{
463
488
uint8_t i ;
464
- void (* app )(void ) = 0x0000 ;
465
489
466
490
/* blink the LED */
467
- outb (LED_PORT , inb (LED_PORT ) | _BV (LED7 ));
468
- sbi (LED_DDR , LED7 );
491
+ outb (LED_PORT , inb (LED_PORT ) | _BV (led ));
492
+ sbi (LED_DDR , led );
469
493
for (i = 0 ; i < 16 ; ++ i ) {
470
- outb (LED_PORT , inb (LED_PORT ) ^ _BV (LED7 ));
494
+ outb (LED_PORT , inb (LED_PORT ) ^ _BV (led ));
471
495
_delay_loop_2 (0 );
472
496
}
497
+ }
498
+
499
+ static void launch_app (void )
500
+ {
501
+ void (* app )(void ) = 0x0000 ;
502
+
503
+ cli ();
504
+
505
+ // Move interrupt vectors to the beginning of FLASH and disable them
506
+ GICR = 1 <<IVCE ;
507
+ GICR = 0 ;
508
+
509
+ blink_led (LED7 );
510
+
511
+ /* disable all LEDs */
512
+ outb (LED_PORT , 0xFF );
473
513
474
514
app ();
475
515
}
476
516
517
+ /* Note: interrupt #2 for ATmega16 is not supported by this routine */
518
+ static void enable_interrupt (uint8_t it , uint8_t sence )
519
+ {
520
+ uint8_t shift = it << 1 ;
521
+
522
+ MCUCR &= ~(3 <<shift );
523
+ switch (sence ) {
524
+ case IT_LEVEL :
525
+ /* nothing to do */
526
+ break ;
527
+ case IT_RAISING_EDGE :
528
+ MCUCR |= 3 <<shift ;
529
+ break ;
530
+ case IT_FALLING_EDGE :
531
+ MCUCR |= 2 <<shift ;
532
+ break ;
533
+ }
534
+
535
+ GICR |= 1 << (it + 6 );
536
+ }
537
+
538
+ /* Note: interrupt #2 for ATmega16 is not supported by this routine */
539
+ static void disable_interrupt (uint8_t it )
540
+ {
541
+ GICR &= ~(1 << (it + 6 ));
542
+ }
543
+
477
544
/* end of file ATmega16BOOT.c */
0 commit comments