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