找回密码
 立即注册
查看: 676|回复: 0

STC32G FreeRTOS入门(10):STC32G单片机的Keil C251引导过程简析

[复制链接]

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10904
发表于 2023-8-7 01:33:25 | 显示全部楼层 |阅读模式
STC32G12K128是宏晶公司新推出的基于80251 CPU架构的32位单片机,使用Keil的C251进行代码编译和程序调试。由于80251CPU比8051CPU新增加了两个关键的SFR寄存器“DPXL”和“SPH”,前者将8051的“MOVX”指令的地址范围从16位扩展到了24位,后者将8051。的堆栈指令“PUSH”和“POP”的堆栈空间从8位扩展到了16位。
在标准的Intel  8xC251SA/SB/SQ/SP系列单片机中,它们的定义为(见头文件:$include (reg251s.inc)):
sfrDPXL = 0x84;
sfrSPH  = 0xBE;
但对于STC32G12K128单片机,它们的定义为:
sfrDPXL = 0x84;
sfrSPH  = 0x85;
显然“SPH”的地址是不同的,同时在STC32G的技术手册中“DPXL”的复位值为“00”与Intel的“01”不同。因此一些从8051架构的8位单片机向32位单片机过渡的编程者在学习了解STC32G单片机的过程中产生了一些疑惑,主要集中在下两个问题上:
第一个问题:STC32G的“SPH”的SFR地址与标准的80251不同,是否影响程序的运行,是否影响DEBUG的结果?
第二个问题:STC32G的“SPH”和“DPXL”的硬件加电时的“初值”是否影响程序的正常运行?
笔者认为产生这两个问题的根源在于不了解STC32G单片机的Keil C251引导过程,以为80251CPU硬件与Keil C251编译器软件是深度捆绑的,其实不是。本文将对C251的引导过程进行分析,给出这两个问题的答案。
(1)Keil C251编译器并不与80251的SFR寄存器地址进行捆绑。下图为一个最简单的C251程序和编译效果:
Fig_X01_程序.jpg
在这个程序里,没有加入任何SFR定义的头文件,结果C251编译器将所有这些80251的SFR(包括8051的SP)都认定是未知的,产生严重编译错误。
结论:Keil的C251编译器并没有绑定任何SFR寄存器地址(也包括标准的Intel的80251CPU的SFR地址),因此编程者只需要针对自己实际使用的单片机,包含对应该单片机的SFR地址定义的头文件,C251编译器就能产生正确的编译结果。

(2)C251引导过程对“DPXL”的设置。下图是C251从地址FF:0000加电复位的开始程序:
Fig_X02_DPXL.jpg
从中可以看到引导程序一开始第188行就是设置“DPXL”.然后是对以“EDATALEN”为顶的EDATA区域进行清零,由于WR8循环一直递减到0,因此EDATA区域包括的IDATA区域被清零了。
再然后就是对XDATA区域清零。由于前面已经设置了“DPXL”了,所以第202行的“MOVX”指令能够正确地对XDATA区域进行赋值操作。

第188行的段值“?C?XDATASEG”是由C251的编译环境给出的。项目的目标属性选项页如下:
Fig_X03_RAM设置.jpg
如果下面的扩展存储器选项框中对RAM区域有设置话,就从中计算出XDATA区域的段值赋值给常数“?C?XDATASEG”,如果用户没有对RAM区域进行设置,就将常数“?C?XDATASEG”确定为缺省值“01”。
结论:不管STC32G单片机复位时“DPXL”的值是多少,C251在引导程序的一开始就进行了正确的设置,保证了以后程序的正确运行。
(3)知识点:Keil的C251编译器除了在这里设置“DPXL”的值外,以后不会再改变它的值,这样就保证了整个程序对XDATA区域定义的一致性。或者说除非用户故意(比如用DPXL=0这样的语句),C251对任何C语言程序的编译结果和库函数都不包含改变“DPXL”SFR值的内容。因此如果用户在自己的程序中改变了“DPXL”的值,应该及时保留和恢复它的值。

(4)C251引导过程对“SPX”的设置。下图是引导程序的最后部分:
Fig_X04_SPX.jpg
图中第235行程序“MOV  DR60,#WORD0(?STACK-1)”使用80251的对32位寄存器的低16位用立即数赋值的指令,直接对DR60的低16位SPX堆栈指针赋值。由于引导程序是一次性地直接给16位的堆栈指针赋值,不是分别对SPX的高低8位部分“SPH”和“SP”赋值,因此无论STC32G将“SPH”的SFR地址映射在什么地方,使用C251编译器,都能正确地设置堆栈,不会影响编译结果的正确性。
同时,除非用户指定,C251编译器产生的代码只会对整个“DR60”进行操作,不会也不能对16位的寄存器SPX进行操作,当然也更不会对8位的寄存器“SPH”和“SP”进行单独的操作。
PS:按照C251这个神操作,不但是“SPH”,甚至连“SP”映射在什么地方都无所谓了。
重要提示:在进行DEBUG分析程序时,必须要看整个16位指针的SPX的值,不要分别只看SP和SPH两个8位的值。
(5)对于80251CPU,堆栈是向上增长的。SPX的初始值等于堆栈段“?STACK”区域的首地址。从前面程序的第171行到第174行可以看到堆栈段位于EDATA区域,长度缺省位100H字节。
根据C251的内存分配原则,堆栈段是在EDATA空间中最后一个分配的。如果用户没有自己定义EDATA变量,库函数也没有使用EDATA变量,那么堆栈段从地址“08H”开始(SPX=07H),绕开了R0~R7的DATA地址。
由于80251的寄存器有自己专用的“寄存器空间”,将堆栈位于08H开始的EDATA空间后,寄存器操作与堆栈操作就不会互相影响了。
(6)本文C251引导程序是Keil给出的针对“Intel 8xC251SA”CPU的“START251.A51”文件,它与C51引导程序最大的不同是没有对“PSW”和“PSW1”进行初始化设置。

这意味着C251编译器将C语言编译为机器码时,使用“纯80251指令”,即使对8位寄存器的操作,也只使用“R0~R15”的80251指令,不使用8051的依赖寄存器页映射的指令。
下面是本文范例的程序:
FreeRTOS_010_C251_Boot.rar (22.6 KB, 下载次数: 45)
回复 送花

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2024-5-17 12:47 , Processed in 0.057205 second(s), 32 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表