summaryrefslogtreecommitdiff
path: root/flash/uart_boot/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'flash/uart_boot/client.c')
-rw-r--r--flash/uart_boot/client.c738
1 files changed, 738 insertions, 0 deletions
diff --git a/flash/uart_boot/client.c b/flash/uart_boot/client.c
new file mode 100644
index 0000000000..a98edc60cb
--- /dev/null
+++ b/flash/uart_boot/client.c
@@ -0,0 +1,738 @@
1// client.cpp : functions for monitor download and communication.
2//
3
4#include <stdio.h>
5#include <stdlib.h>
6#include "scalar_types.h" // (U)INT8/16/32
7#include "Uart.h" // platform abstraction for UART
8#include "minimon.h" // protocol of my little monitor
9
10// do the baudrate configuration for the Player
11int ConfigFirstlevelPlayer (tUartHandle serial_handle)
12{
13 UINT32 result_nbr;
14
15 if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8))
16 {
17 UINT32 dwErr = GET_LAST_ERR();
18 printf("Error %d setting up COM params for baudrate byte\n", dwErr);
19 exit(1);
20 }
21
22 // this will read as 0x19 when viewed with 2300 baud like the player does
23 result_nbr = UartWrite(serial_handle, (UINT8*)"\x86\xC0", 2);
24 if (result_nbr != 2)
25 {
26 UINT32 dwErr = GET_LAST_ERR();
27 printf("Error %d setting up COM params for baudrate byte\n", dwErr);
28 }
29
30 SLEEP(100); // wait for the chars to be sent, is there a better way?
31
32 // the read 0x19 means 14423 baud with 12 MHz
33 if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8))
34 {
35 printf("Error setting up COM params for 1st level loader\n");
36 exit(1);
37 }
38
39 return 0;
40}
41
42
43// do the baudrate configuration for the Recoder/FM
44int ConfigFirstlevelRecorder (tUartHandle serial_handle)
45{
46 UINT32 result_nbr;
47
48 if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8))
49 {
50 UINT32 dwErr = GET_LAST_ERR();
51 printf("Error %d setting up COM params for baudrate byte\n", dwErr);
52 exit(1);
53 }
54
55 // this will read as 0x08 when viewed with 2120 baud like the recorder does
56 result_nbr = UartWrite(serial_handle, (UINT8*)"\x00\x00", 2);
57 if(result_nbr != 2)
58 {
59 printf("Error transmitting baudrate byte\n");
60 exit(1);
61 }
62
63 SLEEP(100); // wait for the chars to be sent, is there a better way?
64
65 // the read 0x08 means 38400 baud with 11.0592 MHz
66 if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8))
67 {
68 UINT32 dwErr = GET_LAST_ERR();
69 printf("Error %d setting up COM params for 1st level loader\n", dwErr);
70 exit(1);
71 }
72
73 return 0;
74}
75
76
77// transfer a byte for the monitor download, with or without acknowledge
78int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck)
79{
80 unsigned char received;
81 bool bRecorder = true; // false for player
82
83 while (1)
84 {
85 UartWrite(serial_handle, &byte, 1);
86 if (bAck)
87 {
88 UartRead(serial_handle, &received, 1);
89 if (received == byte)
90 {
91 UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success
92 break; // exit the loop
93 }
94 else
95 {
96 printf("Error transmitting monitor byte 0x%02X, got 0x%0X\n", byte, received);
97 UartWrite(serial_handle, (UINT8*)"\x00", 1); // ack fail, try again
98 }
99 }
100 else
101 break; // no loop
102 }
103 return 1;
104}
105
106
107// download our little monitor, the box must have been just freshly switched on for this to work
108int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename)
109{
110 FILE* pFile;
111 size_t filesize;
112 UINT8 byte;
113 unsigned i;
114
115 // hard-coded parameters
116 bool bAck = true; // configure if acknowledged download (without useful for remote pin boot)
117 UINT32 TargetLoad = 0x0FFFF000; // target load address
118
119 pFile = fopen(szFilename, "rb");
120 if (pFile == NULL)
121 {
122 printf("\nMonitor file %s not found, exiting\n", szFilename);
123 exit(1);
124 }
125
126 // determine file size
127 fseek(pFile, 0, SEEK_END);
128 filesize = ftell(pFile);
129 fseek(pFile, 0, SEEK_SET);
130
131 // This is _really_ tricky! The box expects a BRR value in a nonstandard baudrate,
132 // which a PC can't generate. I'm using a higher one with some wild settings
133 // to generate a pulse series that:
134 // 1) looks like a stable byte when sampled with the nonstandard baudrate
135 // 2) gives a BRR value to the box which results in a baudrate the PC can also use
136 if (bRecorder)
137 {
138 ConfigFirstlevelRecorder(serial_handle);
139 }
140 else
141 {
142 ConfigFirstlevelPlayer(serial_handle);
143 }
144
145 UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode
146
147 // transmit the size, little endian
148 DownloadByte(serial_handle, (UINT8)( filesize & 0xFF), bAck);
149 DownloadByte(serial_handle, (UINT8)((filesize>>8) & 0xFF), bAck);
150 DownloadByte(serial_handle, (UINT8)((filesize>>16) & 0xFF), bAck);
151 DownloadByte(serial_handle, (UINT8)((filesize>>24) & 0xFF), bAck);
152
153 // transmit the load address, little endian
154 DownloadByte(serial_handle, (UINT8)( TargetLoad & 0xFF), bAck);
155 DownloadByte(serial_handle, (UINT8)((TargetLoad>>8) & 0xFF), bAck);
156 DownloadByte(serial_handle, (UINT8)((TargetLoad>>16) & 0xFF), bAck);
157 DownloadByte(serial_handle, (UINT8)((TargetLoad>>24) & 0xFF), bAck);
158
159 // transmit the command byte
160 DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image
161
162 // transmit the image
163 for (i=0; i<filesize; i++)
164 {
165 fread(&byte, 1, 1, pFile);
166 DownloadByte(serial_handle, byte, bAck);
167 }
168
169 fclose (pFile);
170
171 // now the image should have been started, red LED off
172
173 return 0;
174}
175
176
177// wait for a fixed string to be received (no foolproof algorithm,
178// may overlook if the searched string contains repeatitions)
179int WaitForString(tUartHandle serial_handle, char* pszWait)
180{
181 int i = 0;
182 unsigned char received;
183
184 while(pszWait[i] != '\0')
185 {
186 UartRead(serial_handle, &received, 1);
187
188 printf("%c", received); // debug
189
190 if (received == pszWait[i])
191 i++; // continue
192 else
193 i=0; // mismatch, start over
194 }
195 return 0;
196}
197
198
199// send a sting and check the echo
200int SendWithEcho(tUartHandle serial_handle, char* pszSend)
201{
202 int i = 0;
203 unsigned char received;
204
205 while(pszSend[i] != '\0')
206 {
207 UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char
208 do
209 {
210 UartRead(serial_handle, &received, 1); // receive echo
211 printf("%c", received); // debug
212 }
213 while (received != pszSend[i]); // should normally be equal
214 i++; // next char
215 }
216 return 0;
217}
218
219
220// rarely used variant: download our monitor using the built-in Archos monitor
221int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename)
222{
223 FILE* pFile;
224 size_t filesize;
225 UINT8 byte;
226 UINT16 checksum = 0;
227 unsigned i;
228
229 // the onboard monitor uses 115200 baud
230 if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8))
231 {
232 UINT32 dwErr = GET_LAST_ERR();
233 printf("Error %d setting up COM params for baudrate %d\n", dwErr, 115200);
234 exit(1);
235 }
236
237 // wait for receiving "#SERIAL#"
238 WaitForString(serial_handle, "#SERIAL#");
239
240 // send magic "SRL" command to get interactive mode
241 SendWithEcho(serial_handle, "SRL\r");
242
243 // wait for menu completion: "ROOT>" at the end
244 WaitForString(serial_handle, "ROOT>");
245
246 // send upload command "UP"
247 SendWithEcho(serial_handle, "UP\r");
248
249 pFile = fopen(szFilename, "rb");
250 if (pFile == NULL)
251 {
252 printf("\nMonitor file %s not found, exiting\n", szFilename);
253 exit(1);
254 }
255
256 // determine file size
257 fseek(pFile, 0, SEEK_END);
258 filesize = ftell(pFile);
259 fseek(pFile, 0, SEEK_SET);
260
261 // calculate checksum
262 for (i=0; i<filesize; i++)
263 {
264 fread(&byte, 1, 1, pFile);
265 checksum += byte;
266 }
267 fseek(pFile, 0, SEEK_SET);
268
269 // send header
270
271 // size as 32 bit little endian
272 byte = (UINT8)( filesize & 0xFF);
273 UartWrite(serial_handle, &byte, 1);
274 byte = (UINT8)((filesize>>8) & 0xFF);
275 UartWrite(serial_handle, &byte, 1);
276 byte = (UINT8)((filesize>>16) & 0xFF);
277 UartWrite(serial_handle, &byte, 1);
278 byte = (UINT8)((filesize>>24) & 0xFF);
279 UartWrite(serial_handle, &byte, 1);
280
281 // checksum as 16 bit little endian
282 byte = (UINT8)( checksum & 0xFF);
283 UartWrite(serial_handle, &byte, 1);
284 byte = (UINT8)((checksum>>8) & 0xFF);
285 UartWrite(serial_handle, &byte, 1);
286
287 UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash)
288 UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
289
290 // wait for monitor to accept data
291 WaitForString(serial_handle, "#OKCTRL#");
292
293 // transmit the image
294 for (i=0; i<filesize; i++)
295 {
296 fread(&byte, 1, 1, pFile);
297 UartWrite(serial_handle, &byte, 1); // payload
298 }
299 fclose (pFile);
300
301 UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
302
303 // wait for menu completion: "ROOT>" at the end
304 WaitForString(serial_handle, "ROOT>");
305
306 // send start program command "SPRO"
307 SendWithEcho(serial_handle, "SPRO\r");
308
309 SLEEP(100); // wait a little while for startup
310
311 return 0;
312}
313
314
315/********** Target functions using the Monitor Protocol **********/
316
317// read a byte using the target monitor
318UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr)
319{
320 UINT8 send;
321 UINT8 received;
322
323 // send the address command
324 send = ADDRESS;
325 UartWrite(serial_handle, &send, 1);
326
327 // transmit the address, big endian
328 send = (UINT8)((addr>>24) & 0xFF);
329 UartWrite(serial_handle, &send, 1);
330 send = (UINT8)((addr>>16) & 0xFF);
331 UartWrite(serial_handle, &send, 1);
332 send = (UINT8)((addr>>8) & 0xFF);
333 UartWrite(serial_handle, &send, 1);
334 send = (UINT8)(addr & 0xFF);
335 UartWrite(serial_handle, &send, 1);
336
337 UartRead(serial_handle, &received, 1); // response
338 if (received != ADDRESS)
339 {
340 printf("Protocol error!\n");
341 return 1;
342 }
343
344 // send the read command
345 send = BYTE_READ;
346 UartWrite(serial_handle, &send, 1);
347
348 UartRead(serial_handle, &received, 1); // response
349
350 return received;
351}
352
353
354// write a byte using the target monitor
355int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte)
356{
357 UINT8 send;
358 UINT8 received;
359
360 // send the address command
361 send = ADDRESS;
362 UartWrite(serial_handle, &send, 1);
363
364 // transmit the address, big endian
365 send = (UINT8)((addr>>24) & 0xFF);
366 UartWrite(serial_handle, &send, 1);
367 send = (UINT8)((addr>>16) & 0xFF);
368 UartWrite(serial_handle, &send, 1);
369 send = (UINT8)((addr>>8) & 0xFF);
370 UartWrite(serial_handle, &send, 1);
371 send = (UINT8)(addr & 0xFF);
372 UartWrite(serial_handle, &send, 1);
373
374 UartRead(serial_handle, &received, 1); // response
375 if (received != ADDRESS)
376 {
377 printf("Protocol error, receiced 0x%02X!\n", received);
378 return 1;
379 }
380
381 // send the write command
382 send = BYTE_WRITE;
383 UartWrite(serial_handle, &send, 1);
384
385 // transmit the data
386 UartWrite(serial_handle, &byte, 1);
387
388 UartRead(serial_handle, &received, 1); // response
389
390 if (received != BYTE_WRITE)
391 {
392 printf("Protocol error!\n");
393 return 1;
394 }
395
396 return 0;
397}
398
399
400// read many bytes using the target monitor
401int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
402{
403 UINT8 send, received;
404
405 // send the address command
406 send = ADDRESS;
407 UartWrite(serial_handle, &send, 1);
408
409 // transmit the address, big endian
410 send = (UINT8)((addr>>24) & 0xFF);
411 UartWrite(serial_handle, &send, 1);
412 send = (UINT8)((addr>>16) & 0xFF);
413 UartWrite(serial_handle, &send, 1);
414 send = (UINT8)((addr>>8) & 0xFF);
415 UartWrite(serial_handle, &send, 1);
416 send = (UINT8)(addr & 0xFF);
417 UartWrite(serial_handle, &send, 1);
418
419 UartRead(serial_handle, &received, 1); // response
420 if (received != ADDRESS)
421 {
422 printf("Protocol error!\n");
423 return 1;
424 }
425
426 while (size)
427 {
428 if (size >= 16)
429 { // we can use a "burst" command
430 send = BYTE_READ16;
431 UartWrite(serial_handle, &send, 1); // send the read command
432 UartRead(serial_handle, pBuffer, 16); // data response
433 pBuffer += 16;
434 size -= 16;
435 }
436 else
437 { // use single byte command
438 send = BYTE_READ;
439 UartWrite(serial_handle, &send, 1); // send the read command
440 UartRead(serial_handle, pBuffer++, 1); // data response
441 size--;
442 }
443 }
444
445 return 0;
446}
447
448
449// write many bytes using the target monitor
450int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
451{
452 UINT8 send, received;
453
454 // send the address command
455 send = ADDRESS;
456 UartWrite(serial_handle, &send, 1);
457
458 // transmit the address, big endian
459 send = (UINT8)((addr>>24) & 0xFF);
460 UartWrite(serial_handle, &send, 1);
461 send = (UINT8)((addr>>16) & 0xFF);
462 UartWrite(serial_handle, &send, 1);
463 send = (UINT8)((addr>>8) & 0xFF);
464 UartWrite(serial_handle, &send, 1);
465 send = (UINT8)(addr & 0xFF);
466 UartWrite(serial_handle, &send, 1);
467
468 UartRead(serial_handle, &received, 1); // response
469 if (received != ADDRESS)
470 {
471 printf("Protocol error!\n");
472 return 1;
473 }
474
475 while (size)
476 {
477 if (size >= 16)
478 { // we can use a "burst" command
479 send = BYTE_WRITE16;
480 UartWrite(serial_handle, &send, 1); // send the write command
481 UartWrite(serial_handle, pBuffer, 16); // transmit the data
482 UartRead(serial_handle, &received, 1); // response
483 if (received != BYTE_WRITE16)
484 {
485 printf("Protocol error!\n");
486 return 1;
487 }
488 pBuffer += 16;
489 size -= 16;
490 }
491 else
492 { // use single byte command
493 send = BYTE_WRITE;
494 UartWrite(serial_handle, &send, 1); // send the write command
495 UartWrite(serial_handle, pBuffer++, 1); // transmit the data
496 UartRead(serial_handle, &received, 1); // response
497 if (received != BYTE_WRITE)
498 {
499 printf("Protocol error!\n");
500 return 1;
501 }
502 size--;
503 }
504 }
505
506 return 0;
507}
508
509
510// write many bytes using the target monitor
511int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
512{
513 UINT8 send, received;
514
515 // send the address command
516 send = ADDRESS;
517 UartWrite(serial_handle, &send, 1);
518
519 // transmit the address, big endian
520 send = (UINT8)((addr>>24) & 0xFF);
521 UartWrite(serial_handle, &send, 1);
522 send = (UINT8)((addr>>16) & 0xFF);
523 UartWrite(serial_handle, &send, 1);
524 send = (UINT8)((addr>>8) & 0xFF);
525 UartWrite(serial_handle, &send, 1);
526 send = (UINT8)(addr & 0xFF);
527 UartWrite(serial_handle, &send, 1);
528
529 UartRead(serial_handle, &received, 1); // response
530 if (received != ADDRESS)
531 {
532 printf("Protocol error!\n");
533 return 1;
534 }
535
536 while (size)
537 {
538 if (size >= 16)
539 { // we can use a "burst" command
540 send = BYTE_FLASH16;
541 UartWrite(serial_handle, &send, 1); // send the write command
542 UartWrite(serial_handle, pBuffer, 16); // transmit the data
543 UartRead(serial_handle, &received, 1); // response
544 if (received != BYTE_FLASH16)
545 {
546 printf("Protocol error!\n");
547 return 1;
548 }
549 pBuffer += 16;
550 size -= 16;
551 }
552 else
553 { // use single byte command
554 send = BYTE_FLASH;
555 UartWrite(serial_handle, &send, 1); // send the write command
556 UartWrite(serial_handle, pBuffer++, 1); // transmit the data
557 UartRead(serial_handle, &received, 1); // response
558 if (received != BYTE_FLASH)
559 {
560 printf("Protocol error!\n");
561 return 1;
562 }
563 size--;
564 }
565 }
566
567 return 0;
568}
569
570
571// read a 16bit halfword using the target monitor
572UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr)
573{
574 UINT8 send;
575 UINT8 received;
576 UINT16 halfword;
577
578 // send the address command
579 send = ADDRESS;
580 UartWrite(serial_handle, &send, 1);
581
582 // transmit the address, big endian
583 send = (UINT8)((addr>>24) & 0xFF);
584 UartWrite(serial_handle, &send, 1);
585 send = (UINT8)((addr>>16) & 0xFF);
586 UartWrite(serial_handle, &send, 1);
587 send = (UINT8)((addr>>8) & 0xFF);
588 UartWrite(serial_handle, &send, 1);
589 send = (UINT8)(addr & 0xFF);
590 UartWrite(serial_handle, &send, 1);
591
592 UartRead(serial_handle, &received, 1); // response
593 if (received != ADDRESS)
594 {
595 printf("Protocol error!\n");
596 return 1;
597 }
598
599 // send the read command
600 send = HALFWORD_READ;
601 UartWrite(serial_handle, &send, 1);
602
603 UartRead(serial_handle, &received, 1); // response
604 halfword = received << 8; // highbyte
605 UartRead(serial_handle, &received, 1);
606 halfword |= received; // lowbyte
607
608 return halfword;
609}
610
611
612// write a 16bit halfword using the target monitor
613int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword)
614{
615 UINT8 send;
616 UINT8 received;
617
618 // send the address command
619 send = ADDRESS;
620 UartWrite(serial_handle, &send, 1);
621
622 // transmit the address, big endian
623 send = (UINT8)((addr>>24) & 0xFF);
624 UartWrite(serial_handle, &send, 1);
625 send = (UINT8)((addr>>16) & 0xFF);
626 UartWrite(serial_handle, &send, 1);
627 send = (UINT8)((addr>>8) & 0xFF);
628 UartWrite(serial_handle, &send, 1);
629 send = (UINT8)(addr & 0xFF);
630 UartWrite(serial_handle, &send, 1);
631
632 UartRead(serial_handle, &received, 1); // response
633 if (received != ADDRESS)
634 {
635 printf("Protocol error!\n");
636 return 1;
637 }
638
639 // send the write command
640 send = HALFWORD_WRITE;
641 UartWrite(serial_handle, &send, 1);
642
643 // transmit the data
644 send = halfword >> 8; // highbyte
645 UartWrite(serial_handle, &send, 1);
646 send = halfword & 0xFF; // lowbyte
647 UartWrite(serial_handle, &send, 1);
648
649 UartRead(serial_handle, &received, 1); // response
650
651 if (received != HALFWORD_WRITE)
652 {
653 printf("Protocol error!\n");
654 return 1;
655 }
656
657 return 0;
658}
659
660
661// change baudrate using target monitor
662int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate)
663{
664 UINT8 send;
665 UINT8 received;
666 UINT8 brr;
667 long lBRR;
668
669 lBRR = lClock / lBaudrate;
670 lBRR = ((lBRR + 16) / 32) - 1; // with rounding
671 brr = (UINT8)lBRR;
672
673 // send the command
674 send = BAUDRATE;
675 UartWrite(serial_handle, &send, 1);
676 UartWrite(serial_handle, &brr, 1); // send the BRR value
677 UartRead(serial_handle, &received, 1); // response ack
678
679 if (received != BAUDRATE)
680 { // bad situation, now we're unclear about the baudrate of the target
681 printf("Protocol error!\n");
682 return 1;
683 }
684
685 SLEEP(100); // give it some time to settle
686
687 // change our baudrate, too
688 UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8);
689
690 return 0;
691}
692
693
694// call a subroutine using the target monitor
695int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns)
696{
697 UINT8 send;
698 UINT8 received;
699
700 // send the address command
701 send = ADDRESS;
702 UartWrite(serial_handle, &send, 1);
703
704 // transmit the address, big endian
705 send = (UINT8)((addr>>24) & 0xFF);
706 UartWrite(serial_handle, &send, 1);
707 send = (UINT8)((addr>>16) & 0xFF);
708 UartWrite(serial_handle, &send, 1);
709 send = (UINT8)((addr>>8) & 0xFF);
710 UartWrite(serial_handle, &send, 1);
711 send = (UINT8)(addr & 0xFF);
712 UartWrite(serial_handle, &send, 1);
713
714 UartRead(serial_handle, &received, 1); // response
715 if (received != ADDRESS)
716 {
717 printf("Protocol error!\n");
718 return 1;
719 }
720
721 // send the execute command
722 send = EXECUTE;
723 UartWrite(serial_handle, &send, 1);
724 if (bReturns)
725 { // we expect the call to return control to minimon
726 UartRead(serial_handle, &received, 1); // response
727
728 if (received != EXECUTE)
729 {
730 printf("Protocol error!\n");
731 return 1;
732 }
733 }
734
735 return 0;
736}
737
738