// client.cpp : functions for monitor download and communication. // #include #include #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 %lu 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 %lu 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 %lu 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 %lu 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; 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" 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>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" 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; }