Arrrgh. Fix red now. :\
[kugel-rb.git] / flash / uart_boot / client.c
blob71749a2c5535a5453425de4a4597981abf66214d
1 // client.cpp : functions for monitor download and communication.
2 //
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
10 // do the baudrate configuration for the Player
11 int ConfigFirstlevelPlayer (tUartHandle serial_handle)
13 UINT32 result_nbr;
15 if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8))
17 UINT32 dwErr = GET_LAST_ERR();
18 printf("Error %lu setting up COM params for baudrate byte\n", dwErr);
19 exit(1);
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)
26 UINT32 dwErr = GET_LAST_ERR();
27 printf("Error %lu setting up COM params for baudrate byte\n", dwErr);
30 SLEEP(100); // wait for the chars to be sent, is there a better way?
32 // the read 0x19 means 14423 baud with 12 MHz
33 if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8))
35 printf("Error setting up COM params for 1st level loader\n");
36 exit(1);
39 return 0;
43 // do the baudrate configuration for the Recoder/FM
44 int ConfigFirstlevelRecorder (tUartHandle serial_handle)
46 UINT32 result_nbr;
48 if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8))
50 UINT32 dwErr = GET_LAST_ERR();
51 printf("Error %lu setting up COM params for baudrate byte\n", dwErr);
52 exit(1);
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)
59 printf("Error transmitting baudrate byte\n");
60 exit(1);
63 SLEEP(100); // wait for the chars to be sent, is there a better way?
65 // the read 0x08 means 38400 baud with 11.0592 MHz
66 if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8))
68 UINT32 dwErr = GET_LAST_ERR();
69 printf("Error %lu setting up COM params for 1st level loader\n", dwErr);
70 exit(1);
73 return 0;
77 // transfer a byte for the monitor download, with or without acknowledge
78 int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck)
80 unsigned char received;
82 while (1)
84 UartWrite(serial_handle, &byte, 1);
85 if (bAck)
87 UartRead(serial_handle, &received, 1);
88 if (received == byte)
90 UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success
91 break; // exit the loop
93 else
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
99 else
100 break; // no loop
102 return 1;
106 // download our little monitor, the box must have been just freshly switched on for this to work
107 int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename)
109 FILE* pFile;
110 size_t filesize;
111 UINT8 byte;
112 unsigned i;
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
118 pFile = fopen(szFilename, "rb");
119 if (pFile == NULL)
121 printf("\nMonitor file %s not found, exiting\n", szFilename);
122 exit(1);
125 // determine file size
126 fseek(pFile, 0, SEEK_END);
127 filesize = ftell(pFile);
128 fseek(pFile, 0, SEEK_SET);
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)
137 ConfigFirstlevelRecorder(serial_handle);
139 else
141 ConfigFirstlevelPlayer(serial_handle);
144 UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode
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);
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);
158 // transmit the command byte
159 DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image
161 // transmit the image
162 for (i=0; i<filesize; i++)
164 fread(&byte, 1, 1, pFile);
165 DownloadByte(serial_handle, byte, bAck);
168 fclose (pFile);
170 // now the image should have been started, red LED off
172 return 0;
176 // wait for a fixed string to be received (no foolproof algorithm,
177 // may overlook if the searched string contains repeatitions)
178 int WaitForString(tUartHandle serial_handle, char* pszWait)
180 int i = 0;
181 unsigned char received;
183 while(pszWait[i] != '\0')
185 UartRead(serial_handle, &received, 1);
187 printf("%c", received); // debug
189 if (received == pszWait[i])
190 i++; // continue
191 else
192 i=0; // mismatch, start over
194 return 0;
198 // send a sting and check the echo
199 int SendWithEcho(tUartHandle serial_handle, char* pszSend)
201 int i = 0;
202 unsigned char received;
204 while(pszSend[i] != '\0')
206 UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char
209 UartRead(serial_handle, &received, 1); // receive echo
210 printf("%c", received); // debug
212 while (received != pszSend[i]); // should normally be equal
213 i++; // next char
215 return 0;
219 // rarely used variant: download our monitor using the built-in Archos monitor
220 int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename)
222 FILE* pFile;
223 size_t filesize;
224 UINT8 byte;
225 UINT16 checksum = 0;
226 unsigned i;
228 // the onboard monitor uses 115200 baud
229 if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8))
231 UINT32 dwErr = GET_LAST_ERR();
232 printf("Error %lu setting up COM params for baudrate %d\n", dwErr, 115200);
233 exit(1);
236 // wait for receiving "#SERIAL#"
237 WaitForString(serial_handle, "#SERIAL#");
239 // send magic "SRL" command to get interactive mode
240 SendWithEcho(serial_handle, "SRL\r");
242 // wait for menu completion: "ROOT>" at the end
243 WaitForString(serial_handle, "ROOT>");
245 // send upload command "UP"
246 SendWithEcho(serial_handle, "UP\r");
248 pFile = fopen(szFilename, "rb");
249 if (pFile == NULL)
251 printf("\nMonitor file %s not found, exiting\n", szFilename);
252 exit(1);
255 // determine file size
256 fseek(pFile, 0, SEEK_END);
257 filesize = ftell(pFile);
258 fseek(pFile, 0, SEEK_SET);
260 // calculate checksum
261 for (i=0; i<filesize; i++)
263 fread(&byte, 1, 1, pFile);
264 checksum += byte;
266 fseek(pFile, 0, SEEK_SET);
268 // send header
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);
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);
286 UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash)
287 UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
289 // wait for monitor to accept data
290 WaitForString(serial_handle, "#OKCTRL#");
292 // transmit the image
293 for (i=0; i<filesize; i++)
295 fread(&byte, 1, 1, pFile);
296 UartWrite(serial_handle, &byte, 1); // payload
298 fclose (pFile);
300 UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
302 // wait for menu completion: "ROOT>" at the end
303 WaitForString(serial_handle, "ROOT>");
305 // send start program command "SPRO"
306 SendWithEcho(serial_handle, "SPRO\r");
308 SLEEP(100); // wait a little while for startup
310 return 0;
314 /********** Target functions using the Monitor Protocol **********/
316 // read a byte using the target monitor
317 UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr)
319 UINT8 send;
320 UINT8 received;
322 // send the address command
323 send = ADDRESS;
324 UartWrite(serial_handle, &send, 1);
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);
336 UartRead(serial_handle, &received, 1); // response
337 if (received != ADDRESS)
339 printf("Protocol error!\n");
340 return 1;
343 // send the read command
344 send = BYTE_READ;
345 UartWrite(serial_handle, &send, 1);
347 UartRead(serial_handle, &received, 1); // response
349 return received;
353 // write a byte using the target monitor
354 int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte)
356 UINT8 send;
357 UINT8 received;
359 // send the address command
360 send = ADDRESS;
361 UartWrite(serial_handle, &send, 1);
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);
373 UartRead(serial_handle, &received, 1); // response
374 if (received != ADDRESS)
376 printf("Protocol error, receiced 0x%02X!\n", received);
377 return 1;
380 // send the write command
381 send = BYTE_WRITE;
382 UartWrite(serial_handle, &send, 1);
384 // transmit the data
385 UartWrite(serial_handle, &byte, 1);
387 UartRead(serial_handle, &received, 1); // response
389 if (received != BYTE_WRITE)
391 printf("Protocol error!\n");
392 return 1;
395 return 0;
399 // read many bytes using the target monitor
400 int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
402 UINT8 send, received;
404 // send the address command
405 send = ADDRESS;
406 UartWrite(serial_handle, &send, 1);
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);
418 UartRead(serial_handle, &received, 1); // response
419 if (received != ADDRESS)
421 printf("Protocol error!\n");
422 return 1;
425 while (size)
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;
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--;
444 return 0;
448 // write many bytes using the target monitor
449 int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
451 UINT8 send, received;
453 // send the address command
454 send = ADDRESS;
455 UartWrite(serial_handle, &send, 1);
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);
467 UartRead(serial_handle, &received, 1); // response
468 if (received != ADDRESS)
470 printf("Protocol error!\n");
471 return 1;
474 while (size)
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)
484 printf("Protocol error!\n");
485 return 1;
487 pBuffer += 16;
488 size -= 16;
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)
498 printf("Protocol error!\n");
499 return 1;
501 size--;
505 return 0;
509 // write many bytes using the target monitor
510 int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
512 UINT8 send, received;
514 // send the address command
515 send = ADDRESS;
516 UartWrite(serial_handle, &send, 1);
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);
528 UartRead(serial_handle, &received, 1); // response
529 if (received != ADDRESS)
531 printf("Protocol error!\n");
532 return 1;
535 while (size)
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)
545 printf("Protocol error!\n");
546 return 1;
548 pBuffer += 16;
549 size -= 16;
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)
559 printf("Protocol error!\n");
560 return 1;
562 size--;
566 return 0;
570 // read a 16bit halfword using the target monitor
571 UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr)
573 UINT8 send;
574 UINT8 received;
575 UINT16 halfword;
577 // send the address command
578 send = ADDRESS;
579 UartWrite(serial_handle, &send, 1);
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);
591 UartRead(serial_handle, &received, 1); // response
592 if (received != ADDRESS)
594 printf("Protocol error!\n");
595 return 1;
598 // send the read command
599 send = HALFWORD_READ;
600 UartWrite(serial_handle, &send, 1);
602 UartRead(serial_handle, &received, 1); // response
603 halfword = received << 8; // highbyte
604 UartRead(serial_handle, &received, 1);
605 halfword |= received; // lowbyte
607 return halfword;
611 // write a 16bit halfword using the target monitor
612 int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword)
614 UINT8 send;
615 UINT8 received;
617 // send the address command
618 send = ADDRESS;
619 UartWrite(serial_handle, &send, 1);
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);
631 UartRead(serial_handle, &received, 1); // response
632 if (received != ADDRESS)
634 printf("Protocol error!\n");
635 return 1;
638 // send the write command
639 send = HALFWORD_WRITE;
640 UartWrite(serial_handle, &send, 1);
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);
648 UartRead(serial_handle, &received, 1); // response
650 if (received != HALFWORD_WRITE)
652 printf("Protocol error!\n");
653 return 1;
656 return 0;
660 // change baudrate using target monitor
661 int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate)
663 UINT8 send;
664 UINT8 received;
665 UINT8 brr;
666 long lBRR;
668 lBRR = lClock / lBaudrate;
669 lBRR = ((lBRR + 16) / 32) - 1; // with rounding
670 brr = (UINT8)lBRR;
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
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;
684 SLEEP(100); // give it some time to settle
686 // change our baudrate, too
687 UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8);
689 return 0;
693 // call a subroutine using the target monitor
694 int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns)
696 UINT8 send;
697 UINT8 received;
699 // send the address command
700 send = ADDRESS;
701 UartWrite(serial_handle, &send, 1);
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);
713 UartRead(serial_handle, &received, 1); // response
714 if (received != ADDRESS)
716 printf("Protocol error!\n");
717 return 1;
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
727 if (received != EXECUTE)
729 printf("Protocol error!\n");
730 return 1;
734 return 0;