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

📄 chip45boot.c

📁 AVR的引导程序。 chip45boot s-record bootloader.
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// chip45boot.c
// ------------
//
// chip45boot .srec bootloader for Atmel AVR microcontrollers
//
// Copyright 2006 by Erik Lins, www.chip45.com
//
// License
// -------
// chip45boot is distributed under the Lesser General Public License (LGPL).
// You should have received a copy (lgpl.txt) of the license along with
// this file or go to http://www.gnu.org/licenses/lgpl.html.
//
// Description
// -----------
// The bootloader can receive a Motorola s-record file through USART.
// An interactive mode can be entered after reset and provides simple
// commands.
//
// Usage
// -----
// The bootloader waits a short while for receiving an 'i' from USART.
// (In a terminal program, hold the 'i' key pressed during reset.)
// If so, a prompt "> " will be shown.
// Available commands are:
// 'f' starts the flash programming (the character f is echoed plus an '\r')
//     Now an s-record file (see above) can be uploaded to the controller.
//     During programming a line of '.' is shown, each '.' marks the end of
//     a valid s-record line.
//     When programming has been completed successfully 'OK' is shown and the
//     bootloader starts again.
//     Note: It will start the application, if it doesn't receive an 'i' again!
//     Possible errors during programming are:
//     'B' wrong byte count in s-record
//     'C' wrong checksum in s-record
//     'P' wrong page count, i.e. s-record number of data bytes are not an
//          integer factor of flash page size
// 'g' starts the application, i.e. interrupt vector table is rearranged to
//     bottom of flash and bootloader jumps to 0x0000
// 'e' starts the programming of the EEPROM
//     This command is only available if you #define EEPROM_CODE!
//     It increases bootloader code by about 200 bytes, keep this in mind when
//     setting the fuse bits for boot block size!
//
// S-Record Upload with Terminal Program
// -------------------------------------
// Any terminal program can be used for uploading the .srec file to
// the MCU, e.g. HyperTerminal, which comes with any Windows system or
// TeraTermPro (http://hp.vector.co.jp/authors/VA002416/teraterm.html),
// which I prefer. Since the bootloader receives an s-record (one line
// of the file), then programs the s-record to flash, then receives the
// next s-record, programs it and so on, it is necessary to delay the 
// transmission of each line for the time the bootloader needs to
// program the flash page. For an ATmega8 (64 byte flash page size) running
// at 14.7456MHz a delay of 100msec after each line is sufficient. I will do
// further tests and add the experiences in this text.
// To set this delay with the terminal program do this:
// TeraTermPro: Menu Setup -> Serial Port -> Transmit Delay -> "100" msec/line
// HyperTerminal: Datei -> Eigenschaften -> Einstellungen ->
// ASCII-Konfiguration -> Zeilenverz鰃erung "100" Millisekunden
//
// S-Record Upload with chip45prog
// -------------------------------
// chip45prog is a simple command line tool, which can be used to progam
// an MCU target with chip45boot installed.
// See chip45prog.c (included in the ZIP) for details.
// The necessary changes to a regular WinAVR Makefile are listed in
// the chip45prog.c source code.
//
// S-record File Criteria:
// -----------------------
// The maximum number of data bytes per s-record (each line of the
// s-record file) is 64. avr-objcopy usually generates s-record files
// with 32 data bytes / s-record -> good for all AVRs!
// The data bytes of the s-record must not be larger than the flash
// page size of the target AVR MCU, but must be an integer factor of
// the flash page size (e.g. 64 byte flash page size and 16, 32 or 64
// data bytes per s-record). Since all major AVRs have at least 64 bytes
// flash page size and common s-records have 32 data bytes per record,
// everything should fine most of the time!
//
// In case you need to generate an s-record file from the normally used
// Intel hex file, srec_cat will do the job. srec_cat comes with WinAVR:
//
// srec_cat input.hex -Intel -Output output.srec -Motorola
//
// You can specify the line length for the s-records:
// srec_cat input.hex -Intel -Output output.srec -Motorola -Line_Length 142
// (the line length of 142 results in a byte count of 64, which is the maximum)
//
// Cheers, ER!K ;-)
//

// Subversion keywords
//
// $Rev: 24 $
// $Date: 2006-06-12 14:10:27 +0200 (Mo, 12 Jun 2006) $
//


// includes
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/boot.h>
#include <util/delay.h>


