当前位置:首页 > 嵌入式 > 嵌入式软件
[导读]Gdb/Armulator 源代码分析

作者Email: Anti_chen2000@sohu.com

    摘要

    Gdb/Armulator 是Gdb自带的arm7模拟器,是调试arm程序的一个好工具.而了解它的原码结构对扩展它的IO功能有重要意义.本文介绍了从Armulator的启动到其内部运作和IO扩展的大部分原代码功能.

    说明

    源代码用的是gdb-5.0.tar+ gdb-5.0-uclinux-armulator-20021127.patch

    A. 和GDB间的通迅

    Armulator一般和Gdb通讯有两种方式,其一是在Gdb内部直接调用模拟器的相关函数,另一方法则是用pipe或socket传递RDP协议来连接Gdb和Amulator.而第一种方法是现在Gdb/Armulator所真正使用的(第二种是早期使用的方法),下面就分析了函数直接调用法.

    函数直接调用

这个方法是由Steve (sac@cygnus.com) 修改原RDP方法而来的,Steve本人的描述如下:
/******************************************************
This directory contains the standard release of the ARMulator from
Advanced RISC Machines, and was ftp'd from.

ftp.cl.cam.ac.uk:/arm/gnu

It likes to use TCP/IP between the simulator and the host, which is
nice, but is a pain to use under anything non-unix.

I've added created a new Makefile.in (the original in Makefile.orig)
to build a version of the simulator without the TCP/IP stuff, and a
wrapper.c to link directly into gdb and the run command.

It should be possible (barring major changes in the layout of
the armulator) to upgrade the simulator by copying all the files
out of a release into this directory and renaming the Makefile.

(Except that I changed armos.c to work more simply with our
simulator rigs)
********************************************************/
/gdb/target.c,/gdb/remote_sim.c以及在/sim/arm/wrapper.c是在Armulator和Gdb的通信中起着至关重要做用的几个文件.所有的Gdb调试命令最后都是通过在target.h里定义的target_ops结构中的函数指针调用在/sim/arm/wrapper.c中型如sim_xxx的函数完成的.以前这些sim_xxx函数是位于/sim/common中的,是建立RDP通讯的关键,代码修改后此目录中的文件不再有用,被wrapper.c取而代之了.

以下是RDP 通讯和直接函数调用的图示:

要清楚Armulator的执行过程就要从它的启动说起,当你在Gdb中键入target sim 去激活Amulator后Gdb首先进行命令行解释,并将current_target指针指向sim变量,即将Armulator的调试函数集赋予Gdb,随后的函数调用堆栈如下:

--àgdbsim_open (…) in remote-sim.c.
--àsim_open(…) in /sim/arm/wrapper.c /*这里Amulator对调用参数进行分析处理*/
--à*current_target->to_fetch_registers(-1) /*此函数指针实指向sim_fetch_register(…) in /sim/arm/wrapper.c*/
--àsim_fetch_register(-1) /*此函数指针是在将current_target指向sim时,通过注册target_ops 结构完成挂接的*/
sim_fetch_register (sd, rn, memory, length)
{
  ARMword regval;
  init ();   file://就在这,Amulator进行了初始化
  …
}

至此Armulator被装载完毕,其后Gdb就是通过target_ops(定义在target.h)结构中的各个函数指针来完成对它的调试工.

    B. Armulator 内部机制

    a. 初始化

    从上述可知整个模拟器的初始化入口是在wrapper.c中的init( )函数,那么它到底又做了些什么呢?

    (原始的Gdb5.0中的Armulator是模拟ARM7DTMI 的,而补丁代码修改了memory map 并添加了timer 和uart 的IO能力使其能够模拟AT91.因为后者是对前者的增强,所以我们的分析以后者为准)

    Once the armulator to reset ,the ARMul_NewState will be called.And its task is to malloc a ARMul_state stuct which saves the armulator’s states and initialize it .And the ARMul_MemoryInit() will malloc 4m ram for you.
#1 static void
#2 init ()
#3 
#4 static int done;
#5  if (!done)
#6  {
#7  ARMul_EmulateInit (); file://Call this routine once to set up the emulator's tables.
#8  state = ARMul_NewState ();
#9  state->bigendSig = (big_endian ? HIGH : LOW);
#10  RMul_MemoryInit (state, mem_size); file://原始代码中的内存初始,但现在无用
#11  ARMul_OSInit (state);    file://预装系统初始化
#12  ARMul_CoProInit (state);   file://协处理器初始
#13  state->verbose = verbosity;
#14  done = 1;
#15  file://the below is added for AT91
#16  ARMul_SelectProcessor(state, ARM600);
#17  ARMul_SetCPSR(state, USER32MODE);
#18  ARMul_Reset(state);
#19  }
#20 }

    因为这是补丁代码,难免又冗余出现,实际10-11行的两处掉用是没有实际意义的,而12行是协处理器的初始化,因为并没又模拟协处理器所以此处只是以备扩展.

    重点的初始化过程是在ARMul_NewState(…)中的.首先它给模拟器的核心状态结构ARMul_State分配了空间,这个结构里保存了Armulator的所有方面的状态,包括arm寄存器,流水线状态等等.

    并赋予初值,我们以后就用state表示之.然后调用ARMul_Reset(…)进行更近一步的设置.而后者又主要完成模拟器内存结构的分配和rom映象的加载--/sim/arm/armmem.c/mem_reset(…),IO设备的状态初始—/sim/arm/armio.c/io_reset(…),你也可在这添加你的初始代码.到这就完成了Armulator的装载.

   (大家注意到18行也调用了ARMul_Reset(…),这是一个BUG,使得模拟器进行了两次内存分配,而浪费了系统内存.此处可删去.)

    Memory map 是所有模拟器的关键.Armulator由AT91向其他MCU移植时Memory map又是首先要处理的.Armulator的各个内存区是由mem_bank_t结构来描述的:

typedef struct mem_bank_t {
 ARMword (*read_word)(ARMul_State *state, ARMword addr);
 void (*write_word)(ARMul_State *state, ARMword addr, ARMword data);
 unsigned long addr, len;
 char *filename;
} mem_bank_t;  file://定义在armmem.h中
Armulator的整个内存则是又此结构的数组static mem_bank_t mem_banks[]管理的.
AT91的memory map如下:
static mem_bank_t mem_banks[] = {
 /* the yuk's below are to work around a uClinux/mount options problem */
 { real_read_word, real_write_word, 0x01000000, 0x00400000, }, /* 2.4 */
 { real_read_word, _write_word,  0x01400000, 0x00400000, "boot.rom"},
 { real_read_word, real_write_word, 0x02000000, 0x00400000, }, /* 2.0 */
 { real_read_word, real_write_word, 0x02400000, 0x00001000, }, /* yuk!*/
 { real_read_word, _write_word,  0x04000000, 0x00400000, "boot.rom"},
 { real_read_word, real_write_word, 0x00000000, 0x00004000, },
 { io_read_word,  io_write_word,  0xf0000000, 0x10000000, },
 { fail_read_word, fail_write_word,  0,    0 }
};

    根据mem_banks,mem_reset( )将分配空间,加载boot.rom文件.

    (原来的内存是由ARMul_MemoryExit( )释放的,但补丁后的代码就没了释放功能,这也是需要纠正的地方)

    a. 指令流

    Armulator 加载完成后,就开始等待Gdb的运行命令了.最终/sim/wrapper.c/sim_resume( )是启动arm指令执行的地方.

    Sim_resume( )根据Gdb的要求选择用/sim/arm/arminit.c/ARMul_DoInstr()还是用/sim/arm/arminit.c/ARMul_DoProg()来调用 流水线模拟函数/sim/arm/armemu.c/ARMul_Emulate32().ARMul_DoInstr()和ARMul_DoProg()的区别就是一个单步执行,一个连续执行指令. ARMul_DoProg()又不停的判断state->Emulate是否为STOP,如果是,模拟器又将停下等待Gdb的调试.

    而在arm/armemu.c, /arm/armvirt.c 和 /arm/armsupp.c中的函数则模拟指令预取,指令译码,指令执行以及数据回写的功能.这三个文件时可以说时Armulator的核心!

    b. 中断

    Armulator 的中断机制主要靠以下两个例程实现:

    1.IntPending(): 用来检测state中的各个中断标志是否置位,从而判断是否又需要中断.

    2.ARMul_Abort():当需要中断时,用来改变处理器模式,并将pc指向相应的中断向量.

    在流水线函数ARMul_Emulate32()执行当中,有多处调用IntPending() 去检测中断.而Ispending() 也十分简单,它仅仅判断state中的四个变量:

State->Exception : 中断使能标志.
State->NresetSig : reset 中断信号.
State->NirqSig : irq 中断信号.
State->NfiqSig : fiq 中断信号.
所以当你的虚拟外设产生中断时,你只要调用/sim/arm/armio.c/ update_int()即可:
static void update_int(ARMul_State *state)
{
 ARMword requests = state->io.intsr & state->io.intmr;
 
 state->NfiqSig = (requests & 0x000f) ? LOW : HIGH;
 state->NirqSig = (requests & 0xfff0) ? LOW : HIGH;
}

    b. 读写操作

    无论是CPU指令还是Gdb调试时读写内存或IO空间,最后都将要落到/armvirt.c/getword(), /armvirt.c/putword()这两个函数身上.

    在原始代码中这两个函数马上就进行内存数组的读写了.而补丁代码的流程如下:

--àgetword()/putword()
--àmmu_read_data()/mmu_write_data() in armmmu.c
/*进行mmu的地址转换和cache 查询*/
  --à real_read_data()/real_write_data() :读写ram,rom
io_read_data()/io_write_data() :读写IO空间
_write_data()/fail_read_data()/fail_write_data() :非法读写,如地址错误,rom读操作等.

    可以看出最后几个函数的选择是由读写地址在相应的mem_bank_t结构中的读写函数指针决定的.

    c. 设备同步

    写这篇文章的初衷是让读者能很快进入Armulator的移植和IO扩展的实际工作中去.所以这里有必要讨论一下IO设备和CPU的同步问题.很显然我们模拟的设备不能太快,也不能太慢.快了CPU正常的指令流将被堵塞,慢了就无法反映操作系统的实时性.也就是说设备的速度和指令流要有个比例关系,即要有一定的同步.

    Armulator 中有个很好的接口:

    ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay, unsigned (*what) ()) in armvirt.c

    它的目的就是注册你的同步例程,并且每个时钟周期即ARMul_Emulate32()将调用ARMul_ScheduleEvent()查看是否需要同步你的设备.

    也许你在ARMul_Emulate32()中还发现了/sim/arm/armio.c/io_do_cycle(),没错它是AT91的timer和uart用来和指令流同步的函数,但我并不赞成你象这样把自己的同步例程直接放入指令执行过程中,破坏代码的结构性.

 a.       源文件描述

The original files

The modified codes

File descriptions

arminit.c

arminit.c

初始代码

armemu.c

armemu.c

指令流模拟

armvirt.c

armvirt.c

内存读写

armsupp.c

armsupp.c

辅助指令流模拟

armcopro.c

armcopro.c

协处理器模拟(可忽略)

armos.c

armos.c

初始操作系统(可忽略)

 

armmem.c

内存管理

 

armmmu.c

Mmu模拟

 

armio.c

IO设备模拟

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

wrapper.c

wrapper.c

Gdb通讯的例程

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

武汉2025年9月9日 /美通社/ -- 7月24日,2025慧聪跨业品牌巡展——湖北•武汉站在武汉中南花园酒店隆重举办!本次巡展由慧聪安防网、慧聪物联网、慧聪音响灯光网、慧聪LED屏网、慧聪教育网联合主办,吸引了安防、...

关键字: AI 希捷 BSP 平板

上海2025年9月9日 /美通社/ -- 9月8日,移远通信宣布,其自研蓝牙协议栈DynaBlue率先通过蓝牙技术联盟(SIG)BQB 6.1标准认证。作为移远深耕短距离通信...

关键字: 蓝牙协议栈 移远通信 COM BSP

上海2025年9月9日 /美通社/ -- 为全面落实党中央、国务院和上海市委、市政府关于加快发展人力资源服务业的决策部署,更好发挥人力资源服务业赋能百业作用,8月29日,以"AI智领 HR智链 静候你来&quo...

关键字: 智能体 AI BSP 人工智能

北京2025年9月8日 /美通社/ -- 近日,易生支付与一汽出行达成合作,为其自主研发的"旗驭车管"车辆运营管理平台提供全流程支付通道及技术支持。此次合作不仅提升了平台对百余家企业客户的运营管理效率...

关键字: 一汽 智能化 BSP SAAS

深圳2025年9月8日 /美通社/ -- 晶泰科技(2228.HK)今日宣布,由其助力智擎生技制药(PharmaEngine, Inc.)发现的新一代PRMT5抑制剂PEP0...

关键字: 泰科 AI MT BSP

上海2025年9月5日 /美通社/ -- 由上海市经济和信息化委员会、上海市发展和改革委员会、上海市商务委员会、上海市教育委员会、上海市科学技术委员会指导,东浩兰生(集团)有限公司主办,东浩兰生会展集团上海工业商务展览有...

关键字: 电子 BSP 芯片 自动驾驶

推进卓越制造,扩大产能并优化布局 苏州2025年9月5日 /美通社/ -- 耐世特汽车系统与苏州工业园区管委会正式签署备忘录,以设立耐世特亚太总部苏州智能制造项目。...

关键字: 智能制造 BSP 汽车系统 线控

慕尼黑和北京2025年9月4日 /美通社/ -- 宝马集团宣布,新世代首款量产车型BMW iX3将于9月5日全球首发,9月8日震撼亮相慕尼黑车展。中国专属版车型也将在年内与大家见面,2026年在国内投产。 宝马集团董事...

关键字: 宝马 慕尼黑 BSP 数字化

北京2025年9月4日 /美通社/ -- 在全球新一轮科技革命与产业变革的澎湃浪潮中,人工智能作为引领创新的核心驱动力,正以前所未有的深度与广度重塑各行业发展格局。体育领域深度融入科技变革浪潮,驶入数字化、智能化转型快车...

关键字: 人工智能 智能体 AI BSP

上海2025年9月2日 /美通社/ -- 近日,由 ABB、Moxa(摩莎科技)等八家企业在上海联合发起并成功举办"2025 Ethernet-APL 技术应用发展大会"。会议以"破界•融合...

关键字: ETHERNET 智能未来 BSP 工业通信
关闭