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

📄 main.c

📁 AVR单片机的一个免费的开发环境.开发语言为GCC.
💻 C
字号:
/*
ezLCDboot.c

01-SEP-2004 Michal
            Done the following modyfications:
            - changed file name to main.c
            - removed all references to the MCUs other than ATmega128
            - formated the code acording to Sane-C coding standard
            - replaced __lpm_inline by GetFlashByte
            - replaced __lpm_inline by GetExtFlashByte
            - moved the inline assembly into SystemAsm.s
            - replaced else if statements by switch structures
              because, the new version of GCC does a very good job
              optimizing the switch structures.

stk500boot.c  20030810

Copyright (c) 2003, Jason P. Kyle
All rights reserved.

    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
    (at your option) 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.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Licence can be viewed at http://www.fsf.org/licenses/gpl.txt


Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169,m8515,m8535
ATmega161 has a very small boot block so isn't supported.

Tested with m128,m8,m163 - feel free to let me know how/if it works for you.
*/

#define F_CPU       7372800

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/delay.h>

typedef unsigned char byte;
typedef unsigned short word;

#define BAUD_RATE    115200

#define DECRYPT 0
#define ENCRYPT 1
//#define DES_ENCRYPTION

#define HW_VER          0x02
#define SW_MAJOR        0x01
#define SW_MINOR        0x12


// Adjust to suit whatever pin your hardware uses to enter the bootloader

#define BL_DDR DDRB
#define BL_PORT PORTB
#define BL_PIN PINB
#define BL PINB0

#define SIG1       0x1E    // Yep, Atmel is the only manufacturer of AVR micros.
#define SIG2       0x97
#define SIG3       0x02
#define PAGE_SIZE  0x80U   //128 words
#define UART0

#ifndef cbi
  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


extern byte GetFlashByte(word address);
extern byte GetExtFlashByte(word address);
extern void ProgrFlash(void);
void putchar_bt(char);
char getch(void);
void getNch(byte);
void byte_response(byte);
void nothing_response(void);


union address_union
{
  word word;
  byte  byte[2];
} address;

union length_union
{
  word word;
  byte  byte[2];
} length;

byte EepromFlag;
byte RampzFlag;

byte buff[256];
byte address_high;
// word Fonts_End __attribute__ ((section (".boot")));
byte pagesz=0x80;

void (*app_start)(void) = 0x0000;