// include additional MCU definitions to allow compiling
// for different MCUs from same source code
#include "mcudefs.h"


// definitions

// #define this to include code for programming the EEPROM
// it reduced bootloader code size by 124 bytes.
// code size with eeprom code:   1022 bytes
// code size without eeprom code: 898 bytes
// #undef EEPROM_CODE
#define EEPROM_CODE

// CPU frequency is normally defined in the Makefile
#ifndef F_CPU
#define F_CPU 14745600
#endif

// TRUE and FALSE
#define TRUE  1
#define FALSE 0

// UART baudrate
#define BAUDRATE 115200

// memory type to program
#define NONE 0
#define FLASH 1
#define EEPROM 2

// function prototypes
void uartPutChar(char);  // put a character over USART
char uartGetChar(void);  // read (wait for) a character from USART
void uartPutHex(uint8_t);  // print hex byte over USART
void uartPutString(char *);
uint8_t hexCharToInt(char);  // convert hex character to unsigned integer
uint8_t hexByteToInt(char, char);  // convert hex byte (two characters) to unsigned integer
uint8_t parseSrecBuffer(char *);  // parse the current s-record in the buffer
void (*startApplication)( void ) = 0x0000;  // pointer to application at flash start
// adjust the following to the startaddress of the bootloader section in flash
// this is the same value, you have to adjust in the Makefile
void (*startBootloader)( void ) = 0x1800;  // pointer to application at flash start


// global variables
char receiveBuffer[150];
char *receiveBufferPointer;
uint8_t receiveBufferFull;
uint32_t writeBaseAddress = 0;
int8_t flashPageSizeCounter = SPM_PAGESIZE;
#ifdef EEPROM_CODE
char eepromWriteBuffer[SPM_PAGESIZE+2];  // SPM_PAGESIZE used as eeprom buffer size
#endif
uint8_t srecEndOfFile = FALSE;
uint8_t programThisMemory = NONE;


//
// interrupt routine called when a character was received from USART
//
ISR(myUSART_ReceiveCompleteVect) {

    char c = myUDR;  // save the character

    if((c != '\r') && (c != '\n')) {
	*receiveBufferPointer++ = c;  // write character to the buffer
    } else {
	// if end of line is reached, set buffer full flag
	// this starts s-record processing in the main program
	receiveBufferFull = TRUE;
    }
}


//
// main function
//
int main(void) {

    char c;
    uint16_t loop = 0;
    uint8_t bootloaderEnableFlag = FALSE;


    // init USART
    myUBRRH = (F_CPU/(BAUDRATE*16L)-1) >> 8;          // calculate baudrate and set high byte
    myUBRRL = (uint8_t)(F_CPU/(BAUDRATE*16L)-1);      // and low byte
    myUCSRB = _BV(myTXEN) | _BV(myRXEN) | _BV(myRXCIE);  // enable transmitter and receiver and receiver interrupt
    myUCSRC = myURSEL | _BV(myUCSZ1) | _BV(myUCSZ0);  // 8 bit character size, 1 stop bit, no parity

    // the bootloader may be activated either if
    // the character 'i' (interactive mode) was received from USART
    // or the flash is (still) empty

    // poll USART receive complete flag 64k times to catch the 'i' reliably
    do {
	if(bit_is_set(myUCSRA, myRXC))
	    if(myUDR == 'i')
		bootloaderEnableFlag = TRUE;
    } while(--loop);

    // test if flash is empty (i.e. flash content is 0xff)
    if(pgm_read_byte_near(0x0000) == 0xFF) {
	bootloaderEnableFlag = TRUE;  // set enable flag
    }

    // check enable flag and start application if FALSE
    if(bootloaderEnableFlag == FALSE) {
	startApplication();
    }


    //
    // now the bootloader code begins
    //


    // move interrupt vector table to boot loader area
    myIVSELREG = _BV(IVCE);
    myIVSELREG = _BV(IVSEL);
 
    // welcome message and prompt
    uartPutChar('\r');
    uartPutChar('>');

    // loop until a valid character is received
    do {

	c = uartGetChar();  // read a character

	if(c == 'f') {  // 'f' selects flash programming
	    uartPutChar('f');           // echo the 'f'
	    programThisMemory = FLASH;  // set flag
	}

#ifdef EEPROM_CODE
	if(c == 'e') {  // 'e' selects eeprom programming

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -