📄 inpisp.c
字号:
/******************************************************************************MODULE INPISP for MICA platforms PURPOSE: In-Network Program Bootloader for MICA2 ATMega 128 platformDESCRIPTION Bootloader for the Atmel atmega 128 processor. Accesses MOTOROLA srec format binary image from external FLASH (via SPI bus) Parses srec address and opcode/data Writes opcode/data to address in uC FLASH When the process has completed, it sets up the watchdog timer, and loops until the watchdog reset. Eventually it should reboot. FLASH SREC Structure0 ProgID1 2 CID34 SType5 NofBytes6 S0:ProgID, S1:Address78 S1:Instruction0... *******************************************************************************ATMEGA128 Boot & FLASH ParametersFLASH Page Size = 128 words (256bytes)FLASH Pages = 512 (128Kbytes)FLASHEND = $FFFF (words)BOOTSECTIONMinimum (512Bytes) $FE00 - $FFFF. Bootstart=$FE00 WORD ADDRESSNOTE: gnu compiler/linker uses BYTE Addressing ATMega163 ParametersFLASH PageSize = 64 words (128bytes)FLASH Pages = 128BootSection: 0x1C00 - 0x1FFF (maximum=1K) <<WORD ADDRESS =============================================================================== REVISION HISTORY07jul03 mm disable WDTimer on entry07apr03 mm removed S0 rec - all recs include program ID30mar03 mm revised record struct to include Program and CapsuleID01jan03 mm compile under avr-gcc 3.3 for ATM128 native mode29dec02 mm modified for ATMEGA128*/#define JTAG#define new//#define new1#define ATMega128//----------------------INCLUDES --------------------------------------------#include <avr/io.h>#include "inttypes.h"//#include <io.h>#include <hardware.h>#include <avr/wdt.h>#ifdef new1#include "avr/eeprom.h"#endif//----------------------DEFINITIONS --------------------------------------------#define UINT8 char#define UINT16 unsigned short#define OK 1#define FINI 2#define ERROR 3#define FALSE 0#define TRUE 1//uC FLASH Instructions#define PAGE_ERASE 0x03#define PAGE_LOAD 0x01#define PAGE_WRITE 0x05#define APP_ENABLE 0x11#define SPMEN_BIT 0x01 //StoreProgramEnable bit//External FLASH Instructions#define EE_AUTOREAD 0x68 //<opcode:8><addr:24><fill:32>:then data streams out#define EE_STATUS 0x57 //EE Status command#define EE_BYTESPERPAGE 256 //nof actual bytes used in EEflash page//ATMega FLASH Parameters#ifdef ATMega163#define UFPAGE_SIZEW 64 //#of words per page#define UFPAGE_SIZELOG 6 //shift word address to page address#define UFPAGE_NOF 128#endif#ifdef ATMega128#define UFPAGE_SIZEW 128 //#of words per page#define UFPAGE_SIZELOG 7 //shift word address to page address#define UFPAGE_NOF 512#endif#define PROG_LENGTH 0x0004 //Location in External FLASH where New Program length stored#define UFLASH_ADDRESS_START 0x1000 //Destination (uC Flash) starting byte address#define XFLASH_ADDRESS_START_PAGE 0x0001 //Source (Exernal Flash) starting address#define XFLASH_ADDRESS_START_BYTE 0x00 //Source (Exernal Flash) starting address-skip 1st S0 record#define SPMCR1 0x0068 //equivalent to iom128 SPMCR w/o type#define EE_SRECSIZE 32 //nof bytes per S record in EEFlash#define STYPE_0 0#define STYPE_1 1#define STYPE_2 2#define STYPE_9 9//positions in FLASH Srex #define POS_PID 0 //new#define POS_CID POS_PID+2#define POS_STYPE POS_CID+2#define POS_SNOFB POS_STYPE+1#define POS_S0_PID POS_SNOFB+1#define POS_S0_CRC POS_S0_PID+2#define POS_S1_ADDR POS_SNOFB+1#define POS_S1_I0 POS_S1_ADDR+2 //1st instruction//EEPROM of ATMEga holds programid#define AVREEPROM_PID_ADDR 0xFF4 #define strcat(...)#define dbg(...)#if 0#define SET_CLOCK() sbi(PORTD, 3)#define CLEAR_CLOCK() cbi(PORTD, 3)#define MAKE_CLOCK_OUTPUT() sbi(DDRD, 3)#define MAKE_CLOCK_INPUT() cbi(DDRD, 3)#define SET_DATA() sbi(PORTD, 4)#define CLEAR_DATA() cbi(PORTD, 4)#define MAKE_DATA_OUTPUT() sbi(DDRD, 4)#define MAKE_DATA_INPUT() cbi(DDRD, 4)#define GET_DATA() (inp(PIND) >> 4) & 0x1#endif#define SET_CLOCK SET_I2C_BUS1_SCL_PIN#define CLEAR_CLOCK CLR_I2C_BUS1_SCL_PIN#define MAKE_CLOCK_OUTPUT MAKE_I2C_BUS1_SCL_OUTPUT#define MAKE_CLOCK_INPUT MAKE_I2C_BUS1_SCL_INPUT#define SET_DATA SET_I2C_BUS1_SDA_PIN#define CLEAR_DATA CLR_I2C_BUS1_SDA_PIN#define MAKE_DATA_OUTPUT MAKE_I2C_BUS1_SDA_OUTPUT#define MAKE_DATA_INPUT MAKE_I2C_BUS1_SDA_INPUT#define GET_DATA READ_I2C_BUS1_SDA_PIN//-----------FUNCTION DECLARATIONS -------------------------------------------/*****************************************************************************__SPM(addr,command)SelfProgramMode OperationLoad z register (R30/31) with addrLoad SPMCR register with commandExecute SPM instructionSPMCR reg is at 0x0068 accessable only by STS (not I/O) instructions*****************************************************************************/#define __SPM(a, c) ({ \ unsigned short __addr16 = (unsigned short) a; \ unsigned char __cmd = (unsigned char) c; \ __asm__ __volatile__ ( \ "sts 0x0068, %0" "\n\t" \ "spm" "\n\t" \ ".short 0xffff" "\n\t" \ "nop" "\n\t" \ : \ : "r" (__cmd), "z" (__addr16) ); \})/**************************************************************************SoftSPI bus macros***************************************************************************/static inline wait1() { asm volatile("nop" "\n\t"); asm volatile("nop" "\n\t");}#define SPIOUTPUT if (spi_out & 0x80) { \ SET_FLASH_OUT_PIN(); \ } else { \ CLR_FLASH_OUT_PIN(); \ } \ spi_out <<=1;#define SPIINPUT spi_in <<= 1; \ if (READ_FLASH_IN_PIN()) { \ spi_in |= 1; \ } else { \ wait1(); \ }/**************************************************************************/void wait(void);void fUPageFlush( UINT16 wUAddress );void page_erase(unsigned short addr);void page_write(unsigned short addr);void page_load(unsigned short *pInstr, unsigned short addr);void fSPMWait(void);void reset();char fEEStartRead( UINT16 PA, UINT16 BA);unsigned short fEEGetInstruction(void);UINT8 fEERead32( UINT8 *pEEBuff );void fEEStopRead(void); //deselect the flashvoid fEEExecCommand(UINT8 opcode, UINT16 PA, UINT16 BA);char fEEReady(void);char fSPIInit(void);UINT8 fSPIByte( UINT8 cOut);void fSPIClockCycle(void);//-----------CODE START-------------------------------------------------------#ifdef JTAG__asm__(".org 0x1f800, 0xff" "\n\t");//and ENABLE appropriate line in makefile... //#Linker LIne for AVRSTUDIO JTAG (also see source file for changes)//LD = avr-ld -v -mavr5 -Map=BLMica2a.map -Tdata 0x800100#endifchar _start(UINT16 wProgID, UINT16 wPageStart, UINT16 nwProgID, UINT8 param1){ UINT16 EEPageA; UINT16 EEByteA; //EEFlash Addresss int i = 0; char bOK; UINT8 cNofBytes; UINT16 wDestAddrW; UINT16 wUAddress; UINT8 EEBuff[32]; UINT8 *pEEBuff; UINT16 *pEEBuffW; UINT16 wPID; cli(); //No INTERRUPTS allowed during reprogramming!! //Note: uses CALLERS STACK POINTER wPID = wProgID; if( wPID != ~(nwProgID) ) return; //error by caller -in future better to reboot?//Disable WatchDog timer - may have been enabled by application wdt_disable(); EEPageA = wPageStart; //Get IO Ports into defined state outp(0x00, DDRA); outp(0x00, DDRD); outp(0x00, DDRC); outp(0x00, DDRB); outp(0x00, PORTA); outp(0x00, PORTD); outp(0x00, PORTC); outp(0x00, PORTB); SET_RED_LED_PIN(); SET_YELLOW_LED_PIN(); SET_GREEN_LED_PIN(); MAKE_RED_LED_OUTPUT(); MAKE_YELLOW_LED_OUTPUT(); MAKE_GREEN_LED_OUTPUT(); fEEStopRead(); //deselect the flash fSPIInit(); CLR_GREEN_LED_PIN(); wUAddress = 0x00; //this MUST be fixed - should be first addr from srec/*****************************************************************************Get EEFlash Start Address (from caller)Read out a 32byte SREC record from EEFlashCheck for valid SREC TypeParse the SREC type (and write to UP program memory etc)At end of each EEFlash Page Close Autoread Open next EE PageRepeat until invalid/termination SREC type or error condition****************************************************************************/ //Starting point in EEFlash (Future caller will supply this) EEPageA = XFLASH_ADDRESS_START_PAGE; EEByteA = XFLASH_ADDRESS_START_BYTE; //setup External Flash for autoinc readout fEEStartRead( EEPageA, EEByteA); bOK = 1; while (bOK==OK) { pEEBuff = &EEBuff[0]; bOK = fEERead32(pEEBuff); //Read a 32byte S record line switch( EEBuff[POS_STYPE] ) { case STYPE_1: //Verify Program ID - if wrong abort pEEBuffW = &EEBuff[POS_PID]; wPID = (UINT16)*pEEBuffW; if( wPID != wProgID){ bOK = ERROR; //exit-wrong PID break; } //S2 Parse cNofBytes = EEBuff[POS_SNOFB];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -