~ubuntu-branches/debian/experimental/arduino/experimental

« back to all changes in this revision

Viewing changes to hardware/arduino/bootloaders/diskloader/src/DiskLoader.cpp

  • Committer: Package Import Robot
  • Author(s): Scott Howard
  • Date: 2012-03-11 18:19:42 UTC
  • mfrom: (1.1.5) (5.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20120311181942-be2clnbz1gcehixb
Tags: 1:1.0.1~rc1+dfsg-1
New upstream release, experimental.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}