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

📄 main.c

📁 AVR_butterfly_BOOT是AVR单片机的BOOT程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
*
* Copyright (C) 1996-1998 Atmel Corporation
*
* File          : main.c
* Created       : 16-jun-99
* Last Modified : 3-dec-1999  (mt: ??)
* Author(s)     : BBrandal, PKastnes, ARodland, LHM
*
* Description   : This Program allows an AVR with bootloader capabilities to 
*                 Read/write its own Flash/EEprom. 
* 
*
****************************************************************************
*
* 1/2004 port to avr-gcc/avr-libc by Martin Thomas, Kaiserslautern, Germany
*
*  Many functions used by "AVRPROG" (fuses) have been disabled by ATMEL in 
*  the original source code not by me. Please 'diff' against the original 
*  source to see everything that has been changed for the gcc port.
*  As in the BF-application source most of my changes are marked with "mt" 
*  or enclosed with "//mtA" "//mtE".
*
*  The boot interrupt vector is included (this bootloader is completly in
*  ".text" section). If you need this space for further functions you have to
*  add a separate section for the bootloader functions and add an attribute
*  for this section to _all_ function prototypes of functions in the loader. 
*  With this the interrupt vector will be placed at .0000 and the bootloader 
*  code (without interrupt vector) at the adress you define in the linker
*  options for the newly created section. Take care since the pin-change 
*  interrupt is used in the Butterflys bootloader for power-saving reasons.
*  See the avr-libc FAQ and the avr-libc boot.h documentation for further 
*  details.
*
*  5/2005 - added receive-buffer in function BufferLoad()
*         - made register-definitions compatible with avr-libc V1.2.3
*  5/2007 - avoid delay loop removal
*           SIGNAL->ISR
*
****************************************************************************/

// mt redundant: #define ENABLE_BIT_DEFINITIONS

//mtA
// #include <inavr.h>
// #include "iom169.h"
// #include "assembly.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <lowlevel.h>

// Enable functions originaly disabled
// #define ENABLEREADFUSELOCK // keep this disabled until AVRPROG supports ATmega169
//mtE

// ATmega169 is not suppored by AVRPROG V1.37, so "mimic" an ATmega16 instead
// AVRProg 1.40 supports an ATmega169 device-type
// #define _ATMEGA16
#define _ATMEGA169

//* Select Boot Size (select one, comment out the others) */
// #define _B128
//#define _B256  
//#define _B512 
#define _B1024 

#include "main.h"

unsigned char gBuffer[UART_RX_BUFFER_SIZE];

void sendchar(char ) ;
char recchar(void) ;

// cbA void USART_Init(unsigned int );
unsigned char BufferLoad(unsigned int , unsigned char ) ;
void BlockRead(unsigned int , unsigned char ) ;
void OSCCAL_calibration(void) ;
void Delay(unsigned int) ;

unsigned int address;
unsigned char device;

