📄 chip45boot.c
字号:
uartPutChar('e'); // echo the 'e'
programThisMemory = EEPROM; // set flag
}
#endif
if(c == 'g') { // 'g' starts the application
uartPutChar('g'); // echo the 'g'
myIVSELREG = _BV(IVCE); // relocate interrupt vector table
myIVSELREG = 0; // to bottom of flash
startApplication(); // and jumpt to 0x0000
}
} while(!programThisMemory); // exit loop when a valid key was pressed
uartPutChar('\r'); // set cursor to next line
receiveBufferFull = FALSE; // reset full flag
receiveBufferPointer = (char *)receiveBuffer; // reset buffer pointer to start of buffer
// enable interrupts
sei();
// endless loop
while(1) {
// if buffer is full, parse the buffer and write to flash
if(receiveBufferFull) {
cli(); // disable interrupts
// if parsing produced an error, restart bootloader
if(!parseSrecBuffer(receiveBuffer)) {
uartPutChar('\r'); // set cursor to next line
startBootloader(); // restart the bootloader
}
// was an end-of-file s-record found?
if(srecEndOfFile) {
uartPutChar('O'); // '+' indicates successful programming
uartPutChar('K'); // '+' indicates successful programming
startBootloader(); // restart the bootloader
}
receiveBufferFull = FALSE; // reset full flag
receiveBufferPointer = (char *)receiveBuffer; // reset buffer pointer to start of buffer
sei(); // enable interrupts
}
}
}
//
// parse the current s-record in the buffer
//
uint8_t parseSrecBuffer(char *thisBuffer) {
uint8_t srecBytecount, srecChecksum, srecType;
uint32_t srecAddress;
uint8_t tmpAddress;
char hi, lo;
char c1, c2;
uint16_t i;
// check if current buffer is a data record (starts with S1, S2 or S3)
if(*thisBuffer++ == 'S' ) {
// get s-record type
srecType = hexCharToInt(*thisBuffer++);
// only process the record in case it's a data record
if((srecType == 1) || (srecType == 2) || (srecType == 3)) {
// get the byte count
hi = *thisBuffer++;
lo = *thisBuffer++;
srecBytecount = hexByteToInt(hi, lo);
// one could directly put *thisBuffer++ into the arguments,
// but the arguments are put on stack last first, i.e. the
// lo character is fetched from the *thisBuffer first and
// this changes lo and hi character! Using seperate variables
// hi and lo is more clear and readable than changing the
// sequence in the hexByteToInt function.
// check if byte count is larger than 0x43, i.e. we have more
// than 64 bytes in the record -> not allowed
if(srecBytecount > (0x43 + srecType - 1)) {
uartPutChar('B'); // 'B' indicates this error
return FALSE;
}
srecChecksum = srecBytecount; // add byte count to checksum
srecAddress = 0; // reset s-record address
// extract the address depending of s-record type
for(i = 0; i <= srecType; ++i) {
hi = *thisBuffer++;
lo = *thisBuffer++;
tmpAddress = hexByteToInt(hi, lo); // get next address byte
srecAddress <<= 8; // shift existing address one byte left
srecAddress += tmpAddress; // add new lower address byte
srecChecksum += tmpAddress; // add address portion to checksum
}
// read all data bytes
for(i = 0; i < (srecBytecount - 3 + (srecType - 1)); i += 2) {
// assemble a 16 bit little endian data word and calculate checksum
hi = *thisBuffer++;
lo = *thisBuffer++;
c1 = hexByteToInt(hi, lo);
srecChecksum += c1;
hi = *thisBuffer++;
lo = *thisBuffer++;
c2 = hexByteToInt(hi, lo);
srecChecksum += c2;
#ifdef EEPROM_CODE
if(programThisMemory == FLASH) {
#endif
// write word to flash write buffer
boot_page_fill(srecAddress + i, (c2 << 8) + c1);
#ifdef EEPROM_CODE
} else {
// write hi and lo byte into eeprom buffer
eepromWriteBuffer[srecAddress + i] = c1;
eepromWriteBuffer[srecAddress + i + 1] = c2;
}
#endif
// This counter decrements from SPM_PAGESIZE to zero,
// when zero is reached, the flash page may be written.
// If it goes below zero, the bytecount of an s-record
// was not a integer factor of the flash page size.
// See description on top of this file.
if((flashPageSizeCounter -= 2) < 0) {
uartPutChar('P'); // 'P' indicates this error
return FALSE;
}
}
// get checksum and compare to 0xff
hi = *thisBuffer++;
lo = *thisBuffer++;
srecChecksum += hexByteToInt(hi, lo);
// compare checksum to 0xff
if(srecChecksum != 0xff) {
uartPutChar('C'); // if checksum is wrong, 'C' indicates this error
return FALSE;
}
uartPutChar('.'); // '.' indicates some progress
}
// check if end of file record
if((srecType == 9) || (srecType == 8) || (srecType == 7)) {
srecEndOfFile = TRUE;
}
}
// check if either page size counter is zero (i.e. buffer is full)
// or end of file was reached (i.e. the previously received
// bytes must be written to flash)
if((flashPageSizeCounter == 0) || (srecEndOfFile == TRUE)){
#ifdef EEPROM_CODE
if(programThisMemory == FLASH) {
#endif
boot_page_erase(writeBaseAddress); // do a page erase
boot_spm_busy_wait(); // wait for page erase done
boot_page_write(writeBaseAddress); // do a page write
boot_spm_busy_wait(); // wait for write completed
boot_rww_enable(); // reenable rww section again
#ifdef EEPROM_CODE
}
if(programThisMemory == EEPROM) {
eeprom_busy_wait(); // wait for eeprom no longer busy
eeprom_write_block(eepromWriteBuffer,
(void *)(uint16_t)writeBaseAddress,
SPM_PAGESIZE); // write the block to eeprom
}
#endif
flashPageSizeCounter = SPM_PAGESIZE; // set byte counter to correct value
writeBaseAddress += SPM_PAGESIZE;
}
return TRUE;
}
//
// convert a hex number character into 4 bit unsigned integer
//
uint8_t hexCharToInt(char c) {
// test if character is letter or number
if(c <= '9')
return (c - '0');
else
return (c - 'A' + 0xa);
}
//
// convert a hex byte (two characters) into 8 bit unsigned integer
//
uint8_t hexByteToInt(char hi, char lo) {
return ( (hexCharToInt(hi) << 4) + hexCharToInt(lo) ); // return the unsigned integer
}
//
// send a character through the USART
//
void uartPutChar(char c) {
if(c == '\r') // if character is 'caraige return', then
uartPutChar('\n'); // send an additional 'new line'
loop_until_bit_is_set(myUCSRA, myUDRE); // wait until transmit buffer is empty
myUDR = c; // write character to transmit buffer
}
//
// receive a character from the USART
//
char uartGetChar(void) {
loop_until_bit_is_set(myUCSRA, myRXC); // wait until character is received
return myUDR; // return the character
}
//
// end of file chip45boot.c
////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -