uint64_t mac2int (const std::string& mac) { char const *beg = mac.data(); char const *end = beg + mac.size(); uint64_t r = 0; try { r = readHexByte(&beg, end); beg += beg != end && ':' == *beg; r = r << 8 | readHexByte(&beg, end); beg += beg != end && ':' == *beg; r = r << 8 | readHexByte(&beg, end); beg += beg != end && ':' == *beg; r = r << 8 | readHexByte(&beg, end); beg += beg != end && ':' == *beg; r = r << 8 | readHexByte(&beg, end); beg += beg != end && ':' == *beg; r = r << 8 | readHexByte(&beg, end); } catch (std::invalid_argument&) { beg = end - 1; } if (beg != end) { throw std::runtime_error("invalid mac address format " + mac); } return r; }
static FirmwareArchive::Block processXmlBlock( const tinyxml2::XMLElement * element) { assert(element != NULL); FirmwareArchive::Block block; // Get the address. const char * addressCStr = element->Attribute("address"); if (addressCStr == NULL) { throw std::runtime_error("A block is missing an address attribute."); } unsigned long address; if (niceStrToULong(addressCStr, &address)) { throw std::runtime_error("A block has an invalid address attribute."); } block.address = address; // Get the contents. const char * contentsCStr = element->GetText(); if (contentsCStr == NULL) { throw std::runtime_error("A block has missing or invalid contents."); } std::string contents(contentsCStr); if ((contents.size() % 2) != 0) { throw std::runtime_error("A block has an odd number of characters."); } uint32_t byteCount = contents.size() / 2; std::istringstream stream(contents); block.data.resize(byteCount); for (uint32_t i = 0; i < byteCount; i++) { block.data[i] = readHexByte(stream); } return block; }
//! \brief Parses individual S-records. //! //! Takes a single S-record line as input and appends a new SRecord struct //! to the m_records vector. //! \exception StSRecordParseException will be thrown if any error occurs while //! parsing \a inLine. void StSRecordFile::parseLine(std::string &inLine) { int checksum = 0; SRecord newRecord; memset(&newRecord, 0, sizeof(newRecord)); // must start with "S" and be at least a certain length if (inLine[0] != SRECORD_START_CHAR && inLine.length() >= SRECORD_MIN_LENGTH) { throw StSRecordParseException("invalid record length"); } // parse type field char typeChar = inLine[1]; if (!isdigit(typeChar)) { throw StSRecordParseException("invalid S-record type"); } newRecord.m_type = typeChar - '0'; // parse count field newRecord.m_count = readHexByte(inLine, 2); checksum += newRecord.m_count; // verify the record length now that we know the count if (inLine.length() != 4 + newRecord.m_count * 2) { throw StSRecordParseException("invalid record length"); } // get address length int addressLength = 0; // len in bytes bool hasData = false; switch (newRecord.m_type) { case 0: // contains header information addressLength = 2; hasData = true; break; case 1: // data record with 2-byte address addressLength = 2; hasData = true; break; case 2: // data record with 3-byte address addressLength = 3; hasData = true; break; case 3: // data record with 4-byte address addressLength = 4; hasData = true; break; case 5: // the 2-byte address field contains a count of all prior S1, S2, and S3 records addressLength = 2; break; case 7: // entry point record with 4-byte address addressLength = 4; break; case 8: // entry point record with 3-byte address addressLength = 3; break; case 9: // entry point record with 2-byte address addressLength = 2; break; default: // unrecognized type // throw StSRecordParseException("unknown S-record type"); break; } // read address int address = 0; int i; for (i = 0; i < addressLength; ++i) { int addressByte = readHexByte(inLine, SRECORD_ADDRESS_START_CHAR_INDEX + i * 2); address = (address << 8) | addressByte; checksum += addressByte; } newRecord.m_address = address; // read data if (hasData) { int dataStartCharIndex = 4 + addressLength * 2; int dataLength = newRecord.m_count - addressLength - 1; // total rem - addr - cksum (in bytes) uint8_t *data = new uint8_t[dataLength]; for (i = 0; i < dataLength; ++i) { int dataByte = readHexByte(inLine, dataStartCharIndex + i * 2); data[i] = dataByte; checksum += dataByte; } newRecord.m_data = data; newRecord.m_dataCount = dataLength; } // read and compare checksum byte checksum = (~checksum) & 0xff; // low byte of one's complement of sum of other bytes newRecord.m_checksum = readHexByte(inLine, (int)inLine.length() - 2); if (checksum != newRecord.m_checksum) { throw StSRecordParseException("invalid checksum"); } // now save the new S-record m_records.push_back(newRecord); }
int main(int argc, char* argv[]) { FILE* f; char c; unsigned int len; unsigned int add; unsigned int typ; unsigned int u; char progBuf[8192]; char* p = progBuf; unsigned int sum, checksum, total_len; if (argc != 3) { fprintf(stderr, "Usage: sendprog <file.hex or file.bin> <comm port name/path>\n"); fprintf(stderr, "File extension .hex is case sensitive\n"); exit(1); } #if LINUX fd = open(argv[2], O_RDWR | O_NOCTTY | O_NDELAY ); if(!isatty(fd)) { printf("Error - not a tty!\n"); exit(1); } if(tcgetattr(fd, &config) < 0) { printf("Error - getattr failed\n"); exit(1); } // // Input flags - Turn off input processing // convert break to null byte, no CR to NL translation, // no NL to CR translation, don't mark parity errors or breaks // no input parity check, don't strip high bit off, // no XON/XOFF software flow control // config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); // // Output flags - Turn off output processing // no CR to NL translation, no NL to CR-NL translation, // no NL to CR translation, no column 0 CR suppression, // no Ctrl-D suppression, no fill characters, no case mapping, // no local output processing // // config.c_oflag &= ~(OCRNL | ONLCR | ONLRET | // ONOCR | ONOEOT| OFILL | OLCUC | OPOST); config.c_oflag = 0; // // No line processing: // echo off, echo newline off, canonical mode off, // extended input processing off, signal chars off // config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); // // Turn off character processing // clear current char size mask, no parity checking, // no output processing, force 8 bit input // config.c_cflag &= ~(CSIZE | PARENB); config.c_cflag |= CS8; // // One input byte is enough to return from read() // Inter-character timer off // config.c_cc[VMIN] = 1; config.c_cc[VTIME] = 0; // // Communication speed (simple version, using the predefined // constants) // if(cfsetispeed(&config, B9600) < 0 || cfsetospeed(&config, B9600) < 0) { printf("Error - can't set baud rate to 9600\n"); exit(1); } // // Finally, apply the configuration // if(tcsetattr(fd, TCSAFLUSH, &config) < 0) { printf("Error - could not set configuration\n"); exit(1); } #else { char sName[32]; COMMCONFIG lpCC; sprintf(sName, "\\\\.\\%s", argv[2]); hComm = CreateFile(sName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hComm == INVALID_HANDLE_VALUE) { fprintf(stderr, "Error opening port %s\n", argv[2]); exit(1); } GetCommState( hComm, &lpCC.dcb); /* Initialisation of parameters */ lpCC.dcb.BaudRate = CBR_9600; //lpCC.dcb.BaudRate = CBR_19200; lpCC.dcb.ByteSize = 8; lpCC.dcb.StopBits = ONESTOPBIT; lpCC.dcb.Parity = NOPARITY; lpCC.dcb.fDtrControl = DTR_CONTROL_DISABLE; lpCC.dcb.fRtsControl = RTS_CONTROL_DISABLE; SetCommState(hComm, &lpCC.dcb ); } #endif f = fopen(argv[1], "r"); if (f == NULL) { fprintf(stderr, "Could not open %s for reading\n", argv[1]); exit(1); } memset(progBuf, '\xFF', 8192); if (strcmp(argv[1] + strlen(argv[1]) - 4, ".hex") == 0) { unsigned int first_addr = (unsigned int) -1; total_len = 0; do { readColon(f); sum = 0; len = readHexByte(f); add = readHexWord(f); typ = readHexByte(f); if (typ == 1) break; if (typ > 0) { fprintf(stderr, "Unexpected record type %X at address %X\n", typ, address); exit(1); } if (add < 0xE000) continue; /* Repeat the loop, looking for the colon on the next line */ if (first_addr == (unsigned int) -1) /* Assume that the first address past E000 is the start of the image */ first_addr = add; address = add; p = progBuf + add - first_addr; for (u=0; u < len; ++u) { *p++ = readHexByte(f); } total_len += len; checksum = readHexByte(f); if (sum & 0xFF) { fprintf(stderr, "Bad checksum %X expected %X\n", checksum, 0-(sum-checksum) & 0xFF); exit(1); } address += len; } while (!feof(f)); } else /* Assume a binary file */ { struct stat st; stat(argv[1], &st); total_len = st.st_size; fread(progBuf, 1, total_len, f); } printf("Read %d bytes\n", total_len); fclose(f); /* Calculate the checksum, and place at 0xFFFD (first unused interrupt vector, starting at highest address, after reset */ sum = 0; for (u=0; u < 0xE00-1; ++u) sum ^= progBuf[u]; progBuf[0xE00-1] = sum; /* Now it will checksum to zero */ /* Now send this image to the CMUs */ { int i, j, k; /* Write the prefix */ #define PASSLEN (1+4) char* pfx = "\x1B\x07\x06\x05\x04\x00"; /* ESC ^G ^F ^E ^D */ for (i=0; i < PASSLEN; ++i) { writeByte(pfx+i); /* Write prefix */ usleep(2000); /* Time to transmit byte to CMU, and for it to echo to next CMU */ } /* NOTE: We are putting the delay in two positions now, because we have two versions of the BSL. Soon the second delay can go away */ /* Allow extra time for bulk erase; approximately 3 characters */ usleep(32000); // But this is ~ 32 chars worth, could likely cut down /* Send the $E00-2 bytes of the binary image */ // writeByte(progBuf); /* Write first byte */ /* Allow time for bulk erase; approximately 3 characters */ usleep(32000); /* To be safe, enough for 32 chars */ for (u=0; u < 0xE00; ++u) { if ((u & 0x7F) == 0x7F) { printf("."); fflush(stdout); } writeByte(progBuf+u); /* Write byte */ usleep(3000); /* Time to transmit, echo, and flash write */ } } #if LINUX close(fd); #else CloseHandle(hComm); #endif printf("Done\n"); return 0; }
unsigned int readHexWord(FILE* f) { return (readHexByte(f) << 8) + readHexByte(f); }