// mt__C_task void main(void)
int main(void)
{
    void (*funcptr)( void ) = 0x0000;       // Set up function pointer 

    unsigned int tempi;
    char val;
    char OK = 1;    

    OSCCAL_calibration();   // Calibrate the OSCCAL byte

    ACSR = (1<<ACD);

    // Disable Digital input on PF0-2 (power save)
    // mt DIDR1 = (7<<ADC0D);
    DIDR0 = (7<<ADC0D);

    PORTB = 0xFF;       // Enable pullups on Ports B and E
    PORTE = 0xFF;
    
    // boost IntRC to 2Mhz to achieve 19200 baudrate
    CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable
    // set prescaler = 4, Inter RC 8Mhz / 4 = 2Mhz
    CLKPR = (1<<CLKPS1);    

    UBRRH = 0;//(unsigned char)(baudrate>>8);
    UBRRL = 12;//(unsigned char)baudrate;

    // Enable 2x speed
    UCSRA = (1<<U2X);

    // Enable receiver and transmitter
    UCSRB = (1<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<UDRIE);

    // Async. mode, 8N1
    UCSRC = (0<<UMSEL)|(0<<UPM0)|(0<<USBS)|(3<<UCSZ0)|(0<<UCPOL);
        
    MCUCR = (1<<IVCE);       
    MCUCR = (1<<IVSEL);             //move interruptvectors to the Boot sector    

    sei(); // mt __enable_interrupt();
    
    // mt PCMSK1 = (1<<PORTB6) | (1<<PORTB4);
	PCMSK1 = (1<<PINB6) | (1<<PINB4);       // set pin-change interrupt mask
  	EIFR   = (1<<PCIF1);                    // clear external intterupt flag 1
	EIMSK  = (1<<PCIE1);                    // enable external interrupt 1

	for(;OK;)
	{
		if(!(PINB & (1<<PINB6)))	// mt if(!(PINB & (1<<PORTB6)))
        {   // joystick "up" detected
            MCUCR = (1<<IVCE); 
            MCUCR = (0<<IVSEL);             //move interruptvectors to the Application sector
            funcptr();      // Jump to application sector   
        }
        //else if(PINB & (1<<PORTB4))                     // If joystick not in the ENTER-position
		else if(PINB & (1<<PINB4))                     // If joystick not in the ENTER-position
        {
            UCSRA = 0x02;
            SMCR = (3<<SM0) | (1<<SE);      // Enable Power-save mode
			// mt __sleep();  // Go to sleep
            asm volatile ("sleep"::);		 // Go to sleep
			
            SMCR = 0;                       // Just woke, disable sleep
        }
        else
        {	
            val = recchar();
   
            if( val == 0x1B)
         	{							// AVRPROG connection
          		while (val != 'S')				// Wait for signon 
          		{
          		  val = recchar();
          		}
                sendchar('A');					// Report signon
                sendchar('V');
                sendchar('R');
                sendchar('B');
                sendchar('O');
                sendchar('O');
                sendchar('T');
                
                cli(); 	// mt __disable_interrupt();
                
                OK = 0;
            }
    		else
	    		sendchar('?');
        }
	}			

      for(;;)                               // If PINDX is pulled low: programmingmode. (mt: here PINB4)
      {
        val=recchar();
         
        if(val=='a')                        //Autoincrement?
        {
          sendchar('Y');		    		//Autoincrement is quicker
        }
 
        else if(val=='A')                   //write address 
        {
          address=recchar();                //read address 8 MSB
          address=(address<<8)|recchar();
        
          address=address<<1;               //convert from word address to byte address
          sendchar('\r');
        }
        
        else if(val=='b')
		{									// Buffer load support
			sendchar('Y');					// Report buffer load supported
			sendchar((UART_RX_BUFFER_SIZE >> 8) & 0xFF);
											// Report buffer size in bytes
			sendchar(UART_RX_BUFFER_SIZE & 0xFF);
		}

		else if(val=='B')					// Start buffer load
		{
			tempi = recchar() << 8;			// Load high byte of buffersize
			tempi |= recchar();				// Load low byte of buffersize
			val = recchar();				// Load memory type ('E' or 'F')
			sendchar (BufferLoad(tempi,val));
											// Start downloading of buffer
		}
		
		else if(val == 'g')					// Block read
		{
			tempi = (recchar() << 8) | recchar();

			val = recchar();				// Get memtype
			BlockRead(tempi,val);			// Perform the block read
		}		
/*
        else if(val=='c')                   //Write program memory, low byte
        {       
          ldata=recchar();
          sendchar('\r');
        }

        else if(val== 'C')                  //Write program memory, high byte 
        {
          data=ldata|(recchar()<<8);
		  if (device == devtype)
          {
            fill_temp_buffer(data,(address)); //call asm routine. 
          }
          address=address+2;  
          sendchar('\r');
        }
*/        
        else if(val=='e')                   //Chip erase 
        {
		  if (device == devtype)
          {
            for(address=0;address < APP_END;address += PAGESIZE)    //Application section = 60 pages
            {
                write_page(address,(1<<PGERS) + (1<<SPMEN));    //Perform page erase
                write_page(address,(1<<RWWSRE) + (1<<SPMEN));   //Re-enable the RWW section
            }
          }
          write_page(address,(1<<RWWSRE) + (1<<SPMEN));   //Re-enable the RWW section
          sendchar('\r');        
        }

        else if(val=='E')                   //Exit upgrade
        {
		  WDTCR = (1<<WDCE) | (1<<WDE);     //Enable Watchdog Timer to give reset
		  sendchar('\r');
        }
/*
        else if(val=='l')                   // write lockbits 
        {
		  if (device == devtype)
          {
            write_lock_bits(recchar());
  		  }
          sendchar('\r');
        }
       
        else if(val== 'm')                  // write page
        {
		  if (device == devtype)
          {
            write_page(address,(1<<PGERS) + (1<<SPMEN));    //Perform page erase
            write_page((address),0x05);       
            write_page(address,(1<<RWWSRE) + (1<<SPMEN));   //Re-enable the RWW section
           }
          sendchar('\r');
        }
*/        
        
        else if(val=='P')     // Enter programming mode 
        {
          sendchar('\r');
        }
        
        else if(val=='L')   // Leave programming mode
        { 
          sendchar('\r');
        }
        
        else if (val=='p')		// mt: return programmer type
        {
          sendchar('S');		// serial programmer
        }        
/*        
        else if(val=='R')                   //Read program memory 
        {        
          write_page(0,(1<<RWWSRE) + (1<<SPMEN));   //Re-enable the RWW section
//          SPMCSR = (1<<RWWSRE) | (1<<SPMEN);
//          __store_program_memory();
//          while((SPMCSR & 0x01));
          
          intval=read_program_memory(address,0x00);
          sendchar((char)(intval>>8));      //send MSB  
          sendchar((char)intval);           //send LSB
          address=address+2;  
        }

        else if (val == 'D')		// write EEPROM
        {
		  if (device == devtype)
          {
            EEARL = address;
            EEARH = (address >> 8);
            address++;
            EEDR = recchar();
            EECR |= (1<<EEMWE);
            EECR |= (1<<EEWE);
            while (EECR & (1<<EEWE))
              ;
          }
          sendchar('\r');
        }

        else if (val == 'd')		// read eeprom
        {
          EEARL = address;
          EEARH = (address >> 8);
          address++;
          EECR |= (1<<EERE);
          sendchar(EEDR);
        }       
*/
#ifdef ENABLEREADFUSELOCK
#warning "Extension 'ReadFuseLock' enabled"
// mt TODO: Read fuse bit seems to work for clock speed, other settings are not
// interpreted correctly. Locks and high fuse do not work at all (in AVRPROG 1.37)
// Reason for this should be the difference between ATmega16 and ATmega169.
// AVRPROG interprets the results as from an ATmega16 while they are from an ATmega169
        else if(val=='F')                   // read fuse bits

⌨️ 快捷键说明

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