一、前提
1、要保证编写的app文件能够正常运行除了前面所提到的设置之外,编译程序的先后顺序也非常重要,系统程序先编译,然后再编译APP程序,如果系统程序因为一些修改而重新编译,则APP程序也必须重新编译,因为生成的syscall.sym文件中的函数地址会随着系统工程的重新编译而更新。
2、如果要在APP中调用在系统程序中声明过但未使用的函数,为了防止被编译器优化掉,可以在系统工程中"C/C++"选项卡中去掉 One ELF section par function 前面的勾选,然后删除 syscall.sym 文件再重新编译。
3、如果在系统工程中添加了新函数,并且希望在APP程序中能够调用此函数,则需要在编译系统工程前,删除 syscall.sym 文件,然后自动生成的 syscall.sym 文件中才会有新添加的函数。
二、编写并编译示例代码
1、按照前面的方法建立APP工程,同时还要包含系统工程的头文件目录,这一步是为了得到要调用的系统函数原型。
2、编写代码
新建main_inc.h文件,包含所有要调用的系统函数原型:
#ifndef MAIN_INC_H__
#define MAIN_INC_H__
#include "main.h"
#include "rtthread.h"
#include "mywin_demo.h"
#include "ui_io.h"
#include "mywin_inc.h"
#endif
新建main.c文件,编写如下代码,由于本文使用的stm32f429开发板带有图形界面,所以编写图形界面的代码用以更直观地观察现象:
#include "main_inc.h"
//定义窗口类
typedef struct
{
WIN_TouchWinStruct win;
int timer_refresh;
}WIN_DemoStruct;
//消息处理函数
void Demo_defaultMsgLoop (WIN_DemoStruct *axis,WIN_MsgStruct *msg);
WIN_DemoStruct *WIN_CreatDemo (WIN_WindowStruct *base,
void (*msgLoop)(struct _WIN_WindowStruct *win,WIN_MsgStruct *msg),
int x,int y,int x_size,int y_size)
{
//重设消息循环
if (msgLoop==0)
{
msgLoop=(void (*)(struct _WIN_WindowStruct *win,WIN_MsgStruct *msg))Demo_defaultMsgLoop;
}
WIN_DemoStruct *ret=mymalloc (sizeof ( WIN_DemoStruct));
//调用父类的构造函数
if (ret)
{
mymemset (ret,0,sizeof ( WIN_DemoStruct));
if (0==WIN_CreatTouchEx((WIN_TouchWinStruct *)ret,base,msgLoop,x,y,x_size,y_size))
{
//创建失败
myfree (ret);
ret=0;
}
else
{
((WIN_WindowStruct *)ret)->winType="WIN_DemoStruct";
((WIN_WindowStruct *)ret)->intercept=1;
((WIN_WindowStruct *)ret)->bkcolor=0xffffff;
((WIN_WindowStruct *)ret)->color=0;
ret->timer_refresh=WIN_CreatTimer ((WIN_WindowStruct *)ret,500);
}
}
return ret;
}
//绘制函数
void Demo_DefaultPaint (WIN_DemoStruct *axis)
{
int x=0;
int y=0;
int x_size=((WIN_WindowStruct *)axis)->x_size;
int y_size=((WIN_WindowStruct *)axis)->y_size;
char *txt=mymalloc(128);
WIN_PaintBackGround ((WIN_WindowStruct *)axis);
int font=WIN_SetFontType(24);
u32 color=~((WIN_WindowStruct *)axis)->bkcolor;
WIN_SetLcdColor(color);
WIN_DrawTxtAt("这是运行在APP中的窗口",0,0);
WIN_SetFontType(font);
myfree(txt);
}
//周期刷新屏幕
void Demo_Refresh(WIN_DemoStruct *axis)
{
u32 color=((WIN_WindowStruct *)axis)->bkcolor;
((WIN_WindowStruct *)axis)->bkcolor=((WIN_WindowStruct *)axis)->color;
((WIN_WindowStruct *)axis)->color=color;
}
//消息处理函数
void Demo_defaultMsgLoop (WIN_DemoStruct *axis,WIN_MsgStruct *msg)
{
WIN_MoveStruct *m=0;
WIN_KeyStruct *k=0;
switch (msg->msg)
{
case WIN_MSG_PAINT:
//绘制屏幕
Demo_DefaultPaint(axis);
break;
case WIN_MSG_TIMER:
//定时器到期时刷新屏幕
if(msg->data.v==axis->timer_refresh)
{
Demo_Refresh(axis);
WIN_SetInvalidWhenTop((WIN_WindowStruct *)axis);
}
break;
case WIN_MSG_KEY:
k=msg->data.p;
//按下HOME键返回
if (k->shortPress&KEY_VALUE_HOME)
{
((WIN_WindowStruct *)axis)->deleteWindow((WIN_WindowStruct *)axis);
}
break;
case WIN_MSG_MOVE:
m=msg->data.p;
switch (m->moveType)
{
//短按屏幕返回
case MOVE_DATA_SHORT:
((WIN_WindowStruct *)axis)->deleteWindow((WIN_WindowStruct *)axis);
break;
default:
break;
}
break;
default:
WIN_DefaultMsgLoop((WIN_WindowStruct *)axis,msg);
break;
}
}
int Demo_StartTest(void)
{
//获取基础窗口作为父窗口
WIN_WindowStruct *base=WIN_GetBaseWindow( );
WIN_DemoStruct *ret=WIN_CreatDemo (base,0,base->x_size/4,base->y_size/4,base->x_size/2,base->y_size/2);
//等待窗口返回
return WIN_RunBlock ((WIN_WindowStruct *)ret);
}
//主函数
int my_main (void)
{
Demo_StartTest();
return 0;
}
代码的功能是创建一个四分之一屏幕大小的窗口,每隔500ms改变一次窗口颜色,窗口中显示“这是运行在APP中的窗口”字样。
3、生成axf文件
编译成功:
如图生成的axf文件,更名为 win_demo.axf并复制到SD卡中:
三、运行
如视频所示:
stm32 动态加载运行app程序演示