第1 章 体系结构
第1 问:
Q:请问在初始化CPU 堆栈的时候一开始在执行mov r0, LR 这句指令时处理器是什么模式
A:复位后的模式,即管理模式.
第2 问:
Q:请教:MOV 中的8 位图立即数,是怎么一回事 0xF0000001 是怎么来的
A:是循环右移,就是一个0—255 之间的数左移或右移偶数位的来的,也就是这个数除以4
一直除, 直到在0-255 的范围内它是整数就说明是可以的!
A:8 位数(0-255)循环左移或循环右移偶数位得到的,F0000001 既是0x1F 循环右移4 位,
符合规范,所以是正确的.这样做是因为指令长度的限制,不可能把32 位立即数放在
32 位的指令中.移位偶数也是这个原因.可以看一看ARM 体系结构(ADS 自带的英文文
档)的相关部分.
第3 问:
Q:请教:《ARM 微控制器基础与实战》2.2.1 节关于第2 个操作数的描述中有这么一段:
#inmed_8r 常数表达式.该常数必须对应8 位位图,即常熟是由一个8 位的常数循环移
位偶数位得到.
合法常量:0x3FC,0,0xF0000000,200,0xF0000001.
非法常量:0x1FE,511,0xFFFF,0x1010,0xF0000010.
常数表达式应用举例:
...
...
LDR R0,[R1],#-4 ;读取 R1 地址上的存储器单元内容,且 R1 = R1-4
针对这一段,我的疑问:
1. 即常数是由一个8 位的常数循环移位偶数位得到,这句话如何理解
2. 该常数必须对应8 位位图,既然是8 位位图,那么取值为0-255,怎么0x3FC 这种超
出255 的数是合法常量呢
3. 所举例子中,合法常量和非法常量是怎么区分的 如0x3FC 合法,而0x1FE 却非法
0xF0000000,0xF0000001 都合法,而0xF0000010 又变成了非法
4. 对于汇编语句 LDR R0,[R1],#-4,是先将R1 的值减4 结果存入R1,然后读取R1 所
指单元的 值到R0,还是先读取R1 到R0,然后再将R1 减4 结果存入R1
A:提示,任何常数都可用底数*2 的n 次幂 来表示.
1. ARM 结构中,只有8bits 用来表示底数,因此底数必须是8 位位图.
2. 8 位位图循环之后得到常数,并非只能是8 位.
3. 0xF0000010 底数是9 位,不能表示.
4. LDR R0, [R1], #-4 是后索引,即先读,再减.
可以看一看ARM 体系结构对相关寻址方式的说明.
3
第4 问:
Q:在程序移植的过程中,什么代码段处于什么样的模式,这可真是一个困扰人的大难题,
有没有一种标志或办法能够识别"代码段处于什么样的模式"
A:读取 CPSR ,任何时候都是可以读.
第5 问:
Q:为什么保护现场时,总是保护 R0-R3,R12,为什么不保护R4-R11
A:请看一看"ARM-thumb 过程调用标准"这个文档.
第6 问:
Q:请问 mov R1,#0x00003DD0 错误:out of the range of operation 是怎么回事情
我就是想IODIR=0x00003dd0,汇编就是
LDR R0,=IODIR
MOV R1,#0x00003dd0
STR R1,[R0]
编译时候说是超出操作范围
A:使用ldr,mov 的操作数为8 位位图数.
第7 问:
Q:"在ARM7TDMI(-S)处理器内部有37 个用户可见的寄存器:"
问题:"用户可见"应该怎样理解 这37 个寄存器是否是37 个不同的物理寄存器,
例如R8 与R8_fiq 应该是两个不同的物理寄存器吧
A:用户可见是指用户可以通过程序操作的.R8 与R8_fiq 是两个不同的寄存器.
第8 问:
Q:USR 模式,SVC 模式,IRQ 模式分别有哪些限制
A:对于外设操作限制与芯片设计有关.USR 模式不能设置CPSR 寄存器.
用户模式下无SPSR 寄存器,代码可以为ARM,Thumb.
第9 问:
Q:请问"在初始化堆栈时就决定了工作模式"是什么意思 如何决定工作模式的
A:设置CPSR 寄存器.
第10 问:
Q:请问:ARM 汇编程序设计中所谓的"文字池"作何理解
A:可以理解为常量数组,文字池中保存的是常量,这些常量可以是正常的常量,也可以是
地址.
4
第11 问:
Q:为什么在中断向量表中不直接LDR PC,"异常地址".而是使用一个标号,然有再在后面
使用DCD 定义这个标号
A:因为LDR 指令只能跳到当前PC 4kB 范围内,而B 指令能跳转到32MB 范围,而现在这样
在LDR PC, "xxxx"这条指令不远处用"xxxx"DCD 定义一个字,而这个字里面存放最终异
常服务程序的地址,这样可以实现4GB 全范围跳转.
Q:LDR 不是可以全空间跳转的吗 《ARM 微控制器基础与实战》程序清单5.3.
A:LDR 伪指令通过设置指令缓冲池才能实现全范围跳转,而LDR 指令则只能实现4KB 范围
跳转.
第12 问:
Q:ARM7TDMI-S 和ARM7TDMI 有何区别
A:ARM7TDMI-S 是ARM7TDMI 的可综合(synthesizable)版本(软核).
对应用工程师来说,除非芯片生产厂商对ARM7TDMI-S 进行了裁减,
否则ARM7TDMI-S 与ARM7TDMI 没有太大的区别,其编程模型与ARM7TDMI 一致.
第13 问:
Q:DCD 伪指令的疑惑.
"StackUsr DCD UsrStackSpace + (USR_STACK_LEGTH - 1) * 4"
这句话是什么意思 DCD 后面的程序标号或数字表达式是何意
A:它的内容是初始化递减堆栈的最高地址,看《ARM 微控制器基础与实战》2.3.2 节.
5
第2 章 编译器与语言
第14 问:
Q:00254: Unimplemented RDI message 是什么错误提示 我的设置连接都正常,是不是
芯片烧了
A:是JTAG 的问题.可以先使用ISP 操作试试就知道了,如果能ISP,说明LPC2104 没有损
坏,还能正常运行程序.
第15 问:
Q:请教:我在调试程序的时候在AXD 中出现这样的提示信息:
RDI Warning 00159:could not open specified device port.
我是根据配套教程的步骤设置的.
A:请按照光盘/easyarm_drive/readme.txt 安装驱动程序.
第16 问:
Q:我用实验程序运行经常出现下列信息! 程序不能下载到目标板.
Warnning! interrupt vectors data is not correct!
Program you downloaded can not run freely!
A:1.仿真器配置一定要正确,即"EasyARM Configuration"设置窗口中的"FLASH"项中选择
"Erase Flash when need";
2.向量表累加和要为0;
3.可以先在RAM 调试一个程序(运行),然后STOP,再使用File->Load Image...加载要
下载到FLASH 的调试文件.
第17 问:
Q:在ADS 中是否可以进行软件调试基于UCOS-II 的程序
A:ADS 软件调试只能调试ARM 的内核,不能调试外设.但是取消 PLL 锁定检测后,
可以调试任务切换,最终到空闲任务上.开始移植时软件仿真是最好的工具.
第18 问:
Q:ARMulate 软件是干什么的 2104 不是用EasyJTAG.dll 来仿真吗
A:软件仿真只能仿真 ARM 核.
第19 问:
Q:有关LPC2106.INC 的问题.我无法在project 引用lpc2106.inc 文件,只能引用lpc2106.h
文件, 这是什么原因 且当我的主程序用汇编编写时,不能引用lpc2106.h,用
lpc2106.inc 则无法加入project,请问汇编器应如何设置
A:不用加2106.inc 只要该文件在你的工程文件夹中,就可以直接在汇编程序的开始处加
6
"include 2106.inc".
注意:该文件是汇编文件定义的头文件,定义内部寄存器.
第20 问:
Q:入口点是什么意思 我在使用LPC2106 上移植UCOS-II,每次MAKE 时总是提示我
Image does not have an entry point,可是我是把光盘的vetctors.s 复制过来的,
而且仔细看了看,已经声明了ENTERY,这是怎么回事
A:需要在ADS 中设置入口.
第21 问:
Q:请教:如何定义不被初始化变量
A:让编译器不知道有这个内存地址即可.
A:如用分散加载文件分配RAM 故意预留一部分RAM 不分配,用它来存您不需要初始化的东
西.或者不调用编译器提供的启动代码,不过这样可能编程会麻烦一些.
第22 问:
Q:我直接通过JTAG 口下载EasyArm 板带的Ext1_test 程序到ARM 中,出现中断向量的告警:
interrupt vector is not correct arm is not running freely.
果然复位后芯片不能运行.但是我用串口下载后芯片能正常工作,中断也行的.
并且我用JTAG 仿真的话,芯片能正常工作,中断也行的,唯独JTAG 口下载不行.
不知道是什么原因
A:仿真器配置中要设置Erase Flash when need.也可以这样试试:
1.可以先打开一个工程在RAM 中调试运行;
2.stop 程序;
3.使用File->Load Image…重新加载Ext1_test 生成的*.axf 文件.
Q:仿真器配置中我是设置了Erase Flash when need,但照你说的话,那不是在RAM 下调
试吗
在RAM 下调试我是可以的,但是下载后出现interrupt vector data is not correct.
我又看了几篇文章,是不是跟中断向量表的累加和不为零有关系啊
A:是的,是向量表的累加和不为零.
因为如果用ISP 下载能运行,说明向量表的累加和已为零,而用JTAG 下载不能运行的情
况可能是 没有正常下载代码.先在RAM 中调试,目的是为了后面正确下载程序到
FLASH.
第23 问:
Q:用Scatter 怎样将某个函数或文件定位在Flash 的某个位置
A:参考http://www.zlgmcu.com/download/downs.asp ID="1009"
7
第24 问:
Q:我在仿真时遇到这样的提示:
Error, Flash is protected by user configation!
怎么写到flash 里面呢
A:看配套《ARM 微控制器基础与实战》附录一.
第25 问:
Q:我在移植实验中想到了两个问题,如下:
1.Debug 和Release 以及DebugRel 有什么不同,为什么在作2104 移植实验时,要用
Release
2.在Release 中为什么要将RW Base 设置为0x40000040 我将其设置为0x40003000,
为什么不能工作
A:都只是一个问题,内存空间的使用,因为跑OS 要比较大的内存空间,所以要腾出点地方.
第26 问:
Q:请问没有MMU 的ARM 芯片是否支持使用malloc()函数动态分配内存
A:是否支持malloc()函数与芯片没有多大关系,主要与编译器有关.
Q:再问:如果没有操作系统支持呢
A:也支持.
第27 问:
Q:在I2C 实验程序中,我想查看数据缓冲区DataBuf 的值,怎么查看
A:watch 窗口或鼠标停留在要查看的变量名上.
Q:我查询的是写入DataBuf 缓冲区的值,鼠标在上面根本就不会出现他的值,即使在watch
中加入,
结果也是"name not found".
A:变量被优化,调试时可以把该变量定义为全局变量查看.
第28 问:
Q:仿真软件和2104 开发板连接不上
DBE Warning 00041:
!An unspecified Debug Toolbox call failed
电源和开发板都连好,错误和没接开发板一样,驱动也安装了,安装时按确定键时,软
件很长时间才有如上反应,请帮忙
A:1.并口是否正常
2.在其它操作系统(如98)下或其它台式PC 下试试.
第29 问:
Q:如何生成32 位hex 文件
8
我在Release Setting->ARM fromELF->Output Format 中设置为Intel 32bit HEX,可
是好像没有生成hex 文件
A:试试这种方法:
Target-->Target Setting-->Post Link 中选择"ARM fromELF"加上你上面设的应该不
成问题.
第30 问:
Q:请问关于settings 中r0 base rw base 的意思
A:ro:read only,rw:read and write.
第31 问:
Q:编译成功后的信息第一行,code,R0 data,RW data,ZI data,debug 分别代表什么
A:R0 只读段,即程序代码空间;
RW 可读/写段,即数据变量空间;
ZI 清零变量段,即需要清零初始化的数据变量空间.
第32 问:
Q:如何在ADS 里面看任务执行的一些情况 比如堆栈.
A:多任务环境下的堆栈,内存等信息需要调试软件的支持才可以实现.
ucos 下有一个统计功能的模块可以间接实现部分功能.
第33 问:
Q:请问向flash 烧数据时出现:exceeds flash limitation 请予赐教!
A:要写入的flash 地址超过了范围.如果不是代码太大的问题,可以检查scf 文件是否正
确.
第34 问:
Q:在LPC2214 之类的芯片中如何实现数组的绝对地址定位,比如51 的_at_的用法.
A:*((char*)0x40000300)类似访问
Q:谢谢,但这样做就无须定义数组变量,访问也不便,还有高招吗
A:可以使用分散加载.
第35 问:
Q:请问 ADS 编译错误"L6221E:Execution region ER_RO overlays with Execution region
ER_ZI" 该如何解决
A:请用我们网站上的工程模板试一试,最大的可能是因为你的RELEASE 或者DEBUG 选项里
面没有正确设置,按照参考《ARM 微控制器基础与实战》上面的设置,是不会有这个问
题的.
9
第36 问:
Q:请教一下:将程序写入flash,再用从JTAG 方式调试写入之后再复位程序没什么反映.
看了很多以前的帖子,说memmap 寄存器要为1,我用的是一个很简单的控制led 的例子,
改动了参数之后写入flash 的.在这个程序的vectors 中找不到关于memmap 寄存器操作
的部分啊,这是怎么回事,该怎么办呢
A:《ARM 微控制器基础与实战》上附录有"常见问题",列举了几点程序写到FLASH 不能运
行的原因. memmap 操作可以在target.c 中的TargetResetInit()函数内添加.
第37 问:
Q:HEX 文件.EASY2100 配套《ARM 微控制器基础与实战》上讲:把项目编译成HEX 文件,
我不会呀,咋办
A:Target-〉target settings 设置Post-linker 并且设置Linker-〉fromELF.
Q:再问:我用的是光盘里的例子,打开工程项目里是DebugInARM.DebugInFlash.
RelInFlash.不是《ARM 微控制器基础与实战》上的DebugRel 呀,我都照《ARM 微控制
器基础与实战》上设置的,可用ISP 下载,提示无法找到HEX 文件.
A:光盘上的例子是用专用工程模板建立,已经设置好参数,与默认模板不同.
第38 问:
Q:EasyARM2100 开发板如何通过JTAG 接口下载到Flash
我在用EasyARM2100 开发板时JTAG 接口不能进行Flash 中的调试(DebugInFlash),但
是可以在RAM 中调试(DebugInRAM),且通过ISP 编程可以写入Flash.
通过JTAG 接口进行DebugInFlash 调试时,总是出现如下提示:
Flash Sector 0 write failed!
Warnning interrupt vectors data is not correct!
Program you downloaded can not run freely!
请问是什么原因 我该如何办
A:仿真器设置选项有一个允许擦除FLASH 的选项,选择它.
第39 问:
Q:我发现程序在RAM 调试时(RO=0X40000000) OK,但是JTAG 下载到FLASH(RO=0X00000000),
显示如下:
The session file 'c:/Documents and Settings/jan/default-1-2-0-0.ses'
could not be loaded.
A:这是ADS 自身的问题,请不要通过IDE 运行AXD,而是通过开始菜单运行,然后Load 调
试文件调试.
第40 问:
Q:我有几个问题想问问大家.
10
调试主机负责对ARM 源程序进行编译链接,最好用什么样的高级语言对ARM 源程序进行
编译链接 使用调试程序(如AXD)进行JTAG 调试,AXD 是什么调试程序,是否是类
似什么软件之类的 到哪能下载AXD 的调试程序呢 怎么样进行AXD 程序进行JTAG 调
试
如何通过JTAG 仿真器发送到目标机上呢
对于单片机的调试,都用到了什么软件
都个有什么作用呢
A:可以使用 ADS1.2,Keil C 也支持.AXD 是ADS 的一个组件.
您可以在本公司网站下载 EasyARM2100 开发套件快速入门看一看.
第41 问:
Q:EasyARM2100AXD 调试时出错,故障现象:
按照光盘上的方法设置好ADS1.2 后打开光盘上的expamples/gpio/c/LedDisp 的工程文
件(从光盘上拷贝到硬盘,已去处只读属性).
编译通过后,按Debug 按键运行调试,进入AXD.按Go 按键,EasyARM 没有反应.再按
Stop 按键.
AXD 弹出两个确认框窗口:
"No disassembly could be read at the requested address".
如果进入AXD 直接按Step 按键,也是会弹出同样的两个确认框.
软件是光盘上的,没有经过任何改动.光盘上的程序试过4,5 个都是这种情况.
AXD 的设置是按照光盘上的说明设置的.
EasyARM 上的JP8 是断开的.ADS 在出现这种问题后重新安装过,故障依旧.
出现这个问题前,可以调试.只是单步的时候感觉比较慢.差不多1-2 秒钟才能单步一
次.
A:原因找到了,是芯片被加密了,无法写入新的程序,用FLASH ISP 清除后解决.
加密后JTAG 完全不能控制芯片,否则可能被解密.
第42 问:
Q:我板上的lpc2214 开始可以在线编程,只搞了两三次可以把文件写进去.但我发现P0.14
未置低电平时也进入ISP 模式,烧入的文件原来可以ISP 下载到2014 开发板中运行的.
最后只能读芯片的一些ID,载文件都不能进行.以下是对整片ERASE 时,对串口的捕获,
命令返回是19.
Synchronized
Synchronized
OK
11059
OK
U 23130
0
P 0 14
0
E 0 14
11
19 configure tar... -> ARMUL , 只能仿真ARM 核外设不能仿真.
第48 问:
Q:为什么盘中的工程会出错啊
A:文件的只读属性去掉了吗
第49 问:
Q:您在2104 的《ARM 微控制器基础与实战》中提到ucos 与应用代码分开编译,在分开编
译调试成功之后,最后要将代码统一固化到芯片中.在最后一步需要注意什么 统一编
译时感觉要改动很多东西,有没有什么最简单的办法 能否详细介绍一下方法 多谢!
A:使用我们的工程模板,可在本公司网站下载.其实不分开编译也可调试.
http://www.zlgmcu.com/tools/kaifaban/EasyARM2104.asp
的EasyARM2104 开发套件快速入门和LPC210...
第50 问:
Q:请问,我的2104 板子,通过EasyJTAG 仿真时,在AXD 上没有文件,而且出现这样
"Error, Flash is protected by user configation!"
的提示,这是怎么回事啊 在AXD 应该打开什么类型的文件啊 谢谢啦!!!!
A:在仿真器的配置窗口设置仿真器允许擦除FALSH.
AXD->Options->configure target->configure->erase……
13
第51 问:
Q:关于arm 汇编语言跳转指令的特殊用法.有如下两条跳转指令:
beq lablef
beq lableb
其中lable 为某段程序的标号,beq lablef 表示向前跳转到与当前指令最接近的标号
lable 处执行,而beq lableb 表示向后跳转到与当前指令最接近的标号lable 处执行.
在arm 汇编中有定义这样的用法吗
A:没有.
第52 问:
Q:我将一段程序从flash 从复制到了RAM 中,但是因为混合编程中不能直接向PC 寄存器中
赋值来实行跳转,这样我该如何跳转到这个RAM 中的地址呢
A:用函数指针.可参考IAP 例子.
第53 问:
Q:我想详细的了解一下ADS 开发工具中的stack.s ,heap.s 和startup.s 中代码的含义,
各位高手推荐本书或给解释一下
A:开发套件用户指南的第3.1.3 节有说明.
stack.s 定义了系统模式堆栈的起始地址.
heap.s 为初始化库函数的堆,是按ADS 的编译器要求编写的.
startup.s 向量表及初始化代码,是根据CPU 来编写的.
第54 问:
Q:我不知道所选择的C 文件到底是用ARM 还是THUMB 编译的,请大侠指点!
A:看配套《ARM 微控制器基础与实战》7.1,7.2,7.3 节.
第55 问:
Q:我重新建立了一个工程,没有用模板,TEST.C 程序在编译的时候提示OS_EVENT 没有申
明,但是我看了代码,TEST.C 中包含了CONFIG_EX.H,而congif_ex.h 中又包含了
include_ex.h, include_ex.h,这两个头文件又包 含了ucos_ii.h,而OS_EVENT 是在
ucos_ii.h 中申明的,不知道为什么会出现这种错误,能不能给我一个比较合理的目录
结构
A:请参考我们光盘的目录结构.最好使用我们的工程模板.
第56 问:
Q:请问,我现在做2114 的产品开发.出现以下问题,特向您请教! 问题:
我们开发的产品要采样,采用周期固定.于是我们采用timer0 进行时钟触发,利用触发
中断程序 每隔10 毫秒采样一次并显示波形.这都能很好的进行.但是在中断程序里
面对几个全局变量赋值, 跳出中断后却不能使用该全局变量.很是头疼!请赐教!!
14
框架如下:
uint8 a; //全局变量
void __irq funtimer0()
{
...
a=0; //在中断函数里面对全局变量赋值
...
}
void fun1()
{
uint8 i;
i=0;
.......
i=a; // 出错位置,在调试过程中运行到当前位置,鼠标移动到变量a 上
// 显示数值是0,但是不能传给i,i 的值不会随该命令改变.
......
}
因此,我在中断函数中采集到的数据放到全局数组中.采集完成关中断后在用户模式下
的程序中来处理该数组,但是该数组中的数据也不能使用!全局数组变量占1000 个字节,
IRQ 堆栈长度是256.
A:全局变量用volatile 声明.
第57 问:
Q:在AXD 里打开Debuger Internals,在Variable Name 里为什么没有PINSEL2,ADDR,ADCR
等寄存器 要在哪里设置
A:有些片内外设寄存器是不能读出,《ARM 微控制器基础与实战》上的P33 页有说明及处理
方法(在Memory 窗口写入相应寄存器地址).
第58 问:
Q:请问不连easyArm 板可不可以直接软件调试程序
我是指如果想直接调软件部分,能不能在ads 或axd 里直接调试
A:这和板子没关系啊,你直接选ARMulate 不就行了,注意把等待PLL 配置完那条语句屏蔽
就可以啦!
第59 问:
Q:AXD 里面出现 "RDI Warning 00159: Could not open specified device port"
谁能告诉我这个是问题啊我一直搞不懂啊,全部是按照《ARM 微控制器基础与实战》第4
章上配的图做的啊,但是就是不能仿真啊.
A:请先按照光盘的easyarm_drive/readme.txt 安装驱动程序.
15
第60 问:
Q:1.在《ARM 微控制器基础与实战》的2.6.3 节有说到"浮点数寄存器(F0-F7...)",2104
是否具有这些寄存器
2.如果EasyArm 不支持浮点运算,而我的程序需要用到浮点运算,请问可以实现吗
A:1.没有.
2.用C 就可以用浮点运算.
第61 问:
Q:EASYARM2104 的例子程序怎么都是调用C 写的程序,汇编那个怎么没用的啊
A:按如下步骤进行处理:
1.在项目管理窗口中删除原来的所有文件;
2.在项目管理窗口中增加汇编文件*.S;
3.编译链接,调试.
第62 问:
Q:请问版主:在AXD 调试软件中,我单步运行到一定时候,我想让自己编的软件从复位处
重新运行, 在AXD 软件中,EXECUTE 栏目中有单步,连续,运行到光标处等功能,但
无复位功能,如果要实现此功能,如何操作
A:我也没有发现,目前只能用重新装载的操作实现.
第63 问:
Q:在AXD 调试中,通过从jtag 接口,连接上lpc2106,出现如下信息:
TKSimulator for ADS, V1.2, 2003/08
Software Supplied by: ZLGMCU
ARM7TDMI-S, Little Endian
在从file|load imgage...文件,出现两种情况:
1.正常,完全能调试;
2.出现问题,如下:
RDI Warning 00254: Unimplemented RDI message
请问,这是错在哪里 如何解决 谢谢!
A:可能是电源或其他接插件接触不良引起.
第64 问:
Q:请教几个问题:
1.移植中底层接口里的__swi 关键字在SDT 中能用吗
2.为什么在勘误文档中时钟节拍服务子程序里去掉了开中断及关中断的宏
3.时钟节拍中断的优先级应该设为最高吗
16
A:1.不知,请自己看一看软件自带文档.
2.因为中断服务程序中肯定是关中断的.
3.不必.
第65 问:
Q:arm 汇编中的中括号是什么意思 比如下面的例子中括号是什么作用呀
[ PLLONSTART
ldr r0,=PLLCON
ldr r1,=((0xe8<<12)+(0x4<<4)+0x2)
str r1,[r0]
]
A:等效于:
IF PLLONSTART
ldr r0,=PLLCON
ldr r1,=((0xe8<<12)+(0x4<上电->启动AXD.现象:数码管能
显示不断变化的数字0--F,但是AXD 的连接失败,提示"DBE Warning 00041: ....".
重复试了几遍,现象相同.
请教原因以及对策.
A:刚才把我机器的Win2K 系统的用户属性从"PowerUser"修改为"Administrator"就没
问题了.可能是ADS/AXD 安装的时候用了Administrator 权限,在"PowerUser"下工作
有问题吧.
如果哪位老兄有类似问题,不妨试一下这个方法.
第67 问:
Q:在Init.s 中有这样一段:
Reset
BL InitStack ;初始化堆栈
BL TargetResetInit ;目标板基本初始化
B __main ;跳转到c 语言入口
谁知道__main()函数的具体内容
假如我不需要调用库函数的话,是否可以改为B main
A:看调试是汇编代码里有__main(),组成成分与一些链接选项有关.
可以.但是全局变量初始化不了.
17
第68 问:
Q:我在C 中嵌入这样一条语句
__asm
{
MRS R4,CPSR;
STMFD SP!,{R4};
ORR R4,R4,0x80;
MSR CPSR_cxsf,R4
}
会出新报错"illegal write to sp"版主和各位大侠有什么办法解决阿
A:嵌入汇编不能使用SP.
第69 问:
Q:请问 ADS 如下的编译错误是什么意思
L6221E:Execution region ER_RO overlays with Execution region ER_ZI
A:程序段内存分配可能有问题,RO(只读),ZI(0 初始化)
第70 问:
Q:在axd 中有没有运行程序的时间计算器 keil 中就有那样的东西.
A:有的,不过不是时间而是执行周期,可以换算成时间.在debugger internals 中,具体
可以参考帮助文档.
第71 问:
Q:我最初的init.s 中没有加入heap 的分配和__user_initial_stackheap 函数,结果程序
跳到SWI 中死循环.我把他们加入后就好了.或者不加入他们,把B __main 改为B main
也可以.请问何解 另外,就算目标板会陷入死循环,但是用软件仿真却可以正常运
行.何解
A:堆的位置没有分配到有效的RAM 中.
第72 问:
Q:在ARM 汇编语言中,对立即数的有要求,我记得原来没有这样一说了.现在反而糊涂了,
用立即数时候,很小心很忌讳,不回象51 下随心所欲的使用了,有对立即数熟悉的朋友
站出来给大家释疑.
A:如使用"非法数据可以使用lrd 送到寄存器"的方法.
首先在存储器中定义一个常量,再ldr 进去,编译器是这样弄的.可以看下面语句反汇
编的区别;
int z="0x101";
int z="0Xff";
18
第73 问:
Q:请教各位:我在AXD 中单步运行一段程序后,想回到程序的开始重新运行,除了重新加
载,
还有其他方法或按键
A:你的程序有多大 程序在Flash 运行点击Reload Current Image 也不需要1 秒吧~
或在代码窗口Set PC="0"
第74 问:
Q:在《ARM 微控制器基础与实战》程序清单6.22 的376 页的OSIntCtxSW_1 中:
LDR R4, [R6]
ADD SP, R4, #68
LDR LR, [SP, #-8]
MSR CPSR_c, #(NoInt | SVC32Mode)
MOV SP, R4
LDMFD SP!, {R4,R5}
LDR R3, =OsEnterSum
STR R4, [R3]
MSR SPSR_cxsf, R5
LDMFD SP!, {R0-R12, LR, PC }^
请问高手:LDMFD SP!, {R0-R12, LR, PC }^是不是恢复新任务工作寄存器和工作模式,
LR 寄存器一并得到恢复,那么ADD 指令后面的 LDR LR, [SP, #-8] 指令是不是可
以去掉
A:两者恢复的是两个不同处理器模式的LR.
第75 问:
Q:既然option 页中的Image entry Point 填入的是调试入口地址,那么在实际的程序运行
当中它是不会 覆盖代码中的ENTRY 入口声明的,对吗 仅仅是为了调试的方便.
A:Image entry Point 优先.其实代码中的ENTRY 是为了确保代码不被优化掉.
第76 问:
Q:我想使用标准C 语言的库函数,比如memset 在string.h 中有定义,可是我直接包含
#include , 但是编译没错误,运行确有错误,应当怎么设置
A:请使用最新的工程模板
第77 问:
Q:软件中断是不是必须由SWI 指令触发
A:可以直接用你定义成软中断的函数名啊.比如:
19
__SWI(0x12) void myswi(void); // 声明函数
__asm // 调用方式1
{
swi 0x12
}
myswi(); // 调用方式2
第78 问:
Q:《ARM 微控制器基础与实战》程序清单6.9 的程序是在哪里被调用的
_user_initial_stackheap
LDR r0,=bottom_of_heap
MOV pc,lr
A:__main.千万别删哟, 否则出大事的.
第79 问:
Q:"LDR R0, =PINSEL0" 中"="是什么意思 这语句是取地址还是取地址中的内容呢
A:这是LDR 伪指令,可用来加载32 位立即数或地址,LDR R0,=PINSEL0 是将PINSEL0 的地
址加载到R0 中.
第80 问:
Q:我不明白"SWI 0"和"SWI 0X123456"这两条指令中的0 和0X123456 中有何用.
有没有应用SWI 的具体例子让我看看
A:那是特定的中断入口地址,见ADS_DeveloperGuide_D.pdf 下的swi.
第81 问:
Q:SWI 的功能表吗
A:SWI 的功能表由swi 异常服务程序决定.很多时候由编程者自己决定.
第82 问:
Q:请问:我在实验您的原代码进行ucos 移植时用的是例1,但是在按照图7.17 设置处理
器的仿真器模式时enable comms channel view 和semihostin 项为不可激活状态.为
什么,能否给一点提示
A:在一些仿真器上使能了它们会影响swi 异常处理程序.
第83 问:
Q:请问"Unimplemented RDI message"这个出错提示是什么意思啊
20
还有,有的时候当我用axd load 一个.axf 文件时,常常loading 的没完没了,这是怎
么回事啊
A:Unimplemented RDI message:为命令操作失败,需要重新连接.
下载不结束为出现不正常现象,请重新连接并下载.如果每次都出现该现象请联系我们
的技术支持.
第84 问:
Q:各位高手好,我是ARM 初学者我在程序调试中"LDR PC,[PC,R2]"命令执行后PC 为什么
=0x0000000c, 在这条命令执行前PC+R2 地址上的值是0x0000000c 吗
A:要使用软件仿真.0x0000000C 是预取中止了.
Q:请问:ARM7 在初始化CPU 堆栈时,寄存器CPSR 和CPSR_c 有什么关系 CPSR_c 是在那里
定义的
A:这是MSR 指令的语法,"_"后部分指定CPSR 的域,请参考《ARM 微控制器基础与实战》
上关于这条指令的说明.
第85 问:
Q:软中断SWI 作底层接口的问题.以下函数为啥要通过软中断调用,可以直接调用吗
OS_TASK_SW(),
_OSStartHighTdy(),
OS_ENTER_CRITICAL),
OS_EXIT_CRITICAL(),
A:在用户模式或Thumb 状态不能直接调用.
第86 问:
Q:ARM 的一条指令是32bit 长, 但有时一个立即数也是32bit, 这是如何解释的
A:指令中使用的立即数需要时8 位数移位获得,并非所有数都可以.
第87 问:
Q:请教:全局变量的值在复位(不断电)后会不会自动清零 (用光盘自带的启动代码)
A:在C 语言中一般会会初始化0 或用户指定的值,但这不是硬件自动的.
第88 问:
Q:the setting files for *.mcp is locked!是什么问题
A:文件属性只读.
第89 问:
21
Q:请问,关于printf() 在ads 中怎么用不了 谢谢!
A:请用我们我们网站上下载2104 的工程模板,它解决了这个问题.
即使这样,也不能真正使用prinf.您还需要自己编写一些底层函数才能使用,详细参
考ads 自带的ADS_CompilerGuide_D.pdf.
第90 问:
Q:swi 的功能号是如何来的 它和LR 寄存器的值是何关系
如《ARM 微控制器基础与实战》程序清单6.13
LDREQ R0,[LR,#-4] ;BICEQ R0,R0,0xff000000
A:LDREQ R0,[LR,#-4] ;用来读SWI 的代码
BICEQ R0,R0,0xff000000 ;是ARM 方式进入,取低24bit
第91 问:
Q:请问在TargetInit()中函数开始会执行srand((INT32U)TargetInit),它是做什么用的
A:ex1 用它来产生随机数种子的.
Q:请问:我建立的工程中,所有源文件与2104 附带的光盘例子源文件相同,编译链接也一
切正常, 可就是不能到板子上跑!
提示错误是:向量中断有错误,无法自由运行!!
这是怎么回事 相同的源文件,加在你的工程里,正常;加到我的工程中就出错!
我创建的是ARM 可执行映象.
A:vector.s 你自己的吗 如果是要计算向量去的累加和了.
第92 问:
Q:请问:vectors.s 中"DCD 0xb9205f80" 的0xb9205f80 在实际运用中需要改动吗
A:不需要更改,除非改动了向量表中的指令代码.
第93 问:
Q:请问,为什么queue 数据队列,《ARM 微控制器基础与实战》上给画成了环形
A:因为头跟尾的指针指向一个地址,队列逻辑上是环状的.
第94 问:
Q:有没有人成功的把一个数据定义到程序空间里 各种方法我都试了,是不是有什么编译
开关
A:使用const 修饰,定义变量时带初始化值,要定义为全局的变量.
第95 问:
Q:ads 里没有CODE 关键词,怎样使定义的字符串数组不占用RAM 空间
22
A:const unsigned char string[]
第96 问:
Q:在例程中TIME_test 中的TIMEOUT 当写入时提示:
Warnning! interrupt vectors data is not correct!
Program you downloaded can not run freely!
我不知怎样改设置,哪位提醒一下
A:中断向量表的校验和不为0,用AXD 看0 地址的数据(32 位方式),自己加一下.注意把
高于32 位的部分去掉.
第97 问:
Q:请教各位:我做TIMEOUT 实验(2104 板),Make 通过,Debug 时出现了如下错误提示:
Warnning! interrupt vectors data is not correct!
Program you downloaded can not run freely!
设置Link:ARM Link
r0 base:0x00000000
rw base:0x40003000
image entry point:0x00000000 其它的没变!!
而我使用ISP 完全可以下载而且可以运行!这可以说是设置问题,但是我实在找不到!
怎么办
A:请看一看配套《ARM 微控制器基础与实战》附录1,ISP 软件可能对它进行了处理,而JTAG
没有特殊处理
第98 问:
Q:*(volatile unsigned int *)是什么意思 例如*(volatile unsigned int *)addr 具体
是什么意思
A:分开来看,(volatile unsigned int *)就是定义一个可变的无符号整形指针,前面的那
个*就是取起内容.
第99 问:
Q:如何理解#define VICIRQStatus (*((volatile unsigned long *) 0xFFFFF000))
A:宏定义,参考C 语言的书籍.
(volatile unsigned long *) 0xFFFFF000 将0xFFFFF000 强行转换为指针,然后 *(指
针) 即可对此地址进行访问.
第100 问:
Q:在异常处理向量表的设置中,为什么不直接将异常向量的入口地址写入PC 中呢,为什么
非要用什么DCD 这些伪指令,到底有什么用啊
A:为了保证任何时候其累加和为零,不然改一次程序就要计算一次.
23
第101 问:
Q:单步调试i2cINT.C 在ISendStr 中启动总线后,程序怎么又跑到vectors.o 中,进行初
始化了呢
A:由于VIC 的限制,程序不能在0x18 停下来,否则执行非向量中断.如果没有设置,则非
向量中断为0,将从0 地址执行.
建议:有中断时不要单步执行程序,可以手动暂时关中断或设置断点代替单步.
(编者注:下载最新的驱动可以解决这个问题)
第102 问:
Q:请教:如何修改 ADS 的启动代码,从__main 到main,按道理应该有一个文件,修改这
个小文件, 就可以修改 启动代码.
A:__main 是ADS 运行库,最好不要修改,要是不使用库就不要用main()函数,起个别的名
字.直接跳转过去就行了.
详见:《ARM 体系结构与编程》P328.
第103 问:
Q:我在JTAG 仿真时出现的对话框,提示:
Warnning! interrupt vectors data is not correct!
Program you downloaded can not run freely!
A:参见《ARM 微控制器基础与实战》附录一第一个问题的第二部分,选择源代码的启动代
码文件夹下的vectors.s,并参照《ARM 微控制器基础与实战》图7.11 设置.
第104 问:
Q:初始化代码中分配堆栈的问题
MSR CPSR_c, #0xd3 ;进入特定的处理器模式
LDR SP, StackSvc ;给当前处理器模式的堆栈指针赋值,这只是一个值而已,
;他在接下去的DCD 语句赋值
SvcStackSpace SPACE SVC_STACK_LEGTH * 4
这个语句开辟一个SVC_STACK_LEGTH * 4 大小的内存,SvcStackSpace 是这块内存的标
号,我想应该就是内存的首地址,这样应该好理解了.
StackSvc DCD SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4
这个语句就是把这个首地址加上堆栈大小值.
A:计算出堆栈指针来,我想这个堆栈是向下生长的,所以SP 赋值的是堆栈地址最高的那个.
第105 问:
Q:请问启动代码中这句是什么意思
24
__user_initial_stackheap
LDR r0,=bottom_of_heap
MOV pc,lr
;/* 分配堆空间 */
AREA Myheap, DATA, NOINIT, ALIGN="2"
bottom_of_heap SPACE 256 ;库函数的堆空间
我的问题是:
1.这个函数在哪里被调用
2.赋值给r0 以后就完事了 r0 起什么作用
A:堆和栈的分配函数,由ADS 提供的初始化代码调用,具体参考配套《ARM 微控制器基础
与实战》的相关部分.
第106 问:
Q:2104 的启动代码是否适用2124 呢
网站上下载的那个easyarm2104 工程模版里面写着arm executable imag for lpc21**,
是否说也适用2124 呢 如果不行,哪些地方需要修改 希望能够指点一下!
A:您可以下载2100 的工程模板.
第107 问:
Q:我在用ARM 的IAP 功能,要把已经烧到flash 中的数据写到RAM 中,我是这么写的:
uint32 *q,data;
q = 0x00006000;
data = *q;
这是要读的flash 的起始地址,但是第二句编译出错,我想应该是C 编译器不许给指针
直接赋值, 我用汇编解决了这个简单的问题,但是怎么用C 来解决呢
A:q = (uint32 *)0x00006000;
第108 问:
Q:问一个有关汇编的基础问题.
例程: ANDS R1,R1,#0x0400
BEQ WAITOK
请问 ANDS 是如何影响标志位的,而BEQ 判断的是那两个操作数相等时执行
A:R1&0x0400 => R1,若结果为0(即R1 为0),则标志位Z=1.
当Z=1 时,BEQ WAITOK 有效执行.
第109 问:
Q:请教:在ADS 中怎么给某个变量确定固定物理地址
就是类似KEIL 中的 XDATA xxx _AT_ 0x4456 的功能.
A:使用分散加载机制,mem_c.scf 等就是例子.
25
第110 问:
Q:哪里有介绍ARM 的C 语言编程的
A:其实大多数嵌入式系统的C 语言都差不多,可找一本写嵌入式C 语言的书即可.
第111 问:
Q:请问在系统复位后首先执行的是否为Boot Block 的中断向量
然后由boot block 里面的程序决定是执行用户程序还是ISP 程序.
那么这时启动的boot block 里的中断向量表和用户程序里的中断向量表是如何在flash
里安排的
在《ARM 微控制器基础与实战》上看到的是复位后boot 扇区的最低64 字节出现在
0x00000000 区域,那用户的中断向量表应该在哪个区域
产品中一般为0x00000000,在开发板中重启后实际为boot block 的中断向量地址,对
吗
A:看一看3.3.6 节.产品中一般为物理0 地址处.
第112 问:
Q:《ARM 微控制器基础与实战》上有一段程序:
uint32 i;
i = VICIRQStatus;
i = IOSET;
请问:为何先要读取VICIRQStatus 的值,才能读IOSET 的值
A:读出VICIRQStatus 只是为了方便观察当前VICIRQStatus 的值,没其它用途.
第113 问:
Q:请问处理器在什么情况下处于用户模式 多谢!
A:需要你去设置CPSR 寄存器.
用户程序前台程序一般在用户模式/系统模式下运行.
第114 问:
Q:在EINT1_LED.S 中的倒数第二行有一个单独的B 指令,它是什么含义 多谢!
A:是"B .",跳转到当前地址,即死循环,与以下代码等效:
HALT B HALT
第115 问:
Q:模板里到底有些什么
A:起动代码,相关编译链接设置.
起动代码是用来初始化系统的程序,如Startup.s,target.c,stack.s 等等.
26
第116 问:
Q:今天试用了工程模板.使用了ARM Executable Image for lpc21xx 建了个项目,看了下
启动文件与原来的不同了,用了个《ARM 微控制器基础与实战》上的例程来作试验,用
的是time0 定时中断来亮灯的程序,用的例程的TargetInit()和int main(void);
修改了用户堆栈和bottom_of_heap 的长度,程序能运行,但不能产生中断,time0 和VIC
初始化的是正确的,是什么原因
用工程模板建立的项目文件夹的src 中多了几个文件,其中的
mem_a.scf,mem_b.scf,mem_c.scf,怎样才能导入到项目中来 谢谢!
A:原来startup.s 默认是关了中断的!
第117 问:
Q:在easyarm 2104 的配套光盘中的IAP 例子中,定义了一个函数指针
void (*IAP_Entry)(uint32 param_tab[], uint32 result_tab[]);
我看不懂,这个函数和普通的函数定义方法不一样,尤其是(*IAP_Entry),大家教教我.
A:这是一个指向函数的指针!!
第118 问:
Q:变量定义中volatile 是什么意思 请大侠告诉我一下《ARM 微控制器基础与实战》上c
语言定义变量时出现了volatile,不知道是做什么用的.C 语言里好像没有这个语法阿!
A:告诉编译器不要优化掉,volatile 是易变的意思.
第119 问:
Q:请问ARM 中的一个编译方面碰到的问题.
在ARM 地汇编语言中,有条件编译伪指令IF..ELSE...ENDIF;
而在C 语言中,有相应的条件编译伪指令#IF...#ELSE...#ENDIF,在较大的程序设计中,
往往需要对整个程序进行条件编译.
我要问的问题是:我在CONFIG.H 中设置一个编译开关,对所有的C 文件进行条件编译是
有效的, 因为每个C 文件中都有一个语句:#include "config.h",我如何将该编译
开关的信息传递给汇编语言文件,如VECYORS.S
A:好像没有直接的方法,可以编写一个CONFIG.INC 来管理汇编程序的配置.
27
第3 章 操作系统
第120 问:
Q:在SWI_Exception 的0x40 中的_OSFunctionAddr[regs[0]]中的Regs[0]指的是堆栈中的
R0 还是其它
A:是堆栈中的R0.
第121 问:
Q:《ARM 微控制器基础与实战》中在ucos 移植中说C 语言无法保证堆栈的结构,请问这是
什么含义
A:就是不能保证有哪些寄存器入栈及寄存器入栈的顺序.
第122 问:
Q:请问斑竹OSNeedToSwapContext 在哪个文件里声明的,我找不到
A:这是要删除的,我的OS_CPU_C.C 中函数OSIntCtxSw:
/*
***************************************************************************
* 函数: OSIntCtxSw.
* 描述: 中断级任务切换,此处并不真正进行任务切换,具体切换在 IRQ 服务程序中.
***************************************************************************
*/
void OSIntCtxSw (void)
{
}
第123 问:
Q:我的情况如下:我自己制作了一个硬件模块,用的是lpc2214,现在需要将ucos-ii 移
植到上面去.我用板子做ZLG 公司提供的实验,是可以做的,如led 灯等,按道理说串
口等硬件应该没有问题,然后我就做公司提供的那三个移植实例:ex2_arm.编译等是通
过的,生成了hex 文件,下载到flash 中,运行easyarm,但是没有任何显示,不知道是
什么问题,应该是硬件上呢,还是其他的
A:这主要是RAM 的问题,请用我们的工程模板,并选择在FALSH 中调试,如果编译通过,
则一般行, 否则请减少任务堆栈的大小.
第124 问:
Q:下载了工程模板以后,将工程模板目录下的文件都拷贝到了stationary 目录下,然后建
立了一个 ARM Executable Image for UCOSII(for lpc21xx)的工程,在PROJECT 目
录下的文件结构如下:
28
test.c
inlcudes.h
src->config.h,heap.s,includes.h,irq.s,lpc2294.h,
lpc2106.h,mem_a.scf,os_cfg.s,stack.s,startup.s
target.c,target.h,ucos_ii.c,ucos_ii.h,
arm->os_cpu.h,os_cup_a.s,os_cup_c.c
uCOS->ucos 源文件
arm_pc->pc.h,pc.c
编译可以通过,但是MAKE 时提示:
ERROR:Execution region IRAM overlaps with Execution region STACKS.
如果我表述得不是很清楚的话,那么可否告诉我工程模板到底怎么操作,怎样才能把例
子在 ARM2104 上跑起来.
A:RAM 占用太大,请在flash 中调试,并减少任务堆栈的大小.
第125 问:
Q:我改了以下SCF 文件,把堆栈的值设置大了一些,但是还是出现以前的老问题,那就是
程序跑到
TargetResetInit()函数处后就跳到取数据终止的异常中断去了.
A:不能把堆栈设置到内部RAM 之外.
第126 问:
Q:新旧任务级的切换是不是必须在管理模式下切换 切换后新任务的运行是不是必须在管
理模式下
A:在配套《ARM 微控制器基础与实战》里的任务切换是通过SWI 实现的.SWI 会使CPU 进入
管理模式.同时CPU 自动将任务的CPSR 保存到管理模式的SPSR 中.
SWI 程序还保存了一些寄存器到管理模式的堆栈中.然后任务切换程序会在管理模式
和系统模式间来回切换,目的是把保存在管理模式堆栈的寄存器内容拷贝到任务的堆栈
中(注意:任务是运 行在用户模式或系统模式的,这两个模式使用同一个SP,这时的
系统模式的SP 指向的就是任务的堆栈),也会将管理模式的SPSR 拷贝到任务堆栈(注意
管理模式的SPSR 就是在执行SWI 时CPU 自动保存的任务运行时的CPSR,它记录了任务
运行的CPU 模式和其他的运行状态信息).最后把任务模式SP 保存到任务的任务控制块
中(注意此时CPU 已经是运行在系统模式下的了).以上大致就是uC/OS-II 中所说的保
存任务运行环境的工作.
任务的恢复运行就比较好理解了.
接着前面的说,CPU 还在系统模式下.程序从任务控制块中得到任务的堆栈指针.
(OSIntCtxSw_1 的第一句)将这个指针的值加上一定的偏移量保存到SP 中.为什么要
加上一定 的偏移量呢 因为这时任务的堆栈中除了保存任务运行时的数据外还保存
了任务的上下文,即任 务切换时保存的CPU 寄存器等内容.而我们恢复任务等一下是
在管理模式下进行的,用的是管理模式的堆栈指针.等恢复任务后CPU 就开始执行任务
29
代码了.我们已经没有机会再修改系统模式下的SP 值了.所以在这个时候就应该对SP
进行调整.调整的大小就应该是所保存的上下文占用的大小.从堆栈中恢复LR 的值.同
样的道理,管理模式和系统模式使用不同的LR,在切换到管理模式之前,必须先在系统
模式下恢复任务运行时的LR.(OSIntCtxSw_1 的第三句)接下来就切换到管理模式了.
(OSIntCtxSw_1 的第四句)使管理模式SP 指向任务堆栈(第五句)注意这是没调整过
的任务SP,也就是保存了上下文环境的SP.
接下来的事情就真的很简单了.从堆栈中恢复出保存的东西.先是OSEnterSum,然后是
任务的CPSR (注意任务的CPSR 就是进入SWI 时由CPU 自动保存到管理模式的SPSR
中的,所以此时也是恢复到管理模式的SPSR 中)最后一句就是典型的中断返回语句了.
恢复寄存器,恢复PC,加了一个^号意味着同时将SPSR 拷贝到CPSR 中.
现在是回答你的问题的时候了.
切换前任务是运行在什么环境下的(包括CPU 模式,所有的寄存器),任务切换后任务就
是运行在 什么环境下的.对任务来说,什么也没改变.只有PC 值指向了下一条指令,
哈哈.
第127 问:
Q:请教:在rtos51 解释的概念里的"信号量"比较难懂,"消息队列"可以理解为任务之间
互相传递的参数,但"信号量"怎样理解呢 具体一点,谢谢!
A:信号量是60 年代中期Edgser dijkstra 发明的,它实际上是一种程序间的约定机制,
这种约定决 定那个程序(任务)可以执行.在多任务内核中普遍使用信号量用于:
1.控制共享资源的使用权(满足互斥条件);
2.标志某事件的发生;
3.使两个任务的行为同步.
信号量像是通行证,且通行证的数目是有限的.任务要运行下去,要先拿到通行证.如
果信号量 已被别的任务占用,该任务只得被挂起,直到信号量被当前使用者释放掉.
信号量的值可以是0 到255 或0 到65535,或0 到4294967295,取决于信号量规约机制
使用的是8 位,16 位还是32 位.到底是几位,实际上是取决于用的那种内核.根据信
号量的值,内核跟踪那些等待信号量的任务.
一般地说,对信号量只能实施三种操作:初始化,也可称作建立;等信号也可称作挂起;
给信号或发信号.信号量初始化时要给信号量赋初值,等待信号量的任务表应清为空.
想要得到信号量的任务执行等待操作.如果该信号量有效(即信号量值大于0),则信号
量值减1,任务得以继续运行.如果信号量的值为0,等待信号量的任务就被列入等待信
号量任务表.多数内核允许用户定义等待超时,如果等待时间超过了某一设定值时,该
信号量还是无效,则等待信号量的任务进入就绪态准备运行,并返回出错代码(指出发
生了等待超时错误).任务以发信号操作释放信号量.如果没有任务在等待信号量,信号
量的值仅仅是简单地加1.如果有任务在等待该信号量,那么就会有一个任务进入就绪
态,信号量的值也就不加1.于是通行证给了等待信号量的诸任务中的一个任务.至于
给了那个任务,要看内核是如何调度的.收到信号量的任务可能是以下两者之一:
1.等待信号量任务中优先级最高的任务;
2.最早开始等待信号量的那个任务,即按先进先出的原则(FIFO).
30
有的内核有选择项,允许用户在信号量初始化时选定上述两种方法中的一种.但Small
RTOS51 只 支持优先级法.如果进入就绪态的任务比当前运行的任务优先级高(假设,
是当前任务释放的信号量激活了比自己优先级高的任务).则内核做任务切换(假设,使
用的是占先式内核),高优先级的任务开始运行.当前任务被挂起.直到又变成就绪态中
优先级最高任务.
第128 问:
Q:我用了两个串口,但当我把程序做大的时候,发现在这个任务里所建立的邮箱失败,
我只用一个串口时是没有这种事情的.
Uart0ReviceMbox = OSMboxCreate((void *)0 ); /* 建立邮箱 */
if (Uart0ReviceMbox == NULL)
{
while (1);
}
我想问一下有几种可能会造成这种分配失败 我的程序存储器用量如下:
Total R0 size 22168
Total RW size 7956
Total ROM size 22168
A:在OS_CFG.H 中定义最大事件数,太小的话,分配会失败的.
第129 问:
Q:在周立功的原例子中,系统代码事先烧到ROM 中,应用代码在RAM 中运行.我想知道,
(RAM)应用代码调用系统函数,那么2104 是如何把ROM 中的系统函数的地址传递给RAM,
也就是应用代码和系统代码是如何关联在一起的 我猜是通过swi(软中断),应用代码
通过swi 调用系统代码,但是swi 中断程序中,是如何获得烧到RAM 中的系统函数的地
址哪 百思不得其解.
A:您看一看romcode 工程中swi 的0x40 和0x41 功能,
及Os_call.c,Os_call_arm.s,Usr_call_arm.s.
第130 问:
Q:16k 的RAM,128 的FLASH ROM 跑uc/os-II 够吗 再跑点应用程序够吗
A:取决于您的应用程序对RAM 的需求,及代码量.一般程序可以.
第131 问:
Q:利用lpc2104 开发应用程序时,在Os_call_arm.s,Os_call.c 两个文件中,那几个函数
需要在汇编中实现,哪几个需要在.c 文件中实现,为什么 谢谢各位大虾 !
A:4 个以上参数用c 实现.因为通过寄存器只能传递4 个参数.
31
第132 问:
Q:如果禁止SmallRTOS51 进行中断嵌套管理(#define EN_OS_INT_ENTER 0),是否还需要
设置中断优先级寄存器IP,使得所有中断的优先级都相同(全高或全低)
A:受SmallRTOS51 管理的设置为最低优先级,不受SmallRTOS51 管理的设置其它优先级较
好.
第133 问:
Q:在OS_CPU_S.s 文件中有如下一段代码,其中有两句代码的作用不是很明白,请解说一下.
OSIntCtxSw_1
LDR R4, [R6] ;获取新任务堆栈指针
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;这两行代码有何作用呢
ADD SP, R4, #68 ;17 寄存器CPSR,OsEnterSum,R0-R12,LR,SP
LDR LR, [SP, #-8]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式
MOV SP, R4 ;设置堆栈指针
LDMFD SP!,{R4, R5} ;CPSR,OsEnterSum
;恢复新任务的OsEnterSum
LDR R3, =OsEnterSum
STR R4, [R3]
MSR SPSR_cxsf, R5 ;恢复CPSR
LDMFD SP!, {R0-R12, LR, PC }^ ;运行新任务
A:这两条指令是在系统模式下恢复用户模式下的LR;可以参考配套《ARM 微控制器基础与
实战》6.4.9 节.
第134 问:
Q:我将《ARM 微控制器基础与实战》上uC/OS-II 的第一章例2 移植例在ARM2104 开发版上
实现例2 中的TEST.C 中的"#define TASK_STK_SIZE 512"改为"...256",程序编译
后,数据量低于16K,能正常运行,但运行时"Total Stack"不是256 全是1024.另
UC/OS-II 书上,第一章例2 每一个任务的堆栈都是512,为什么书上11 页"Total Stack"
是"624,1024,1024,1024,1024,1024,1024",请老师指点,万分感谢!
A:显示的是字节而定义的是字.
第135 问:
Q:可不可以把所有的任务和相关信号量(二值)在一个任务里面一起创建呢 我现在是这
样做的, 不知是不是这方面的原因 而且全部信号量是这样创建的:
XX1 = OSSemCreate(0);
32
XX2 = OSSemCreate(0);
XX3 = OSSemCreate(0);
一共创建了十个信号量,以前程序代码版本是分开写的执行起来没有问题,不知现在为
什么这样写就会出现小问题呢 这样的问题和我的任务和信号里书写位置有关系吗
A:必须在使用信号量前创建信号量.
第136 问:
Q:UCOS 在中断处理完后调用 OSIntExit(),该函数将判断是不是要进行任务切换,如果是
则调用 OSIntCtxSw()切换任务, 然后才恢复寄存器,中断返回.这样说来,在中断
返回前,已经切换到别的任务去了,在再次回到被中断的任务前,是不是一直没有中断
返回
A:如果进行任务调度,则不会执行OSIntCtxSw()后的语句,相当于中断已退出.
第137 问:
Q:最近我在学习使用SMALL RTOS 时发现一个 BUG.
任务在调用系统等待函数 OSWait(K_TMO | K_SIG,x) 后,不能在延时 x 个 ticks 后
被唤醒.
我分析了一下原因如下:
在 OS_CORE.C uint8 OSWait(uint8 typ, uint8 ticks) small 中,
case (K_TMO | K_SIG): 中执行了函数 OSTaskSuspend(OSTaskID);
( OS_CORE.C 第549 行)而此函数将延时值改为了 0!
解决办法:将此函数改用另一个函数 OS_TaskSuspend(TaskID);
并在其后加入任务切换函数 OSSched();
便能工作正常.
A:对,这是疏忽,谢谢.您的更改是对的.
第138 问:
Q:在文件Os_cpu_a.s 中的函数OSIntCtxSw 中有如下语句:
……
(1) LDR R4, [R6]
(2) ADD SP, R4, #68
;17 寄存器 CPSR,OsEnterSum,R0-R12,LR,SP
(3) LDR LR, [SP, # --8]
(4) MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式
(5) MOV SP, R4
……
(6) LDMFD SP!, {R0-R12, LR, PC }^ ;运行新任务
《ARM 微控制器基础与实战》404 页中解释:只所以要(1)(2)是因为"OSTCBHighRdy
—>OSTCBStkPtr 保存的是任务栈位置,而寄存器恢复后堆栈指针并不指向这,所以要调
33
整新任务堆栈指针." 可是将堆栈指针调整到 "新任务入栈的其它数据(见《ARM 微控
制器基础与实战》图6.3)"处后,除了取出了LR 以外并没有做 什么,而当执行了(4)
后又重新将堆栈指针指向了栈顶(即第(5)句).我认为可以将(2)省去,直接将(3)改为
"LDR LR, [SP, # 60]",而当执行完(6)后,堆栈指针就自动指向了"新任务入栈的其它
数据"处.这样修改后我运行了EX1_arm 例子,正常.
请问这利用(3)进行堆栈指针调整的原因是什么 不调整可以吗 谢谢.
A:注意不同模式有不同的SP 指针.您这样做会造成内存泄漏,长时间运行会耗尽堆栈而使
程序崩溃.
第139 问:
Q:不明白在光盘上ROMCODE/SRC/下的os_call.c 做什么用.
A:是应用程序与事先固化到flash 中的ucosii 接口的一些代码.在本例中为应用程序如何
调用事先 固化到flash 中的ucosii 的OSFlagPend 等函数的接口代码.请看配套《ARM
微控制器基础与实战》的7.4.3 节的第10 点.
第140 问:
Q:请问在OS_CORE.C 中的常数数组OSUnMapTbl[]是做什么用的
A:用来计算优先级的,查表计算比较快.
第141 问:
Q:ucos 的中断嵌套层数是否受到初始化时分配的IRQ 堆栈大小的限制 我的理解是每一次
中断需入栈的寄存器有R0-R3,R12,LR,SPSR,共7 个,如果想达到8 层嵌套的话,堆栈长
度IRQ_STACK_LEGTH 应设为56,不知这样理解对不对.
A:是,但中断至少占用8 个字,因为c 语言的中断处理函数会将一些数据压入堆栈.
要达到8 级嵌套需要的堆栈长度与具体的代码有关.
(编者注:新移植代码已有改变)
第142 问:
Q:请问:核心定时器中断不进入可能因为……
我的程序在运行一段时间以后,核心定时器中断即操作系统用的Timer0 不能进入,查发
现CPSR 的I 位为1,请教这可能是哪个原因
A:估计为开关中断次数不匹配造成.
第143 问:
Q:请问:GetOSPprioCur()函数应怎样调用 它是一个内核函数吗
为什么我在内核和任务分别编译时正常,而合到一起编译时它告警为未定义呢
同时我已给您发了一个邮件,请教如何将分别编译的程序合在一起编译的方法,请指教!
A:这是我自己编写的函数,其实就是返回OSPrioCur 的值,请参考MyFunction.c.
34
第144 问:
Q:关于不受uc/os 控制的中断:在ARM 板中,非屏蔽中断可以挂起正在执行的uc/os 任务,
除了不能使用uc/os 中的函数外,它的执行工序是不是和受管理的中断一样,先挂起当
前任务,再保存CPU 寄存,然后再执行中断ISR,完成后,内核脱离,寄存器恢复,最
后任务调度.
另外,《ARM 微控制器基础与实战》中提到不受管理的中断,它的工作是否和非屏蔽中断
一样,也可以在uc/os 正执行时发生中断.如果不同,它们是怎样工作
最好是象受管理中断一样说明一下它的工作时序!
A:必须比受管理的中断的优先级高,编写方法与没有OS 时中断的编写方法一样.
第145 问:
Q:不受uc/os-ii 管理的中断和受管理的中断是否具有相同的响应方式,即不受管理的中断
在中断 uc/os 正执行的任务后,是不是也是先挂起当前的任务,保存CPU 寄存器,再
执行中断子程序,恢复CPU 寄存器,进行最优先级任务的调度.
A:不受uc/os-ii 管理,uc/os-ii 都不知道,还有什么任务调度
Q:我知道不受管理的中断不能调用uc/os 的函数,但《ARM 微控制器基础与实战》上说:
FIQ 不受uc/os 管理,但可以用来执行紧急任务,就是说在uc/os 运行时,不受uc/os
管理的中断还是可以发生的,它是把整个uc/os 操作系统中止,还是只是中止uc/os 正
在执行的任务.不受管理的中断完成后,接着执行什么
A:可以发生,中断整个RTOS.
Q:我看了您在lpc210x 上的移植代码,你在说明中说:"如果您想通过软件仿真,请将
target.c 中的第 51 行屏蔽, 这样就可以看到任务逐个切换,最后将进入空闲任务."
我照这做了,但是在单步或者设断点执行时会产生异常,原因是未定义指令
OS_ENTER_CRITICAL()引起的,经过编译的函数都会变成蓝色,但这个函数还是黑色,因
为它实际上是一个软中断,请教您如何调试才能看到任务逐个切换 谢谢!
A:1.屏蔽的那一行是死等锁相环锁定,软件仿真时是没有锁相环的.
2.黑色是正常的,因为没有定义成函数.
3.因为你的 AXD -> OPTION -> 配置处理器中的 VECTOR CATCH 中的 S 选中了,所以 AXD
将你的软件中断当成了异常给捕
ARM 经典300 问
最新推荐文章于 2023-05-16 11:45:35 发布