这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » Flash 想在程序运行时通过串口更新Flash中数据表应该怎么办?

共2条 1/1 1 跳转至

Flash 想在程序运行时通过串口更新Flash中数据表应该怎么办?

院士
2006-09-17 18:14:16     打赏
Flash 想在程序运行时通过串口更新Flash中数据表应该怎么办?



关键词: Flash     想在     程序     运行时     通过     串口     更新         

院士
2006-12-22 22:43:00     打赏
2楼
1: 用MEGALOAD吧用MEGALOAD吧,好用! 2: 请问楼上MEGALOAD下载下来后用在哪个芯片我用在M8上位机可以认到M8发来的信息可就是实现不了下一步编程的功能 3: 好好分析一下main.c文件该MEGALOAD程序的主要通讯过程是这样的,目标板上电后以一循环控制UBRR的值从1至255往PC机发送字符“>”并等待PC端返回字符“<”,以表示响应目标板的连接,理论上这样可以实现以各种标准波特率的连接,达到自动测试PC端波特率的功能,但是当你的目标板的晶振不是特定的7.3728M或是14.7456的话高波特率连接就会失败,导致无法连接,可换用晶振或是选择19200或以下的波特率连接,一般就可以解决问题;当目标板收到PC机的“<”字符后开始用特定的字符发送芯片型号,页大小,启动区大小等信息(可参考附带的main.c源程序),结束后发送“!”告知PC机可以发送程序给目标板芯片,PC机收到“!”后发送一个字节的高位地址,接着再发送一个字节低位地址,第一页以00 00开始,依次为00 01, 00 02, 00 03……;然后PC端开始发送程序数据,最后发送校验码,如果校验码不对说明发送过程有错,目标板发送“@”告知PC机再发送一次程序数据和校验码,直到校验通过为止,如果PC端连续5次收到“@”则写入失败。当所有的页都正常写入后PC端再发送两个字节的FF表示下载完成。其实你根据这些信息可以自己编写一个上位机的程序了,当时我可是用一台双串口的PC用软件监控+慢慢分析源程序推导出来的,好辛苦◎_◎

以下是简化了的MEGA16芯片的BOOTLOAD程序,用ICCAVR编译。

main.c文件

#define  PageByte     128    
#define  NSHIFTPAGE    7
#define  INTVECREG    GICR
#define  PULLUPPORT    PORTD
#define  PULLUPPIN    0x01
#define  FALSE     0
#define  TRUE     1

#include "assembly.h"
#include <macros.h>
#include <iom16v.h>

void FlashLoad(void);
void GetPageNumber(void);
void ExecCode(void);
char GetPage(void);
void WriteFlash(void);
char CheckFlash(void);
unsigned char IsChar(void);
unsigned char RxChar(void);
void TxChar(unsigned char ch);
void Wait(void);
void main(void);

unsigned char PageBuffer[PageByte];
unsigned int PageAddress;
unsigned int RealPageAddress;

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

void FlashLoad(void)
{
TxChar('!');
while (1)
   {
   GetPageNumber();

   if (RealPageAddress == 0xffff) return;

   if (GetPage())
   {
   WriteFlash();
   if (CheckFlash()) TxChar('!');
   else TxChar('@');
   }
   else TxChar('@');
   }
}

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

void GetPageNumber(void)
{
unsigned char PageAddressHigh;
unsigned char PageAddressLow;

while(!IsChar());
PageAddressHigh = RxChar();

while(!IsChar());
PageAddressLow = RxChar();

RealPageAddress = (int)((PageAddressHigh << 8) + PageAddressLow);
PageAddress = RealPageAddress << NSHIFTPAGE;
}

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

char GetPage(void)
{
unsigned int i;
unsigned char LocalCheckSum = 0;
unsigned char CheckSum = 0;

for (i=0;i<PageByte;i++)
{
while(!IsChar());
PageBuffer[i]=RxChar();
LocalCheckSum += PageBuffer[i];
    }
     
while(!IsChar());
CheckSum = RxChar();
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;
}

/*****************************************************************************/
/* Serial Port Code                               */
/*****************************************************************************/
unsigned char IsChar(void)
{
if(UCSRA & 0x80) return 1;
else return 0;
}

/*****************************************************************************/
unsigned char RxChar(void)
{
return UDR;
}

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

void TxChar(unsigned char ch)
{
while(!(UCSRA & 0x20));  // wait for empty transmit buffer
UDR = ch;          // write char
}

/*****************************************************************************/
/* Helpers Code                                */
/*****************************************************************************/
void Wait()
{
int i;
for (i=0;i<32000;i++);
}

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

void ExecCode(void)
{
#ifdef INTVECREG
INTVECREG = 0x01;      // Enable interrupt vector select
INTVECREG = 0x00;      // Move interrupt vector to flash
#endif
asm("jmp 0x0000");       // Run application code   
}

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

void main(void)
{
unsigned char i;
CLI();                  // disable all interrupts

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

    {
    UBRRL = 3;
    RxChar();
TxChar('>');
Wait();
if (RxChar() == '<')
    {
    FlashLoad();
    ExecCode();
    }
}
ExecCode();
}


assembly.s文件

  .text
  
;*********************************************************
; Place a 1 for the processor you want use
;*********************************************************

MEGATYPE16  =  1

;*********************************************************
;*********************************************************
;*********************************************************
;*********************************************************
; DO NOT CHANGE ANYTHING BELOW THIS LINE !!!!!!!
;*********************************************************
;*********************************************************
;*********************************************************
;*********************************************************

SPMCR = 0x57

;-----------------------------------------

; void write_page (unsigned int adr, unsigned char function);
; bits 8:15 adr addresses the page...(must setup RAMPZ beforehand!!!)
_write_page::
    XCALL __WAIT_SPMEN__
    movw    r30, r16        ;move address to z pointer (R31 = ZH, R30 = ZL)
    STS     SPMCR, R18      ;argument 2 decides function
    SPM                     ;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::
    XCALL __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     SPMCR, R19
    SPM                     ;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     SPMCR, R18      ;if so, place second argument in SPMEN register
    LPM     r16, Z+
    LPM     r17, Z
    RET

;-----------------------------------------

;void write_lock_bits (unsigned char val);
_write_lock_bits::
     MOV     R0, R16   
     LDI     R17, 0x09     
     STS     SPMCR, R17
     SPM                ;write lockbits
     RET

;-----------------------------------------
        
_enableRWW::
XCALL __WAIT_SPMEN__
    LDI R27,0x11
    STS SPMCR,R27
    SPM
    RET   

;-----------------------------------------           

__WAIT_SPMEN__:
    LDS     R27,SPMCR       ; load SPMCR to R27
    SBRC    R27,0           ; check SPMEN flag
    RJMP    __WAIT_SPMEN__  ; wait for SPMEN flag cleared        
    RET

;-----------------------------------------
4: 我想在程序运行过程中,而不是在系统启动时,应该怎么办?不是说在程序运行过程中可以通过串口接收到特定命令,转入BOOT区,改写程序区内容吗?如何是好呢? 5: 一个比较变态的方法(搞笑)在主程序里设计一个模块,使系统收到串口特定指令就进入死循环,然后狗叫了,系统重启,顺便就更新用户应用程序了!这方法比较变态吧……哈哈哈 6: 应该可以改写!?,书上是这样写的。但要怎么办呢? 7: 接收到命令后直接jmp 0x3800不就可以了? 下载完成后再bootload里面直接jmp 0

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]