共2条
1/1 1 跳转至页
Flash 想在程序运行时通过串口更新Flash中数据表应该怎么办?
问
答 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
以下是简化了的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 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |