让嵌入式想java一样一处编写到处运行
第一次写博客,其实接触嵌入式已经快两年了,从开始学51单片机的时候,怀着满腔的热情。写出了点亮第一个流水灯代码的时候那个无比的激动,到后面自己做许多有趣的东西(比如光立方,电子时钟,无线通讯等等),刚开始连单片机知识一点也不了解,c语言写的很烂的时候,到后面开始慢慢的学着别人写代码,经过了两年的时光,,, 现在我觉得我应该证明我自己。于是我决定写一篇做了快一个月的东西,分享给大家,同时大家相互的学习,互相的进步。
在学习stm32的时候,当时是犹如大海找针一样的学习,完全不知道重哪儿开始,后面找到了刘凯的视频,发现视频讲的很全面,于是就花了15天的时间,专心的学习,晚上专研到2,3点,当时很穷,买的开发板也是淘宝上最便宜的那种,所以资料少的可怜。自己在写程序的时候也总是想自己把所有的代码全部都写出来,这期间走了不少的弯路,造了不少的轮子,这里就不细说了,后面在谈,下面我来介绍一下这个平台把:
起初想到这个想法的时候,完全是起源与mtk手机上的一个冒泡开发实验系统,在这套系统上移植一个一个picoc的嵌入式c语言解释器,我就在想能不能在嵌入式上也跑上这个解释器,在嵌入式上运行许多的应用程序,其他的嵌入式芯片只需要移植我这个平台就可以了,到目前为止,项目的函数的构建已经完成了一大半,只有网络与对话框等没有完成,还存在一定的bug
这个轻量级的嵌入式虚拟平台,开发工程用板stm32 picoc解释器,大量自定义函数,sarm拓展,lwip移植,nes模拟器移植,系统优化,等等技术的融合
在这个虚拟平台上,不仅完成了按键事件的结构,还支持触屏接口,支持page页面,button的创建等等
下面列出完成的功能:
完成了字库的驱动,可以加载任意的字库,一个字库的简单管理。、
完成了字库读取优化,字库第一次从sd卡读取到ram时会保存,第二次就会自动的去ram读取,不会在读写sd卡了
完成了unciode 码到gb2312码的转换,能够在内部自动的转换
完成了菜单的创建,菜单的创建采用链表管理,不受长度的限制,
完成了button的创建,button做的比较简单,能狗进行事件的回调(回调函数),颜 {MOD}设置,内容设置等(只支持触屏)
完成了page页面的管理,能够创建任意多的页面,可以将button等加入到页面中,button就收到了page的管理,page的释放,将释放掉button
完成了软定时器,用户可以创建任意多个软定时器,定时器由回调函数返回结果。、
完成了sram的拓展,实现动态内存的管理
完成了lwip的移植,运行链接网络,测试服务器成功(socket为实现)
完成了file文件的扫描,能够直接运行应用程序。
完成了bmp图片解码,自己花了几天时间写的bmp图片解码,支持8bit 16bit 24bit图片解码(1,2,4,想做的还没来的急)
完成了bmp565纯数据格式的显示(速度很快),做界面最爱
完成了txt文字的显示,可以字节写一个小说阅读器啥的。
完成了nes模拟器的移植,能够运行40kb一下的游戏(本来想移植一个支持全部游戏的,觉得麻烦)
完成了屏幕缓冲区的设置,能够通过宏开关打开或关闭屏幕缓存(这个玩意可是暂用150kb的ram)
完成了gpio口到picoc的添加,能够在应用程序中直接控制gpio
今天就将这么多了,都说没图没真相,今天太晚了,明天上图。
下面我一一的讲解:、
picoc解释器:
Picoc C语言解释器的STM32平台移植Picoc是google开源代码项目中看到的一个项目,其初衷貌似是要做一个在小的嵌入设备上的C解释器。它的核心代码只有3500行左右,可读性不错,虽然没有实现完整的ISO C标准,基本的C运行库还是具备了。picoc代码上看,基本有如下几块:lex词法解析,table一个基本数据结构(用于存放变量),是个字符串hash表,heap管理内存分配(包括了stack frame的实现), type做类型管理(基本型别和程序自定义的struct,typedef等),expression做表达式解析,variable变量管理分配释放栈帧。picoc的定位是一个解释器,它的解析和代码运行是在同一块代码块里做
-
PicoC是一个非常小的C解释器的脚本。它最初是作为一个无人机的飞行系统板上的脚本语言。它也非常适合于其他机器人,嵌入式和非嵌入式应用。
-
核心的C源代码是大约4500行代码。它并不打算成为一个完整的ISO C实现的,但它拥有所有的必需品。在编译时,只需要几K的代码空间也很不遗余力的数据空间。这意味着,在小型嵌入式设备,它可以很好地工作。这也是一个有趣的例子,如何创建一个非常小的语言实现,同时仍保持代码的可读性。
-
picoc已经过测试的x86-32,x86-64的的PowerPC,ARM,以UltraSPARC,HP-PA和Blackfin处理器上,并很容易地移植到新的目标。
项目地址,有文档和源码:GOOGLE https://code.google.com/p/picoc/GitHub https://github.com/larryhe/tiny-c-interpreterSVN 地址,貌似还有人在开发当中,但是只有 win32版本可以编译过去,变化比较大...# Non-members may check out a read-only working copy anonymously over HTTP.svn checkout http://picoc.googlecode.com/svn/trunk/ picoc-read-only
以及我已经完成的函数列表:
#ifndef MRC_BASE_H
#define MRC_BASE_H
/*
本文件只相当于帮助文件,没有任何实际意义,也就是说在这里增加或修改定义不会有任何效果
如果你需要增加定义,请定义在其他文件中,要使用以下所有接口请在你的代码中增加“#include "base.h"”
请不要将此文件改名为其他文件名后包含在你的代码中!否则可能会导致系统异常!!!
*/
//系统版本,由于软件的更新,可能会造成有些函数、宏、类型等不一致而导致运行出错
//建议在源码中判断系统版本是否相同
#define _VERSION 1001
/*
此文件为系统内部简单封装的MRP函数实现了MRPAPI库
的部分功能
*/
typedef unsigned short uint16; //有符号16bit整型
typedef unsigned long int uint32; //无符号32bit整型
typedef long int int32; //有符号32bit整型
typedef unsigned char uint8; //无符号8bit整型
typedef signed char int8; //有符号8bit整型
typedef signed short int16; //有符号16bit整型
//下面四项为大部分系统函数的返回值,没有在系统内定义,如果需要这些宏定义请在其他头文件中定义
#define MR_SUCCESS 0 //成功
#define MR_FAILED -1 //失败
#define MR_IGNORE 1 //不关心
#define MR_WAITING 2 //异步(非阻塞)模式
#define NULL (void*)0
#define TRUE 1
#define FALSE 0
#define SCRW //系统内部宏,值为屏幕宽
#define SCRH //系统内部宏,值为屏幕高
//基本按键值(未定义的其他按键也可以使用,但需知道其键值)
enum {
_0, //按键 0
_1, //按键 1
_2, //按键 2
_3, //按键 3
_4, //按键 4
_5, //按键 5
_6, //按键 6
_7, //按键 7
_8, //按键 8
_9, //按键 9
_STAR, //按键 * 10
_POUND, //按键 # 11
_UP, //按键 上 12
_DOWN, //按键 下 13
_LEFT, //按键 左 14
_RIGHT, //按键 右 15
_SLEFT=17, //按键 左软键
_SRIGHT, //按键 右软键
_SEND, //按键 接听键
_SELECT //按键 确认/选择(若方向键中间有确认键,建议设为该键)
};
//基本事件(其他事件需自己定义)
enum {
KY_DOWN, //按键按下
KY_UP, //按键释放
MS_DOWN, //鼠标按下
MS_UP, //鼠标释放
MN_SLT, //菜单选择
MN_RET, //菜单返回
MR_DIALOG, //对话框
MS_MOVE=12 //鼠标移动
};
enum {
DLG_OK, //对话框/文本框等的"确定"键被点击(选择)
DLG_CANCEL //对话框/文本框等的"取消"("返回")键被点击(选择)
};
enum
{
SEEK_SET, //从文件起始开始
SEEK_CUR, //从当前位置开始
SEEK_END //从文件末尾开始
};
enum
{
IS_FILE=1, //文件
IS_DIR=2, //目录
IS_INVALID=8, //无效(非文件、非目录)
};
typedef struct {
uint16 x;
uint16 y;
uint16 w;
uint16 h;
}rectst;
typedef struct {
uint8 r;
uint8 g;
uint8 b;
}colorst;
/********************************C库函数********************************/
/*该函数功能与printf函数相似,区别是本函数的输出
信息将打印在print.txt文件中(与mrpapi有点区别)*/
void printf(const char *format,...);
//申请内存接口,注意!必须严格管理申请的内存,以防内存泄漏!系统不会为你检查申请的内存的使用情况
void* malloc(int size);
//释放由malloc申请的内存
void free(void *address);
//由src所指内存区域复制count个字节到dest所指内存区域。src和dest所指内存区域不能重叠,函数返回指向dest的指针。
void *memcpy(void *dest, void *src, unsigned int count)
//由src所指内存区域复制count个字节到dest所指内存区域。src和dest所指内存区域可以重叠,但复制后dest内容会被更改。
void *memmove(void *dest, const void *src, unsigned int count);
//把src所指由NULL结束的字符串复制到dest所指的数组中。src和dest所指内存区域不可以重叠,且dest必须有足够的空间来容纳src的字符串。
char *strcpy(char *dest,char *src);
//将字符串src中最多n个字符复制到字符数组dest中,它并不像strcpy一样遇到NULL就开始复制,而是等凑够n个字符才开始复制。
char *strncpy(char *dest, char *src, int32 n);
//把src所指字符串添加到dest结尾处(覆盖dest结尾处的'