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

📄 bootloader_smbus.c

📁 用AVR453开发的电池保护板的C语言程序,希望对大家有用!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
 *
 * \brief
 *       SMBus Bootloader for ATmega406
 *
 * \par Application note:
 *      AVR453: Smart Battery Reference Design
 *
 * \par Documentation:
 *      For comprehensive code documentation, supported compilers, compiler
 *      settings and supported devices see readme.html
 *
 * \author
 *      Atmel Corporation: http://www.atmel.com \n
 *      Support email: avr@atmel.com \n
 *      Original author: Rob G. Fries - Apt Inc.\n
 *
 * $Name$
 * $Revision: 2687 $
 * $RCSfile$
 * $Date: 2007-11-12 10:39:44 +0100 (ma, 12 nov 2007) $  \n
 ******************************************************************************/


/*! \page doc_page1 Compilation Info
* \section Bootloader
* This software was written for the IAR Embedded Workbench, 4.11A/4.10B, but can also be
* built using 3.20C \n
* To make project:
* Add this file, bootloader_smbus.c to project, use用于 device -v3, enhanced core增强核,
* no RAMPZ register, enable bit definitions in I/O include files, optimization was set
* to medium, override default linker command file with: $PROJ_DIR$\\m406s_2kwBootLdr.xcl
* (included with the source), output format: ubrof8 for Debug and intel_extended for Release.\n
* To program the device with bootloader, one first has to erase the device and program the
* bootloader, then program the main section without erasing the device first.
*/


//#define ENABLE_TESTCODE;测试使能代码


//#include <pgmspace.h>
#include <inavr.h>

#define MODULE_BOOTLDR		/* ensure that we instantiate our variables in bootldr.h */
#include "bootldr.h"
//#include "iom406_320.h"
#include "iom406.h"     // IAR headerfile for Mega406 (EW 410)
#include "flash.h"


void TWI_handler(void);
void SMB_RestoreBus(void);
unsigned char FastCRC(unsigned char LastCRC, unsigned char newbyte);
void SMB_BusTimeout(void);
void SMB_Reply(void);
void SMB_CmdInterpreter(void);
void LoopMemory(void);


//=======================================================================

//This is used to check for an out-of-bounds SMBus command.
#define HIGHEST_SMB_CMD 0x3F


//Two-Wire-Interface TWSR (STATUS) values
//Note that since our Prescale value is 0, we don't need to MASK the Status byte.

//  Globally applicable TWI status codes:
#define TWS_MASK  0xF8		/* Two-Wire Status Mask */
#define TWS_NSTAT 0xF8		/* No Status Available now */

//  MASTER-related Status codes:
#define TWS_START 0x08
#define TWS_RESTART 0x10
#define TWS_WRITE_ACK 0x18	/* sent a SLA+W, got ACK */
#define TWS_WRITE_NAK 0x20	/* sent SLA+W, got NAK */
#define TWS_TXDATA_ACK 0x28	/* Data tx'd & was ACK'd */
#define TWS_TXDATA_NAK 0x30	/* Data tx'd & was NAK'd */
#define TWS_LOST_ARB 0x38	/* lost bus arbitration */

#define TWS_READ_ACK 0x40	/* got ACK from a SLA+R request */
#define TWS_READ_NAK 0x48	/* got NAK from a SLA+R request */
#define TWS_RXDATA_ACK 0x50	/* We rcvd data and ACKd back */
#define TWS_RXDATA_NACK 0x58	/* We rcvd data and we NACKd back */


//  SLAVE-related Status codes:
#define TWS_SLA_W 0x60		/* Got SLA + Write */
#define TWS_SLA_R 0xA8		/* Got SLA + Read  */
#define TWS_RDATA 0x80		/* Got a data byte */
#define TWS_RCMD  0x80		/* Got a command byte */
#define TWS_RSTOP 0xA0		/* Got a Stop */
#define TWS_REPEAT 0xA0		/* Got a Repeated-Start */
#define TWS_RACK  0xB8		/* Send a data byte and got an ACK back */
#define TWS_RNAK  0xC0		/* Sent a data byte and got a NAK back */
#define TWS_FINAL 0xC8		/* Sent the final byte, got ACK back */
#define TWS_BERR  0x00		/* Saw a Bus Error */


// Two-Wire CONTROL values

#define TWC_GO 0x85	    /* clr TWINT; assert ENA & IntEna */
#define TWC_READ_NoACK 0x85 /* read a byte, but don't ACK when done */
#define TWC_START 0xA5	    /* send START bit, assert ENA & IntEna */
#define TWC_STOP 0x94	    /* leave INT *DISabled* when done */
#define TWC_RESTART 0xB5    /* send STOP, then START again; INT ena */


//=======================================================================


unsigned char TW_TxBuf[36];	//must be long enough for any outbound strings
unsigned char TW_TxBufCnt;	//how many valid bytes are in the buffer
unsigned char TW_TxBufIndex;

unsigned char TW_RxBuf[36];	//must be big enough for inbound programming data
unsigned char TW_RxBufCnt;	// SLA + Cmd + Count + 32bytes + PEC = 36
unsigned char TW_RxBufIndex;

unsigned char TW_state;		//state variable
unsigned char UsePEC;		//PEC usage is disabled by default.

unsigned char LoopFlag;		//if we're looping on a slow memory operation
unsigned char BigData;		//flag, if doing multi=packet 'I' command
unsigned char src_i;
unsigned char dest_i;
unsigned char ctr;
unsigned char lomemptr;
unsigned char himemptr;
unsigned char __flash *fptr;
unsigned int eptr;

unsigned char SRAMbuffer[128];          //this is the size of a Flash page (64 *WORDS*)

//This byte contains flags from the TWI handler to tell the Foreground code what to do.
//If this byte is ever non-zero, the foreground code will act on its contents.
//Although it is written by both the Handler and the Foreground code, it does not
//  need to be declared VOLATILE because the SMBus is halted until the foreground
//  code finishes processing the associated command and has cleared this flag byte.
unsigned char TWI_CmdFlags;
  #define SMB_GenBusTimeout 1	/* Tell Foreground to generate a bus timeout, as we saw an error! */
  #define SMB_SetUpReply 2	/* Have Foreground set up TW_TxBuf[]. */
  #define SMB_GotCmdData 4	/* Have Foreground interpret the complete received command. */


unsigned char Status;           //this is a global variable and is the sole response to a READ using cmd 0x2F.
  #define SUCCESS 0
  #define BUSY    1
  #define BADPARAM 2
  #define CRCERROR 3
  #define FAILURE  0xFF


//=======================================================================

// Reset Management theory:
//
// To make it easier to enter the bootloader when the OptionalMfgCmd5 command is received
// while running the SMBus interpreter in the application code, we monitor the Reset
// Source flags.  If we arrive here without any flags being asserted, then we can assume
// that we have jumped here from the application, and we can therefore assume that it is
// intended that the bootloader code be run.
// Otherwise, if any reset flag IS asserted when we enter, we check if there is a valid
// vector present at 0x0000; if not, we run the bootloader in order to retrieve a valid
// image, otherwise, we jump down to the application program and run it.
//
//! \todo  EXCEPTION: if the Watchdog flag is asserted, there is a POSSIBILITY that there's
//! a problem with the App code image.  It is left to the user to determine if this is the
//! case and to take remedial action.

