make bootloader able to cope with different watchdog settings
[pub/USBaspLoader.git] / firmware / spminterface.h
1 /* Name: spminterface.h
2 * Project: USBaspLoader
3 * Author: Stephan Baerwolf
4 * Creation Date: 2012-08-01
5 * Copyright: (c) 2012 by Stephan Baerwolf
6 * License: GNU GPL v2 (see License.txt)
7 */
8
9 #ifndef SPMINTERFACE_H_f70ba6adf7624275947e859bdbff0599
10 #define SPMINTERFACE_H_f70ba6adf7624275947e859bdbff0599
11
12 /*
13 * spminterface.h offers a lightweight interface by inserting
14 * an small machine-subroutine into the bootsection. (right
15 * after the interrupt-vector-table)
16 * This subroutine can be called by normal code in order to
17 * enable it to program the flash (and depending on BLB11-lockbit
18 * also the bootsection itself). Since SPM-calls from RWW-sections
19 * will fail to work. The Routine will be called "bootloader__do_spm".
20 * Its principle assembler-code is depicted below (real code is a
21 * little machinedependen).
22 * Interfaces will be the 8-bit registers r10..r13, for details
23 * also see below. As also the pageaddress-registes (Z and rampZ)
24 * are interfaced via different registers, it is possible to call
25 * this routine via indirect call (icall).
26 * Traditionally it is also possible to rcall, therefore you can
27 * define "bootloader__do_spm" for your normal code via defsym at
28 * linking time.
29 * Example for an atmega8: "-Wl,--defsym=transfer_point=0x1826"
30 * (since BOOTLOADER_ADDRESS is 0x1800 and there are
31 * 2x19 = 38 = 0x26 byte for interrupts)
32 *
33
34 bootloader__do_spm:
35 ;disable interrupts (if enabled) before calling!
36 ;you may also want to disable wdt, since this routine may busy-loop
37 ;==================================================================
38 ;-->INPUT:
39 ;spmcr (spmcrval determines SPM action) will be register: r10
40 ;MCU dependend RA(MPZ should be transfered within register: r11
41 ;lo8(Z) should be transfered within register: r12
42 ;hi8(Z) should be transfered within register: r13
43
44 ;<-->USED/CHANGED:
45 ;temp0 will be register: r11
46 ;temp1 will be register: r12
47 ;temp2 will be register: r13
48 ;Z (r31:r30) wil be changed during operation
49
50 ;<--OUT:
51 ;==================================================================
52
53 ;load pageaddress (Z) from r13:12 since it may was used for icall
54 mov rampZ, r11
55 mov r30, r12
56 mov r31, r13
57
58 wait: ;check for previous SPM complete
59 in temp1, SPMCR
60 sbrc temp1, SPMEN
61 rjmp wait
62
63 out SPMCR, spmcrval ;SPM timed sequence
64 spm
65
66 ret
67
68 *
69 */
70
71 #include <avr/io.h>
72 #include <avr/pgmspace.h>
73
74 #ifndef BOOTLOADER_ADDRESS
75 // this header is the interface for user-code
76
77
78
79
80 #else /*ifndef BOOTLOADER_ADDRESS*/
81 // this header is used directly within bootloader_do_spm
82 #include "bootloaderconfig.h"
83
84 #if HAVE_SPMINTEREFACE
85
86
87 /*
88 * insert architecture dependend "bootloader_do_spm"-code
89 *
90 * try to make this array as big as possible
91 * (so bootloader always uses 2kbytes flash)
92 */
93 #if defined (__AVR_ATmega8__) || defined (__AVR_ATmega8HVA__)
94 //assume SPMCR==0x37, SPMEN==0x00
95 const uint16_t bootloader__do_spm[22] PROGMEM = {0x0000, 0x2dec, 0x2dfd, 0xb6c7, 0xfcc0, 0xcffd, 0xbea7, 0x95e8, 0x9508,
96 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
97 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
98 #else
99 #error "bootloader__do_spm has to be adapted, since there is no architecture code, yet"
100 #endif
101
102
103 #endif
104 #endif /*ifdef BOOTLOADER_ADDRESS*/
105
106 #endif