int main(void)
{
  byte ch,ch2;
  word w;

  cbi(BL_DDR,BL);
  sbi(BL_PORT,BL);
  asm volatile("nop\n\t");
  if(GetFlashByte(0x0000) != 0xFF) // Don't start application if
  {                                 // it isn't programmed yet
    // Do we start the application or enter bootloader?
    if(bit_is_set(BL_PIN,BL)) app_start();
  }

  #if defined UART0
     UBRR0L = (byte)(F_CPU/(BAUD_RATE*16L)-1);
     UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
     UCSR0A = 0x00;
     UCSR0C = 0x06;
     UCSR0B = _BV(TXEN0)|_BV(RXEN0);
  #else
     UBRR1L = (byte)(F_CPU/(BAUD_RATE*16L)-1);
     UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
     UCSR1A = 0x00;
     UCSR1C = 0x06;
     UCSR1B = _BV(TXEN1)|_BV(RXEN1);
  #endif
  putchar_bt('\0');

  while (1)
  {
    ch = getch();
    switch (ch)
    {
      case '0':
        nothing_response();
        break;

      // Request programmer ID
      case '1':
        if (getch() == ' ')
        {
          putchar_bt(0x14);
          putchar_bt('A');
          putchar_bt('V');
          putchar_bt('R');
          putchar_bt(' ');
          putchar_bt('I');
          putchar_bt('S');
          putchar_bt('P');
          putchar_bt(0x10);
        }
        break;

      // AVR ISP/STK500 board commands
      // DON'T CARE so default nothing_response
      case '@':
        ch2 = getch();
        if (ch2 > 0x85) getch();
        nothing_response();
        break;

      // AVR ISP/STK500 board requests
      case 'A':
        ch2 = getch();
        switch (ch2)
        {
          // Hardware version
          case 0x80:
            byte_response(HW_VER);
            break;
          // Software major version
          case 0x81:
            byte_response(SW_MAJOR);
            break;
          // Software minor version
          case 0x82:
            byte_response(SW_MINOR);
            break;
          // Unknown but seems to be required by avr studio 3.56
          case 0x98:
            byte_response(0x03);
            break;
          // Covers various unnecessary responses we don't care about
          default:
            byte_response(0x00);
            break;
        }
        break;

      // Device Parameters  DON'T CARE, DEVICE IS FIXED
      case 'B':
        getNch(20);
        nothing_response();
        break;

      // Parallel programming stuff  DON'T CARE
      case 'E':
        getNch(5);
        nothing_response();
        break;

      // Enter programming mode
      case 'P':
      // Leave programming mode
      case 'Q':
      // Erase device, don't care as we will
      // erase one page at a time anyway.
      case 'R':
        nothing_response();
        break;


      //Set address, little endian. EEPROM in bytes, FLASH in words
      //Perhaps extra address bytes may be added in future to support > 128kB FLASH.
      //This might explain why little endian was used here, big endian used everywhere else.
      case 'U':
        address.byte[0] = getch();
        address.byte[1] = getch();
        nothing_response();
        break;

      // Universal SPI programming command, disabled.
      // Would be used for fuses and lock bits.
      case 'V':
        getNch(4);
        byte_response(0x00);
        break;

      // Write memory, length is big endian and is in bytes
      case 'd':
       length.byte[1] = getch();
       length.byte[0] = getch();
       EepromFlag = 0;
       if (getch() == 'E') EepromFlag = 1;
       // Store data in buffer,
       // can't keep up with serial data stream
       // whilst programming pages
       for (w = 0; w < length.word; w++)
       {
         buff[w] = getch();
       }

       if (getch() == ' ')
       {
         if (EepromFlag)
         {
           // Write to EEPROM one byte at a time
           for (w =0; w < length.word; w++)
           {
             eeprom_write_byte((byte *)address.word, buff[w]);
             address.word++;
           }
         }
         else
         {
           // Write to FLASH one page at a time
           if (address.byte[1] > 127)
           {
             address_high = 0x01;
           }
           else
           {
             address_high = 0x00;
           }
           RAMPZ = address_high;
           address.word = address.word << 1;  // address * 2 -> byte location
           // Even up an odd number of bytes
           if ((length.byte[0] & 0x01))
           {
             length.word++;
           }
           cli();
           // Wait for previous EEPROM writes to complete
           while(bit_is_set(EECR,EEWE));
           ProgrFlash();
           // Should really add a wait for RWW section to be enabled, don't actually need it since we never
           // exit the bootloader without a power cycle anyhow
         }
         putchar_bt(0x14);
         putchar_bt(0x10);
       }
       break;

      // Read memory block mode, length is big endian.
      case 't':
        length.byte[1] = getch();
        length.byte[0] = getch();
        if (address.word > 0x7FFF)
        {
          RampzFlag = 1;
        }
        else
        {
          RampzFlag = 0;
        }
        if (getch() == 'E')
        {
          EepromFlag = 1;
        }
        else
        {
          EepromFlag = 0;
          address.word = address.word << 1;       //address * 2 -> byte location
        }
        // Command terminator
        if (getch() == ' ')
        {
          putchar_bt(0x14);
          // Can handle odd and even lengths okay
          for (w = 0; w < length.word; w++)
          {
            if (EepromFlag) // Byte access EEPROM read
            {
              putchar_bt(eeprom_read_byte((byte *)address.word));
              address.word++;
            }
            else
            {
              if (!RampzFlag)
              {
                putchar_bt(GetFlashByte(address.word));
              }
              else
              {
                putchar_bt(GetExtFlashByte(address.word + 0x10000));
              }
              address.word++;
            }
          }
          putchar_bt(0x10);
        }
        break;

      // Get device signature bytes
      case 'u':
        if (getch() == ' ')
        {
          putchar_bt(0x14);
          putchar_bt(SIG1);
          putchar_bt(SIG2);
          putchar_bt(SIG3);
          putchar_bt(0x10);
        }
        break;

      // Read oscillator calibration byte
      case 'v':
        byte_response(0x00);
        break;

      default:
        break;
    }
  }
}

void putchar_bt(char ch)
{
  #ifdef UART0
    while (bit_is_clear(UCSR0A, UDRE));
    UDR0 = ch;
  #else
    while (bit_is_clear(UCSR1A, UDRE));
    UDR1 = ch;
  #endif
}


char getch(void)
{
  #ifdef UART0
    while (bit_is_clear(UCSR0A, RXC));
    return UDR0;
  #else
    while (bit_is_clear(UCSR1A, RXC));
    return UDR1;
  #endif
}

void getNch(byte count)
{
  byte i;
  byte n;
  for(i = 0; i < count; i++)
  {
    #ifdef UART0
    while (bit_is_clear(UCSR0A, RXC));
      n = UDR0;
    #else
    while (bit_is_clear(UCSR1A, RXC));
      n = UDR1;
    #endif
  }
}

void byte_response(byte val)
{
  if (getch() == ' ')
  {
    putchar_bt(0x14);
    putchar_bt(val);
    putchar_bt(0x10);
  }
}

void nothing_response(void)
{
  if (getch() == ' ')
  {
    putchar_bt(0x14);
    putchar_bt(0x10);
  }
}

⌨️ 快捷键说明

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