Statistics
| Branch: | Revision:

root / arduino-1.0 / hardware / arduino / bootloaders / diskloader / src / DiskLoader.cpp @ 58d82c77

History | View | Annotate | Download (4.74 KB)

1

    
2

    
3
#include "Platform.h"
4

    
5
//        This bootloader creates a composite Serial device
6
//
7
//        The serial interface supports a STK500v1 protocol that is very similar to optiboot
8
//
9
//        The bootloader will timeout and start the firmware after a few hundred milliseconds
10
//        if a usb connection is not detected.
11
//        
12
//        The tweakier code is to keep the bootloader below 2k (no interrupt table, for example)
13

    
14
extern "C"
15
void entrypoint(void) __attribute__ ((naked)) __attribute__ ((section (".vectors")));
16
void entrypoint(void)
17
{
18
        asm volatile (
19
                "eor        r1,                r1\n"        // Zero register
20
                "out        0x3F,        r1\n"        // SREG
21
                "ldi        r28,        0xFF\n"
22
                "ldi        r29,        0x0A\n"
23
                "out        0x3E,        r29\n"        // SPH
24
                "out        0x3D,        r28\n"        // SPL
25
                "rjmp        main"                        // Stack is all set up, start the main code
26
                ::);
27
}
28

    
29
u8 _flashbuf[128];
30
u8 _inSync;
31
u8 _ok;
32
extern volatile u8 _ejected;
33
extern volatile u16 _timeout;
34

    
35
void Program(u8 ep, u16 page, u8 count)
36
{
37
        u8 write = page < 30*1024;                // Don't write over firmware please
38
        if (write)
39
                boot_page_erase(page);
40

    
41
        Recv(ep,_flashbuf,count);                // Read while page is erasing
42

    
43
        if (!write)
44
                return;
45

    
46
        boot_spm_busy_wait();                        // Wait until the memory is erased.
47

    
48
        count >>= 1;
49
        u16* p = (u16*)page;
50
        u16* b = (u16*)_flashbuf;
51
        for (u8 i = 0; i < count; i++)
52
                boot_page_fill(p++, b[i]);
53

    
54
    boot_page_write(page);
55
    boot_spm_busy_wait();
56
    boot_rww_enable ();
57
}
58

    
59

    
60
int USBGetChar();
61
#define getch USBGetChar
62

    
63
#define HW_VER         0x02
64
#define SW_MAJOR 0x01
65
#define SW_MINOR 0x10
66

    
67
#define STK_OK              0x10
68
#define STK_INSYNC          0x14  // ' '
69
#define CRC_EOP             0x20  // 'SPACE'
70
#define STK_GET_SYNC        0x30  // '0'
71

    
72
#define STK_GET_PARAMETER   0x41  // 'A'
73
#define STK_SET_DEVICE      0x42  // 'B'
74
#define STK_SET_DEVICE_EXT  0x45  // 'E'
75
#define STK_LOAD_ADDRESS    0x55  // 'U'
76
#define STK_UNIVERSAL       0x56  // 'V'
77
#define STK_PROG_PAGE       0x64  // 'd'
78
#define STK_READ_PAGE       0x74  // 't'
79
#define STK_READ_SIGN       0x75  // 'u'
80

    
81
extern const u8 _readSize[] PROGMEM;
82
const u8 _readSize[] = 
83
{
84
        STK_GET_PARAMETER,        1,
85
        STK_SET_DEVICE,                20,
86
        STK_SET_DEVICE_EXT,        5,
87
        STK_UNIVERSAL,                4,
88
        STK_LOAD_ADDRESS,        2,
89
        STK_PROG_PAGE,                3,
90
        STK_READ_PAGE,                3,
91
        0,0
92
};
93

    
94
extern const u8 _consts[] PROGMEM;
95
const u8 _consts[] = 
96
{
97
        SIGNATURE_0,
98
        SIGNATURE_1,
99
        SIGNATURE_2,
100
        HW_VER,                // Hardware version
101
        SW_MAJOR,        // Software major version
102
        SW_MINOR,        // Software minor version
103
        0x03,                // Unknown but seems to be required by avr studio 3.56
104
        0x00,                // 
105
};
106

    
107

    
108
void USBInit(void);
109
int main(void) __attribute__ ((naked));
110

    
111
//        STK500v1 main loop, very similar to optiboot in protocol and implementation
112
int main()
113
{
114
        wdt_disable();
115
        TXLED0;
116
        RXLED0;
117
        LED0;
118
        BOARD_INIT();
119
        USBInit();
120

    
121
        _inSync = STK_INSYNC;
122
        _ok = STK_OK;
123

    
124
        if (pgm_read_word(0) != -1)
125
                _ejected = 1;
126

    
127
        for(;;)
128
        {
129
                u8* packet = _flashbuf;
130
                u16 address = 0;
131
                for (;;)
132
                {
133
                        u8 cmd = getch();
134

    
135
                        //        Read packet contents
136
                        u8 len;
137
                        const u8* rs = _readSize;
138
                        for(;;)
139
                        {
140
                                u8 c = pgm_read_byte(rs++);
141
                                len = pgm_read_byte(rs++);
142
                                if (c == cmd || c == 0)
143
                                        break;
144
                        }
145
                        _timeout = 0;
146
                        //        Read params
147
                        Recv(CDC_RX,packet,len);
148

    
149
                        //        Send a response
150
                        u8 send = 0;
151
                        const u8* pgm = _consts+7;                        // 0
152
                        if (STK_GET_PARAMETER == cmd)
153
                        {
154
                                u8 i = packet[0] - 0x80;
155
                                if (i > 2)
156
                                        i = (i == 0x18) ? 3 : 4;        // 0x80:HW_VER,0x81:SW_MAJOR,0x82:SW_MINOR,0x18:3 or 0
157
                                pgm = _consts + i + 3;
158
                                send = 1;
159
                        }
160

    
161
                        else if (STK_UNIVERSAL == cmd)
162
                        {
163
                                if (packet[0] == 0x30)
164
                                        pgm = _consts + packet[2];        // read signature
165
                                send = 1;
166
                        }
167
                        
168
                        //        Read signature bytes
169
                        else if (STK_READ_SIGN == cmd)
170
                        {
171
                                pgm = _consts;
172
                                send = 3;
173
                        }
174

    
175
                        else if (STK_LOAD_ADDRESS == cmd)
176
                        {
177
                                address = *((u16*)packet);                // word addresses
178
                                address += address;
179
                        }
180

    
181
                        else if (STK_PROG_PAGE == cmd)
182
                        {
183
                                Program(CDC_RX,address,packet[1]);
184
                        }
185

    
186
                        else if (STK_READ_PAGE == cmd)
187
                        {
188
                                send = packet[1];
189
                                pgm = (const u8*)address;
190
                                address += send; // not sure of this is required
191
                        }
192

    
193
                        // Check sync
194
                        if (getch() != ' ')
195
                                break;
196
                        Transfer(CDC_TX,&_inSync,1);
197

    
198
                        // Send result
199
                        if (send)
200
                                Transfer(CDC_TX|TRANSFER_PGM,pgm,send);        // All from pgm memory
201

    
202
                        //        Send ok
203
                        Transfer(CDC_TX|TRANSFER_RELEASE,&_ok,1);
204

    
205
                        if (cmd == 'Q')
206
                                break;
207
                }
208
                _timeout = 500;                // wait a moment before exiting the bootloader - may need to finish responding to 'Q' for example
209
                _ejected = 1;
210
        }
211
}
212

    
213
//        Nice breathing LED indicates we are in the firmware
214
u16 _pulse;
215
void LEDPulse()
216
{
217
        _pulse += 4;
218
        u8 p = _pulse >> 9;
219
        if (p > 63)
220
                p = 127-p;
221
        p += p;
222
        if (((u8)_pulse) > p)
223
                LED0;
224
        else
225
                LED1;
226
}
227

    
228
void Reboot()
229
{
230
        TXLED0;                // switch off the RX and TX LEDs before starting the user sketch
231
        RXLED0;
232
        UDCON = 1;                // Detatch USB
233
        UDIEN = 0;
234
        asm volatile (        // Reset vector to run firmware
235
                "clr r30\n"
236
                "clr r31\n"
237
                "ijmp\n"
238
        ::);
239
}