2 This file is part of AutoQuad.
4 AutoQuad is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 AutoQuad is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with AutoQuad. If not, see <http://www.gnu.org/licenses/>.
16 Copyright © 2011 Bill Nesbitt
29 #define STM_RETRIES_SHORT 1000
30 #define STM_RETRIES_LONG 50000
32 unsigned char getResults
[11];
34 unsigned char stmHexToChar(const char *hex
) {
36 unsigned char nibble1
, nibble2
;
38 // force data to upper case
39 hex1
= toupper(hex
[0]);
40 hex2
= toupper(hex
[1]);
52 return (nibble1
<< 4 | nibble2
);
56 unsigned char stmWaitAck(serialStruct_t
*s
, int retries
) {
60 for (i
= 0; i
< retries
; i
++) {
61 if (serialAvailable(s
)) {
64 // putchar('+'); fflush(stdout);
68 putchar('-'); fflush(stdout
);
72 printf("?%x?", c
); fflush(stdout
);
82 unsigned char stmWrite(serialStruct_t
*s
, const char *hex
) {
90 c
= stmHexToChar(hex
);
91 serialWrite(s
, (char *)&c
, 1);
100 serialWrite(s
, (char *)&ck
, 1);
102 return stmWaitAck(s
, STM_RETRIES_LONG
);
105 void stmWriteCommand(serialStruct_t
*s
, char *msb
, char *lsb
, char *len
, char *data
) {
106 char startAddress
[9];
107 char lenPlusData
[128];
110 strncpy(startAddress
, msb
, sizeof(startAddress
));
111 strcat(startAddress
, lsb
);
113 sprintf(lenPlusData
, "%02x%s", stmHexToChar(len
) - 1, data
);
116 // send WRITE MEMORY command
119 serialWrite(s
, &c
, 1);
121 serialWrite(s
, &c
, 1);
122 } while (!stmWaitAck(s
, STM_RETRIES_LONG
));
125 if (!stmWrite(s
, startAddress
)) {
131 if (!stmWrite(s
, lenPlusData
)) {
136 putchar('='); fflush(stdout
);
139 char *stmHexLoader(serialStruct_t
*s
, FILE *fp
) {
140 char hexByteCount
[3], hexAddressLSB
[5], hexRecordType
[3], hexData
[128];
142 static char addressJump
[9];
144 // bzero(addressJump, sizeof(addressJump));
145 // bzero(addressMSB, sizeof(addressMSB));
146 memset(addressJump
, 0, sizeof(addressJump
));
147 memset(addressMSB
, 0, sizeof(addressMSB
));
149 while (fscanf(fp
, ":%2s%4s%2s%s\n", hexByteCount
, hexAddressLSB
, hexRecordType
, hexData
) != EOF
) {
150 unsigned int byteCount
, addressLSB
, recordType
;
152 recordType
= stmHexToChar(hexRecordType
);
153 hexData
[stmHexToChar(hexByteCount
) * 2] = 0; // terminate at CHKSUM
155 // printf("Record Type: %d\n", recordType);
156 switch (recordType
) {
158 stmWriteCommand(s
, addressMSB
, hexAddressLSB
, hexByteCount
, hexData
);
165 // MSB of destination 32 bit address
166 strncpy(addressMSB
, hexData
, 4);
169 // 32 bit address to run after load
170 strncpy(addressJump
, hexData
, 8);
178 void stmLoader(serialStruct_t
*s
, FILE *fp
, unsigned char overrideParity
, unsigned char noSendR
) {
180 unsigned char b1
, b2
, b3
;
184 // turn on parity generation
190 printf("Sending R to place Baseflight in bootloader, press a key to continue");
193 serialWrite(s
, &c
, 1);
200 printf("Poking the MCU to check whether bootloader is alive...");
204 printf("p"); fflush(stdout
);
206 serialWrite(s
, &c
, 1);
207 } while (!stmWaitAck(s
, STM_RETRIES_SHORT
));
208 printf("STM bootloader alive...\n");
213 serialWrite(s
, &c
, 1);
215 serialWrite(s
, &c
, 1);
216 } while (!stmWaitAck(s
, STM_RETRIES_LONG
));
218 b1
= serialRead(s
); // number of bytes
219 b2
= serialRead(s
); // bootloader version
221 for (i
= 0; i
< b1
; i
++)
222 getResults
[i
] = serialRead(s
);
224 stmWaitAck(s
, STM_RETRIES_LONG
);
225 printf("Received commands.\n");
228 // send GET VERSION command
231 serialWrite(s
, &c
, 1);
233 serialWrite(s
, &c
, 1);
234 } while (!stmWaitAck(s
, STM_RETRIES_LONG
));
238 stmWaitAck(s
, STM_RETRIES_LONG
);
239 printf("STM Bootloader version: %d.%d\n", (b1
& 0xf0) >> 4, (b1
& 0x0f));
241 // send GET ID command
244 serialWrite(s
, &c
, 1);
246 serialWrite(s
, &c
, 1);
247 } while (!stmWaitAck(s
, STM_RETRIES_LONG
));
249 printf("STM Device ID: 0x");
250 for (i
= 0; i
<= n
; i
++) {
254 stmWaitAck(s
, STM_RETRIES_LONG
);
261 serialWrite(s, &c, 1);
263 serialWrite(s, &c, 1);
265 // if read not allowed, unprotect (which also erases)
266 if (!stmWaitAck(s, STM_RETRIES_LONG)) {
270 serialWrite(s, &c, 1);
272 serialWrite(s, &c, 1);
273 } while (!stmWaitAck(s, STM_RETRIES_LONG));
276 if (stmWaitAck(s, STM_RETRIES_LONG))
281 if (!stmWrite(s, "1FFFF7E0"))
284 // send # bytes (N-1 = 1)
285 if (!stmWrite(s, "01"))
290 printf("STM Flash Size: %dKB\n", b2<<8 | b1);
295 printf("Global flash erase [command 0x%x]...", getResults
[6]); fflush(stdout
);
298 serialWrite(s
, &c
, 1);
300 serialWrite(s
, &c
, 1);
301 } while (!stmWaitAck(s
, STM_RETRIES_LONG
));
304 if (getResults
[6] == 0x44) {
306 if (!stmWrite(s
, "FFFF"))
311 serialWrite(s
, &c
, 1);
313 serialWrite(s
, &c
, 1);
315 if (!stmWaitAck(s
, STM_RETRIES_LONG
))
322 printf("Flashing device...\n");
323 jumpAddress
= stmHexLoader(s
, fp
);
325 printf("\nFlash complete, executing.\n");
331 serialWrite(s
, &c
, 1);
333 serialWrite(s
, &c
, 1);
334 } while (!stmWaitAck(s
, STM_RETRIES_LONG
));
337 if (!stmWrite(s
, jumpAddress
))
341 printf("\nFlash complete.\n");