void __low_level_init(void)
{
  unsigned char __flash * ptr = 0;

  if(!(MCUSR))    //If no reset source is asserted, we probably came here from the App code deliberately.
    return;       //Assume we need to run the BootLoader.

  // Some reset source was asserted. If it was Wdog, there may be a code problem and we
  // may need to handle it differently from other reset sources.  If so, add that code here.
  if(MCUSR & (1<<WDRF))
  {
    //! \todo  Add code here to handle Wdog reset.
  }

  //Some reset source was asserted, so if Reset vector is FFFF, assume we need to run the bootloader,
  // otherwise jump to the application code reset vector at 0x0000 and assume the App code is OK.
  if((*ptr++ != 0xFF) || (*ptr != 0xFF))
  {
    MCUCR &= (1<<IVSEL);
    asm("jmp 0");
  }

  //At this point, we apparently need to run the Bootloader code, as App section image appears invalid.
}




void init_boot(void);主引导初始化程序
{
  __disable_interrupt();
  TW_TxBufCnt = 0;	//how many valid bytes are in the buffer
  TW_TxBufIndex = 0;
  TW_RxBufCnt = 0;
  TW_RxBufIndex = 0;
  TW_state = 0;
  UsePEC = 0;
  Status = SUCCESS;
  LoopFlag = 0;
  BigData = 0;

  SMB_RestoreBus();
  TWBCSR = (1<<TWBCIF) | (1<<TWBDT1) | (1<<TWBDT0) | (0<<TWBCIP);
}


/* ************************************************************* */
/* ************************************************************* */
/* ************************************************************* */

//The following functions are included to demonstrate how the incoming
// data should be set up for SMBus-based ISP commands.接下来的功能包括证明如何增加设置命令。

#ifdef ENABLE_TESTCODE;如果该宏名在前面#define已经定义过,则语句后的代码将被编译。承上启下

void BOOT_TEST_EF(void);测试flash页写入功能性
{
  //Test the Flash Page Erase functionality 功能性(put junk at 0x0000-0x007F first)
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'E';     //Erase
  TW_RxBuf[TWRX_MEM] = 'F';	//flash
  TW_RxBuf[TWRX_LOADDR] = 0x80;
  TW_RxBuf[TWRX_HIADDR] = 0;
  UsePEC = 0;
}

void BOOT_TEST_EE(void);EEPROM功能性写入测试。
{
  //Test the EEPROM Erase functionality (put junk at 0x1F0-0x1FF first; should only erase through 0x1F9)
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'E';     //Erase
  TW_RxBuf[TWRX_MEM] = 'E';	//EEPROM
  TW_RxBuf[TWRX_LOADDR] = 0xF0;
  TW_RxBuf[TWRX_HIADDR] = 0x01;
  TW_RxBuf[TWRX_SIZE] = 0x0a;	//only do 10 bytes (test non-power-of-2 case)
  UsePEC = 0;
}

void BOOT_TEST_I(void)
{
  unsigned char i;
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'I';     //Insert插入
  TW_RxBuf[TWRX_LOADDR] = 0;
  TW_RxBuf[TWRX_HIADDR] = 0;
  for(i=0; i<16; i++)
    TW_RxBuf[TWRX_DATA+i]=i+33;	//arbitrary data任意数据
  TW_RxBuf[TWRX_OFFSET] = 0x33;	//insert data into SRAM buffer starting at arbitrary offset偏移量 0x33,33的偏移量留给其他初始化程序使用勿随意占用。
  TW_RxBuf[TWRX_SIZE] = 16;
  UsePEC = 0;
}

void BOOT_TEST_WF(void)
{
  unsigned char i;
  //Test the Flash Page WRITE functionality (store SRAMbuffer to flash 0x0000-0x007F)往FLASH内存储SRAMBUFFER中的资料。
  //Fill the buffer before doing WRITE tests.在写测试之前写满。
  for(i=0; i<128; i++)
    SRAMbuffer[i]=i+33;
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'W';     //Write
  TW_RxBuf[TWRX_MEM] = 'F';	//flash
  TW_RxBuf[TWRX_LOADDR] = 0x80;
  TW_RxBuf[TWRX_HIADDR] = 0;
  UsePEC = 0;
}

