summaryrefslogtreecommitdiffstats
path: root/flash/uart_boot
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2003-11-30 11:37:43 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2003-11-30 11:37:43 +0000
commit6a4e4c87c24455e18bbd77565cb3e993ee350618 (patch)
tree6f2ceac4da97aa63ff8deef939bd3cc2d56d3466 /flash/uart_boot
parent014c4fa1f8d56850cfd504a90221c293e4a158f6 (diff)
downloadrockbox-6a4e4c87c24455e18bbd77565cb3e993ee350618.tar.gz
rockbox-6a4e4c87c24455e18bbd77565cb3e993ee350618.tar.bz2
rockbox-6a4e4c87c24455e18bbd77565cb3e993ee350618.zip
source code for all my flash stuff, now finally in cvs
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4083 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'flash/uart_boot')
-rw-r--r--flash/uart_boot/README8
-rw-r--r--flash/uart_boot/client.c738
-rw-r--r--flash/uart_boot/client.h21
-rw-r--r--flash/uart_boot/flash.c77
-rw-r--r--flash/uart_boot/flash.h9
-rw-r--r--flash/uart_boot/minimon.h23
-rw-r--r--flash/uart_boot/scalar_types.h44
-rw-r--r--flash/uart_boot/uart.h56
-rw-r--r--flash/uart_boot/uart_boot.c337
-rw-r--r--flash/uart_boot/uart_boot.dsp130
-rw-r--r--flash/uart_boot/uart_win.c138
11 files changed, 1581 insertions, 0 deletions
diff --git a/flash/uart_boot/README b/flash/uart_boot/README
new file mode 100644
index 0000000000..edfa20c121
--- /dev/null
+++ b/flash/uart_boot/README
@@ -0,0 +1,8 @@
+(c) 2003 by Jrg Hohensohn
+
+This is the client side for MiniMon, a command line program that communicates with it.
+It can be used to reflash a box from ground up, load a program like gdb stub or Rockbox,
+and other diagnostics.
+
+Current implementation is for Windows, but with a different UART implementation
+it should work for other platforms (Linux) as well.
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;
+}
+
+
diff --git a/flash/uart_boot/client.h b/flash/uart_boot/client.h
new file mode 100644
index 0000000000..d2ef29aa2e
--- /dev/null
+++ b/flash/uart_boot/client.h
@@ -0,0 +1,21 @@
+#ifndef _CLIENT_H
+#define _CLIENT_H
+
+
+// setup function for monitor download
+int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename);
+int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename);
+
+// target functions using the Monitor Protocol
+UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr);
+int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte);
+int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
+int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
+int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer);
+UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr);
+int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword);
+int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate);
+int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns);
+
+
+#endif \ No newline at end of file
diff --git a/flash/uart_boot/flash.c b/flash/uart_boot/flash.c
new file mode 100644
index 0000000000..f27bb7ec0a
--- /dev/null
+++ b/flash/uart_boot/flash.c
@@ -0,0 +1,77 @@
+// flash.cpp : higher-level functions for flashing the chip
+//
+
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h" // platform abstraction for UART
+#include "client.h" // client functions
+
+
+// read the manufacturer and device ID
+int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID)
+{
+ base &= 0xFFF80000; // round down to 512k align, to make shure
+
+ WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+ WriteByte(serial_handle, base + 0x2AAA, 0x55);
+ WriteByte(serial_handle, base + 0x5555, 0x90); // ID command
+ SLEEP(20); // Atmel wants 20ms pause here
+
+ *pManufacturerID = ReadByte(serial_handle, base + 0);
+ *pDeviceID = ReadByte(serial_handle, base + 1);
+
+ WriteByte(serial_handle, base + 0, 0xF0); // reset flash (back to normal read mode)
+ SLEEP(20); // Atmel wants 20ms pause here
+
+ return 0;
+}
+
+
+// erase the sector which contains the given address
+int EraseSector(tUartHandle serial_handle, UINT32 address)
+{
+ UINT32 base = address & 0xFFF80000; // round down to 512k align
+
+ WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+ WriteByte(serial_handle, base + 0x2AAA, 0x55);
+ WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
+ WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+ WriteByte(serial_handle, base + 0x2AAA, 0x55);
+ WriteByte(serial_handle, address, 0x30); // eraze the sector
+ SLEEP(25); // sector eraze time: 25ms
+
+ return 0;
+}
+
+
+// erase the whole flash
+int EraseChip(tUartHandle serial_handle, UINT32 base)
+{
+ base &= 0xFFF80000; // round down to 512k align, to make shure
+
+ WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+ WriteByte(serial_handle, base + 0x2AAA, 0x55);
+ WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command
+ WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+ WriteByte(serial_handle, base + 0x2AAA, 0x55);
+ WriteByte(serial_handle, base + 0x5555, 0x10); // chip eraze command
+ SLEEP(100); // chip eraze time: 100ms
+
+ return 0;
+}
+
+
+// program a bunch of bytes "by hand"
+int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size)
+{
+ UINT32 base = address & 0xFFF80000; // round down to 512k align
+
+ while (size--)
+ {
+ WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode
+ WriteByte(serial_handle, base + 0x2AAA, 0x55);
+ WriteByte(serial_handle, base + 0x5555, 0xA0); // byte program command
+ WriteByte(serial_handle, address++, *pData++);
+ // UART protocol is slow enough such that I don't have to wait 20us here
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/flash/uart_boot/flash.h b/flash/uart_boot/flash.h
new file mode 100644
index 0000000000..70c620108d
--- /dev/null
+++ b/flash/uart_boot/flash.h
@@ -0,0 +1,9 @@
+#ifndef _FLASH_H
+#define _FLASH_H
+
+int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID);
+int EraseSector(tUartHandle serial_handle, UINT32 address);
+int EraseChip(tUartHandle serial_handle, UINT32 base);
+int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size);
+
+#endif \ No newline at end of file
diff --git a/flash/uart_boot/minimon.h b/flash/uart_boot/minimon.h
new file mode 100644
index 0000000000..51406d4b12
--- /dev/null
+++ b/flash/uart_boot/minimon.h
@@ -0,0 +1,23 @@
+#ifndef _MINIMON_H
+#define _MINIMON_H
+
+
+// Commands
+// all multibyte values (address, halfwords) are passed as big endian
+// (most significant of the bytes first)
+
+// set the address (all read/write commands will auto-increment it)
+#define BAUDRATE 0x00 // followed by BRR value; response: command byte
+#define ADDRESS 0x01 // followed by 4 bytes address; response: command byte
+#define BYTE_READ 0x02 // response: 1 byte content
+#define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte
+#define BYTE_READ16 0x04 // response: 16 bytes content
+#define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte
+#define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte
+#define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte
+#define HALFWORD_READ 0x08 // response: 2 byte content
+#define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte
+#define EXECUTE 0x0A // response: command byte if call returns
+
+
+#endif // _MINIMON_H
diff --git a/flash/uart_boot/scalar_types.h b/flash/uart_boot/scalar_types.h
new file mode 100644
index 0000000000..88d82c4ec1
--- /dev/null
+++ b/flash/uart_boot/scalar_types.h
@@ -0,0 +1,44 @@
+// this is meant to resolve platform dependency
+
+#ifndef _SCALAR_TYPES_H
+#define _SCALAR_TYPES_H
+
+
+#ifdef WIN32
+#include <windows.h>
+#define SLEEP Sleep
+#define GET_LAST_ERR GetLastError
+#endif
+// ToDo: add stuff for Linux
+
+
+
+#ifndef UINT8
+#define UINT8 unsigned char
+#endif
+
+#ifndef UINT16
+#define UINT16 unsigned short
+#endif
+
+#ifndef UINT32
+#define UINT32 unsigned long
+#endif
+
+#ifndef bool
+#define bool int
+#endif
+
+#ifndef true
+#define true 1
+#endif
+
+#ifndef false
+#define false 0
+#endif
+
+
+
+
+
+#endif \ No newline at end of file
diff --git a/flash/uart_boot/uart.h b/flash/uart_boot/uart.h
new file mode 100644
index 0000000000..46b082c497
--- /dev/null
+++ b/flash/uart_boot/uart.h
@@ -0,0 +1,56 @@
+// A general definition for the required UART functionality.
+// This will be used to gain platform abstraction.
+
+#ifndef _UART_H
+#define _UART_H
+
+// data types
+
+typedef void* tUartHandle;
+#define INVALID_UART_HANDLE (tUartHandle)-1
+
+typedef enum
+{
+ eNOPARITY,
+ eODDPARITY,
+ eEVENPARITY,
+ eMARKPARITY,
+ eSPACEPARITY,
+} tParity;
+
+typedef enum
+{
+ eONESTOPBIT,
+ eONE5STOPBITS,
+ eTWOSTOPBITS,
+} tStopBits;
+
+
+// prototypes
+
+tUartHandle UartOpen( // returns NULL on error
+ char* szPortName); // COMx for windows
+
+bool UartConfig( // returns true on success, false on error
+ tUartHandle handle, // the handle returned from UartOpen()
+ long lBaudRate, // must be one of the "standard" baudrates
+ tParity nParity, // what kind of parity
+ tStopBits nStopBits, // how many stop bits
+ int nByteSize); // size of the "payload", can be 5 to 8
+
+long UartWrite( // returns how much data was actually transmitted
+ tUartHandle handle, // the handle returned from UartOpen()
+ unsigned char* pData, // pointer to the data to be transmitted
+ long lSize); // how many bytes
+
+long UartRead( // returns how much data was actually received
+ tUartHandle handle, // the handle returned from UartOpen()
+ unsigned char* pBuffer, // pointer to the destination
+ long lSize); // how many bytes to read (pBuffer must have enough room)
+
+
+void UartClose(tUartHandle handle);
+
+
+
+#endif // _UART_H \ No newline at end of file
diff --git a/flash/uart_boot/uart_boot.c b/flash/uart_boot/uart_boot.c
new file mode 100644
index 0000000000..8110e9b678
--- /dev/null
+++ b/flash/uart_boot/uart_boot.c
@@ -0,0 +1,337 @@
+// uart_boot.cpp : Defines the entry point for the console application.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h" // platform abstraction for UART
+#include "client.h" // client functions
+#include "flash.h" // flash high level functions
+
+// command line configuration: what shall we do?
+struct
+{
+ char* szPort; // COM port to use
+ bool bRecorder; // it's a recorder
+ bool bArchos; // use the Archos monitor to load, instead of UART boot
+ bool bSpindown; // spindown the harddisk
+ bool bReadID; // read manufacturer+device ID
+ char* szFlashfile; // file to be programmed
+ char* szDumpfile; // file to dump into
+ char* szExecfile; // file with the executable
+ bool bTest; // debug action
+ bool bBlink; // blink red LED
+ bool bNoDownload;
+} gCmd;
+
+
+int ProcessCmdLine(int argc, char* argv[])
+{
+ argc--; // exclude our name
+ argv++;
+
+ memset(&gCmd, 0, sizeof(gCmd));
+
+ if (argc == 0)
+ {
+ printf("Usage: uart_boot [-option {filename}]\n");
+ printf(" uses activated UART boot mod, box has to be fresh started\n");
+ printf("The order of the options does not matter, one letter is sufficient.\n");
+ printf("Possible options are (in the order of later processing):\n");
+ printf("-port <name of COM port to use>\n");
+ printf("-recorder (this is a recorder/FM, default is player if not specified)\n");
+ printf("-archos (use Archos bootloader, this one needs powerup while program waits)\n");
+ printf("-nodownload (no MiniMon download, it's already active)\n");
+ printf("-spindown (spindown the harddisk, else it stays on by default)\n");
+ printf("-id (read manufacturer and device ID of flash, no checks)\n");
+ printf("-flash <filename of binary to program into flash>\n");
+ printf("-dump <filename to write flash content to>\n");
+ printf("-exec <filename of executable for 0x09000000:0x09000200>\n");
+ printf("-test (some test action currently under development, don't use!)\n");
+ printf("-blink (blink red LED forever, meant as diagnostics)\n");
+ printf("\n");
+ printf("Examples:\n");
+ printf("uart_boot -r -p COM1 -s -f flashfile.bin -d dumpfile.bin\n");
+ printf(" recorder on COM1, spindown HD, program and dump (for e.g. offline verify)\n");
+ printf("uart_boot -r -p COM2 -e rockbox.bin\n");
+ printf(" recorder on COM2, load Rockbox from file and start it\n");
+ exit (0);
+ }
+
+
+ while (argc)
+ {
+ if (!strncmp("-port", *argv, 2))
+ {
+ gCmd.szPort = *++argv;
+ if (--argc <= 0 || **argv == '-')
+ {
+ printf("No argument given for option %s, aborting.\n", argv[-1]);
+ exit (-2);
+ }
+ }
+ else if (!strncmp("-recorder", *argv, 2))
+ {
+ gCmd.bRecorder = true;
+ }
+ else if (!strncmp("-archos", *argv, 2))
+ {
+ gCmd.bArchos = true;
+ }
+ else if (!strncmp("-nodownload", *argv, 2))
+ {
+ gCmd.bNoDownload = true;
+ }
+ else if (!strncmp("-spindown", *argv, 2))
+ {
+ gCmd.bSpindown = true;
+ }
+ else if (!strncmp("-id", *argv, 2))
+ {
+ gCmd.bReadID = true;
+ }
+ else if (!strncmp("-flash", *argv, 2))
+ {
+ gCmd.szFlashfile = *++argv;
+ if (--argc <= 0 || **argv == '-')
+ {
+ printf("No argument given for option %s, aborting.\n", argv[-1]);
+ exit (-2);
+ }
+ }
+ else if (!strncmp("-dump", *argv, 2))
+ {
+ gCmd.szDumpfile = *++argv;
+ if (--argc <= 0 || **argv == '-')
+ {
+ printf("No argument given for option %s, aborting.\n", argv[-1]);
+ exit (-3);
+ }
+ }
+ else if (!strncmp("-exec", *argv, 2))
+ {
+ gCmd.szExecfile = *++argv;
+ if (--argc <= 0 || **argv == '-')
+ {
+ printf("No argument given for option %s, aborting.\n", argv[-1]);
+ exit (-4);
+ }
+ }
+ else if (!strncmp("-test", *argv, 2))
+ {
+ gCmd.bTest = true;
+ }
+ else if (!strncmp("-blink", *argv, 2))
+ {
+ gCmd.bBlink = true;
+ }
+ else
+ {
+ printf("Unknown option %s, aborting. Use 'uart_boot' without options for help.\n", *argv);
+ exit(-1);
+ }
+
+ argv++;
+ argc--;
+ }
+
+ return 0;
+}
+
+
+int main(int argc, char* argv[])
+{
+ tUartHandle serial_handle;
+ UINT16 reg;
+ FILE* pFile;
+ size_t size;
+ UINT8 abFirmware[512*1024]; // blocksize
+ memset(abFirmware, 0xFF, sizeof(abFirmware));
+
+ ProcessCmdLine(argc, argv); // what to do
+
+ if (!gCmd.szPort)
+ {
+ printf("No serial port given, use 'uart_boot' without parameters for options.\n");
+ exit(-1);
+ }
+
+ serial_handle = UartOpen(gCmd.szPort); // opening serial port
+ if (serial_handle == NULL)
+ {
+ printf("Cannot open port %s\n", gCmd.szPort);
+ return -1;
+ }
+
+ if (gCmd.bNoDownload)
+ { // just set our speed
+ if (!UartConfig(serial_handle, gCmd.bRecorder ? 115200 : 14400, eNOPARITY, eONESTOPBIT, 8))
+ {
+ printf("Error setting up COM params\n");
+ exit(1);
+ }
+ }
+ else
+ { // download the monitor program
+ if (gCmd.bArchos)
+ {
+ printf("Waiting for box startup to download monitor...");
+ DownloadArchosMonitor(serial_handle, "minimon_v2.bin"); // load the monitor image
+ printf("\b\b\b done.\n");
+ }
+ else
+ {
+ printf("Downloading monitor...");
+ DownloadMonitor(serial_handle, gCmd.bRecorder, "minimon.bin"); // load the monitor image
+ // From now on, we can talk to the box.
+ printf("\b\b\b done.\n");
+
+ if (gCmd.bRecorder)
+ { // we can be faster
+ SetTargetBaudrate(serial_handle, 11059200, 115200); // set to 115200
+ }
+ }
+ }
+
+ // do the action
+
+ if (gCmd.bSpindown)
+ {
+ // spindown the disk (works only for master)
+ UINT32 ata; // address of ATA_ALT_STATUS
+ printf("Harddisk spindown...");
+ ata = (gCmd.bRecorder && (ReadHalfword(serial_handle, 0x020000FC) & 0x0100)) ? 0x06200206 : 0x06200306;
+ WriteHalfword(serial_handle, 0x05FFFFCA, 0xBF99); // PACR2 (was 0xFF99)
+ WriteHalfword(serial_handle, 0x05FFFFC4, 0x0280); // PAIOR (was 0x0000)
+ WriteHalfword(serial_handle, 0x05FFFFC0, 0xA27F); // PADR (was 0xA0FF)
+ while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
+ WriteByte(serial_handle, 0x06100107, 0xE0); // ATA_COMMAND = CMD_STANDBY_IMMEDIATE;
+ //while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY
+ printf("\b\b\b done.\n");
+ }
+
+
+ if (gCmd.bReadID)
+ {
+ UINT8 bMan, bID;
+ ReadID(serial_handle, 0x02000000, &bMan, &bID);
+ printf("Manufacturer ID = 0x%02X, Device ID = 0x%02X\n", bMan, bID);
+ }
+
+
+ if (gCmd.szFlashfile)
+ {
+ // flash a firmware file
+ printf("Flashing file %s...", gCmd.szFlashfile);
+ pFile = fopen(gCmd.szFlashfile, "rb");
+ if (pFile == NULL)
+ {
+ printf("\nFlash file %s not found, exiting.\n", gCmd.szFlashfile);
+ return -2;
+ }
+ size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
+ fclose (pFile);
+
+ EraseChip(serial_handle, 0x02000000);
+ FlashByteMultiple(serial_handle, 0x02000000, size, abFirmware);
+ printf("\b\b\b done.\n");
+ }
+
+
+ if (gCmd.szDumpfile)
+ {
+ // dump the flash content
+ printf("Writing flash dump into file %s...", gCmd.szDumpfile);
+ ReadByteMultiple(serial_handle, 0x02000000, sizeof(abFirmware), abFirmware);
+ pFile = fopen(gCmd.szDumpfile, "wb");
+ if (pFile == NULL)
+ {
+ printf("\nDump file %s cannot be opened, exiting.\n", gCmd.szDumpfile);
+ return -3;
+ }
+ fwrite(abFirmware, 1, sizeof(abFirmware), pFile);
+ fclose (pFile);
+ printf("\b\b\b done.\n");
+ }
+
+
+ if (gCmd.szExecfile)
+ {
+ UINT32 size;
+
+ printf("Downloading program...");
+
+ // init the DRAM controller like the flash boot does
+ reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2
+ reg &= 0xFFFB; // PA1 config: /RAS
+ reg |= 0x0008;
+ WriteHalfword(serial_handle, 0x05FFFFCA, reg); // PACR2
+ reg = 0xAFFF; // CS1, CS3 config: /CASH. /CASL
+ WriteHalfword(serial_handle, 0x05FFFFEE, reg); // CASCR
+ reg = ReadHalfword(serial_handle, 0x05FFFFA0); // BCR
+ reg |= 0x8000; // DRAM enable, default bus
+ WriteHalfword(serial_handle, 0x05FFFFA0, reg); // BCR
+ reg = ReadHalfword(serial_handle, 0x05FFFFA2); // WCR1
+ reg &= 0xFDFD; // 1-cycle CAS
+ WriteHalfword(serial_handle, 0x05FFFFA2, reg); // WCR1
+ reg = 0x0E00; // CAS 35%, multiplexed, 10 bit row addr.
+ WriteHalfword(serial_handle, 0x05FFFFA8, reg); // DCR
+ reg = 0x5AB0; // refresh, 4 cycle waitstate
+ WriteHalfword(serial_handle, 0x05FFFFAC, reg); // RCR
+ reg = 0x9605; // refresh constant
+ WriteHalfword(serial_handle, 0x05FFFFB2, reg); // RTCOR
+ reg = 0xA518; // phi/32
+ WriteHalfword(serial_handle, 0x05FFFFAE, reg); // RTCSR
+
+
+ // download Rockbox/gdb
+ pFile = fopen(gCmd.szExecfile, "rb");
+ if (pFile == NULL)
+ {
+ printf("\nExecutable file %s cannot be opened, exiting.\n", gCmd.szExecfile);
+ return -3;
+ }
+
+ size = fread(abFirmware, 1, sizeof(abFirmware), pFile);
+ WriteByteMultiple(serial_handle, 0x09000000, size, abFirmware);
+ fclose (pFile);
+ printf("\b\b\b done.\n");
+
+ // start rockbox/gdb
+ printf("Starting program...");
+ Execute(serial_handle, 0x09000200, false);
+ printf("\b\b\b done.\n");
+ }
+
+
+ if (gCmd.bTest)
+ {
+ // test code: query keypad
+ while (1)
+ {
+ WriteByte(serial_handle, 0x05FFFEE8, 0x24); // ADCSR
+ while (!(ReadByte(serial_handle, 0x05FFFEE8) & 0x80));
+ reg = ReadHalfword(serial_handle, 0x05FFFEE0); // ADDRA
+ printf("ADC(4): %d\n", reg>>6);
+ }
+ }
+
+
+ if (gCmd.bBlink)
+ {
+ // blinking LED
+ UINT8 byte;
+ printf("Flashing red LED forever... (stop with Ctrl-C)\n");
+ byte = ReadByte(serial_handle, 0x05FFFFC3);
+ while (1)
+ {
+ byte ^= 0x40;
+ WriteByte(serial_handle, 0x05FFFFC3, byte);
+ Sleep(200);
+ }
+ }
+
+ return 0;
+}
+
diff --git a/flash/uart_boot/uart_boot.dsp b/flash/uart_boot/uart_boot.dsp
new file mode 100644
index 0000000000..4d94c72530
--- /dev/null
+++ b/flash/uart_boot/uart_boot.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="uart_boot" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=uart_boot - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "uart_boot.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "uart_boot.mak" CFG="uart_boot - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "uart_boot - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "uart_boot - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "uart_boot - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "uart_boot - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "uart_boot - Win32 Release"
+# Name "uart_boot - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\client.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\flash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\uart_boot.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\uart_win.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\flash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\minimon.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\scalar_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\uart.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/flash/uart_boot/uart_win.c b/flash/uart_boot/uart_win.c
new file mode 100644
index 0000000000..243017ac88
--- /dev/null
+++ b/flash/uart_boot/uart_win.c
@@ -0,0 +1,138 @@
+// UART wrapper implementation for the Win32 platform
+// make a new version of this file for different systems, e.g. Linux
+
+#include <windows.h>
+#include "scalar_types.h" // (U)INT8/16/32
+#include "Uart.h"
+
+// COMx for windows, returns NULL on error
+tUartHandle UartOpen(char* szPortName)
+{
+ HANDLE serial_handle;
+ DCB dcb;
+ COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
+
+ memset(&dcb,0,sizeof(dcb));
+
+ /* -------------------------------------------------------------------- */
+ // set DCB to configure the serial port
+ dcb.DCBlength = sizeof(dcb);
+
+ dcb.fOutxCtsFlow = 0;
+ dcb.fOutxDsrFlow = 0;
+ dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable for power
+ dcb.fDsrSensitivity = 0;
+ dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable for power
+ dcb.fOutX = 0;
+ dcb.fInX = 0;
+
+ /* ----------------- misc parameters ----- */
+ dcb.fErrorChar = 0;
+ dcb.fBinary = 1;
+ dcb.fNull = 0;
+ dcb.fAbortOnError = 0;
+ dcb.wReserved = 0;
+ dcb.XonLim = 2;
+ dcb.XoffLim = 4;
+ dcb.XonChar = 0x13;
+ dcb.XoffChar = 0x19;
+ dcb.EvtChar = 0;
+
+ /* ----------------- defaults ----- */
+ dcb.BaudRate = 4800;
+ dcb.Parity = NOPARITY;
+ dcb.fParity = 0;
+ dcb.StopBits = ONESTOPBIT;
+ dcb.ByteSize = 8;
+
+
+ /* -------------------------------------------------------------------- */
+ // opening serial port
+ serial_handle = CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
+
+ if (serial_handle == INVALID_HANDLE_VALUE)
+ {
+ //printf("Cannot open port \n");
+ return NULL;
+ }
+
+ SetCommMask(serial_handle, 0);
+ SetCommTimeouts(serial_handle, &cto);
+
+ if(!SetCommState(serial_handle, &dcb))
+ {
+ //printf("Error setting up COM params\n");
+ CloseHandle(serial_handle);
+ return NULL;
+ }
+
+ return serial_handle;
+}
+
+// returns true on success, false on error
+bool UartConfig(tUartHandle handle, long lBaudRate, tParity nParity, tStopBits nStopBits, int nByteSize)
+{
+ DCB dcb;
+
+ if (!GetCommState (handle, &dcb))
+ {
+ return false;
+ }
+
+ dcb.BaudRate = lBaudRate;
+ dcb.Parity = nParity;
+ dcb.StopBits = nStopBits;
+ dcb.ByteSize = nByteSize;
+
+ if(!SetCommState(handle, &dcb))
+ {
+ //DWORD dwErr = GetLastError();
+ //printf("Error %d setting up COM params for baudrate byte\n", dwErr);
+ return false;
+ }
+
+ return true;
+}
+
+// returns how much data was actually transmitted
+long UartWrite(tUartHandle handle, unsigned char* pData, long lSize)
+{
+ BOOL success;
+ DWORD result_nbr;
+
+ success = WriteFile(handle, pData, lSize, &result_nbr, NULL);
+
+ if(!success)
+ {
+ return 0;
+ }
+
+ return result_nbr;
+}
+
+// returns how much data was actually received
+long UartRead(tUartHandle handle, unsigned char* pBuffer, long lSize)
+{
+ BOOL success;
+ DWORD read_nbr;
+
+ success = ReadFile(handle, pBuffer, lSize, &read_nbr, NULL);
+ if(!success)
+ {
+ return 0;
+ }
+
+ return read_nbr;
+}
+
+
+void UartClose(tUartHandle handle)
+{
+ if (handle != NULL)
+ {
+ CloseHandle(handle);
+ }
+
+ return;
+}