用C扩展你的HP 50g - 总目录与第一部分

Extend your 50g with C

CONTENTS & SECTION 1

总目录与第一部分

原文章版本:1.12 (2008-10-09)
翻译版本:0.01 (2016-09-23)
基于HPGCC版本:2.0SP2
作者:Egan Ford (egan NO_SPAM_AT sense.net)
译者:Andy Lithia (Lithcore.cn)

原文地址:http://sense.net/~egan/hpgcc/


目录

第一部分

前言

-为什么用C?

-为什么不用C?

-什么是HPGCC

-免责声明

开发环境

-硬件要求

-软件要求

-用户要求(误

-安装 Cygwin/X (仅针对Windows用户)
-安装 HPGCC 及扩展
-HPGCC 2GB SD 卡支持

//注:因为windows下开发可以使用HPGCC2的集成开发环境,该部分内容已省略

-题外话: 先把玩一番!

-ARM工具集(ARM Toolbox)安装

-设置环境变量

HPGCC上手

-Hello, World

-崩溃(Crash)

-宕机(Hang)

-C的封装器(Wrapper)

-数据类型

-C程序真是太大了

-基本程序模板(Base Template)

-用C扩展你的50g

-调试

-HPGCC的测试环境——HPAPINE 101
-Makefiles

-支援

-总结

第二部分:例子

-准备工作

-例1:实数/复数的 LogGamma函数:

该例子展示了在C语言中使用复数的方法。C本身不像是C99,C++,FORTRAN,它没有对复数的原生支持。而且LogGamma函数是一个特别的函数,和50g提供的ln(gamma())并不一样

-例2:稀疏矩阵系统求解器

该例子是一个执行速度非常快的稀疏矩阵系统求解器,它可以求解一些对于50g自带的求解器太庞大的稀疏矩阵。该例子还会展示如何使用列表和数组

-例3:多种计算π的方法

这个例子似乎对于我们使用50g没有什么直接的用处,不过它很有趣!这恶个例子展示了如何使用 任意精度数学库 和 长整数数学库,以及如何处理文件与屏幕文字输出

-例4:使用计算机图形库

该例子展示了如何将现有的C语言CG程序(包括二位凸包几何,维诺图这些)转换为静态或可交互的CG应用程序。该例子同时会展示如何截取屏幕图像(黑白或灰度),以及结尾展示的,带有一个APPS界面,可以再发行的CG库。

第三部分:更多例子

-准备工作

-例:Viète函数快速算法:

该例子展示了使用libfsystem,对SD卡读写超大数组的方法;SD卡速度测试的方法;如何文字模式光标定位;如何生成Excel 3D图表以及如何在C程序结束后,留下一段动态生成的UserRPL程序以进行进一步处理。

总结

特别感谢

参考

 


第一部分

前言

这篇长长的文章将解释为何,与如何使用C语言,来扩展HP 50g计算器的机能。我们提供了详细的例子,来演示如何使用C语言在HP 50g上实现高性能的数学函数(比如对复数的LogGamma函数);稀疏矩阵系统求解器;还有二位凸包几何的绘制

本文将始终围绕两个主题进行:

  1. 坚持简洁的原则,用正确的工具干正确的事:C语言不能替代UserRPL,比如在进行栈操作的时候,一两个UserRPL指令就可以完成C语言需要好几行才能完成的事情。而换个角度来说,C语言运行的速度比Saturn汇编还要快一些,而且在编写大型程序时,C语言更容易编写,阅读与调试。
  2. 不要从头造轮子:现在有很多数学方面的C程序可供使用,本文的例子中大多数都是基于现有的C程序编写的。

这篇文章不能代替HPGCC,C以及HP 50g的文档,而应该算作“教程”一类。阅读本文不需要对C语言特别深入的了解,其实一个没有写过C的人也可以编译并运行文中所有的例子。不过如果想要真正从本文中学到什么,最好还是要对这门语言有个了解,下面有一些推荐:

  1. 「The C Programming Language」 by Kernighan and Ritchie:这就是传说中的“the C book”,也经常被简称作“K&R”,这本书短小精悍,如果你理解能力比较强的话直接看这本书就可以了。我是用第一版学的,第一版现在已经是收藏品了。希望我买到第二版后还能找到我的那本书。
  2. 「C Primer Plus」by Stephen Prata:风趣又详细,人们觉得这本圣经尺寸的砖头书比K&R要更好理解一些。书中还详细讲解了指针和结构体这些人们常用的东西。

为什么用C?

  • C很快,非常快
  • 有很多现成的数学程序和库,可以节省不少时间
  • 可以快速开发,设计程序原型。书中的例子最早都是在我的工作站上实现的,然后要不了一会儿就移植到50g上了
  • C用的更广泛,C(不像是SysRPL和saturn汇编这些)几乎可以用在任何地方。50g的C语言编程是一个嵌入式编程的典例。嵌入式交叉编译,对象体积优化和除错的技能在其他很多场合都能派上用场。
  • 可移植性很强。花不了多少功夫就能让你的50gC语言程序运行在PC,Mac,PDA甚至是TI的计算器上(TIGCC)
  • C很酷

什么不用C?

  • 串口和USB I/O还不支持
  • 在计算器上,小巧的UserRPL程序已经很好了,为什么要用更麻烦的方法呢?“用正确的工具做正确的事”嘛。

什么是HPGCC

HPGCC是一个在x86平台运行的基于GCC的HP-50g交叉编译工具包,不需要费多大力气就能被移植到几乎任何平台。
原版HPGCC2只支持C语言,后来由Jean-Yves Avenard改进的linux/Mac版本也可以支持C++。因为是基于GCC的缘故,其他语言比如FORTRAN的前端也可以被移植过来,想想你可以在50g上运行原有的FORTRAN代码了,甚至可以比编写那些代码用的电脑跑的还快呢!
不像是UserRPL、SysRPL和Saturn汇编,50g的ARM二进制文件是运行在RPL环境之外的。这带来一些优点:比如更快的运行速度和更多可用内存。HPGCC将port0和port1用做一个完整的内存块,再加上未被RPL系统使用的90K内存,总共有459K可用内存(假设port0和port1都是空的)。尽管50g的ARM二进制文件是运行在RPL环境外的,它仍可以通过直接读写被RPL环境控制的内存块而实现与堆栈系统的交互。

免责声明

请自行承担风险!虽然到现在为止还没有因为用HPGCC而砖了HP50g的事情发生,但凡事皆有可能。我觉得可能发生的最糟糕的事就是因为捅的次数太多而搞坏reset键。只有一个事情有点吓人:在写屏幕的时候崩溃了一次,而那条线一直保持在屏幕上,过了十几秒才消失。当然我不担心,因为我后来还试了好几次,发现不会损坏什么。

开发环境

硬件要求

  • 一台50g:不管你信不信,其实没有这个你也能开发并测试很多东西了,不过最终还是要有一台实机来运行一下子嘛。要注意:48EMU只是个Saturn的模拟器,所以不能运行ARM二进制文件
  • 一条50g的USB或串口线:因为同时还能供电,50gUSB线似乎是个更好的选择。如果遇到了一些USB文件传输方面的问题,可能需要使用串口线(注:很难买)
  • 一个SD卡:有10M就够了。我用的是一张128M的卡,用起来感觉跟无穷大一样。
  • 一个SD卡读卡器:(略)
  • 一个小纸片:如果没有这么个小纸片来帮助你随时断开7号电池的电源,你绝对不会想要在50g上调试程序。
  • 一个工作站:因为暂时还不能机上编译,你需要用这个来进行HPGCC交叉编译

软件要求

(注:win下使用HPGCC2即可,该部分内容省略)

用户要求(误

你应该掌握:

  • 在PC和50g之间传输文件
  • 在PC和SD卡之间传输文件

在50g上操作SD卡,感觉有困难的话可以阅读这篇文档:50gUsing_an_SD_Card.pdf

题外话: 先把玩一番!

在HPGCC目录下有两个文件,包括了所有的包装过的C程序,二进制文件和库,安装方法:
1.把HPGCC.hp放到50g的HOME下
2.把EXTEND.ZIP解压到SD卡根目录
不想为了找这两个文件重新安装HPGCC?没关系:
http://sense.net/~egan/hpgcc/EXTEND.ZIP
http://sense.net/~egan/hpgcc/HPGCC.hp

ARM工具集(ARM Toolbox)安装

如果要运行ARM二进制文件,你需要在50g上安装ARM工具集,使用ARM工具集运行该文件,或者使用ARM工具集将该二进制文件转换为50g可以直接执行的可执行文件。作为开发者,你必须使用ARM工具集,而在将那个ARM二进制文件转换为可执行文件后,在没有安装该工具集的设备上也可以直接运行了。

  1. 将HPGCC2安装目录下的/sources/ARMToolbox/SETUP.BIN文件复制到50g中
    armtool1
  2. 把数字“2”放到堆栈上(意为安装到Port2,也就是Flash内存中)接下来,把SETUP.BIN放到堆栈上,注意是对象本身而不是它的名字('SETUP.BIN'),你的50g应该显示如下:
    armtool2
    现在,按 botton_eval ,然后按 botton_on + button_f3
  3. 通过按 button_right button_two soft_armto 确认安装成功

设置环境变量

(略)

HPGCC上手

假设50g上的当前目录是HOME/HPGCC/TEST

Hello, World

就让我们从K&R最经典的hello, world程序开始吧

这个hello, world和最经典的那个有一些细小的差异:
1.头文件hpgcc49.h替代了普遍存在的stdio.h,hpgcc49.h包括了HPGCC使用的其余头文件。基本上所有的HPGCC函数都是由这个头文件定义的。
2.clear_screen(),这个函数尽管不是必须的,在显示文字时,最好还是调用一次以清屏:(上:调用清屏,下:未调用)

helloclearhellonoclear
3.WAIT_CANCEL,也不是必须的,但是如果你想在退出到50g UserRPL环境前看清显示了什么,你需要一条暂停的指令。WAIT_CANCEL将暂停执行,等被按下后继续执行。
要编译并执行该程序,在电脑上输入下列指令:(注:windows的IDE下不需要)
make clean
make hello.hp
接下来,在50g上新建一个HOME/HPGCC/TEST目录,把hello.hp发送过去,需要运行该程序的话,按soft_hello(在var菜单),你会看到一堆乱码,接下来button_right button_two soft_armto soft_prrun,要退出的话按botton_on

可以让这个程序不依赖ARM Toolbox执行,按soft_hello,然后button_rightbutton_two soft_armto button_nxt soft_prrun,接下来按 button_var button_left soft_hello,这个过程是将原本需要soft_prrun执行的soft_hello覆盖为不需要就可以执行的文件,现在要运行的话只需按soft_hello,很简单吧!
从这里往后的例子,都需要被转换为可直接执行的文件

Hi Bob!

接下来我们来尝试一些更有趣的东西:

这个程序以栈上一个字符串为参数,返回一个在源字符串前后加上"Hi"和"!"的新字符串,接下来我详细解释一下这个程序:
"name = sat_stack_pop_string_alloc()"从RPL堆栈上取一个字符串,给该字符串分配一些内存,然后把指向该字符串的指针返回到name里
"sprintf(buf,"Hi %s!",name);"将name指向的字符串复制到buf里,前后加上"Hi"和"!"
"sat_stack_push_string(buf);"将字符串buf压入栈

这个程序就不需要一条暂停等待输入的指令了,我们像刚才一样编译这个程序并创建可执行文件,然后往堆栈上随便放一个字符串,执行一下soft_hi,就变成了这样:

(上:执行前,下:执行后)

hi

hibob

崩溃(Crash)

如果你还没有reset过你的50g,找来一张纸片,搓成条后捅进50g后面的复位孔里,你可能经常需要这样做。复位操作后应该只会丢失当前堆栈上的内容。

崩溃可能由你或他人程序里的一个bug导致,希望这些bug都是你写出来的(这样你就能轻松地解决了)。C语言很容易因为误用指针而导致崩溃,这被称作“段错误”,想要触发这样的错误只需要尝试访问未被定义的内存空间即可。在多数基于CLI的工作站上,这样的错误会返回一些有用的错误信息,比如"Segmentation fault (core dumped)"。HPGCC上,段错误不会带来任何提示,死循环亦不会有任何提示,这使得调试HPGCC程序变得非常有挑战性。这就算是C语言和它强大力量一起带来的见面礼吧。

看看刚才那个hi.c,找到问题在哪了吗?如果name指向的字符串长于36字符会发生什么?buf只有40字符的宽度,4个被"Hi!"占用了,丢一个长度为40字符串进去,执行soft_hi,然后那个小纸片就能派上用场了。在我的工作站上,这会提示发生了一个“段错误”,HPGCC处理这个错误了吗?不知道,希望在以后的版本里HPGCC能在发生这种错误时将内存dump到SD卡里面,以便调试。

这个问题很容易修复,比如你可以只取前35个字符(加上空字符是36个)然后丢弃其余的,可以动态分配buf,也可以拒绝接收超长的字符串。

宕机(Hang)

宕机与崩溃不一样,宕机时程序可能只是卡在一个循环里或者等待I/O操作的完成,在基于CLI的环境里你可以通过手动发送一个中断来终止这个操作(比如 ctrl+c),但是在HPGCC里没有这样的支持,你可以在你的代码里加入一些东西来提供“紧急出口”
比如,这个死循环:

改成这样:

同样是死循环,加入了这些代码后,你可以通过按键来跳出循环。如果你确实要执行长耗时的操作,可以添加一些指示(例如动态的沙漏图样)来表明程序依然在执行,防止用户当成程序崩溃而使用reset。第二部分的二位凸包几何计算中就有一个进度条的例子

C的包装(Wrapper)

我们提到过,C不能完全取代UserRPL,UserRPL提供了一些异常强大的输入输出功能与堆栈操作功能,这些功能用C实现非常困难。比如使用RPL制作的窗体,换做C来实现并不能比RPL快多少,所以为什么要为难自己呢?代码越长,越容易有bug,换句话说,保持代码短小精悍,用正确的工具做正确的事。使用UserRPL为你的C程序做一些简单的包装在有些时候效果显著,比方说如果像刚才那个程序里输入一些非字符串类的对象

hi_nulls

上图中向hi输入了实数,复数,名称这三类数据,hi.c不能从栈上获取一个字符串,所以结果都是返回了"NULL",现在为这个程序做一个这样的包装:
\<< \->STR hi \>>,就可以解决这个问题,像这样:

hiwrap hiwrap2 hiwrap3

如果什么都不输入,就会(由->STR指令)返回一个"Too Few Arguments"错误。如果要在C中做这样的识别,是可能的,但是非常困难,而且得不偿失

包装还有一个用处就是为C程序显示错误信息,下面有一个改良版的hi2.c程序:

这个改良版的hi程序可以检测非字符串类数据和过长的字符串,并给出一个错误信息和一个错误代码(在这个例子中,错误情况下返回的是1),如果没有错误的话,将新字符串放到栈上并返回0.注意如果name字符串过长的话,它会被放回到栈上,以保持与50g原生指令行为一致。至于NULL的话不管就可以了,因为不会有什么东西被从栈上取走。

新的包装与错误情况的演示如图:

hi2a hi2b hi2c

在这个新的RPL包装里,我们使用一个IF指令来判断返回值是0还是1,如果返回了1,使用DOERR指令来显示一条漂亮的错误信息。如果是0,结束执行,在栈上留下处理后的字符串。这样吃力比之前的hi程序要友好不少——你不会得到不想要的结果了

使用包装的另一个好处是便于创建由C子程序组成的库文件,我们会在后面再聊这个话题。

数据类型

C是一个静态类型语言,也就是说变量的类型要在编译开始时就确定,UserRPL则是动态语言,也就是说变量的声明和分类是在运行时进行的,这种动态/静态的差异可能在C与堆栈交互的时候造成一些麻烦,就像上面的hi.c遇到的一样。协调这种差异的是,UserRPL的数据类型远多于C,而C可以通过结构体定义新的数据类型,比如用两个实数表示一个复数。

在这篇文章中,UserRPL包装主要被用作数据的预处理,将数据传递给C程序,并处理C返回的结果。这是个针对上述差异的简单解决方案,不过不是唯一的,比方说,有一个叫HPStack的HPGCC库提供了一些C语言的结构体和函数来操作UserRPL体系中的数据(比如列表,数组和复数)

关于C数据类型、数组,结构体的详细讲解并不是这篇文章需要关注的,但是我觉得任何一篇好的关于C语言的文章都要涉及一点这个非常重要的内容。从数据管理的角度,了解如何将C与基础的UserRPL相结合,以及每种类型在内存中如何存储,将更有利于节约内存。下面这个程序会返回每种常见的C类型在HPGCC环境中

sizeof

size_t是留给指针使用的,长度为4字节,之使用是这个长度,是因为ARM处理器的地址为32位,char是单个8bit字符,它也可以被用作非常短的整型。注意:C没有字符串这种类型,取而代之的是一个字符数组。short、int和long是有符号整型。float和double是有符号整数

UserRPL中的整数,只要长度合适,就可以C中的任意整型数据进行数据交换。因为50g原生支持超长整数,并不是所有的整数对象都可以被读入C中的整型数据中。如果你的C程序可以操作超长整数(见第二部分的任意精度π计算程序中使用的Unbounded Spigot算法),你可能需要以字符串作为接收的中介。

UserRPL中的实数可以与C中的双精度浮点数进行交换,使用->NUM对C程序进行包装可以省去很多不必要的麻烦,比如在准确模式下接收1/2的,计算器认为这个对象是一个代数对象而不是一个实数对象,->NUM会将所有物体转换为实数(包括整数,甚至符号对象和变量对象)

C程序真是太大了

如果你编译或安装了上面教程的所有例程,你会发现自己的RAM空间已经明显地减少了:

filesizes

共有76KB的空间被这些小程序占用了,一个原生50g只有少于241KB的可用空间。解决方法很简单,就按照数字时代之始那些先驱的做法来做就行了:把内存里的程序放到外部存储器里

创建下面这样一个UserRPL程序,把它保存到HOME/HPGCC目录下叫'INSTALL'的变量里。接下来把它放到用户自定义菜单里面('INSTALL' 1 ->LIST MENU)

install

这个UserRPL程序把一个编译好(但未被转换为可执行文件)的C程序推到栈上,从内存里把它删除,将它转换为可执行文件,然后保存到SD卡的"EXTEND/程序名"目录里,如果SD卡里有重名变量,就将其覆盖,如果EXTEND目录不存在,就新建一个EXTEND目录
把HOME/HPGCC/TEST目录下除了HIWRAP外的东西全部删除,然后把hi2.hp发送到HOME/HPGCC/TEST,要安装这个程序,按button_var button_singlequote  soft_hi2 button_enter button_left button_mode soft_install

用文件管理器打开SD卡,你会看到EXTEND目录,里面有一个已经转换为可执行文件的HI2

sdext1 sdext2 sdext3

注意:SD卡的文件系统有一些限制:

  • 文件和目录名必须是8.3格式:SSSSSSSS.XXX,扩展名可省略
  • 文件名不区分大小写,在通过上位机软件发送文件时,.hp后缀会被移除。

在把C二进制文件发送到SD卡后,如果想要通过内存中的RPL包装程序来调用那个C程序,需要做一些小改动,以HIWRAP为例:(上:旧 下:新)

hi2a hi2d

(注:将原本的 hi2 ,也就是直接执行当前目录下的hi2程序,换成了 :3:(切换为3号存储器)"EXTEND/HI2" (取EXTEND目录下的'HI2'变量名)EVAL(对变量名'HI2'执行求值操作,也就是执行))

基本程序模板(Base Template)

上面的例子已经为你打下了一个不错的基础,不过有一个关键点还没有注意过:速度。
下面是一个更好的程序框架:

50g的默认速度是75MHz,这是为了执行Saturn模拟器而选取的速度。HPGCC默认执行速度是12MHz,但是也可以加速到75MHz。我做了一些测试,发现在12MHz下HPGCC的速度比Saturn快大约15倍(与UserRPL相比),在75MHz下快90~100倍。当然在性能和电池寿命之间是要做出妥协的,虽然我猜大多数人都会选择全速运行

函数 sys_slowOff() 以及 sys_slowOn() 是用于切换运行速度的,在声明完变量后调用 sys_slowOff() ,这会让50g全速运行,并加快电池消耗。完成代码部分后,再以 sys_slowOn() 切换回正常模式

如果你要使用 WAIT_CANCEL来暂停或要调用其它输入函数,我建议你先使用一次 sys_slowOn() 和 beep() 。因为50g在UserRPL环境之外不会自动关机。可能在一次长时间的计算后,你的注意力移开了, beep() 可以提醒你,如果有什么情况使得你依然没有操作,在低速模式下至少能省一些电。

如果你的程序中多处涉及等待或暂停,建议你多使用这些函数,比方说在一个象棋游戏里,为什么要让计算器在人思考的时候继续吃电池呢?

用C扩展你的50g

真的想要扩展50g的话还是要将C程序转换为库,这样才能加强C程序的可泛用性。
在本部分的最后一个例子中,你将学会如何用C为50g创建一个AGM(算数几何平均值)函数。这个例子其实不应该在C里面做,因为该函数收敛的非常快(UserRPL比C运行的还要快),但作为例子还是不错的。
AGM UserRPL版本

agm.c C语言版本

AGM函数使用两个实数作为参数,返回一个实数。AGM的计算精度大约在每次循环之后翻一番,只需四次循环就可以超越64位浮点数能容纳的精度。但是不要这样假设,我们使用while来检测a和b的值从而判断精度是否足够,注意有可能导致无限循环,接下来我们想想解决这个问题的方法:

  1. 留个出口,在C程序的循环中使用keyb_isAnyKeyPressed来判断是否有按键被按下,如果有就break循环并返回到目前为止计算的数值。UserRPL程序因为可以通过CANCEL(botton_on)键中断执行,不需要特意这样做。
  2. 证明对于64位浮点数,总能在有限次数循环中完成计算
  3. 将4这个循环次数硬编码到循环里。花些时间来理解这个算法背后的数学原理对于优化有非常显著的好处,这是计算机算法设计者数十年以来积攒的经验——我们要遵循传统。

既然sqrt函数不能计算负数,我们需要加入额外的检测,这些内容交给包装程序来完成
按照之前说过的方法将agm.C编译并安装到SD卡,接下来我们来创建这个包装程序

(/**/中的内容为注释)

为什么不全部使用C写呢?

  1. 库是需要RPL包装的
  2. 现在用HPGCC的代码来检测操作数是否为实数异常困难
  3. C无法处理如代数对象(如symbol_sqrt2)这类RPL对象,尽管它们也是数值
  4. 性能上没有多大优势
  5. 会导致C程序变得冗长且复杂

我建议不要把C二进制文件或者C可执行文件打包到C中,这会导致库的体积非常大,而内存是很有限的。
我们使用RPL包装的形式,让库去调用保存在SD卡里的C程序。

最后,要建立一个库的话,我们需要借助256号库提供的工具
将以下这些变量放到和刚才的程序相同的目录下:

变量 描述
$TITLE
"EXTEND" 这是你要建立的库的名字,前5个字符会被显示在library菜单里
$ROMID
1313 使用一个实数作为你的库ID,这个ID一定要是唯一的(不能与计算器内其它库的ID冲突),取值范围是769-1792,这里随便取了个1313
$CONFIG
1 默认设置
$VISIBLE
{AGM} 这个list类对象包含里你希望在库菜单里显示出来的对象的名字

刚才那个目录HOME/HPGCC/TEST现在看上去应该像这样:

libdir

现在我们创建该库:

256 ATTACH button_enter
CRLIB button_enter
:3:EXTEND.LIB button_enter

现在堆栈看上去应该像这样:

libext

(一个库对象和一个指向SD卡的变量名'3:EXTEND.LIB')

按一下button_sto,将该对象保存下来,现在SD卡里应该有一个EXTEND目录和一个EXTEND.LIB库对象,如果想要与他人共享你的库文件,将这两个打包发送即可,安装过程如下:

  1. 插入SD卡
  2. 输入:
    :3:EXTEND.LIB button_enter botton_eval(调出库)
    2 button_enter(指定安装到二号端口,也就是FLASH中)libextr
    接下来按button_sto,然后botton_on + button_f3
  3. 测试一下,试试各种类型的数据,看是否正常工作

恭喜,你成功地把AGM加入到了50g的动词库里,如果你想的话可以把我们一开始测试用的HOME/HPGCC/TEST目录删除了,因为现在我们是直接通过1313号库和SD卡下的EXTEND目录里的文件来运行程序了

在计算机图形那些例子中,我会进一步讲解如何创建一个可以显示在APPS菜单中的库(注:比如元素周期表,其本质是一个库)

调试

用调试工具调试C程序有挑战性,不用调试工具的话很有挑战性。HPGCC虽然没有提供传统的那种调试器(比如GDB),但是我们确实包含了原汁原味的80年代调试器——printf,如果你没有笑出声,说明你C语言这边还算年轻

调试的几个途径:

  1. 先在工作站上测试,这是C语言最美妙的地方,它可移植性超强,算法和文件IO这些都可以比较好地跨平台测试,然后再移植到50g上,这样会减轻不少负担
  2. printf,直接通过输出的内容获得当前的状态,这是个久经考验的方法——估计自计算机可以使用打印机输出东西以来就有人这么做了
  3. fprintf,将log信息保存到文件里
  4. 使用HPAPINE模拟器,这个东西对加速开发还是很有帮助的,它兼容GDB这些工具
    (注:EMU48是saturn模拟器,所以无法执行ARM程序,而HPAPINE是个专门为HPGCC开发的工具,可以执行ARM程序,并模仿一些简单的栈操作,这部分内容需要*nix知识,因为该程序只能在*nix环境下或者Cygwin这种支持X的linux on windows环境下运行,在这里省略了,如果一定要使用这个进行调试,可以访问其官网http://kdntl.pagesperso-orange.fr/hp49/hpapine

HPGCC的测试环境——HPAPINE 101

(略)

Makefiles

(windows IDE下不需要使用makefile进行生成,该部分略)

支援

你有以下几种方法获取支援:
1.阅读HPGCC自带文档:
doc_html目录下,有大量详细的文档可供参考:

  • decNumber:完整的ANSI C浮点数实现
  • fsystem:文件系统
  • ggl:灰度图形库,增强的16阶灰度支持:快速图像拷贝,精灵,抗锯齿
  • hpg:提供了基础绘图功能:灰度支持,双缓存硬件换页绘图,图片变换,XPM图片加载,绘制图形,控制指示灯
  • hplib:HPGCC标准库:简化的C标准库实现,硬件操作支持,RPL系统调用支持,栈交互
  • win:窗口库,用于制作图形界面,主要功能:提供了一个多用途消息队列的实现,允许用户以一个简单的模型来制作图形widgets,对HP键盘提供了完整的支持,对软键盘区的支持

2.参考HPGCC官方网站 http://hpgcc.org
3.订阅HPGCC的邮件(已挂)
4.Google搜索,找不到的话可以去comp.sys.hp48新闻组和其他人进行交流,如果你没有NNTP软件的话,可以使用这个:http://groups.google.com/group/comp.sys.hp48/topics
5.使用hpmuseum.org的论坛,或者去http://www.cafepress.com找计算器爱好者帮忙
6.HPGCC是开源软件,可以直接阅读源代码

总结

希望你看完这部分后已经有足够的知识来搞个大新闻了。接下来你可以看一看别人写的代码,借此来学习。安装目录下的examples文件夹里面有很多不错的例子。本文的第二部分是一些借助现有开源C程序构建的,更复杂的例子。阅读愉快

Leave a Reply

Your email address will not be published. Required fields are marked *