马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
指令执行
在RISC的精简指令中,它含有多种意义,因此较难理解。但在Debugger对CPU掌握的全透明下,就可清清楚楚看到指令的执行, 也加深对CPU的了解。为了观看指令与组合语言的执行,我们来开一视窗共解说它各处视窗的意义。首先要把ICE与Creator接上,并执行Domingo程式如图1图2。
图1 Pocket ARM ICE 与Creator的接线图
图2 Domingo IDE视窗画面
Example
在command下键入以下指令,以便等一下观看其各指令执行结果。虽然不甚了解指令,但在执行后,视窗会显示有变更(红色值)的资讯,您就会体悟原来如此。
STMIAR0,{R1-R5}
执行这个指令后,会将R1~R5等暂存器之内涵值储存到R0暂存器所指的记忆体位址。
暂存器值
记忆体变化
程式执行
以keypad与7-seg为例,在project中去download一现成的程式来观看其执行,并在keypad上按键,而观看7-seg的变化。看了以后,发觉它并不陌生,与8051也差不多,只是惊讶Domingo操作环境比早期的ICE有着天壤之别的人机操作介面。
操作介面
上图中主要程式内容如下:
int main(void)
{
__enable_interrupt();
Initial_Creator();
EnableInterrupt(BIT_GMASK);
while (1)
{
UC ch;
while(KEYPAD_get_key(&ch) != OK);
for (i=0;i<1000;i++)
{
_7SEG_put_led(1,0);
_7SEG_put_led(2,0);
_7SEG_put_led(3,0);
_7SEG_put_led(0,ch);
}
}
DisableInterrupt(BIT_GMASK);
return(0);
}
在利用debug\load module载入已经compiler完成之程式后,执行free go便可测试程式之正确性并且进行debug。
程式建立与Compile流程
1.建立project
建立专案以管理您的相关程式并可将自订的工作环境储存起来。
2.Edit
开启Editor以编辑新建立的程式或开启一个已建立的程式。当然,这可以是Assembly或C语言的程式。
3.Compile
Domingo IDE支援外部的Compiler程式,透过一些简单的设定步骤,您可以直接在这个整合式的介面中执行compile与link来build您的project,也可以用make的方式只针对变更处build以增快速度。若您在compile的过程中发现了错误,还可以直接在错误讯息处double click以快速地直接跳至发生误错的原始码位置方便您的除错。
4.ICE的连接
当然除了硬体的接线外,还需要在Domingo中执行connect以与ICE正确地连接起来,此时目标板的控制权才会交给ICE。
5.Download
将compile完毕的程式档download至目标板的RAM区,Domingo支援多种格式的除错档,因此即便是没有整在Domingo介面中的外部除错档也可以下载下来哦。
6.Debug
在Domingo强而有力的除错功能支援下,相信这不会是一个太大的难题,不过却是一个最重要的部份,没有好工具的支援,这里将会是您整个开发专案中最费时的一个部份。
7.烧录
程式完成了,如有需要再配合一些记忆体位置的修改后就可以透过ICE直接烧录至ROM里面了。
8.独立测试
好啦,ICE的任务完成了!这时您已经可以将ICE与目标板脱离让系统板独立运作了,测试一下,是不是成功了呢?整个流程与以前8位元8051的做法似乎大同小异,但其实内里却又大有文章,想进阶至32位元开发的您,如果没有一个好的Debugger与ICE将会困难重重。
系统管理
这是32bit ARM CPU与8051截然不同的地方,一个单独的CPU core是不能动的,它要加上一些外围週边资源才能动起来,例如放程式的ROM区、放资料的RAM区、BUS连接的方式、cache/buffer的情况。这些资源要设定好,才能启动CPU执行指令。以下做一些描述:
一个包含了ARM core的微控制器皆会架构一个系统管理者(System Manager)来管理系统所提供的所有週边资源,其主要的功能有以下几种:
˙仲裁週边之优先权:由于ARM微控制器所提供的週边功能很多,故会发生多个週边同时要求进行存取的情况,这时系统管理者便会依据控制器内固定的优先权顺序,仲裁数个週边的系统匯流排存取要求。
˙记忆体所需的控制信号:提供存取记忆体时,所需的记忆体控制信号。例如:DMA控制器或CPU产生了一个相对应到DRAM bank的位址时,系统管理者的DRAM控制器会产生所需的标准/EDO存取信号或者是SDRAM存取信号。
˙I/O所需的控制信号:提供ROM/SRAM或者外部I/O bank之间匯流排传输所需的信号。
˙内/外部匯流排宽度差异之补偿:补偿外部记忆体匯流排和内部资料匯流排之间,不同匯流排宽度之资料流。
而针对系统记忆体管理部分,各个memory bank的位置、大小皆由current bank base pointer和current bank end pointer之设定所决定。故我们可利用base bank pointer/next bank pointer的概念去建立一个连续的记忆体应对。这个概念也就是将next bank的base pointer设定为与current bank的end pointer相同的位址。但是有一点必需注意的,就是这些连续位址不可有重叠的地方。
在可定址的空间范围里,各种bank的起始位址并不是固定的,我们可以利用系统暂存器去组态一个bank起始位址为bank的基底指标,而这个位址的解析度为64K byte,故bank的起始位址会定义为”基底指标左移16位元”,而bank的结束位址为”下一个指标左移16位元的位址值减1”。
然而在power-on或reset之后,控制所有bank的adress pointer暂存器皆会初始化为预设值;在这个情况下,除了ROM bank0的next pointer以外的所有bank pointer皆会被设定为0。这也就是说,除了ROM bank0以外所有的bank,在系统启动后,皆会成为未定义状态。
ROM bank0的next pointer和base pointer在重置后分别会为0x200和0x000。这代表系统在重置后会自动定义ROM bank0的起始位址由0开始,并且总共拥有32Mbyte的空间,其算法如下:
base point = 0x000
next point = 0x200
故ROM bank0的位址范围为0x000 0000 ~ 0x1ff ffff(32Mbyte)
其计算的方式为:
起始位址 = 0x000左移16位元,故为0x000 0000
结束位址 = 0x200左移16位元-1,故为0x200 0000-0x1 = 0x1ff ffff
由于系统启动后,会由0x0的位址开始动作,故这个ROM bank0的初始定义就是为了使系统可以控制使用者所提供贮存在外部ROM的boot code,以使系统可以正确的启动。boot code的动作内容会依照使用者所需求的规划来撰写,一般会做系统初始化的工作以及依据实际上的外部记忆体应用和周边装置组态重新配置系统记忆体map。
图3 重置后的系统记忆体map
为了控制週边功能以及记忆体的操作,系统管理者使用一些专用的特殊暂存器集(如表1所示)来进行控制和管理。经由规划这些特殊暂存器之内含值,可以说明下列事情:
˙记忆体类型
˙外部匯流排宽度存取週期
˙控制信号时序(例如RAS和CAS)
˙memory bank位置
˙memory bank的大小可在随意的位址空间去使用
每个memory bank base pointer的位址解析度皆为64Kbyte(共16位元),而base address pointer为10bit,故整个可定址的记忆体空间为16Mword=64Mbyte(如表2所示)。
表1 系统管理者暂存器
表2 基本的memory bank位址组成
PCM
在Domingo中PCM就是在设定此一系统功能,因每个人所设计的硬体都不同,如未在PCM中设定正确,那Domingo对程式指令的存取就无法正确动,就像您在coding程式,在一开始也要初始化这些相对应的值,CPU才能正确的动作。
以ARM为基底的Embedded System,其记忆体系统(尤其是DARM)要能使用之前,通常要经过一连串的设定动作,而使用者如果每次使用ICE在下载程式到记忆体之前都要手动地去执行上述初始化记忆体工作的话,实在是一件很辛苦的事。而PCM命令则可为使用者代为执行上述例行之设定工作。
有以下二个方法可以开启PCM设定视窗
■使用configRconfig PCM.......命令
■使用configRHardware Options命令
进入Hardware Options设定视窗后再按Config PCM...按钮
图4 PCM视窗
以下说明PCM视窗内各按钮之功能
■Import
载入一个先前储存好的PCM档案
■Export
将目前PCM之设定存入指定之档案内。
■Move Up
将选定之设定列向上移动一列。
■Move Down
将选定之设定列向下移动一列。
■Delete
将选定之设定列移除。
■Delete All
将所有之设定移除。
■Modify
进行修改选定之设定列,并出现以下之设定视窗
图5 嵌入式系统架构
使用者可透过以上视窗来修改,名称、位址、设定值及资料长度等相位。完成后请按Done钮设定成修改好之工作。
■Insert
将选定之设定列向下推,并在此插入一个设定列,此时会出现以下之设定视窗,供设定之用。
图6
在Name的栏位内如果要使用CPU内定的暂存器名称时,则可点选System Name并使用右侧下拉选单来选择一个已存在暂存器,在选择完毕后右侧的Address及Size栏位亦会被自动设定完成,你只需要输入Value项目即可。
若为自定名称的话,则请点选User Defined之后再依序输入Name、Address、Value及Size各栏位,最后按Insert即可。若要结束设定工作则按Done按钮。
■Append
同Insert命令,其差异在于Append是将新项目加入到最后的一设定列。
■Apply
利用此按钮可以将目前之设定项目立即对CPU及目标板做一次设定之工作。
Embedded Linux
有了CPU、指令与软体的技能后,再来就可建立系统概念,作业系统是一个学期的课程,不是在这里三言二语就可讲完,我们仅作重点说明。因是用现成Open Source的Linux程式,因此为了开发产品,产业界都只针对需自己需加入或修改的部份处理即可,也较快完成软体Porting,除非您是要透澈了解整个OS架构,也想自己创造一个OS,那就需深入各部份。因此Porting成功才是最重要的。
在这架构下就可清楚自己所要开发的是那一部份软体,只要针对它的相关界面了解,就可动手。因此如只开发AP S/W,那当然就不需进入到了解CPU的H/W,用Compiler、Debugger工具即可。但未来的产品,SoC嵌入式系统产品都不仅如此而已,它需与H/W连接,它不仅用到Compiler、Debugger,更需ICE的支援与其他硬体工具。因此如能建立对CPU与H/W的了解,未来的发展空间就更开阔,更有附加价值了。如图7所示,在Linux OS与H/W的中间那一层就是我们要去建立的能力。
图7
Device driver
这是在Linux下一个嵌入式系统产品必经之路,它依不同硬体而有不同之程式,但只要一个通,其他就容易了。因它与硬体有很密切关联性,我们已在Creator板上有些driver,在ICE与Domingo操作下,就容易了解它的过程了。因程式佔篇幅,就不在此描述。
FPGA之IP实作
FPGA上之IP开发、验証,这又是一学期的课程,在此我们也仅以重点式说明。在週边IP FPGA模组连接头上,可更换不同FPGA或CPLD模组(未来性)。在目前的Create Ph-FPGA-XC2S上,它的主要特点是:(一)可做基本组合逻辑与序向逻辑实作,(二)与ARM CPU程式紧密结合之逻辑设计,(三)软体或硬体最佳化选择之评估,(四)序列 ←→并列资料转换。
其他可发挥的硬体功能如下:
■FPGA:
XC2S30-5(30K gate counts)
■Codec:
˙16-Bit,26-KSPS
˙Built-in Microphone
■Analog To Digital:
8-Bit serial I/O ADC with 2 channel multiplexer
■SRAM:
128K×8Bit,12ns
■7 Segment LED×1
■9 LED Lamps
■4 Way DIP Switch
■1 Tag Switch
■1 DC Buzzer for tone generation
■PS2 Connector ×1 for PS2 keyboard or mouse
■Build in Xilinx download cable header circuit
我们仅以简单之解码功能做范例,但它需配合Xilinx ISE 4.1 以上工具来开发,再Download入板上。就可由CPU执行程式去驱动逻辑IP,在LED上看到显示的结果,以培养系统化思考,创作的能力。
【范例】:由ARM CPU送来的值经逻辑解码、Latch显示在LED上
--
-- MICROTIME COMPUTER INC.
--
library IEEE,synopsys;
use synopsys.attributes.all;
use IEEE.std_logic_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity TEST is
port (
GSR_IN : in STD_LOGIC;
IO_ADDR : in std_logic_vector(15 downto 0);
IO_DATA : inout std_logic_vector(15 downto 0);
nECS3 : in std_logic;
IO_nOE : in std_logic;
IO_nWE : in std_logic;
IO : inout std_logic_vector(9 downto 0);
LED : out std_logic_vector(7 downto 0)
);
end TEST;
architecture TEST of TEST is
signal GSR1, nGSR1 : std_logic;
signal PORT_READ : std_logic;
signal CS_PORT : std_logic;
signal sIO_nWE, sIO_nOE : std_logic;
signal FPGA_CTRL : std_logic_vector(7 downto 0);
begin
-- #####################################################################
-- #################### GSR
-- #####################################################################
GSR1 <= GSR_IN;
nGSR1 <= not GSR_IN;
-- #####################################################################
-- ##### DECODING
-- #####################################################################
CS_PORT <= ’1’ when(nECS3=’0’ and IO_ADDR(11 downto 8)=X"0") else ’0’;
PORT_READ <= ’1’ when(CS_PORT=’1’and sIO_nOE=’0’) else ’0’;
LED <= FPGA_CTRL;
IO_DATA <= "000000" & IO when(PORT_READ=’1’) else "ZZZZZZZZZZZZZZZZ";
-- #####################################################################
-- ##### IO PORT
-- #####################################################################
p_PORT_WR : process (GSR1, sIO_nWE)
begin
if(GSR1 = ’0’)then
FPGA_CTRL <= X"00";
elsif(rising_edge(sIO_nWE)) then
if(CS_PORT = ’1’) then
FPGA_CTRL <= IO_DATA(7 downto 0);
end if;
end if;
end process;
end TEST; |