C8051 F12X中多bank的分区跳转处理

发布者:TranquilOasis最新更新时间:2006-10-08 来源: 单片机及嵌入式系统应用关键字:衍生  单片机  嵌入式 手机看文章 扫描二维码
随时随地手机看文章
在8051核单片机庞大的家族中,C8051F系列作为其中的后起之秀,是目前功能最全、速度最快的8051衍生单片机之一,正得到越来越广泛的应用。它集成了嵌入式系统的许多先进技术,有丰富的模拟和数字资源.是一个完全意义上的SoC产品。

C805IFl2X作为该系列中的高端部分,具有最快100MIPS的峰值速度,集成了最多的片上资源。其128 KB的片上Flash和8 KB的片上RAM足以满足绝大多数应用的需求。使用C8051F12X,只需外加为数不多的驱动和接口,就可构成较大型的完整系统。只是其中128 KB的Flash存储器不可避免地要处理bank分区问题。

幸运的是Keil C51开发环境对C8051F系列有良好的支持,包括一般的跨bank分区的程序跳转和调用。作为数据存储器使用时,Flash的分区读写完全是编程者要考虑的事情,与开发环境无关。本文只针对特殊的强制转移和μC/OS—II在多bank分区中的移植问题展开讨论。


1 C8051F12X在Keil C51中的多bank分区转移机制

Keil C51的连接定位器支持分组连接,允许生成代码长度大于64 KB的8051目标程序_1_。一般的8051系统只提供16根地址线,需要附加地址线来实现代码分组切换,而编译器产生bank切换代码时受到配置文件L51_BANK.A51的支持,所以用户必须根据自己的硬件结构来修改这个配置文件。

C8051F12X系列不用考虑硬件部分,也不存在地址线的扩展问题,因为128 KB的4个bank区全部都在CPU内部,所以作为常规跨bank的跳转和调用,不需要处理1.5l_BANK.A51配置文件。但在特殊情况下就必须考虑该问题,否则程序将无法工作。下面以C8051F120为例先讨论代码的透明分组切换过程。

C805IFl20在Keil C51的项目配置中被划分为4个bank,每个32 KB。公共bank地址从0~0x7fff,其余bank从0x8000h~0xffff。在对应的配置文件L51_BANK.A51中,涉及到特殊功能寄存器PSBANK(SFR地址:0B1H)、SWITCHn宏、B_BANKn、B_SWITCHn分组信息保存和切换代码,以及B_CURENTBANK变量。

PSBANK为C8051F120内的特殊功能寄存器,128KB Flash的分bank访问就是通过它来实现的。要想转移到新的bank中去,必须赋予PSBANK正确的值,然后再转向bank区内地址即可。

SWITCHn宏共有4个,分别是SwITCH0、SWlTCH1、SWITCH2和SWITCH3,对应切换到4个bank中。其中SWITCH0对应的语句为:
MOV PSBANK.#00h ;把00h用1Ih、22h和33h替换,

;就是其他三个宏

它将插入到B_SWITCHn代码中,用来切换新的bank和恢复到原来的bank。


所有4组B_BANKn和B_SWlTCHn代码也都是用宏实现的,对应4个bank处理。它们汇集在BANK SWITCH代码段中,整个bank切换及恢复机制非常巧妙,可以实现任意bank之间函数的相互调用及嵌套。下面以bank3区中的main函数调用bankl区的Delay_noOS()延时函数为例说明该机制。
void main(void){
MCUInit(); //初始化CPU
Delay_n00s(10); //延时lO ms
Lcmlnition();
:
:
bank3中被调用的函数Delay_noOS(10)对应的汇编语句为:
LCALL C:5049
公共段(即Common段,对应bank0)中C:5049处的

汇编语句如下:
MOV dptr,#Delay_noOS
AJMP B_BANKl

这里的B_BANKl就是宏?B_BANK&N中N为1的例程。现在进入问题的核心:全部的跨bank区程序切换及恢复过程依靠公共段中?BANK?SWITCH代码段里的以下汇编代码实现,对应的N为0、1、2和3。BANK?SWlTCH SEGMENT CODE PAGE
;
B_BANK&N:
PUSH B_CURRENTBANK (1)
MOV A,#HIGH BANK SWITCH (2)
PUSH ACC (3)
PUSH DPL (4)
PUSH DPH (5)
B_SWITCH&N:
MOV B_CURRENTBANK,#LOW B_SWITCH&N
(6)
SWlTCH&N (7)
RET (8)

Delay_noOS(10)函数的返回地址,即函数LcmIni-tion()的入口地址(也在bank3中),其高低位字节表示为ADDH和ADDL。程序进入main()后的B_CURRENTBANK变量初值是B_SWITCH3的低8位,其意义稍后叙述。AJMP B_BANKl后程序执行B_BANKl和B_SWITCHl的(1)~(8),执行到(5)时的堆栈结构如图1所示。


继续执行B_SWITCHl到(7)时,PSBANK变为指向bankl,B_CURRENTBANK变为B_SWITCHl的低8位。执行(8)后,从堆栈结构可以看出,堆栈弹出①作为新的PC值,程序进入Delay_noOS(10)函数,延时功能完成后,函数最后一条RET指令开始返回。这是Keil C51处理bank机制的关键,此时的返回地址为堆栈中的②,此地址即B_SWITCH&H代码的入口,这里对应main()函数所在的bank3分组,也就是B_SWITCH3的人口。

因为所有B_SWITCH&N的高8位地址,即BANK SWITCH代码段的高8位都一样,由语句(2)中的操作符HIGH BANK SWITCH确定;低8位保存在已经压栈的B_CURRENTBANK变量中,此时堆栈中的?B_CURRENTBANK压栈值是B_SWITCH3的低8位,这样②的地址就是B_SWITCH3。

程序继续执行B_SWITCH3,在执行B_SWITCH3的(6)语句之前,B_CURRENTBANK还是前面执行B_SWITCHl时的值,即B_SWITCHl的低8位。执行语句(6)后,B_CURRENTBANK恢复为B_SWITCH3的低8位,为返回main函数做准备。然后PSBANK置为33h,即指向bank3,接着执行RET语句,堆栈③成为RET的返回地址,程序回到了main()中Delay_noOS(10)的下一条语句继续执行,B_CURRENTBANK也已恢复。

这个调用过程中,用了6个堆栈字节,3条RET指令,关键内容就是B_CURRENTBANK变量,它保存了可以恢复调用前bank环境代码的地址低位。从被调用函数返回 到这个地址后,就能恢复调用前的bank环境,即赋予PSBANK正确的值。

不采用直接保存PSBANK值然后再恢复,而是用压栈的方式保存了相关地址(语句(1)~(3)),是为了实现跨bank区的嵌套调用。例如,在Delay_noOS(10)函数中,如果再次跨bank去调用新函数,会再次重复上述过程,堆栈从②往上再长6个字节。Delay_noOS(10)函数之前执行B_SWITCHI产生的B_CURRENTBANK值(B_SWITCHI的低8位)也会进栈,为调用完新函数后返回到bankl继续执行Delay_noOS(10)提供保证。


2 无操作系统bank分区间的强制跳转
通过上面的分析得知,如果要处理跨bank区的跳转、调用和返回,关键是能正确处理好PSBANK中的内容。当程序没有操作系统用于任务切换,而又需要强制退出某一函数进入到另一函数的某一地址时,比如说在中断发生后,结束原来的工作转入到另一工作去,就需要处理好PSBANK。

如果不考虑bank,可以在转入新地址之前执行一段代码,保存该地址处的环境变量[2],包括堆栈指针sP和需要的入口地址。然后在中断返回之前,恢复此环境变量,执行中断返回指令进入该新地址。这个思路和C51库函数setjump和longjump比较相近,但比它们灵活,因为环境变量可以自己处理。

考虑bank后的情况稍微复杂些,环境变量中需增加bank的处理信息,那么只处理PSBANK行不行呢?

如果仅保存和恢复PSBANK,则很简单,在保存环境变量的程序中加入:
JMPEnv[envl][3]=PSBANK;

在恢复环境变量的程序中加入:
PSBANK=JMPEnv[envl][3];

这里环境变量是二维数组JMPEnv,envl代表一个环境变量,即一个返回点。第二维是变量中的参数个数。因此可以保存多个环境变量以供使用。

初看起来这样处理是没有问题的,可实际上不行。因为进入返回点后,虽然PSBANK正确了,但是B_CUR-RENTBANK可能已经被修改,不能和返回点程序的bank区匹配,如果再次出现跨bank调用的话将不能正确返回。

处理方法是有点技巧的,因为C语言不支持汇编变量B_CURRENTBANK的写法,所以在L51_bank.A51中要加上声明:
PUBLIC BLCURRENTBANK
和伪指令:
B_CURRENTBANK EQU ?B_CURRENTBANK
这样就可以在C程序中使用B_CURRENTBANK
了,先声明B_CURRENTBANK:
extern Uchar data B_CURRENTBANK;
然后在保存环境变量程序中加入:
JMPEnv[envl][3]=PSBANK;
JMPEnv[envl][4]=B_CURRENTBANK;
恢复环境变量程序中加入:
PSBANK=JMPEnv[envl][3];
B_CURRENTBANK=JMPEnv[envl][4];
这样恢复环境变量进入到新程序后,也将恢复该程序对应的正确B_cuRRENTBANK值,问题得到解决。


3 no/0S-ll移植中的bank分区处理
μC/OS-II的51版本已经很成熟,但是所有移植版本均未处理bank问题,需要增加该内容,否则不能在包括C8051F12X系列及其他多bank程序中使用。

如前所述,Keil C51提供对跨bank调用的透明切换支持,但在使用操作系统时,这种透明切换机制还需要提供对任务切换的支持。因为任务的切换,程序可能需要到别的代码分组中去运行,而此时PSBANK和B_CUR-RENTBANK还停留在原来代码分组中的状态,将导致程序崩溃。显然,无论由于什么情况导致的任务切换完成之前,都需要保存和恢复PSBANK和B_CURRENT-BANK的值。解决的办法是在每次任务切换前将PS-BANK和B_CURRENTBANK压入用户任务栈。

按照μC/OS-II的要求,在任务创建时,任务栈必须初始化成像运行中的任务刚刚发生过中断一样嘲。B_CURRENTBANK的初始值取决于该任务所在分组对应的切换代码段的低8位地址。所以,任务堆栈的初始化函数OSTaskStkInit需要加入一个参数INT8U bank,指明该任务位于哪个代码分组中。又由于任务堆栈的初始化函数是被任务创建函数OSTaskCreate调用的,所以该函数一样需要加入参数INT8U bank。
在压栈,出栈宏中需要加入:
PUSH PSBANK
PUSH B_CURRENTBANK

POP  B_CURRENTBANK
POP PSBANK
在任务堆栈的初始化函数OSTaskStkInit中需要加入:
*stk++=17; //堆栈长度增加2个到17

if(bank==0x22:){ //bank2
*stk++=bank;
*stk++=CurrentBank2();
else if(bank==0x33){ //bank3
*stk++=bank;
*stk++=CurrentBank3();
}
else{ //bankl和common
*stk++=0xll; //PSBANK
*stk++=CurrentBankl();
)

其中,bank0用任何的PSBANK值均没有问题,所以简化了PSBANK取值0x00的情况。

函数INT8U CurrentBankl(void),INT8U Current-Bank2(void)和INT8U CurrentBank3(void)是用汇编语言实现的,返回值通过R7传递,目的是获得该任务所在分组对应切换代码段(SWITCHn)的低8位地址。不用C语言编写的原因同样是B_SWITCH&N不被C支持。
CurrentBankl(void)代码如下,其他两个类同。
RSEG PR CurrentBankl Os_CPU_A
CurrentBankl:
MOV DPTR,#B_SWITCHl
MOV R7.DPL
RET


结 语
本文介绍了Keil C51实现大于64 KB程序的bank分组代码切换机制的原理,提出了没有操作系统情况下非正常转移时bank的处理方法以及μc/os—II操作系统在多bank分区程序移植中应采取的措施,在开发实例中均得到了很好的应用。

关键字:衍生  单片机  嵌入式 引用地址:C8051 F12X中多bank的分区跳转处理

上一篇:单片机在微型打印机中的应用
下一篇:MSP430单片机中的WDT研究

推荐阅读最新更新时间:2024-03-16 12:17

学51单片机-UART口发送一个字符
UART口,又叫做通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),是单片机常用功能的一部分,也是早期台式电脑必备的一个硬件接口。 当年我调试UART口的时候,用的还是超级终端,现在都用串口助手了,比我们当时方便多了。 UART口按位发送和接收字节,虽然相比于并口,慢了很多,但是在有限的IO资源面前,这种方式是非常可取的。 UART口主要用于ASCII码的传输,传输过程遵循ANSI/EIA-232标准。ASCII码是啥?看下表: 就是说,当我想发送字符“A”的时候,我要向串口发送十进制数65,或者十六进制数41。 驱动电
[单片机]
学51<font color='red'>单片机</font>-UART口发送一个字符
学51单片机-UART口发送一串字符
昨天说的是如何通过UART口发送一个英文字母,其实对照那个ASCII码表,大小写字母、数字、标点,还有一些符号都可以发送,只要你找到它对应的编码就行。 今天说一下如何用UART口发送字符串和汉字。 如果按照昨天的思路,发送一串字母或者数字也很好实现,我只要把这串字母或者数字对应的ASCII码找出来,写进一个数组就行了。但是这样还要查表,有点麻烦,今天说一个更简单的方法。 假如我想发送5个字母 A,用昨天的方法,怎么实现?定义一个数组: Uchar table = {0x41,0x41,0x41,0x41,0x41}; //五个字母 A 显得很傻,这次的方法:
[单片机]
学51<font color='red'>单片机</font>-UART口发送一串字符
可监测人体脉搏波及心率的健康鼠标
  脉搏波的波形特征与心血管疾病密切相关,为此用户需要一种简单、实时的便携装置。通过安装在正常使用鼠标时大拇指触摸到的鼠标位置的反射式脉搏波光电传感器采集脉搏波信号,信号经过滤波、放大和A/D转换后,利用单片机对脉搏波信号处理并得出心率数据,最后通过USB接口连接电脑端软件显示。将鼠标和反射式光电传感器结合制成成品之后,经过实际测试,传感器能够很好的测得手指脉搏波并输出。这种可监测人体脉搏波及心率的健康鼠标可以在用户使用鼠标的不经意状态时检测并记录脉搏波及心率。   人体脉搏波中蕴藏着丰富的生理病理信息,大量的临床实测结果证实,脉搏波的特征与心血管疾病有着密切的关系。脉搏波所表现出来的形态、强度、速率与节律等方面的综合信息的确在
[单片机]
浅谈嵌入式软件系统设计中的正交性
1 小波漫谈   小波变换是20世纪最辉煌的科学成就之一,已经广泛应用于信号处理、图像分析、非线性科学、地球科学、音乐雷达、CT成像、地震勘探、天体识别、量子场论、机械故障诊断、分形等科技领域。   20世纪初,哈尔(Alfred Haar)对在函数空间中寻找一个与傅里叶类似的基非常感兴趣。1909年他最早发现和使用了小波,后来这被命名为哈尔小波(Haar wavelets)。20世纪 70年代,当时在法国石油公司工作的地球物理学家 Jean Morlet提出了小波变换 WT(Wavelet Transform)的概念。 进入 20世纪 80年代,法国科学家 Y.Meyer和他的同事开始研究系统的小波分析方法。1985年,Da
[单片机]
浅谈<font color='red'>嵌入式</font>软件系统设计中的正交性
32针STM32微控制器系列产品中增加Nucleo开发板
意法半导体(STMicroelectronics,简称ST;纽约证券交易所代码:STM)持续扩大其STM32 Nucleo开发板组合,新增三款可扩展、可支持32针的小型STM32微控制器开发板。新款STM32 Nucleo-32开发板拥有各种集成开发环境(IDE)的直接支持,允许开发人员直接使用mbed在线资源。搭载STM32微控制器,通过Arduino Nano接口插入各种可用硬件,STM32 Nucleo开放平台有助于简化原型开发过程,从而降低开发成本。 开发人员还可充分利用STM32软件库及STM32Cube开发工具,不仅简化了应用软件的开发过程,更可在不同型号的STM32微控制器之间移植应用设计。STM32
[单片机]
MCU,要掀起AI革命了?
昨日,嵌入式界发生了一件大新闻,IAR宣布与Edge Impulse联手为全球客户提供AI与ML整合功能。 可能,很多人对于这个新闻没什么认知。要知道,Keil和IAR作为嵌入式/单片机开发双雄,IAR在全球拥有超过15万开发人员和4.6万家公司,Edge Impulse这家公司的业务,则是MCU巨头纷纷向往的TinyML。 两家联手,意味着,嵌入式领域,即将掀起一场AI革命。想象一下,未来你所使用的咖啡机,都会使用嵌入式视觉和AI,来帮助制作完美的咖啡。 王兆楠、付斌丨作者 电子工程世界(ID:EEworldbbs)丨出品 MCU未来十年市场,靠TinyML Edge Impluse这家公司的名号很多人
[嵌入式]
<font color='red'>MCU</font>,要掀起AI革命了?
单片机嵌入式系统在远程电网监测系统中的应用
摘要:介绍应用UBICOM公司的SX52BD单片机构建用于远程电网监测的嵌入式系统的具体方案,使基于单片机的测控设备可以方便地连接到以太网,实行电网参数的远程网络监控。 关键词:电网监测 嵌入式系统 为了保证电网的安全运行,了解电网运行状况,需要对电网的各种运行参数(如三相电压、电流、有功功率、无功功率等)进行实时监测。嵌入式远程电网监测系统将现代计算机、通信、网络及自动化技术融为一体,对配电网进行远程监测、协调和控制,从而优化配电网络。利用以太网的丰富资源及UBICOM公司高速单片机SX52BD构建分布式以太网嵌入测控系统是一种低成本、高可靠且快捷的技术方案。 1 系统结构 系统结构如图1所示。监控中心工作人员可通过以太
[应用]
单片机内部密码破解方法
1 引言   单片机(Microcontroller)一般都有内部ROM/EEPROM/FLASH供用户存放程序。为了防止未经授权访问或拷贝单片机的机内程序,大部分单片机都带有加密锁定位或者加密字节,以保护片内程序。如果在编程时加密锁定位被使能(锁定),就无法用普通编程器直接读取单片机内的程序,这就是所谓拷贝保护或者说锁定功能。事实上,这样的保护措施很脆弱,很容易被破解。单片机攻击者借助专用设备或者自制设备,利用单片机芯片设计上的漏洞或软件缺陷,通过多种技术手段,就可以从芯片中提取关键信息,获取单片机内程序。因此,作为电子产品的设计工程师非常有必要了解当前单片机攻击的最新技术,做到知己知彼,心中有数,才能有效防止自己花费大量金钱
[工业控制]
热门资源推荐
热门放大器推荐
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

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