P89C51RD2的Boot ROM固件代码的读出方法和ISP功能分析

发布者:hzx312895379最新更新时间:2023-03-21 来源: elecfans关键字:P89C51RD2  Boot  ROM  ISP功能 手机看文章 扫描二维码
随时随地手机看文章

1 概 述

P89C51RD2是PHILIPS公司内核基于8位80C51单片机的派生产品,在完全保留80C51指令系统和硬件结构的大框架下,进行了多方面的加强、扩展和创新,最大限度地利用了原有结构的方方面面。P89C51RD2将原有的对外数据和程序存储器的16位寻址机制加以利用,把片上的RAM扩展到1KB、片上的FLASH EPROM扩展到64KB,满足当今用嵌入式高级语言对片上大存储容量的需要。


P89C51RD2最显著的特点莫过于其ISP(In-System Programming,在系统可编程)功能和IAP(In-Application Programming,在应用可编程)功能。ISP指电路板上的空白器件可以编程写入最终用户代码,而不需要从电路板上取下器件,已经编程的器件也可以用ISP方式擦除或再编程。IAP指MCU可以在系统中获取新代码并对自己重新编程,即可用程序来改变程序。ISP和IAP技术是未来仪器仪表的发展方向。PHILIPS公司为了使ISP技术和IAP技术得以推广,在芯片上免费提供了Boot ROM固件,并且巧妙地解决了固件和FLASH的地址覆盖问题及一些具体实现细节问题,使它们的实现变得简单而现成。


对于Boot ROM中的内容,PHILIPS公司是不公开的。但很多技术人员对于Boot ROM固件中ISP(IAP)功能的实现非常感兴趣。就ISP状态而言,上位机直接跟Boot ROM固件中的程序打交道,因此,必须根据PHILIPS公司提供的流程和协议来编制上位机程序,至于Boot ROM内部是如何实现ISP功能的,则不得而知。如果能够搞明白ISP功能实现的具体方法,则对于上位机软件的编制是大有好处的。以下是对Boot ROM中有关ISP功能实现所作的一些初步探讨。


2 Boot ROM固件代码的读出方法

要对其 ISP功能进行分析,必须读出Boot ROM中的源代码。为此,必须弄清楚Boot ROM空间和FLASH空间的关系。P89C51RD2采用了最先进的FLASH(快闪)EPROM,其容量为64KB,并且分成8KB和16KB的存储块。我们知道,80C51系列8位单片机的最大寻址能力就是64KB,FLASH EPROM已经将全部寻址空间占据。同时,PHILIPS公司为P89C51RD2在片内提供了一个名叫引导ROM(Boot ROM)的1KB的固件。固件上有引导装载程序,可以接收主机经串口传来的命令和数据(如经PC机的RS-232C口),这个固件是放在64KB程序存储器的最高端的,与片内FLASH地址0FC00H“0FFFFH相覆盖。两者之间的切换是通过特殊功能寄存器AUXR1的ENBOOT位来进行的。


ENBOOT=1 地址在0FC00H”0FFFFH范围,寻址到固件

ENBOOT=0 地址在0FC00H“0FFFFH范围,寻址到FLASH

既然当ENBOOT=1时,能够寻址到固件,则利用程序就可以将固件代码读出。下面是实现代码读出时的硬件部分和软件部分。


(1)硬件部分

为了读出Boot ROM中的内容,必须给P89C51RD2搭一个包括复位、晶振和串口通信功能的基本硬件系统。ICL232为单电源串口转换芯片,可以完成TTL电平与RS-232C电平之间的转换。

(2)软件编制

编制软件的目的,是为了从Boot ROM中读出源代码,并送往上位机显示。为了使用现成的软件(如超级终端),程序中将读出的二进制代码转换成ASCII码,并组成HEX文件格式直接传给上位机,这样,将显示的内容存盘并反汇编,就可以对Boot ROM中的内容进行分析。由于程序中涉及到二进制转换成HEX文件格式,故将有关HEX文件格式的有关内容表述如下:

