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

📄 stk500boot.c

📁 与stk相关的avr bootloader程序,采用avr-gcc编写.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
Title:     STK500v2 compatible bootloader
Author:    Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
File:      $Id: stk500boot.c,v 1.11 2006/06/25 12:39:17 peter Exp $
Compiler:  avr-gcc 3.4.5 or 4.1 / avr-libc 1.4.3 
Hardware:  All AVRs with bootloader support, tested with ATmega8
License:   GNU General Public License 
          
DESCRIPTION:
    This program allows an AVR with bootloader capabilities to 
    read/write its own Flash/EEprom. To enter Programming mode   
    an input pin is checked. If this pin is pulled low, programming mode  
    is entered. If not, normal execution is done from $0000 
    "reset" vector in Application area.
    Size < 500 words, fits into a 512 word bootloader section 
	when compiled with avr-gcc 4.1
   
USAGE:
    - Set AVR MCU type and clock-frequency (F_CPU) in the Makefile.
    - Set baud rate below (AVRISP only works with 115200 bps)
    - compile/link the bootloader with the supplied Makefile
    - program the "Boot Flash section size" (BOOTSZ fuses),
      for boot-size 512 words:  program BOOTSZ1
    - enable the BOOT Reset Vector (program BOOTRST)
    - Upload the hex file to the AVR using any ISP programmer
    - Program Boot Lock Mode 3 (program BootLock 11 and BootLock 12 lock bits)
    - Reset your AVR while keeping PROG_PIN pulled low
    - Start AVRISP Programmer (AVRStudio/Tools/Program AVR)
    - AVRISP will detect the bootloader
    - Program your application FLASH file and optional EEPROM file using AVRISP
    
Note: 
    Erasing the device without flashing, through AVRISP GUI button "Erase Device" 
    is not implemented, due to AVRStudio limitations.
    Flash is always erased before programming.

	AVRdude:
	Please uncomment #define REMOVE_CMD_SPI_MULTI when using AVRdude.
	Comment #define REMOVE_PROGRAM_LOCK_BIT_SUPPORT to reduce code size
	Read Fuse Bits and Read/Write Lock Bits is not supported

NOTES:
    Based on Atmel Application Note AVR109 - Self-programming
    Based on Atmel Application Note AVR068 - STK500v2 Protocol    
          
LICENSE:
    Copyright (C) 2006 Peter Fleury

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

*****************************************************************************/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/boot.h>
#include <avr/pgmspace.h>
#include "command.h"

/*
 * Uncomment the following lines to save code space 
 */
//#define REMOVE_PROGRAM_LOCK_BIT_SUPPORT  // disable program lock bits
//#define REMOVE_BOOTLOADER_LED            // no LED to show active bootloader
//#define REMOVE_PROG_PIN_PULLUP           // disable internal pullup, use external 
#define REMOVE_CMD_SPI_MULTI             // disable processing of SPI_MULTI commands

/* 
 * Pin "PROG_PIN" on port "PROG_PORT" has to be pulled low
 * (active low) to start the bootloader 
 * uncomment #define REMOVE_PROG_PIN_PULLUP if using an external pullup
 */
#define PROG_PORT  PORTD
#define PROG_DDR   DDRD
#define PROG_IN    PIND
#define PROG_PIN   PIND2

/*
 * Active-low LED on pin "PROGLED_PIN" on port "PROGLED_PORT" 
 * indicates that bootloader is active
 */
#define PROGLED_PORT PORTB
#define PROGLED_DDR  DDRB
#define PROGLED_PIN  PINB1

/*
 * define CPU frequency in Mhz here if not defined in Makefile 
 */
#ifndef F_CPU
#define F_CPU 7372800UL
#endif

 
/*
 * UART Baudrate, AVRStudio AVRISP only accepts 115200 bps
 */
#define BAUDRATE 115200


/*
 *  Enable (1) or disable (0) USART double speed operation
 */
#define UART_BAUDRATE_DOUBLE_SPEED 0


/*
 * HW and SW version, reported to AVRISP, must match version of AVRStudio
 */
#define CONFIG_PARAM_BUILD_NUMBER_LOW	0
#define CONFIG_PARAM_BUILD_NUMBER_HIGH	0
#define CONFIG_PARAM_HW_VER				0x0F
#define CONFIG_PARAM_SW_MAJOR			2
#define CONFIG_PARAM_SW_MINOR			7



/*
 * Calculate the address where the bootloader starts from FLASHEND and BOOTSIZE
 * (adjust BOOTSIZE below and BOOTLOADER_ADDRESS in Makefile if you want to change the size of the bootloader)
 */
#define BOOTSIZE 512
#define APP_END  (FLASHEND -(2*BOOTSIZE) + 1)



/*
 * Signature bytes are not available in avr-gcc io_xxx.h
 */
#if defined (__AVR_ATmega8__)
    #define SIGNATURE_BYTES 0x1E9307
#elif defined (__AVR_ATmega16__)
    #define SIGNATURE_BYTES 0x1E9403
#elif defined (__AVR_ATmega32__)
    #define SIGNATURE_BYTES 0x1E9502
#elif defined (__AVR_ATmega8515__)
    #define SIGNATURE_BYTES 0x1E9306
#elif defined (__AVR_ATmega8535__)
    #define SIGNATURE_BYTES 0x1E9308
#elif defined (__AVR_ATmega162__)
    #define SIGNATURE_BYTES 0x1E9404
#elif defined (__AVR_ATmega128__)
    #define SIGNATURE_BYTES 0x1E9702
#else
	#error "no signature definition for MCU available"
#endif


#if  defined(__AVR_ATmega8__)    || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
  || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
/* ATMega8 with one USART */
#define	UART_BAUD_RATE_LOW	     UBRRL
#define	UART_STATUS_REG	         UCSRA
#define	UART_CONTROL_REG	     UCSRB
#define	UART_ENABLE_TRANSMITTER	 TXEN
#define	UART_ENABLE_RECEIVER	 RXEN
#define	UART_TRANSMIT_COMPLETE	 TXC
#define	UART_RECEIVE_COMPLETE	 RXC
#define	UART_DATA_REG	         UDR
#define UART_DOUBLE_SPEED        U2X

#elif  defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega162__)
/* ATMega with two USART */
#define	UART_BAUD_RATE_LOW	     UBRR0L
#define	UART_STATUS_REG	         UCSR0A
#define	UART_CONTROL_REG	     UCSR0B
#define	UART_ENABLE_TRANSMITTER	 TXEN0
#define	UART_ENABLE_RECEIVER	 RXEN0
#define	UART_TRANSMIT_COMPLETE	 TXC0
#define	UART_RECEIVE_COMPLETE	 RXC0
#define	UART_DATA_REG	         UDR0
#define UART_DOUBLE_SPEED        U2X0

#else
	#error "no UART definition for MCU available"
#endif


/*
 * Macro to calculate UBBR from XTAL and baudrate
 */
#if UART_BAUDRATE_DOUBLE_SPEED
#define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5)
#else
#define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*16.0)-1.0+0.5)
#endif


/*
 * States used in the receive state machine
 */
#define	ST_START		0
#define	ST_GET_SEQ_NUM	1
#define ST_MSG_SIZE_1	2
#define ST_MSG_SIZE_2	3
#define ST_GET_TOKEN	4
#define ST_GET_DATA		5
#define	ST_GET_CHECK	6
#define	ST_PROCESS		7


/*
 * use 16bit address variable for ATmegas with <= 64K flash
 */
#if defined(RAMPZ)
typedef uint32_t address_t;
#else
typedef uint16_t address_t;
#endif


/*
 * function prototypes
 */ 
static void sendchar(char c);
static unsigned char recchar(void);


/*
 * since this bootloader is not linked against the avr-gcc crt1 functions,
 * to reduce the code size, we need to provide our own initialization
 */
void __jumpMain     (void) __attribute__ ((naked)) __attribute__ ((section (".init9")));

void __jumpMain(void)
{    
    asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
    asm volatile ( "clr __zero_reg__" );                       // GCC depends on register r1 set to 0
    asm volatile ( "out %0, __zero_reg__" :: "I" (_SFR_IO_ADDR(SREG)) );  // set SREG to 0
    asm volatile ( "rjmp main");                               // jump to main()
}


/*
 * send single byte to USART, wait until transmission is completed
 */
static void sendchar(char c)
{
    UART_DATA_REG = c;                                   // prepare transmission
    while (!(UART_STATUS_REG & (1 << UART_TRANSMIT_COMPLETE)));// wait until byte sent
    UART_STATUS_REG |= (1 << UART_TRANSMIT_COMPLETE);          // delete TXCflag
}

/*
 * Read single byte from USART, block if no data available
 */
static unsigned char recchar(void)
{
    while(!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)));  // wait for data
    return UART_DATA_REG;
}



int main(void)
{
    address_t       address = 0;
    address_t       eraseAddress = 0;	
	unsigned char   msgParseState;
    unsigned int    i = 0;
    unsigned char   checksum = 0;
    unsigned char   seqNum = 0;
    unsigned int    msgLength = 0;
    unsigned char   msgBuffer[285];
    unsigned char   c, *p;


	/*
	 * Branch to bootloader or application code ?
	 */	
#ifndef REMOVE_PROG_PIN_PULLUP	 
	PROG_PORT |= (1<<PROG_PIN);		// Enable internal pullup
	asm volatile ("nop");           // wait until port has changed	 
#endif
	if(!(PROG_IN & (1<<PROG_PIN)))  
	{ 	    
#ifndef REMOVE_BOOTLOADER_LED
        /* PROG_PIN pulled low, indicate with LED that bootloader is active */
        PROGLED_DDR  |= (1<<PROGLED_PIN);
        PROGLED_PORT &= ~(1<<PROGLED_PIN);
#endif
        /*
         * Init UART
         * set baudrate and enable USART receiver and transmiter without interrupts 
         */     
#if UART_BAUDRATE_DOUBLE_SPEED
        UART_STATUS_REG   |=  (1 <<UART_DOUBLE_SPEED);
#endif         
        UART_BAUD_RATE_LOW = UART_BAUD_SELECT(BAUDRATE,F_CPU);
        UART_CONTROL_REG   = (1 << UART_ENABLE_RECEIVER) | (1 << UART_ENABLE_TRANSMITTER); 
        
        
        /* main loop */
        for(;;)                             
        {   
            /*
             * Collect received bytes to a complete message
             */            
            msgParseState = ST_START;
	        while ( msgParseState != ST_PROCESS )
	        {
           		c = recchar();
                switch (msgParseState)
                {
                case ST_START:
				    if( c == MESSAGE_START )
				    {
					    msgParseState = ST_GET_SEQ_NUM;
					    checksum = MESSAGE_START^0;
				    }
				    break;
				    
				case ST_GET_SEQ_NUM:
                    if ( (c == 1) || (c == seqNum) )
                    {
				        seqNum = c;
				        msgParseState = ST_MSG_SIZE_1;
				        checksum ^= c;
                    }
                    else
                    {
                        msgParseState = ST_START;
                    }
			        break;
			        
			    case ST_MSG_SIZE_1:			    
				    msgLength = c<<8;
				    msgParseState = ST_MSG_SIZE_2;
				    checksum ^= c;
				    break;
				    
			    case ST_MSG_SIZE_2:			
				    msgLength |= c;
				    msgParseState = ST_GET_TOKEN;
				    checksum ^= c;
				    break;
			    
			    case ST_GET_TOKEN:
			        if ( c == TOKEN )
				    {
					    msgParseState = ST_GET_DATA;
					    checksum ^= c;
					    i = 0;
				    }
				    else
				    {
				        msgParseState = ST_START;
				    }
				    break;
			    
			    case ST_GET_DATA:			        
				    msgBuffer[i++] = c;

⌨️ 快捷键说明

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