⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chip45boot.c

📁 AVR的引导程序。 chip45boot s-record bootloader.
💻 C
📖 第 1 页 / 共 2 页
字号:
	    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 + -