void BOOT_TEST_WE(void)
{  //Test the EEPROM WRITE functionality (store small piece of SRAMbuffer to eeprom 0x1F0-0x1FB);从BUFFER中存少部分给EEPROM
  unsigned char i;
  //Fill the buffer before doing WRITE tests.
  for(i=0; i<128; i++)
    SRAMbuffer[i]=i+33;
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'W';     //Write
  TW_RxBuf[TWRX_MEM] = 'E';	//EEPROM
  TW_RxBuf[TWRX_LOADDR] = 0xF0;	//any address is fine...
  TW_RxBuf[TWRX_HIADDR] = 0x01;
  TW_RxBuf[TWRX_OFFSET] = 0x33;	//use an arbitrary block from inside the buffer area
  TW_RxBuf[TWRX_SIZE] = 0x0c;
  UsePEC = 0;
}

void BOOT_TEST_PF(void)
{
  unsigned char i;
  //Verify that we can read back FLASH contents via the PATCH command.通过扩展命令读取FLASH中的内容即检查。
  //First, clear SRAMbuffer.
  for(i=0; i<128; i++)
    SRAMbuffer[i] = 0;
  //Next, set up the PATCH command
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'P';     //Patch
  TW_RxBuf[TWRX_MEM] = 'F';	//flash
  TW_RxBuf[TWRX_LOADDR] = 0x80;	//any address is fine...
  TW_RxBuf[TWRX_HIADDR] = 0x00;
  UsePEC = 0;
}

void BOOT_TEST_PE(void)
{
  unsigned char i;
  //Verify that we can read back EEPROM contents via the PATCH command.
  //First, clear SRAMbuffer.
  for(i=0; i<128; i++)
    SRAMbuffer[i] = 0;
  //Next, set up the PATCH command
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'P';     //Patch
  TW_RxBuf[TWRX_MEM] = 'E';	//EEPROM
  TW_RxBuf[TWRX_LOADDR] = 0xE0;	//address+size must be less than 0x200...
  TW_RxBuf[TWRX_HIADDR] = 0x01;
  TW_RxBuf[TWRX_OFFSET] = 0x00;	//read it into the bottom of SRAMbuffer (arbitrary)
  TW_RxBuf[TWRX_SIZE] = 0x20;	//grab any size we want, up to 128 bytes
  UsePEC = 0;
}

unsigned char bigI;

void BOOT_TEST_bigI(void)
{
  unsigned char i;
  TW_RxBuf[TWRX_BLKCNT] = 32;
  TWI_CmdFlags = SMB_GotCmdData;
  TW_RxBuf[TWRX_CMD] = 'I';     //Insert
  for(i=0; i<26; i++)
    TW_RxBuf[TWRX_DATA+i]=i+1;	//arbitrary data
  bigI = i+1;                   //save for later
  TW_RxBuf[TWRX_OFFSET] = 0;	//insert data into SRAM buffer starting at arbitrary offset 0x33
  TW_RxBuf[TWRX_SIZE] = 128;
  UsePEC = 0;
}

void BOOT_TEST_bigI32(void)
{
  unsigned char i;
  TW_RxBuf[TWRX_BLKCNT] = 32;
  TWI_CmdFlags = SMB_GotCmdData;
  for(i=0; i<32; i++)
    TW_RxBuf[3+i]=i+bigI;	//arbitrary data
  bigI += i;                    //save for later
}

void BOOT_TEST_bigI8(void)
{
  unsigned char i;
  TW_RxBuf[TWRX_BLKCNT] = 6;
  TWI_CmdFlags = SMB_GotCmdData;
  for(i=0; i<6; i++)
    TW_RxBuf[3+i]=i+bigI;
}





void TestManager(void)
{
  static unsigned char testctr = 0;

  switch(testctr)
  {
    case 0:
      BOOT_TEST_I();
      testctr++;

⌨️ 快捷键说明

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