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 @@
+// client.cpp : functions for monitor download and communication.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h" // platform abstraction for UART
+#include "minimon.h" // protocol of my little monitor
+
+// do the baudrate configuration for the Player
+int ConfigFirstlevelPlayer (tUartHandle serial_handle)
+{
+ UINT32 result_nbr;
+
+ if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8))
+ {
+ UINT32 dwErr = GET_LAST_ERR();
+ printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+ exit(1);
+ }
+
+ // this will read as 0x19 when viewed with 2300 baud like the player does
+ result_nbr = UartWrite(serial_handle, (UINT8*)"\x86\xC0", 2);
+ if (result_nbr != 2)
+ {
+ UINT32 dwErr = GET_LAST_ERR();
+ printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+ }
+
+ SLEEP(100); // wait for the chars to be sent, is there a better way?
+
+ // the read 0x19 means 14423 baud with 12 MHz
+ if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8))
+ {
+ printf("Error setting up COM params for 1st level loader\n");
+ exit(1);
+ }
+
+ return 0;
+}
+
+
+// do the baudrate configuration for the Recoder/FM
+int ConfigFirstlevelRecorder (tUartHandle serial_handle)
+{
+ UINT32 result_nbr;
+
+ if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8))
+ {
+ UINT32 dwErr = GET_LAST_ERR();
+ printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+ exit(1);
+ }
+
+ // this will read as 0x08 when viewed with 2120 baud like the recorder does
+ result_nbr = UartWrite(serial_handle, (UINT8*)"\x00\x00", 2);
+ if(result_nbr != 2)
+ {
+ printf("Error transmitting baudrate byte\n");
+ exit(1);
+ }
+
+ SLEEP(100); // wait for the chars to be sent, is there a better way?
+
+ // the read 0x08 means 38400 baud with 11.0592 MHz
+ if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8))
+ {
+ UINT32 dwErr = GET_LAST_ERR();
+ printf("Error %d setting up COM params for 1st level loader\n", dwErr);
+ exit(1);
+ }
+
+ return 0;
+}
+
+
+// transfer a byte for the monitor download, with or without acknowledge
+int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck)
+{
+ unsigned char received;
+ bool bRecorder = true; // false for player
+
+ while (1)
+ {
+ UartWrite(serial_handle, &byte, 1);
+ if (bAck)
+ {
+ UartRead(serial_handle, &received, 1);
+ if (received == byte)
+ {
+ UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success
+ break; // exit the loop
+ }
+ else
+ {
+ printf("Error transmitting monitor byte 0x%02X, got 0x%0X\n", byte, received);
+ UartWrite(serial_handle, (UINT8*)"\x00", 1); // ack fail, try again
+ }
+ }
+ else
+ break; // no loop
+ }
+ return 1;
+}
+
+
+// download our little monitor, the box must have been just freshly switched on for this to work
+int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename)
+{
+ FILE* pFile;
+ size_t filesize;
+ UINT8 byte;
+ unsigned i;
+
+ // hard-coded parameters
+ bool bAck = true; // configure if acknowledged download (without useful for remote pin boot)
+ UINT32 TargetLoad = 0x0FFFF000; // target load address
+
+ pFile = fopen(szFilename, "rb");
+ if (pFile == NULL)
+ {
+ printf("\nMonitor file %s not found, exiting\n", szFilename);
+ exit(1);
+ }
+
+ // determine file size
+ fseek(pFile, 0, SEEK_END);
+ filesize = ftell(pFile);
+ fseek(pFile, 0, SEEK_SET);
+
+ // This is _really_ tricky! The box expects a BRR value in a nonstandard baudrate,
+ // which a PC can't generate. I'm using a higher one with some wild settings
+ // to generate a pulse series that:
+ // 1) looks like a stable byte when sampled with the nonstandard baudrate
+ // 2) gives a BRR value to the box which results in a baudrate the PC can also use
+ if (bRecorder)
+ {
+ ConfigFirstlevelRecorder(serial_handle);
+ }
+ else
+ {
+ ConfigFirstlevelPlayer(serial_handle);
+ }
+
+ UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode
+
+ // transmit the size, little endian
+ DownloadByte(serial_handle, (UINT8)( filesize & 0xFF), bAck);
+ DownloadByte(serial_handle, (UINT8)((filesize>>8) & 0xFF), bAck);
+ DownloadByte(serial_handle, (UINT8)((filesize>>16) & 0xFF), bAck);
+ DownloadByte(serial_handle, (UINT8)((filesize>>24) & 0xFF), bAck);
+
+ // transmit the load address, little endian
+ DownloadByte(serial_handle, (UINT8)( TargetLoad & 0xFF), bAck);
+ DownloadByte(serial_handle, (UINT8)((TargetLoad>>8) & 0xFF), bAck);
+ DownloadByte(serial_handle, (UINT8)((TargetLoad>>16) & 0xFF), bAck);
+ DownloadByte(serial_handle, (UINT8)((TargetLoad>>24) & 0xFF), bAck);
+
+ // transmit the command byte
+ DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image
+
+ // transmit the image
+ for (i=0; i<filesize; i++)
+ {
+ fread(&byte, 1, 1, pFile);
+ DownloadByte(serial_handle, byte, bAck);
+ }
+
+ fclose (pFile);
+
+ // now the image should have been started, red LED off
+
+ return 0;
+}
+
+
+// wait for a fixed string to be received (no foolproof algorithm,
+// may overlook if the searched string contains repeatitions)
+int WaitForString(tUartHandle serial_handle, char* pszWait)
+{
+ int i = 0;
+ unsigned char received;
+
+ while(pszWait[i] != '\0')
+ {
+ UartRead(serial_handle, &received, 1);
+
+ printf("%c", received); // debug
+
+ if (received == pszWait[i])
+ i++; // continue
+ else
+ i=0; // mismatch, start over
+ }
+ return 0;
+}
+
+
+// send a sting and check the echo
+int SendWithEcho(tUartHandle serial_handle, char* pszSend)
+{
+ int i = 0;
+ unsigned char received;
+
+ while(pszSend[i] != '\0')
+ {
+ UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char
+ do
+ {
+ UartRead(serial_handle, &received, 1); // receive echo
+ printf("%c", received); // debug
+ }
+ while (received != pszSend[i]); // should normally be equal
+ i++; // next char
+ }
+ return 0;
+}
+
+
+// rarely used variant: download our monitor using the built-in Archos monitor
+int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename)
+{
+ FILE* pFile;
+ size_t filesize;
+ UINT8 byte;
+ UINT16 checksum = 0;
+ unsigned i;
+
+ // the onboard monitor uses 115200 baud
+ if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8))
+ {
+ UINT32 dwErr = GET_LAST_ERR();
+ printf("Error %d setting up COM params for baudrate %d\n", dwErr, 115200);
+ exit(1);
+ }
+
+ // wait for receiving "#SERIAL#"
+ WaitForString(serial_handle, "#SERIAL#");
+
+ // send magic "SRL" command to get interactive mode
+ SendWithEcho(serial_handle, "SRL\r");
+
+ // wait for menu completion: "ROOT>" at the end
+ WaitForString(serial_handle, "ROOT>");
+
+ // send upload command "UP"
+ SendWithEcho(serial_handle, "UP\r");
+
+ pFile = fopen(szFilename, "rb");
+ if (pFile == NULL)
+ {
+ printf("\nMonitor file %s not found, exiting\n", szFilename);
+ exit(1);
+ }
+
+ // determine file size
+ fseek(pFile, 0, SEEK_END);
+ filesize = ftell(pFile);
+ fseek(pFile, 0, SEEK_SET);
+
+ // calculate checksum
+ for (i=0; i<filesize; i++)
+ {
+ fread(&byte, 1, 1, pFile);
+ checksum += byte;
+ }
+ fseek(pFile, 0, SEEK_SET);
+
+ // send header
+
+ // size as 32 bit little endian
+ byte = (UINT8)( filesize & 0xFF);
+ UartWrite(serial_handle, &byte, 1);
+ byte = (UINT8)((filesize>>8) & 0xFF);
+ UartWrite(serial_handle, &byte, 1);
+ byte = (UINT8)((filesize>>16) & 0xFF);
+ UartWrite(serial_handle, &byte, 1);
+ byte = (UINT8)((filesize>>24) & 0xFF);
+ UartWrite(serial_handle, &byte, 1);
+
+ // checksum as 16 bit little endian
+ byte = (UINT8)( checksum & 0xFF);
+ UartWrite(serial_handle, &byte, 1);
+ byte = (UINT8)((checksum>>8) & 0xFF);
+ UartWrite(serial_handle, &byte, 1);
+
+ UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash)
+ UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
+
+ // wait for monitor to accept data
+ WaitForString(serial_handle, "#OKCTRL#");
+
+ // transmit the image
+ for (i=0; i<filesize; i++)
+ {
+ fread(&byte, 1, 1, pFile);
+ UartWrite(serial_handle, &byte, 1); // payload
+ }
+ fclose (pFile);
+
+ UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte
+
+ // wait for menu completion: "ROOT>" at the end
+ WaitForString(serial_handle, "ROOT>");
+
+ // send start program command "SPRO"
+ SendWithEcho(serial_handle, "SPRO\r");
+
+ SLEEP(100); // wait a little while for startup
+
+ return 0;
+}
+
+
+/********** Target functions using the Monitor Protocol **********/
+
+// read a byte using the target monitor
+UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr)
+{
+ UINT8 send;
+ UINT8 received;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ // send the read command
+ send = BYTE_READ;
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+
+ return received;
+}
+
+
+// write a byte using the target monitor
+int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte)
+{
+ UINT8 send;
+ UINT8 received;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error, receiced 0x%02X!\n", received);
+ return 1;
+ }
+
+ // send the write command
+ send = BYTE_WRITE;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the data
+ UartWrite(serial_handle, &byte, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+
+ if (received != BYTE_WRITE)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+// read many bytes using the target monitor
+int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
+{
+ UINT8 send, received;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ while (size)
+ {
+ if (size >= 16)
+ { // we can use a "burst" command
+ send = BYTE_READ16;
+ UartWrite(serial_handle, &send, 1); // send the read command
+ UartRead(serial_handle, pBuffer, 16); // data response
+ pBuffer += 16;
+ size -= 16;
+ }
+ else
+ { // use single byte command
+ send = BYTE_READ;
+ UartWrite(serial_handle, &send, 1); // send the read command
+ UartRead(serial_handle, pBuffer++, 1); // data response
+ size--;
+ }
+ }
+
+ return 0;
+}
+
+
+// write many bytes using the target monitor
+int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
+{
+ UINT8 send, received;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ while (size)
+ {
+ if (size >= 16)
+ { // we can use a "burst" command
+ send = BYTE_WRITE16;
+ UartWrite(serial_handle, &send, 1); // send the write command
+ UartWrite(serial_handle, pBuffer, 16); // transmit the data
+ UartRead(serial_handle, &received, 1); // response
+ if (received != BYTE_WRITE16)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+ pBuffer += 16;
+ size -= 16;
+ }
+ else
+ { // use single byte command
+ send = BYTE_WRITE;
+ UartWrite(serial_handle, &send, 1); // send the write command
+ UartWrite(serial_handle, pBuffer++, 1); // transmit the data
+ UartRead(serial_handle, &received, 1); // response
+ if (received != BYTE_WRITE)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+ size--;
+ }
+ }
+
+ return 0;
+}
+
+
+// write many bytes using the target monitor
+int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer)
+{
+ UINT8 send, received;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ while (size)
+ {
+ if (size >= 16)
+ { // we can use a "burst" command
+ send = BYTE_FLASH16;
+ UartWrite(serial_handle, &send, 1); // send the write command
+ UartWrite(serial_handle, pBuffer, 16); // transmit the data
+ UartRead(serial_handle, &received, 1); // response
+ if (received != BYTE_FLASH16)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+ pBuffer += 16;
+ size -= 16;
+ }
+ else
+ { // use single byte command
+ send = BYTE_FLASH;
+ UartWrite(serial_handle, &send, 1); // send the write command
+ UartWrite(serial_handle, pBuffer++, 1); // transmit the data
+ UartRead(serial_handle, &received, 1); // response
+ if (received != BYTE_FLASH)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+ size--;
+ }
+ }
+
+ return 0;
+}
+
+
+// read a 16bit halfword using the target monitor
+UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr)
+{
+ UINT8 send;
+ UINT8 received;
+ UINT16 halfword;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ // send the read command
+ send = HALFWORD_READ;
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ halfword = received << 8; // highbyte
+ UartRead(serial_handle, &received, 1);
+ halfword |= received; // lowbyte
+
+ return halfword;
+}
+
+
+// write a 16bit halfword using the target monitor
+int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword)
+{
+ UINT8 send;
+ UINT8 received;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ // send the write command
+ send = HALFWORD_WRITE;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the data
+ send = halfword >> 8; // highbyte
+ UartWrite(serial_handle, &send, 1);
+ send = halfword & 0xFF; // lowbyte
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+
+ if (received != HALFWORD_WRITE)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+// change baudrate using target monitor
+int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate)
+{
+ UINT8 send;
+ UINT8 received;
+ UINT8 brr;
+ long lBRR;
+
+ lBRR = lClock / lBaudrate;
+ lBRR = ((lBRR + 16) / 32) - 1; // with rounding
+ brr = (UINT8)lBRR;
+
+ // send the command
+ send = BAUDRATE;
+ UartWrite(serial_handle, &send, 1);
+ UartWrite(serial_handle, &brr, 1); // send the BRR value
+ UartRead(serial_handle, &received, 1); // response ack
+
+ if (received != BAUDRATE)
+ { // bad situation, now we're unclear about the baudrate of the target
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ SLEEP(100); // give it some time to settle
+
+ // change our baudrate, too
+ UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8);
+
+ return 0;
+}
+
+
+// call a subroutine using the target monitor
+int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns)
+{
+ UINT8 send;
+ UINT8 received;
+
+ // send the address command
+ send = ADDRESS;
+ UartWrite(serial_handle, &send, 1);
+
+ // transmit the address, big endian
+ send = (UINT8)((addr>>24) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>16) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)((addr>>8) & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+ send = (UINT8)(addr & 0xFF);
+ UartWrite(serial_handle, &send, 1);
+
+ UartRead(serial_handle, &received, 1); // response
+ if (received != ADDRESS)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+
+ // send the execute command
+ send = EXECUTE;
+ UartWrite(serial_handle, &send, 1);
+ if (bReturns)
+ { // we expect the call to return control to minimon
+ UartRead(serial_handle, &received, 1); // response
+
+ if (received != EXECUTE)
+ {
+ printf("Protocol error!\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+