HEX文件的INTEL格式,是INTEL公司提出的按地址排列的数据信息,数据宽度为字节,所有数据使用十六进制数字表示,如Boot ROM从地址FC00H开始的前16个数据为(已经转换成ASCII码):

75 89 02 75 C8 30 E4 F5 CD F5 CC 30 B0 FD 20 B0(十六进制)

则转换成HEX文件格式为:

:10FC000075890275C830E4F5CDF5CC30B0FD20B073

”:“符号表明记录的开始;后面的2个字符表明记录的长度,这里是10H,即16个十六进制数字;后面的4个字符给出调入的地址,这里是FC00H;再后面的2个字符表明记录的类型,00表示数据记录,01表示记录文件结束;再后面的16个数据即为真正的数据记录;最后的2位73是校验和,它加上前面所有的数据和为0。

所有HEX格式文件的最后一行为结尾行,它比较特殊,总是如下所示:

:00000001FF

读Boot ROM代码的主程序编制如下:

主程序中用到了两个子程序:READ_ROM和SEND_END。

READ_ROM子程序功能:从FC00H开始将代码读出,将其转变成ASCII码并拼凑成HEX文件记录的形式传给上位机。

读Boot ROM代码所调用的子程序网上查找下。

3 Boot ROM固件的功能分析

通过对Boot ROM中的程序进行分析,可以对ISP的有关指令进行更深入的理解,在一些编程方法上也可以向国外学习。下面对ISP的有关知识点进行阐述。

3.1 关于自动确定波特率

PHILIPS给出的ISP功能的第一个步骤为:上位机向下位机发送一个大写的英文字符”U“,供下位机确定波特率。

3.1.1 工作原理

大写的英文字符”U“有它的特殊性,它的ASCII码为55H,转换成二进制为”01010101B“,也就是说它是一个”0“、”1“相间的数据。如果能够算出其一个位的传输时间tp,则对应的波特率就可以计算出来。

3.1.2 tp对应的计数值

首先看一下在Boot ROM中是如何计算一个位所对应的计数值的。以下为Boot ROM从地址FC00H ”FC17H之间的源代码及反汇编程序:

源代码 反汇编程序

FC00 75 89 02 MOV TMOD,#02H ;T1工作模式2,定时器

FC03 75 C8 30 MOV T2CON,#30H ;T2工作为串行口波特

;率发生器

FC06 E4 CLR A

FC07 F5 CD MOV TH2,A

FC09 F5 CC MOV TL2,A ;T2=0000H

FC0B 30 B0 FD JNB P3.0,$ ;若P3.0=0,则等待,

;直到其变为1

FC0E 20 B0 FD JB P3.0,$ ;若P3.0=1,则等待,

;直到下降沿到来

FC11 D2 CA SETB TR2 ;启动T2定时器

FC13 30 B0 FD JNB P3.0,$ ;若P3.0=0,则等待,

;直到上升沿到来

FC16 C2 CA CLR TR2 ;关闭T2定时器,此时

;T2中的数值为tp

首先将T2清0,然后测下降沿,测到下降沿后,开始置TR2=1,T2开始计数,等测到上升沿后,置TR2=0,停止计数,则此时T2中为传送1bit (低电平)的计数值。以波特率2400 bps为例,则传送1bit所用的时间为1/2400 s,即416.67μs。P89C51RD2主频为11.0592 MHz,再由PHILIPS公司的数据手册可知,当T2工作于波特率发生器模式时,OSC未经分频直接进入T2计数器,由此可得在tp时间内T2的理论计数值为:(T2)=0.000 416 67×110 592 00= 4608(十进制)=1200H。在这里,特别要强调的是:该数只是一个理论值。对波特率为2400 bps时的实际值进行测试,发现实测值为11FAH左右。不管怎样测,实测值总是小于理论值6个数左右。这个数据为下面的波特率计算提供了重要依据。

3.1.3 波特率的计算

程序中对波特率的计算颇有特色,下面是地址FC18H“FC36H之间的源代码和反汇编程序:

源代码 反汇编程序

FC18 E5 CC MOV A,TL2

FC1A C4 SWAP A

FC1B 54 0F ANL A,#0FH ;取TL2高4位

FC1D F8 MOV R0,A

FC1E E5 CD MOV A,TH2

FC20 C4 SWAP A

FC21 54 F0 ANL A,#0F0H;取TH2低4位

FC23 48 ORL A,R0

FC24 F8 MOV R0,A ;组合后送入R0

FC25 E5 CD MOV A,TH2

FC27 C4 SWAP A

FC28 54 0F ANL A,#0FH ;取TH2高4位

FC2A F9 MOV R1,A

FC2B E8 MOV A,R0 ;以上程序实现T2中数据除以

;16,送R1和R0保存

FC2C F4 CPL A ;低位取反

FC2D F5 CC MOV TL2,A

FC2F F5 CA MOV RCAP2L,A

FC31 E9 MOV A,R1

FC32 F4 CPL A ;高位取反

FC33 F5 CD MOV TH2,A

FC35 F5 CB MOV RCAP2H,A

上述程序就是将tp对应值转换成波特率的程序,先来看一下波特率是怎样定义的。定时器2工作在波特率发生器模式,外部时钟信号由T2脚进入,波特率为

(1)

所以程序中首先将T2中的计数值进行处理,相当于右移4位,将低4位去掉,11FAH变为011FH,对应式(1)中除以16,送R1和R0保存,然后将R1和R0中的值取反,其值为FEE0H。该值恰恰与根据式(1)计算出的数值相同。将该数值送T2和RCAP2,即得2400bps对应的赋值。

3.1.4 波特率的校验

在波特率确定以后,首先设定TR2=1以启动波特率,并对串口控制字进行设定。然后,程序对其进行校验。方法是接收上位机的数据并以设定波特率回送该值,一方面通知上位机送出和接收的数据是否相同,如果相同,则上位机认为下位机的波特率设置正确,通信成功;另一方面程序也将接收的数据?quot;U” 的ASCII码相对照,如果相等,则往下执行,如果不等,则继续重复上述过程,直到成功为止,否则进入死循环,只有程序复位才能退出。下面是其源程序与反汇编程序(FC37H至FC40H):

源代码 反汇编程序

FC37 D2 CA SETB TR2

FC39 75 98 52 MOV SCON,#52H ;方式1,TI=1

FC3C 91 A0 RREV0: ACALL REV_SEND0

FC3E B4 55 FB CJNE A,#55H,RREV0 ;判断A=“U”?

其中,REV_SEND0子程序的功能是接收一个数据并回传给上位机。由上述程序可以看出,实际上要通信成功,上位机至少要向下位机发送两个“U”:第一个用于确定波特率,另一个用于校验波特率,并且这两个字符之间必须隔一段时间,以便于波特率计算完毕并有效。所以,有关手册中关于ISP第一步要发送一个“U”来确定波特率的说法本身没有错,但如果在编制上位机程序时,仅仅发送一个“U”是不能够通信成功的,特提醒读者注意。

3.2 命令字的接收

在通信成功后,就可以接收ISP的命令字了。

3.2.1 ISP命令格式说明

ISP编程由Boot ROM中的一系列引导子程序完成。这些子程序采用Intel-Hex记录格式接收PC主机的命令和数据。Intel-Hex记录格式上面已经有所介绍,其命令格式为

:NNAAAARRDD…DDCC

其中,:NNAAAA以及DDCC的含义皆与上面论述的相同,只需对“RR”作以下说明:

“RR”表示记录类型,其中

00--数据记录,即传编程数据并完成编程;

01--文件结束标志;

02--指定振荡器频率;

03--杂项编程功能,和后面的数据相配合完成擦除、加密等功能;

04--显示指定地址端FLASH的数据或做空白检查;

05--各种读功能。

3.2.2 命令字的处理

为了更容易看懂,将使用的通用寄存器和部分地址进行代换如下:

DATA_ADDRL EQU 30H

DATA_ADDRH EQU 31H

DATA_SUM EQU 32H

DATA_LEN EQU 33H

DATA_FOSC EQU 34H

DATA_MODE EQU 35H

DATA_BUFFER EQU 36H

REV_DAT_ADDR EQU 80H

下面来看一下Boot ROM中的源代码与反汇编程序。

源程序 反汇编程序

FC41 75 32 00 MAIN: MOV DATA_SUM,#00H;校验和

FC44 91 A0 ACALL REV_SEND0

FC46 B4 3A F8 CJNE A,#3AH,MAIN;判断A=“:”?

FC49 91 79 ACALL REV_DAT1_SUM

FC4B 85 36 33 MOV DATA_LEN,DATA_BUFFER ;33H字节数

FC4E 91 79 ACALL REV_DAT1_SUM

FC50 85 36 31 MOV DATA_ADDRH,DATA_ BUFFER ;31H数据首地址高8位

FC53 91 79 ACALL REV_DAT1_SUM

FC55 85 36 30 MOV DATA_ADDRL,DATA_ BUFFER ;30H数据首地址低8位

FC58 91 79 ACALL REV_DAT1_SUM

FC5A 85 36 35 MOV DATA_MODE,DATA_ BUFFER ;35H数据操作类型

FC5D E5 33 MOV A,DATA_LEN

FC5F FA MOV R2,A ;循环接收数据指针

FC60 60 09 JZ RREV3 ;字节数=0 转RREV3

FC62 79 80 MOV R1,#REV_DAT_ADDR

FC64 91 79 RREV2: ACALL REV_DAT1_SUM

FC66 A7 36 MOV @R1,DATA_MODE

FC68 09 INC R1

FC69 DA F9 DJNZ R2,RREV2

FC6B AC 32 RREV3: MOV R4,DATA_SUM ;校验和

FC6D 91 79 ACALL REV_DAT1_SUM

FC6F EC MOV A,R4

FC70 B5 36 02 CJNE A,DATA_BUFFER,RREV4

;校验和不等转

FC73 81 BF AJMP RUN_MODE

FC75 74 58 RREV4:MOV A,#58H ; A=“X”

FC77 81 FA AJMP SEND_DT

首先,对程序中用到的子程序作如下的说明。

REV_SEND0子程序:接收1个数据并回传给上位机;

REV_DAT1_SUM子程序:接收2个ASCII字符并回传,将2个ASCII码合成1字节二进制数并计算校验和;

SEND_DT:该地址执行送字符“X”给上位机;

RUN_MODE:该地址解释并执行命令字。

对上段程序分析如下:首先,将校验和单元清零,开始接收第1个ASCII码,并判断是否为“:”。如果是,则说明是一个命令字的开始,下面便依次接收字节数DATA_LEN、数据首地址高8位DATA_ ADDRH、数据首地址低8位DATA_ADDRL和数据操作类型DATA_MODE。这跟其命令字格式是完全对应的。然后,程序根据接收数据字节数 DATA_ LEN来决定下面的数据接收,并将接收的数据存储在从80H开始的内部数据存储器中,以备下一步的处理。最后,进入校验和的接收,将程序计算所得的校验和与上位机传输的校验和作比较,如果不等,回传“X”字符,通知上位机进行异常处理;如果相等,则转入相应的命令执行。

3.3 命令的执行

命令解释和执行的源代码和反汇编程序如下:

源程序 反汇编程序

FCBF E5 35 RUN_MODE: MOV A,DATA_MODE

;35H数据操作类型

FCC1 23 RL A ;A=A*2

FCC2 90 FC C6 MOV DPTR,#BASE_ADDR ;程序散转

FCC5 73 JMP @A+DPTR

FCC6 81 D4 BASE_ADDR: AJMP PRO_DATA

;00=传送编程数据并完成编程

FCC8 81 F8 AJMP SEND_CHAR_OK

;01=传文件结束符

FCCA 81 FE AJMP SETUP_FOSC

;02=指定振荡器频率

FCCC A1 70 AJMP MPRO_DAT

;03=杂项编程功能

FCCE A1 04 AJMP READ_CHECK

;04=显示指定地址段FLASH数据或查空

FCD0 A1 9F AJMP READ_DATA

;05=各种读功能

FCD2 A1 B3 AJMP SETUP_BPS

;06=直接装载波特率

在正确地接收命令后,通过DATA_MODE项(即命令格式中的RR)来判断功能并转入相应的程序。程序中对每一个跳转地址都作出了相应的注释。

4 几点说明

① 上述带源代码的程序均是Boot ROM中反汇编得来的,并且大部分是连续的。这一点可以从地址分布上看出来,读者可以将其合并在一起看,相信可以加强理解。有兴趣的读者也可以参照以上给出的方法将全部代码读出,电路图和源程序几乎都不必重编了。

② Boot ROM中既包括了ISP的程序,也包括了IAP的程序。限于篇幅,只给出了ISP的部分源程序,部分子程序只作了说明而未列出源程序。


关键字:P89C51RD2  Boot  ROM  ISP功能 引用地址:P89C51RD2的Boot ROM固件代码的读出方法和ISP功能分析

上一篇:pid算法温度控制c语言程序
下一篇:单片机C51存储器类型及存储模式

推荐阅读最新更新时间:2024-11-08 11:14

