|
领导要求MEGA128要能够在线升级程序,所以偶下载了很多程序来试,有幸两种方法尝试都成功了,其中一种就是用avrprog下载,不过这种方法下载速度实在有点太那个了,所以我就不用;现在主要是采用下面这种方法: 1,总共有以下几个文件 main.c,assemble.s90,cstartup.s90 defines.h,assemble.h,main.h 2,文件 main.c, ============================ #include "defines.h" #include "assembly.h"
#define HIGH_CRYSTAL //#define LOW_CRYSTAL void FlashLoad(void); void EEpromLoad(void); void WriteEEprom(void); char CheckEEprom(void); void EEPROMwrite(int location, unsigned char byte); unsigned char EEPROMread(int location); void SendDeviceID(void); void GetPageNumber(void); void ExecCode(void); char GetPage(void); void WriteFlash(void); char CheckFlash(void); void LockBit(void); unsigned char chkchar(void); unsigned char recchar(void); void sendchar(unsigned char ch); char HomeNet(void); void main(void);
unsigned char PageBuffer[PageByte]; unsigned int PageAddress; unsigned int RealPageAddress;
/* Flash Programing Code */ void FlashLoad(void) { sendchar('!'); while (1) { GetPageNumber();
if (RealPageAddress == 0xffff) return;
if (GetPage()) { WriteFlash(); if (CheckFlash()) sendchar('!'); else sendchar('@'); } else sendchar('@'); } }
void GetPageNumber(void) { unsigned char PageAddressHigh; unsigned char PageAddressLow;
while(!chkchar()); PageAddressHigh = recchar();
while(!chkchar()); PageAddressLow = recchar();
RealPageAddress = (int)((PageAddressHigh << 8) + PageAddressLow); PageAddress = RealPageAddress << NSHIFTPAGE;
#ifdef RAMPZ_FLAG if (PageAddressHigh) RAMPZ = 1; else RAMPZ = 0; #endif }
char GetPage(void) { unsigned int i; unsigned char LocalCheckSum = 0; unsigned char CheckSum = 0;
for (i=0;i<PageByte;i++) { while(!chkchar()); PageBuffer[i]=recchar(); LocalCheckSum += PageBuffer[i]; } while(!chkchar()); CheckSum = recchar(); if (LocalCheckSum == CheckSum) return 1; else return 0; }
void WriteFlash(void) { unsigned int i; unsigned int TempInt;
for (i=0;i<PageByte;i+=2) { TempInt=PageBuffer[i]+(PageBuffer[i+1]<<8); fill_temp_buffer(TempInt,i); //call asm routine. } write_page(PageAddress,0x03); //Perform page ERASE write_page(PageAddress,0x05); //Perform page write enableRWW(); }
char CheckFlash(void) { unsigned int i; unsigned int TempInt; unsigned int TempInt2;
for (i=0;i<PageByte;i+=2) { TempInt = read_program_memory(PageAddress + i,0x00); TempInt2 = PageBuffer[i] +(PageBuffer[i+1]<<8); if (TempInt != TempInt2) return 0; } return 1; }
/* LockBit Code */ #ifdef LOCKBIT void LockBit(void) { unsigned char Byte; sendchar('%'); while(!chkchar()); Byte = recchar(); while(!chkchar()); if (Byte == ~recchar()) write_lock_bits(~Byte); } #endif /* Serial Port Code */ unsigned char chkchar(void) { if(UCSRA & 0x80) return 1; else return 0; }
unsigned char recchar(void) { return UDR; }
void sendchar(unsigned char ch) { while(!(UCSRA & 0x20)); // wait for empty transmit buffer #ifndef RS485DDR UDR = ch; // write char #endif
#ifdef RS485DDR RS485PORT |= RS485TXE; // RS485 in TX mode UDR = ch; // write char while(!(UCSRA & 0x40)); // Wait for char to be cue off UCSRA |= 0x40; // Clear flag RS485PORT &= ~RS485TXE; // RS485 in RX mode #endif }
/* Helpers Code */ void delayx(unsigned int x) {//Unit 1ms unsigned int i0,i1; for(i0=0;i0<x;i0++){ #ifdef HIGH_CRYSTAL for(i1=0;i1<800;i1++) #endif #ifdef LOW_CRYSTAL for(i1=0;i1<1100;i1++) #endif { i1++; i1--; } //asm("wdr"); } }
void SendDeviceID(void) { sendchar(DeviceID); sendchar(FlashSize); sendchar(BootSize); sendchar(PageSize); sendchar(EEpromSize); recchar(); }
void ExecCode(void) { #ifdef RAMPZ_FLAG RAMPZ = 0; #endif #ifdef INTVECREG INTVECREG = 0x01; // Enable interrupt vector select INTVECREG = 0x00; // Move interrupt vector to flash #endif asm("jmp 0x0000"); // Run application code } #ifdef HOMENET char HomeNet(void) { unsigned char i; unsigned char Exec = 0; unsigned char Boot = 0; unsigned char Address; EEAR = 0x01; EECR |= 0x01; // Set READ strobe Address = EEDR; // Return byte while(1) { while(!chkchar());
i = recchar(); if (i == '>') Exec++; else Exec = 0; if (i == '+') Boot++; else Boot = 0; if (Exec >= 3) return 1; if (Boot >= 5) { while(!chkchar()); if (recchar() != Address) return 1; return 0; } } return 1; } #endif
void main(void) { unsigned char i; asm("cli"); // disable all interrupts PORTA = 0x00;//Initialize Port DDRA = 0xFF; PORTB = 0x0; DDRB = 0xeB; PORTC = 0x10; DDRC = 0xEE; PORTD = 0xff; DDRD = 0x79; PORTE = 0xff; DDRE = 0xce; PORTE = 0xfb; PORTF = 0xFF; DDRF = 0x00; PORTG = 0x7F; DDRG = 0x0E; PULLUPPORT = PULLUPPIN; // Pull up on RX line UCSRB = 0x00; //disable while setting baud rate UCSRA = 0x00; UCSRC = 0x86; // Asyn,NoParity,1StopBit,8Bit, UBRRH = 0x00; //set baud rate hi UCSRB = 0x18; // Rx enable Tx Enable
#ifdef RS485DDR RS485DDR |= RS485TXE; // RS485 Tranceiver switch pin as output RS485PORT &= ~RS485TXE; // RS485 in Rx mode #endif
for(i=0;i<6;i++){ if(i%2) PORTE &= 0xf7;//led on else PORTE |= 0x08;//led off delayx(200); }
// Auto-find baudrate if BAUDRATE is undefine #ifdef BAUDRATE { UBRRL = BAUDRATE; #else for (i = 0; i < 255; ++i) { UBRRL = i; #endif
#ifdef HOMENET if (HomeNet()) ExecCode(); delayx(20); #endif recchar(); sendchar('>'); if(i%2) PORTE &= 0xf7;//led on else PORTE |= 0x08;//led off delayx(20); if (recchar() == '<') { SendDeviceID(); FlashLoad(); #ifdef EEPROM EEpromLoad(); #endif #ifdef LOCKBIT LockBit(); #endif ExecCode(); } } ExecCode(); }
assemble.s90, ============================ NAME ASSEMBLY PUBLIC fill_temp_buffer PUBLIC write_page PUBLIC write_lock_bits PUBLIC read_program_memory PUBLIC enableRWW RSEG CODE #include "defines.h"
;-----------------------------------------
; void write_page (unsigned int adr, unsigned char function); ; bits 8:15 adr addresses the page...(must setup RAMPZ beforehand!!!) write_page: RCALL WAIT_SPMEN MOVW r30, r16 ;move address to z pointer (R31 = ZH, R30 = ZL) STS spm_creg, R18 ;argument 2 decides function ESPM ;perform pagewrite RET
;-----------------------------------------
; void fill_temp_buffer (unsigned int data, unsigned int adr); ; bits 7:1 in adr addresses the word in the page... (2=first word, 4=second word etc..) fill_temp_buffer: RCALL WAIT_SPMEN MOVW r30, r18 ;move adress to z pointer (R31=ZH R30=ZL) MOVW r0, r16 ;move data to reg 0 and 1 LDI R19, 0x01 STS spm_creg, R19 ESPM ;Store program memory RET ;-----------------------------------------
;unsigned int read_program_memory (unsigned int adr ,unsigned char cmd); read_program_memory: MOVW r30, r16 ;move adress to z pointer SBRC R18, 0 ;read lockbits? (second argument = 0x09) STS spm_creg, R18 ;if so, place second argument in SPMEN register ;#ifdef LARGE_MEMORY ;If large memory (>64K) ; ELPM ;Store program memory ;#else ; LPM ;Store program memory ;#endif ELPM r16, Z+ ;read LSB ELPM r17, Z ;read MSB RET ;-----------------------------------------
;void write_lock_bits (unsigned char val); write_lock_bits: MOV R0, R16 LDI R17, 0x09 STS spm_creg, R17 ESPM ;write lockbits RET
;----------------------------------------- enableRWW: RCALL WAIT_SPMEN LDI R27,0x11 STS spm_creg,R27 ESPM RET ;-----------------------------------------
WAIT_SPMEN: LDS R27,spm_creg ; load SPMCR to R27 SBRC R27,0 ; check SPMEN flag RJMP WAIT_SPMEN ; wait for SPMEN flag cleared RET ;-----------------------------------------
END
cstartup.s90 ============================ ; Call main RSEG CODE:CODE:NOROOT(1)
PUBLIC ?cstartup_call_main
?cstartup_call_main: ;#if MEMORY_MODEL != LARGE_MEMORY_MODEL ;#if A90_PROC_OPTION > 1 LDI R16,0 OUT RAMPZ,R16 ;#if A90_POINTER_REG_SIZE > 2 OUT RAMPY,R16 OUT RAMPX,R16 ;#endif /* A90_POINTER_REG_SIZE > 2 */ ;#endif /* A90_PROC_OPTION > 1 */ ;#endif /* MEMORY_MODEL != LARGE_MEMORY_MODEL */
XCALL main XCALL exit XJMP _exit
END defines.h, ============================ 略 assemble.h, ============================ 略 main.h ============================ 略 3,我采用的是IAR2。28编译,不过编译是记得在编译配置文件里加上下面的设置 /* Code memory */ -Z(CODE)INTVEC,SWITCH,CODE=1FC00-1FFFF -Z(FARCODE)FAR_F,INITTAB=1FC00-1FFFF
4,记得好需要一个下载工具哦,如果有需求发mail:xt_xuyi@163.com 不过在用编译器的时候,记得编译里也需要适当的设置. 这个有点多于了。呵呵。。。。
|