| 
  
  加好友  发短信   等级:青蜂侠
	帖子:1393
	积分:14038
	威望:0
	精华:0
	注册:2010-11-12 11:08:23
 | ELF 程序开发教程及技术讨论专贴  Post By:2010-12-10 11:07:00 
 
 | 
	
	西门子x65/x75上的 ELF  程序大家已经见识过了,你有没想过写出自己的 ELF 程序呢?如果你有C语言基础,那么加入 ELF 程序开发的队伍吧。 要在西门子x65/x75上使用 ELF 程序,你应该确定自己的机器 上正确的刷了适合你机型的3个补丁 (如下): function library elfloader swi-hook 查看机型在待机下输入 *#06# 选更多,sW-Version一行就是了 现在的 ELF 程序一般是被刷过以上3个补丁的正确版本的机器所通用的(也有可能会限制机型,看程序怎么写的了8-) ) 下面进入正题目录: 1.IAR SI 安装
 2.在手机上运行 ELF 程序3.如何用 IAR 编写 ELF
 4.例1:内存和文件的操作
 5.例2:屏幕输出和键盘控制
 6.例3:一个后台计时的小程序
 7.例4:内存驻留程序
 8.FAQ1.IAR SI 安装
 从 www.iar.com  上下载  IAR Embedded Workbench  For  ARM 的30天试用版,最新版为4.41好象(>100 mb),程序下载是免费的,但是会要你先注册。填写正确的油箱以后,就会把使用序列号发给你。安装没说的了吧,一路下一步,下一步,等等。2.在手机上运行 ELF 程序论坛 上很多说明了,再扯就远了点:-') 3.如何用 IAR 编写 ELF 开始一个 ELF 程序的编写,还是比较简单 :P  在菜单上选择 “Project->Create New Project”  然后选添加"Project->Add Files"把你用其他IDE写好的C程序添加进来就可以了 工程必须还要有 func.asm (入口点) 和 div.r79 (这个好象莫必要?我也不太清楚,我是业余的:( )  C程序知道怎么写,问题就不大。 你可能会问,怎么使用到手机里面那些需要的功能函数呢?这就需要 swilib.h 这个头文件了(附件提供),这里面定义了n多函数,大家看名字猜吧。。。因为没说明,灭办法,唉。 上面的操作做好以后,就可以编译我们的程序了,在 IAR 环境里左边的 Workspace 下面,把 Debug 选成 Release,然后在工程上点右键,选属性 CPU 可以不用改,下面的 Processor mode 改为 Arm,在 Library Configuration 标签里,把 Library 选成 None,就可以编译了。这里你也可以在 Linker 里面设置相关连接选项。生成完毕后,你就可以在 你的工程\Release\Exe 目录里找到生成的 ELF 文件,放到手机里看看呢?:P 4.例1:内存和文件的操作创建 main.c 如下后添加到你的工程里: 
		最后不要忘了还有 func.asm 这个文件://main.c#include "swilib.h"
 void ElfKiller(void) { //用于 elf 退出时的相关操作
 extern void *ELF_BEGIN;
 //这里一般使用 mfree(), freeWS() 来释放内存
 ((void (*)(void *))(mfree_adr()))(ELF_BEGIN); // 懒得解释 :(
 }
 int main(char *exename, char *fname) { //主函数
 //参数 exename 表示被动使用的ELF? 格式 4:\Zbin\xyz.elf
 //参数 fname 传递文件名, 格式 0:\Misc\data.txt
 //如果 ELF 启动自身则为 0
 char *mem;
 int i, err;
 int handle;
 if (fname) {
 //操作标准文件:
 handle = fopen(fname, A_ReadWrite+A_BIN+A_Append+A_Create, P_READ+P_WRITE, err);
 //表示按记录文件打开,数据添加到文件末尾,如果文件不存在则创建之
 //如果为 handle=fopen (fname,A_ReadOnly+A_BIN, 0,err);
 //则表示按只读方式打开文件,具体常数参看 swilib.h
 if (handle != -1) { //-1 = error
 mem = malloc(10000); //分配内存: AllocWS() 按行分配 (2b)
 if (mem != 0) { //0 = error
 i = fread(handle, mem, 10000, err); //返回读取得字节数,如果错误返回 error。
 //放置你的代码在这里 makesomebody (mem,i);
 fwrite(handle, mem, i, err);
 mfree(mem); //释放内存: FreeWS() 按行释放
 }
 fclose(handle); //关闭文件
 }
 }
 SUBPROC((void *)ElfKiller); //放这个东西在这里就最好了,不存在也没关系!
 return(0);
 }
 //PS. 由于 x65 中文件的读取和记录是按 32767 字节的块操作的,
 //因此将 fread() 和 fwrite() 改造为 fread32 () 和 fwrite32()
 int fread32(int fh, char *buf, int len, unsigned int *err) { // (c) Rst7
 int clen;
 int rlen;
 int total=0;
 while (len) {
 if (len > 16384) clen = 16384; else clen = len;
 total += (rlen = fread(fh, buf, clen, err));
 if (rlen != clen) break;
 buf += rlen;
 len -= clen;
 }
 return(total);
 }
 
		5.例2:屏幕输出和键盘控制;Func.asmPUBLIC ELF_BEGIN
 RSEG ELFBEGIN:DATA
 ELF_BEGIN
 defadr MACRO a,b
 PUBLIC a
 a EQU b
 ENDM
 END
 通过导航键控制屏幕上的符号移动,长按红键退出。本例子基于 TED- A (c) Of rst7 看本例时最好从下往上看:) 创建 main.c 如下后添加到你的工程里: 
		//main.c//屏幕和键盘处理
 #include "swilib.h"
 typedef struct {
 GUI gui;
 //WSHDR *ws1;
 //WSHDR *ws2;
 //int i1;
 } MAIN_GUI;
 typedef struct {
 CSM_RAM csm;
 int gui_id;
 } MAIN_CSM;
 const int minus11 = -11;
 const unsigned int INK = 0;
 const unsigned int PAPER = 1;
 volatile int xx = 0, yy = 0; //绘图坐标
 const char bmp[12] = {0xFC, 0x86, 0xB3, 0xA9, 0xB1, 0xA9, 0x81, 0xFF, 0, 0, 0, 0};
 const IMGHDR img = {8, 12, 0x1, 0, (char *)bmp};
 //============
 //屏幕输出
 //============
 void DrwImg(IMGHDR *img, int x, int y, int *pen, int *brush)  {
 RECT rc;
 DRWOBJ drwobj;
 StoreXYWHtoRECT(rc, x, y, img->w, img->h);
 SetPropTo_Obj5(drwobj, &rc, 0, img);
 SetColor(drwobj, pen, brush);
 DrawObject(drwobj);
 }
 void DrawScreen(void) {
 int *ink = GetPaletteAdrByColorIndex(INK);
 int *paper = GetPaletteAdrByColorIndex(PAPER);
 int x = xx;
 DrwImg((IMGHDR *)img, x, yy, ink, paper);
 }
 //绘制屏幕
 void method0(MAIN_GUI *data) {
 DrawScreen();
 }
 void method1(MAIN_GUI *data, void *(*malloc_adr)(int)) {}
 void method2(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
 void method3(MAIN_GUI *data, void *(*malloc_adr)(int), void (*mfree_adr)(void *)) {}
 void method4(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
 void method7(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
 int method8(void) {return(0);}
 int method9(void) {return(0);}
 //============
 //按键控制
 //============
 int method5 (MAIN_GUI *data, GUI_MSG *msg) {
 //if (msg->gbsmsg->msg==KEY_UP) //释放按键时
 if ((msg->gbsmsg->msg == KEY_DOWN) || (msg->gbsmsg->msg == LONG_PRESS)) //按下键或者长按键时
 switch(msg->gbsmsg->submess) {
 case RED_BUTTON:
 return(1); //发生 generalFunc 流调用 GUI - > 关闭 GUI
 case UP_BUTTON:
 if (yy > 0) --yy; break;
 case LEFT_BUTTON:
 if (xx > 0) --xx; break;
 case DOWN_BUTTON:
 if (yy < 130) ++yy; break;
 case RIGHT_BUTTON:
 if ( xx < 120) ++xx; break;
 //case GREEN_BUTTON:
 //case RIGHT_SOFT:
 //case ENTER_BUTTON:
 //case LEFT_SOFT:
 //case VOL_UP_BUTTON:
 //case VOL_DOWN_BUTTON:
 //case '0':
 //case '9':
 //case '#':
 //SUBPROC((void *)DoDiskAccess,1);
 //降低其他处理的优先级以绘制窗口
 }
 DrawScreen();
 return(0);
 }
 const void *const gui_methods[11] = {
 (void *)method0, //Redraw
 (void *)method1, //Create
 (void *)method2, //Close
 (void *)method3, //Focus
 (void *)method4, //Unfocus
 (void *)method5, //OnKey
 0,
 (void *)method7, //Destroy
 (void *)method8,
 (void *)method9,
 0
 };
 const RECT Canvas={0,0,131,175};
 void maincsm_oncreate(CSM_RAM *data) {
 MAIN_GUI *main_gui = malloc(sizeof (MAIN_GUI));
 MAIN_CSM *csm = (MAIN_CSM *)data;
 zeromem(main_gui, sizeof (MAIN_GUI));
 //ustk=malloc(STKSZ); //为程序分配内存
 //info_ws=AllocWS(512);
 main_gui->gui.canvas = (void *)(Canvas);
 main_gui->gui.flag30 = 2;
 main_gui->gui.methods = (void *)gui_methods; //基本方法(见上面)
 main_gui->gui.item_ll.data_mfree = (void (*)(void *))mfree_adr(); //我也不清楚:(
 csm->csm.state = 0;
 csm->csm.unk1 = 0;
 csm->gui_id = CreateGUI(main_gui); //直接创建 GUI
 }
 void Killer(void) { //退出程序
 extern void *ELF_BEGIN;
 //mfree(ustk); //释放内存
 //FreeWS(info_ws);
 ((void (*)(void *))(mfree_adr()))(ELF_BEGIN);
 }
 void maincsm_onclose(CSM_RAM *csm) {
 //GBS_StopTimer(light_tmr);
 SUBPROC((void *)Killer);
 }
 int maincsm_onmessage(CSM_RAM *data, GBS_MSG *msg) {
 return(1);
 }
 unsigned short maincsm_name_body[140];
 const struct {
 CSM_DESC maincsm;
 WSHDR maincsm_name;
 } MAINCSM = {
 {
 maincsm_onmessage, //信息进程
 maincsm_oncreate, //创建时调用的方法
 //如果机型为 S75 移除以下4行
 //并在 swilib.h 里取消对 #define NEWSGOLD 这行的注释
 //0,
 //0,
 //0,
 //0,
 maincsm_onclose, //关闭时调用的方法
 sizeof (MAIN_CSM),
 1,
 minus11
 },
 {
 maincsm_name_body,
 NAMECSM_MAGIC1,
 NAMECSM_MAGIC2,
 0x0,
 139
 }
 };
 int main(char *exename, char *fname) {
 char dummy[sizeof (MAIN_CSM)];
 //strcpy(filename,fname); //保存数据到文件
 CreateCSM(MAINCSM.maincsm, dummy, 0);
 return 0;
 }
 | 
 
 |