// uart_boot.cpp : Defines the entry point for the console application. // #include #include #include #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 bHold; // hold power (for FMs & V2s) 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 \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("-hold (hold the power, useful for FMs and V2s, so you can release ON)\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 \n"); printf("-dump \n"); printf("-exec \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("-hold", *argv, 2)) { gCmd.bHold = 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.bHold) { // hold power for FM reg = ReadHalfword(serial_handle, 0x05FFFFC2); // PBDR reg |= 0x0020; // set PB5 to keep power WriteHalfword(serial_handle, 0x05FFFFC2, reg); reg = ReadHalfword(serial_handle, 0x05FFFFC6); // PBIOR reg |= 0x0020; // make PB5 an output WriteHalfword(serial_handle, 0x05FFFFC6, reg); printf("Power hold, you can release ON button now.\n"); } if (gCmd.bSpindown) { // power down the disk reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2 reg &= ~0x0400; // clear bit 10: GPIO WriteHalfword(serial_handle, 0x05FFFFCA, reg); reg = ReadHalfword(serial_handle, 0x05FFFFC4); // PAIOR reg |= 0x0020; // set bit 5: output WriteHalfword(serial_handle, 0x05FFFFC4, reg); reg = ReadHalfword(serial_handle, 0x05FFFFC0); // PADR reg &= ~0x0020; // clear PA5 to power down WriteHalfword(serial_handle, 0x05FFFFC0, reg); printf("Harddisk powered down.\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: toggle PA5 to test FM IDE power reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2 reg &= ~0x0400; // clear bit 10: GPIO WriteHalfword(serial_handle, 0x05FFFFCA, reg); reg = ReadHalfword(serial_handle, 0x05FFFFC4); // PAIOR reg |= 0x0020; // set bit 5: output WriteHalfword(serial_handle, 0x05FFFFC4, reg); printf("Toggling PA5 forever... (stop with Ctrl-C)\n"); reg = ReadHalfword(serial_handle, 0x05FFFFC0); // PADR while (1) { reg ^= 0x0020; WriteHalfword(serial_handle, 0x05FFFFC0, reg); // PADR Sleep(1000); } } 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; }