分享

C8051F500 BootLoader

 logicsoft 2023-02-02 发布于浙江

之前上学的时候,一直用stc的51单片机然后可以串口下载程序,曾天真的以为,串口下载程序就是标配。直到今天需要我自己写串口引导。我才明白生活是多么残忍。

串口下载程序,整体思路:写一个引导程序,可以通过串口从上位机读取要下载的程序,然后擦除flash的需要写入的区域。写入执行程序,校验执行程序,跳转到执行程序处,开始执行。

根据引导程序在flash中的位置不同可以分为两大流派。引导程序在前面和引导程序在flash最后面两大流派。下面分析一下两种流派各自的优缺点(注意:我写程序的时候用的是引导程序在最前面的流派,对于引导程序在最后面的描述可能有不准之处):
1.由于C8051的中断入口地址在低字节处,如果把引导程序写在最前面,主程序里面的中断就需要重定向
2.引导程序在前面,主程序就要从某个地址开始,然后会造成串口下载的HEX和用普通下载器下载的程序不同。(后置引导程序的方式好像可以避免这个问题。)
3.(采用后置引导程序时)因为单片机上电首先执行0x0000地址处的命令,而我们需要上电首先执行BootLoader程序,这就要求0x0000处的命令是一个跳转到BootLoader的跳转指令。然后往低地址写入程序前需要先擦除低字节,我们在此时断电的话,可能造成0x0000处的跳转指令丢失。造成引导程序故障。

说了这么多废话,下面是正题。下面将介绍前置引导程序的具体实现方式和及具体设置和程序。

首先要实现的功能就是flash的读写和擦除。具体程序如下:

/*
擦除存储
*/
void FLASH_PageErase (U16 addr)
{
	U8 xdata * data pwrite;		// FLASH write pointer

	U8 SFRPAGE_save = SFRPAGE;
	SFRPAGE = ACTIVE_PAGE;

	VDM0CN = 0xA0; 		// Enable VDD monitor and high threshold

	RSTSRC = 0x02; 		// Enable VDD monitor as a reset source

	pwrite = (U8 xdata *) addr;

	FLKEY = 0xA5; 		// Key Sequence 1
	FLKEY = 0xF1; 		// Key Sequence 2
	PSCTL |= 0x03; 		// PSWE = 1; PSEE = 1

	VDM0CN = 0xA0; 		// Enable VDD monitor and high threshold

	RSTSRC = 0x02; 		// Enable VDD monitor as a reset source

	*pwrite = 0; 		// Initiate page erase

	PSCTL &= ~0x03;		// PSWE = 0; PSEE = 0

	SFRPAGE = SFRPAGE_save;
}
/*
写入一byte
*/
void FLASH_ByteWrite (U16 addr, char byte)
{
	char xdata * data pwrite;           // FLASH write pointer

	VDM0CN = 0xA0;                      // enable VDD monitor

	RSTSRC = 0x02;                      // enable VDD monitor as a reset source

	pwrite = (char xdata *) addr;

	PSCTL |= 0x01;                      // PSWE = 1
	FLKEY  = 0xA5;                      // Key Sequence 1
	FLKEY  = 0xF1;                      // Key Sequence 2

	VDM0CN = 0xA0;                      // enable VDD monitor

	RSTSRC = 0x02;                      // enable VDD monitor as a reset source

	*pwrite = byte;                     // write the byte

	PSCTL &= ~0x01;                     // PSWE = 0
}
/*
读取一byte
*/
unsigned char FLASH_ByteRead (U16 addr)
{
   bit EA_SAVE = EA;                   // preserve EA
   char code * data pread;             // FLASH read pointer
   unsigned char byte;

   EA = 0;                             // disable interrupts

   pread = (char code *) addr;

   byte = *pread;                      // read the byte

   EA = EA_SAVE;                       // restore interrupts

   return byte;
}

调试读写flash的时候遇到过一个问题,就是写flash的时候,会导致程序复位。最后发现原因就是VDM0CN 、RSTSRC 这两个寄存器没有配置。

flash读写搞定以后,引导程序就完成一半了,剩下的就是串口通信,这个需要和上位机配合,制定通信协议。具体思路就是:首先打开上位机串口,然后上位机等待,这时候给下位机上电,下位机上传握手指令。上位机收到握手指令,显示握手成功,同时下发握手指令,下位机收到握手指令进入程序下载模式,收不到握手指令,三秒后跳转到程序区执行原来的程序(此处还可以优化,加一个检测,读取程序存储区是否都是0xFF,如果是就一直重复间隔发送握手指令)。握手成功后,开始擦除程序存储区,可以根据程序大小擦除,也可以擦除除引导外全部程序存储区。擦除完成后读取Hex文件下发(Hex文件的具体格式,哪些内容需要下发,哪些不需要,可以参照我的另一篇博客)。最后从flash读取程序进行校验。完成。

此时引导程序已经完成了百分之九十八了,还剩百分之二的工作。对的,剩下的这百分之二的工作,就是中断重定向。在STARTUP.A51中加入这么几句话(注:STARTUP.A51为一个默认的C语言代码引导程序,主要内容就是初始化堆栈,初始化变量啥的,貌似是如果说错了希望各位批评指正。如果你的工程里没有这个文件,不用担心。新建一个文件,新建的时候keil会提示你要不要把这个文件添加进来。然后你也可以把其他工程里的这个文件拷贝的你的工程路径,然后添加到你的工程里):

ORG 0003H
LJMP 2003H
ORG 000BH
LJMP 200BH
ORG 0013H
LJMP 2013H
ORG 001BH
LJMP 201BH
ORG 0023H
LJMP 2023H
ORG 002BH
LJMP 202BH
ORG 0033H
LJMP 2033H
ORG 003BH
LJMP 203BH
ORG 0043H
LJMP 2043H
ORG 004BH
LJMP 204BH
ORG 0053H
LJMP 2053H
ORG 005BH
LJMP 205BH
ORG 0063H
LJMP 2063H
ORG 006BH
LJMP 206BH
ORG 0073H
LJMP 2073H
ORG 007BH
LJMP 207BH
ORG 0083H
LJMP 2083H
ORG 008BH
LJMP 208BH

(然后就是这段代码在STARTUP.A51文件中的添加的位置。我的程序里,添加在了图片中光标位置,即105行处。至于其他地方是否可行。需要各位自行验证。奥对,解释一下这几句话的意思,在C8051的数据手册里,我们可以查到C8051各个中断函数的入口地址。就是上面代码中 ORG 后面跟的那些地址,然后这个断代码就是把这些中断跳转到别的地址,比如第一个0x0003处的中断跳转到0x2003处。以此类推。OK,那有朋友可能会疑惑了,为什么是跳到对应的0x2003呢?这个和我们后面对主程序的设置有关。后面我们需要设置主程序的中断地址是0x2000以后,具体说明请网下看。)
在这里插入图片描述不知不觉已经啰嗦了这么多了,到这里我们的引导程序就算是写好了。

下面开始进行主程序的设置,主程序就是需要下载的程序,正常编写就可以没啥大问题,有两个点需要设置,第一个是前面提到过的中断的入口位置。第二个就是主程序的存储位置。

先说第一个中断入位置要设置到0x2000.如下图所示,前面对号勾上,然后框里添上0x2000。注意是0x2000不是0x2003,虽然我们第一中断的跳转地址就是0x2003。但是要填0x2000(我用的0x2000可以,填0x2003我也不晓得可以不可以。)
在这里插入图片描述第二个要设置主程序的存储地址,这就需要估计引导程序的大小。当然也可以打开引导程序的HEX看一看。我的引导程序小于0x1000,然后又本着给它留一点余量和选一个好记的地址的原则。我把主程序地址选在了0x1000。具体设置如下:
在这里插入图片描述注意标箭头的两个位置,这两个位置都需要改。一个是程序的存储地址,另一个好像是那个STARTUP.A51的存储地址还是跳转地址来着。我也不太确定了。

在这里插入图片描述注意:上图的这两个框框不要打勾勾,不然你就找不到上面的那个设置了。

至此这个BootLoader就差不多了,还缺个上位机软件。上位机软件的主要功能就是读HEX,然后发给下位机。具体的实现逻辑就留给各位看官自己去想吧。我在这就提供一点思路。如果对这个串口下载有什么不明白的,也可以私信我。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多