OK6410A 开发板 (八) 52 linux-5.11 OK6410A linux内存管理相关配置
arm32 要不要配置 CONFIG_HIGHMEM 前提为 vmalloc_min 为 0xf000 0000 , 且 内核空间大小:用户空间大小 = 1:3 如果内存 = 768MB 想全部内存做 线性映射 不配置CONFIG_HIGHMEM //配置了也无所谓,如果是 vmalloc(基于vmap)会做映射,这样就是双重映射(同一个物理页,线性映射一次,vmap映射一次) 想一部分内存 做 线性映射,一部分做高端内存映射 配置 CONFIG_HIGHMEM 并将 vmalloc_min 设置为比0xf000 0000更低的值(具体取决于一部分与另一部分的比例) // 举个例子,内存有7
[单片机]
移植u-boot-1.1.6之mtdparts分区
和u-boot高版本不同,mtdparts命令没有cmd_mtdparts这么一个单独的文件来实现。 不过,搜索uboot可以在cmd_jffs2.c里面看到如下代码: 1 U_BOOT_CMD( 2 mtdparts, 6, 0, do_jffs2_mtdparts, 3 mtdparts- define flash/nand partitionsn , 4 n 5 - list partition tablen 6 mtdparts delalln 7 - delete all partitionsn 8 mtdparts del part-idn 9
[单片机]
RAM、SRAM、SDRAM、ROM、EPROM、EEPROM、Flash存储器概念
常见存储器概念:RAM、SRAM、SDRAM、ROM、EPROM、EEPROM、Flash存储器可以分为很多种类,其中根据掉电数据是否丢失可以分为RAM(随机存取存储器)和ROM(只读存储器),其中RAM的访问速度比较快,但掉电后数据会丢失,而ROM掉电后数据不会丢失。 在单片机中,RAM主要是做运行时数据存储器,FLASH主要是程序存储器,EEPROM主要是用以在程序运行保存一些需要掉电不丢失的数据. FLASH:单片机运行的程序存储的地方。 SRAM:存储单片机运行过程中产生的了临时数据。 EEPROM:视用户的需要而定,一般用来存储系统的一些参数,这些参数可能需要修改,也可能不会修改。 ROM和RAM指的都是
[单片机]
U-Boot在S3C44B0上的移植方法
Bootloader 给嵌入式操作系统提供板上硬件资源信息,并进一步加载、引导嵌入式操作系统。由于Bootloader 的功能直接与CPU和微处理器系统相关,所以不同的CPU体系将需要不同的Bootload-er。除了依赖于CPU的体系结构外,Bootloader 实际上也依赖于具体的嵌入式板级设备的配置。也就是说,对于两块不同的嵌入式板,即使它们使用同一种CPU 构建,要想让运行在其中一块上的Bootloader程序也能运行在另一板子上,通常也都需要修改Bootloader 的源程序。 本文作者使用基于ARM7TDMI 核的S3C44B0微处理器构建的嵌入式开发板,附有嵌入式开发必须的一些板上硬件资源,针对性地提供了Bootl
[单片机]
U-<font color='red'>Boot</font>在S3C44B0上的移植<font color='red'>方法</font>
MSP430系列单片机-读RAM数据烧写到Flash中
题目一 从RAM地址0x0200中读取一个long数据,并烧写至地址为0x1800的Flash中。 代码: #include io430.h void main(void) { //初始化RAM信息段的指针 unsigned long * RAM_ptr = (unsigned long *) 0x0200; //初始化Flash信息段的指针 unsigned long * Flash_ptr = (unsigned long *) 0x1800; //存放数据的变量 unsigned long value; WDTCTL = WDTPW + WDTHOLD; //关闭看
[单片机]
S3C2440-裸机篇-07 | S3C2440内存控制器(Memory Controller)
1. 作用 S3C2440的内存控制器作用是:负责向外部扩展的存储类设备提供控制信号。 内存控制器支持的外部扩展存储类设备有: SRAM SDRAM Nor Flash 网卡DMA 9000(类存储设备) 内存控制器不支持nand flash,S3C2440提供了独立的nand flash控制器。 2. 内存控制器拓扑结构 CPU、内存控制器、外部扩展存储器三者的拓扑结构如下: 其中这四种信号的意义如下: 地址信号(总线):作为存储器,其中的每个存储空间肯定有地址,地址总线用来传输地址; 数据信号(总线):用来传输某个地址处的写入数据或者读出数据; 读/写选择信号(控制信号):用来控制向地址处写入数据还是从
[单片机]
S3C2440-裸机篇-07 | S3C2440<font color='red'>内存</font>控制器(<font color='red'>Memory</font> Controller)
Ramtron发布两款 V系列串口F-RAM存储器
非易失性铁电随机存取存储器 (F-RAM) 和集成半导体产品开发商及供应商 Ramtron International Corporation宣布其新的并口和串口F-RAM系列增添两款产品,这些F-RAM器件提供高速读/写性能、低电压工作和可选器件特性。Ramtron的V系列F-RAM产品之最新型款为512Kb FM24V05和1Mb FM24V10,是2.0 V至 3.6V的串口非易失性RAM,采用8脚SOIC封装,使用双线 (I2C) 协议。这两款器件的特点包括快速访问、无延迟 (NoDelay™) 写入、几乎无限的读/写次数及低功耗,是工业控制、仪表、医疗、军事、游戏、计算机及其它应用领域的512Kb和 1Mb串口闪存和串口
[半导体设计/制造]
移植u-boot-2010.03问题 --- 支持dnw
1,下载uboot_dnw源码 https://github.com/plinx/uboot_dnw 2、将cmd_usbd.c拷贝到u-boot-2010.03/common目录下 3,修改u-boot-2010.03/common/Makefile # core command ... COBJS-y += cmd_usbd.o 4,将usbd-otg-hs.h,usbd-otg-hs.c拷贝到u-boot/cpu/arm1176/s3c64xx/ 5,将regs.h,s3c64x0.h 拷贝到u-boot/include/ 6,修改include/configs/smdk6410.h文件,加入下面两句 #define CON
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved