本系列前3篇文章介绍硬件设计与实现,但光有硬件,再好的东西也跑不起来。因此,本篇将介绍如何搭建软件开发环境。本文所使用的软件均为开源软件。
软件开发环境的搭建分为2个部分:
(1)Arduino 端软件开发环境;
(2)NDS端软件开发环境。
一、搭建Arduino软件开发环境
可以说搭建Arduino端开发环境几乎没有一点技术含量。只需要从Arduino官网站下载最新版(尽量不要使用beta版)软件,然后在Windows或Mac OS的电脑上安装即可使用,自带IDE。而Linux版相对复杂一些,可以参考官方的Linux安装文档:Installing Arduino on Linux,这里不再详述。
另外一点,由于设计方案中使用最小Arduino系统,上传程序有两种方案:
(1)使用另一块无CPU的Arduino主板提供串口实现程序烧写;
(2)使用一个USB转串口的线(带FDTI芯片)实现程序烧写,如图1。
以上两种方案任选其一即可。使用Arduino主板烧写程序可以参考扩展NDS掌机连接Arduino (1)--Arduino端最小系统实现 中的第三步。
二、搭建NDS软件开发环境
NDS开发环境分为两部分:(1)编译环境;(2)调试环境。下面先讲编译环境的建立。
NDS开发使用开源开发套件:devkitPro。devkitPro分为好几个部分,其中GBA,NDS,GP32都是基于ARM的CPU,因此都使用devkitARM子套件。然后再配套使用一些库。
2.1,需要安装的内容
对于NDS开发必要安装的如下:
(1)devkitARM:含gcc, g++, objcopy, as, ld, gdb等必要工具。
(2)ndstool:用于将NDS的ARM7和ARM9二进制代码进行合并成一个可以运行在NDS上的nds文件的工具。
选择安装的库和工具如下:
(3)libnds:定义了各寄存器必要的宏和相关的常量以及大量实用的库函数,一般开发都需要。
(4)default_arm7:NDS的ARM7端运行的代码。
(5)dswifi:WiFi代码库。
(6)libfat:FAT文件系统库函数,支持各烧录卡文件读写。
(7)libfilesystem:NDS的nitro文件系统的支持库。
(8)maxmod:音频支持库。
(9)dlditool:用于给ndstool产生的nds文件打dldi补丁的工具。如果程序没用到FAT文件读写功能,不需要打dldi补丁,另外一部分烧录卡有自动打dldi补丁的功能,也不需要。
(10)general-tools:提供了几个有用的工具:bin2s, bmp2bin, padbin, raw2c。
(11)dstools:提供r4denc这个工具。
(12)mmutil:提供mmutil这个工具,用于将 MOD, S3M, XM, IT, and/or WAV文件转换成可以运行用的GBA或NDS ROM。
(13)nds-examples:nds的很多例子程序,非常实用,可以对照自己写。
2.2,编译环境安装过程
安装过程在不同操作系统上有明显区别。如果在Windows上安装,devkitPro提供了自动安装文件可自动完成安装。对于Linux和Mac OS X则需要手动安装,下面重点讲解在这两个系统上的安装过程。安装以上内容,可以选择编译源码安装,也可以下载编译好的二进制文件手动复制到相应目录内完成安装。我这里选择编译源码安装。
步骤一:首先下载以上11个内容。除了devkitARM下载二进制文件外,其余全下载源码进行编译安装。
在相应目录下创建devkitPro文件夹,并将解压后的devkitARM文件夹拷到里面。例如我的Mac OS上创建的路径如下:/Users/Vincent/Documents/OS_Dev/devkitPro/devkitARM。devkitARM文件夹内的内容如下图:
步骤二:设置环境变量。根据自己使用的操作系统编辑不同的文件:Linux在~/.bashrc文件,Mac OS X在~/.bash_profile文件(“.“开头的是默认隐藏文件,所以手工用命令行创建)中最后加入以下代码(实际路径按你自己来写):
#Set Variables for DEVKIT_PRO
export DEVKITPRO=/Users/Vincent/Documents/OS_Dev/devkitPro
export DEVKITARM=${DEVKITPRO}/devkitARM
保存后,重启Terminal终端,路径已经完成设置。
步骤三:安装libnds。将libnds库源码解压到devkitPro文件夹内,和devkitARM同级,即devkitPro文件夹内有libnds-src-x.x.x文件夹,其中x.x.x是版本号。进入该文件夹运行 make,以上步骤没出错的话,稍等片刻libnds库就编译好了,然后运行 make install 进行安装。安装完成后会在devkitPro文件夹下创建libnds文件夹,相应的.a库文件被拷到这里。
步骤四:安装各个库。将2.1小节内下载的(4)~(8)源代码按步骤三的方式解压,进入子目录,然后make, make install,完成安装。因为这些库依赖libnds,所以要确保libnds先安装好。特别要注意一点是maxmod库如果用make命令,会同时编译NDS, GBA两个板本,而要成功编译GBA版本需要安装libgba。如果只需要使用NDS版的maxmod库,则需要执行:make dist-nds, 然后执行:make install-nds。细节可参考相应的Makefile文件。
步骤五:安装ndstool, dlditool, general-tools, dstools, mmutil,其中ndstool是必须的。按2.1小节内下载的这些源码按步骤三的方式解压,进入相应子目录,然后先运行 .configure, 然后运行 make, 最后运行sudo make install,完成安装。最后一步因为要安装到系统文件夹路径下,需要管理员权限,所以加sudo运行。
步骤六:编译nds-examples:按2.1小节内下载的这些源码按步骤三的方式解压,进入相应子目录,然后先运行make。不出意外的话,所有例子程序就会编译成功,在nds-examples-xxxxxxxx文件夹(xxxxxxxx是日期版本号)内会多出一个bin子文件夹,里面是编译出来的nds程序。如果有模拟器就可以运行了。
至此,NDS的编译环境安装完成,下面讲解相对复杂的调试环境。
2.3,调试环境建立过程
可以说不使用价格昂贵的任天堂官方开发套件,构建NDS的调试环境是比较复杂的,该部分也是本文最复杂部分。
NDS调试环境搭有几种方案选择:
(1)选择任天堂官方开发套件:价格昂贵,个人几乎不可能购买。
(2)使用no$gba debugger版模拟器:收费,最便宜的$15的个人版功能有限,功能强大的企业版上千美元。而且只支持Windows系统。我用过个人版,调试过程是在no$gba软件内部进行,非常不方便使用,不符合一般开发人员的使用习惯,而且功能实在有限。
(3)使用DeSmuME模拟器 + Insight。devkitPro提供编译好的Insight,只支持Windows系统。
(4)使用DeSmuME模拟器 + GDB + DDD。这是我用过最习惯的最舒服的环境,而且支持Linux, Mac OS X系统。
主张开源,免费的我,方案(1)和(2)直接淘汰。对于方案(3),因为Insight是内部集成GDB调试器的,两者不能独立,而且在Linux和Mac OS X系统下Insight默认使用的GDB是i386架构的版本,读者需要自行配置arm版本进行重新编译,这种捆绑形式对我不是很感冒。因此,本文推荐方案(4),一方面由于DDD体积小,和GDB独立,另一方面这个方案扩展性好。扩展性很重要,以后如果3DS, PSV等掌机破解后,可开发自制程序,都可以使用这个方案进行配置。
下面以Mac OS X系统上如何配置调试方案(4)进行详述。
2.3.1 DeSmuME模拟器及调试功能的使用
DeSmuME是一款NDS模拟器,从玩游戏角度来说没no$gba好,但对开发人员来说支持GDB调试接口。模拟器的Windows和Linux发行版直接集成了GDB stub接口,可直接使用。而且Mac OS X发行版默认不支持GDB stub,因此需要自行编译源码来支持。这不是本文的目的,因此我这里直接采用国外一高手编译好的版本来使用。Mac OS X上的具体编译过程可以参考:Installing DeSmuME from source on OS X 这个官方教程。
使用DeSmuME调试功能,需要命令行带参数执行:
your_path/DeSmuME.app/Contents/MacOS/DeSmuME -arm9gdb 20000
两点说明:
(1)Mac OS X的软件实质上都是.app文件夹,真正的可执行程序在其Contents/MacOS/路径下。因此,Windows版本和Linux版本无需前面部分,直接运行your_path/DeSmuME -arm9gdb 20000。这里的your_path是你电脑上存放DeSmuME的路径。
(2)这里的参数-arm9gdb 20000:前面的 -arm9gdb 是指启动arm9的代码调试功能。20000是GDB远程调试的IP端口号,按约常规的方式不要使用0?1023这1024个保留端号口。因为NDS有两个CPU,如果要调试arm7部分的代码,则使用-arm7gdb xxxx,即可。
按上面的命令行执行后,模拟器就会启动,见图3左。然后选择菜单选择相应的需要调的.nds自制程序,加载后效果见图3右。
图3. 左:带GDB调试功能启动模拟器。右:加载NDS可执行文件后的模拟器。
图3右,模拟器显示白色,下方显示"Executing",这说明此时模拟器已准备就绪,等待GDB调试器的远程连接,并接受GDB发来的命令进行操作。至此,模拟器部分准备工作就绪。
2.3.2 GDB调试器功能的使用
一般一个特定平台(如ARM或MIPS)的工具链中除了提供gcc, as, ld, objcopy等工具外,也同时会提供相应的gdb。devkitARM中提供的GDB位于路径: devkitARM/bin/arm-none-eabi-gdb 。
要使用GDB调试程序,首先被调试程序必须含有可调试信息。这要求在编译程序源码时必须添加 -g 命令行参数,如:
gcc -g hello_world.c
在devkitARM工具链中生成的二进制文件中含有elf格式文件,后缀名也为.elf。这个elf文件就可以用来在GDB中进行调试。执行如下命令:
your_path/arm-none-eabi-gdb file_path/hello_world.elf
然后会进入GDB命令行。因为我们的程序需要和DeSmuME配合调试,程序本质上是在模拟器上运行,因此,GDB需要和DeSmuME建立IP连接,所以在GDB命令行中输入以下命令:
target remote :2000
这条命令的原型为:target remote IP:port 。IP为需要被调试的目标的IP地址,port为端号口。因为我们的目标(模拟器)也在本机上,因为IP可以不写,端口号一定要与模拟器运行时的一致。执行上述命令后,如果DeSmuME已经按上述设置好,GDB就能成功连接上模拟器,显示图4内容:
此时,可以输入GDB命令控制模拟器,比如单步执行(Step, Next),执行到下一个断点(Continue),显示代码(List),设置断点(Break)等等,具体可以参考GDB使用手册。图5为我让显示让程序执行到断点(37行)时的模拟器和GDB调试窗口的截图。
这个例子中我调试的程序使用以下代码,并使用-g参数编译:
#include
#include
volatile int frame = 0;
//---------------------------------------------------------------------------------
void Vblank() {
//---------------------------------------------------------------------------------
frame++;
}
//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
touchPosition touchXY;
irqSet(IRQ_VBLANK, Vblank);
consoleDemoInit();
iprintf(" Hello DS dev'rs\n");
//iprintf(" \x1b[32mwww.devkitpro.org\n");
//iprintf(" \x1b[32;1mwww.drunkencoders.com\x1b[39m");
iprintf("\n blog.congao.net\n");
iprintf(" Vincent(c_gao)'s Blog");
while(1) {
swiWaitForVBlank();
touchRead(&touchXY);
// print at using ansi escape sequence \x1b[line;columnH
iprintf("\x1b[10;0HFrame = %d",frame);
iprintf("\x1b[16;0HTouch x = X, X\n", touchXY.rawx, touchXY.px);
iprintf("Touch y = X, X\n", touchXY.rawy, touchXY.py);
}
return 0;
}
2.3.3 DDD功能的使用
DDD (Data Display Debugger)是一个图形化调试前端工具,其本身没有调试功能,需要配合GDB一起使用。Linux系统下安装DDD非常方便,但在Mac OS X下就比较麻烦。首先讲解如何在Mac OS X下如何安装DDD,对于Linux系统这部分内容可以省略。
OS X上安装DDD
DDD是标准的X11应用程序,X11和OS X系统之前有着很大关系,Apple公司专门有一个项目叫XQuartz,为使X11应用程序在OS X系统运行作努力。为使DDD能在OS X上运行,需要安装以下两个软件:
(1)XQuartz:OS X 10.7自带不用装, 10.9需要另行安装。
(2)Fink:引用wikipedia的一句话,The Fink project is an effort to port and package open-source Unix programs to Mac OS X.
这里我就不讲如何安装这两个软件了。假设你已安装好这两样。
Fink使得你可以使用Debian的很多pkg安装包,还带了非常有用的ap-get命令。因此,熟悉Linux命令的读者很容易上手。首先执行sudo apt-get update,然后sudo apt-get install ddd,即可完成DDD的安装。
安装好DDD后,我们现在使用它来配合DeSmuME调试程序(而不是命令行的GDB)。安照2.3.1节DeSmuME准备就绪后,运行如下代码启动DDD:
ddd --debugger your_path/arm-none-eabi-gdb file_path/hello_world.elf
这里的
(1)第一个参数--debugger,指定后面的your_path/arm-none-eabi-gdb作为DDD的调试用GDB;
(2)第二个参数file_path/hello_world.elf为需要被调试的带-g编译出来的elf文件,这和2.3.2节一样。
如果输入没有错误,回车进入DDD调试窗口,窗口下方是GDB命令行子窗口。在这个命令行子窗口内同样输入以下命:
target remote :2000
此时,DDD内的GDB就能连接上模拟器,就可以进行图形化调试之旅了。图6是调试过程载图:
至此,本篇主要内容讲完了。
后记:
(1)在OS X 10.9的系统中安装Fink有点繁杂,但只要仔细按要求一步步操作就不会有问题。
(2)我在写这篇博文时,用的OS X系统自带的五笔中文输入法,在按了caps lock键后可以转换为英文输文。但是在这样的英文输入状态下,命令行启动DDD时,DDD下方的GDB子窗口输入英文就会变成乱码,即使这时把中文关了也会输入乱码。最后发现必需在命令行启动DDD时,输放法状态就得是标准英文输入状态。
(3)我一开始在DDD下方的GDB子窗口中不管输入什么GDB命令都提示“waiting until GDB gets ready“错误,后google之后发现这是DDD的一个bug,只要按照这篇文章DDD - Bugs: bug #32949, "waiting until GDB gets...,先关闭DDD,然后修改~/.ddd/init文件内的一行:将set extended-prompt not set\n\ 改为 set extended-prompt (gdb) \n\ 最后重启DDD便可。
请待下篇....