Zipit Z1
Upload程式(C/C++)
程式碼(Windows)如下:
#include <stdio.h> #include <assert.h> #include <string.h> #include <stdlib.h> #include <assert.h> #define verify assert #include <windows.h> #include <conio.h> HANDLE OpenSerial(int iPort) { char szPort[32]; sprintf(szPort, "COM%d", iPort); return CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } void CloseSerial(HANDLE hSerial) { CloseHandle(hSerial); } bool SetCommDefaultsPart1(HANDLE hSerial, int baud) { DCB dcb; memset(&dcb, 0, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); dcb.fBinary = TRUE; dcb.fParity = TRUE; dcb.BaudRate = baud; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.fOutxDsrFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fOutxCtsFlow = FALSE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fInX = dcb.fOutX = FALSE; if(!SetCommState(hSerial, &dcb)){ return false; } return true; } bool SetCommDefaults(HANDLE hSerial) { if(!SetCommDefaultsPart1(hSerial, CBR_9600)){ return false; } COMMTIMEOUTS to; memset(&to, 0, sizeof(to)); to.ReadIntervalTimeout = MAXDWORD; if(!SetCommTimeouts(hSerial, &to)){ return false; } PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); return true; } bool SetBaud(HANDLE hSerial, int baud) { if(!SetCommDefaultsPart1(hSerial, baud)){ return false; } PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); return true; } void PurgeSerial(HANDLE hSerial) { while(1){ BYTE b; DWORD cbRead; if(!ReadFile(hSerial, &b, 1, &cbRead, NULL)){ fprintf(stderr, "FATAL: Purge failed for serial port\n"); exit(-1); } if(cbRead == 0){ break; } } } bool PeekSerialByte(HANDLE hSerial, BYTE& bRet) { DWORD cbRead; if(!ReadFile(hSerial, &bRet, 1, &cbRead, NULL)){ fprintf(stderr, "FATAL: ReadFile failed for serial port\n"); exit(-1); } if(cbRead == 1){ return true; } return false; } void SendSerialBytes(HANDLE hSerial, const BYTE* pb, int cb) { DWORD cbWrite; if(!WriteFile(hSerial, pb, cb, &cbWrite, NULL) || cbWrite != cb){ fprintf(stderr, "FATAL: WriteFile failed for serial port\n"); exit(-1); } } void PrUsage(void) { printf("usage: upl -# file.bin\n"); printf(" -# = port number [COM1 default]\n"); exit(-1); } bool LoadFile(const char* szInFile, byte* pbImage, int cbImage) { FILE* pfIn = fopen(szInFile, "rb"); if(pfIn == NULL){ fprintf(stderr, "FATAL: can't open input file '%s'\n", szInFile); return false; } fseek(pfIn, 0, SEEK_END); int cbFile = ftell(pfIn); fseek(pfIn, 0, SEEK_SET); if(cbFile < cbImage){ fclose(pfIn); fprintf(stderr, "FATAL: input file '%s' wrong size\n", szInFile); fprintf(stderr, "\t %d bytes (%d bytes expected)\n", cbFile, cbImage); return false; } if(cbFile > cbImage){ printf("uploading %d bytes of %d byte file\n", cbImage, cbFile); } if(fread(pbImage, cbImage, 1, pfIn) != 1){ fclose(pfIn); fprintf(stderr, "FATAL: read error on input file '%s'\n", szInFile); return false; } if(cbFile > cbImage){ int cbExtra = cbFile - cbImage; byte* pbExtra = new byte[cbExtra]; assert(fread(pbExtra, cbExtra, 1, pfIn) == 1); int nErr = 0; for(int i=0; i<cbExtra; i++){ if(pbExtra[i] != 0){ nErr++; } } delete [] pbExtra; if(nErr > 0){ fclose(pfIn); fprintf(stderr, "FATAL: non-zero data at end of input file '%s'\n", szInFile); return false; } } fclose(pfIn); return true; } FILE* g_pfLog = NULL; bool EchoSerial(HANDLE hSerial) { BYTE b; if(!PeekSerialByte(hSerial, b)){ return false; } if(b >= 0x20 && b < 0x7f){ printf("%c", b); } else if(b == 0xD || b == 0xA){ printf("%c", b); } else{ printf("$%02x$", b); } if(g_pfLog != NULL){ fputc((char)b, g_pfLog); } return true; } void EchoSerialTilEmpty(HANDLE hSerial, int nDelay) { for(int iTry=0; iTry<10; iTry++){ while(EchoSerial(hSerial)); Sleep(nDelay); if(!EchoSerial(hSerial)){ break; } } } BYTE* LoadFile(const char* szFile, long& cbRet) { FILE* pf = fopen(szFile, "rb"); if(pf == NULL){ return NULL; } fseek(pf, 0, SEEK_END); cbRet = ftell(pf); fseek(pf, 0, SEEK_SET); byte* pbFile = new byte[cbRet]; assert(fread(pbFile, cbRet, 1, pf) == 1); fclose(pf); return pbFile; } BYTE CalcChecksum(const BYTE* pb, long cb) { BYTE csum = 0; while(cb--){ csum += *pb++; } return csum; } bool UploadFile(HANDLE hSerial, const char* szFile, BYTE chCmd) { long cbFile; byte* pbFile = LoadFile(szFile, cbFile); if(pbFile == NULL){ printf("No %s to upload!\n", szFile); return false; } assert(cbFile > 0); printf("//Uploading %ld bytes from %s\n", cbFile, szFile); SendSerialBytes(hSerial, &chCmd, 1); SendSerialBytes(hSerial, (BYTE*)&cbFile, 4); Sleep(250); //BLOCK: ZPM should reply with "BEG:xxxxxxxx" where xxxxxxxx = hex length { char reply[4+8+1]; reply[4+8] = '\0'; DWORD cbRead; long cbAck; if(!ReadFile(hSerial, reply, sizeof(reply)-1, &cbRead, NULL) || cbRead != sizeof(reply)-1 || memcmp(reply, "BEG:", 4) != 0 || sscanf(reply+4, "%08lX", &cbAck) != 1 || cbAck != cbFile) { printf("Zipit is not responding - not ready to upload\n"); printf("\t'%s'\n", reply); delete [] pbFile; return false; } } SendSerialBytes(hSerial, pbFile, cbFile); BYTE csum = CalcChecksum(pbFile, cbFile); delete [] pbFile; Sleep(500); //BLOCK: ZPM should reply with "END:xx" where xx = hex checksum { char reply[4+2+1]; reply[4+2] = '\0'; DWORD cbRead; BYTE csumAck; if(!ReadFile(hSerial, reply, sizeof(reply)-1, &cbRead, NULL) || cbRead != sizeof(reply)-1 || memcmp(reply, "END:", 4) != 0 || sscanf(reply+4, "%02X", &csumAck) != 1) { printf("Zipit did not upload properly\n"); return false; } if(csumAck != csum){ printf("Zipit uploaded incorrectly - checksum mismatch\n"); return false; } } printf("// done upload\n"); return true; } bool GrabFile(HANDLE hSerial, const char* szFile, long cbGrab, BYTE chCmd) { byte* pbGrab = new byte[cbGrab]; assert(cbGrab > 0); printf("//Grabbing %ld bytes from ROM - store in %s\n", cbGrab, szFile); // send command byte, 'R' SendSerialBytes(hSerial, &chCmd, 1); int cbSoFar = 0; while (cbSoFar < cbGrab){ DWORD cbRead = 0; if(!ReadFile(hSerial, &pbGrab[cbSoFar], cbGrab-cbSoFar, &cbRead, NULL) || cbRead <= 0){ printf("-"); Sleep(50); continue; } printf("+"); assert(cbRead > 0); cbSoFar += cbRead; } FILE* pf = fopen(szFile, "wb"); verify(pf != NULL); verify(fwrite(pbGrab, cbGrab, 1, pf) == 1); verify(fclose(pf) == 0); delete [] pbGrab; return true; } BYTE g_rgbImage[2*1024]; int main(int argc, char* argv[]) { int iPort = 1; // default COM1 const char* szInputSource; if(argc == 3 && argv[1][0] == '-'){ iPort = atoi(&argv[1][1]); szInputSource = argv[2]; } else if(argc == 2){ szInputSource = argv[1]; } else{ PrUsage(); } assert(iPort > 0); int cbImage = 2*1024; if(!LoadFile(szInputSource, g_rgbImage, cbImage)){ return -1; } HANDLE hSerial = OpenSerial(iPort); if(hSerial == (HANDLE)-1){ fprintf(stderr, "Failed to open serial port COM%d\n", iPort); exit(-1); } if(!SetCommDefaults(hSerial)){ fprintf(stderr, "Failed to set COM%d to 9600 baud\n", iPort); CloseSerial(hSerial); return -1; } printf("Connected\n"); printf("Turn on the Zipit (press button, wait for green, release)\n"); printf(" Wait 10 seconds, then press any key to start transfer\n"); printf(" (DBG pin must be grounded)\n"); int nSkip = 0; BYTE bIgnore; while(PeekSerialByte(hSerial, bIgnore)){ nSkip++; } if(nSkip > 0){ printf("Skipping %d left over data bytes\n"); } while(_kbhit() == 0){ Sleep(100); } _getch(); // eat the character printf("Transfering bootstrap program\n"); SendSerialBytes(hSerial, g_rgbImage, cbImage); printf("Transfer complete\n"); Sleep(100); printf("Switch to 57.6kbps\n"); if(!SetBaud(hSerial, 57600)){ printf("SET BAUD RATE ERROR!\n"); return -1; } #if 0 g_pfLog = fopen("log.txt", "at"); // save session #endif printf("Echo + upload commands\n"); printf("\tDecide what to upload\n"); printf("\t'A' - allrom.bin upload (2MB)\n"); printf("\t'a' - loader.bin upload (8K max)\n"); printf("\t'k' - zimage.dat upload (581K max)\n"); printf("\t'u' - ramdisk.gz upload (1.5MB max)\n"); printf("\tFollow changes with 'WYes' to write\n"); printf("\tOther commands\n"); printf("\t'R' - grab ROM\n"); while(1){ while(EchoSerial(hSerial)); if(_kbhit()){ BYTE b = _getch(); if(b == 'u'){ UploadFile(hSerial, "ramdisk.gz", b); // -> ramdisk.gz } else if(b == 'k'){ UploadFile(hSerial, "zimage.dat", b); // -> kernel.gz } else if(b == 'a'){ UploadFile(hSerial, "loader.bin", b); // -> start of ROM image } else if(b == 'A'){ UploadFile(hSerial, "allrom.bin", b); // -> start of ROM image } else if(b == 'R'){ GrabFile(hSerial, "grabrom.bin", 2*1024*1024, b); printf("// grab done -- I hope...\n"); } else if(b == 'Q'){ printf("// done echo mode\n"); break; } else{ SendSerialBytes(hSerial, &b, 1); } } Sleep(50); // don't be a total CPU pig } if(g_pfLog != NULL){ fclose(g_pfLog); } g_pfLog = NULL; return 0; }