请选择 进入手机版 | 继续访问电脑版
查看: 1813|回复: 0

[补充]关于OSAL初始化流程

[复制链接]
jinfeng 发表于 2013-12-5 13:45:36 | 显示全部楼层 |阅读模式
初来乍到,挺喜欢这边的氛围,看了这一篇帖子我心目中的Zstack OSAL & Message,本来是想回复在下面的,但后面7、8篇翻页,干脆另开一贴。

OSAL功能上看起来与OS一样,但内在实现方式却有所不同,这里不做比较。bootloader加载OSAL到内存中后,指令Jump到OSAL入口-main,在这里面,进行一系列硬件初始化和系统数据结构初始化,最后进入死循环while(1)或者进入睡眠。如果在main中有死循环,那么,消息处理就直接在这里面进行了;而如果是第二种情况,在main中就会fork多个进程,消息处理就在其中一个进程中进行,各个进程之间可以通过消息传递接收函数通信,可以通过同步机制访问系统资源。
硬件初始化的结果可能是建立这样一种模型:
// 驱动结构
typedef struct
{
int (*init)(char *dev_name);
int (*open)(char *dev_name);
void (*read)(int dev_index, char *buffer, U32 count);
....
} driver_t;
// 设备结构
typedef struct
{
U16 dev_id;
char dev_name[256];
...
driver_t opt;
} device_t;
// 用于设备的枚举
enum
{
DEV_ATENA, //天线
DEV_LED,
DEV_KEYBOARD,
DEV_...
};
device_t devices[10] = {....};
设备初始化就是在最后,建立一个数组,可以通过名称、数字检索到对应的设备结构,进而获取驱动程序,这样就实现了设备无关的OSAL设备驱动层,前面也提到,该层可以实现一些管理接口,如get_device, del_device,add_device等等。举个例子,初始化天线设备:
// 第一步,与驱动库建立连接:
devices[DEV_ATENA].dev_id = osal_hal_get_number();//分配一个随机不重复的ID
devices[DEV_ATENA].dev_name = "Atena";
devices[DEV_ATENA].opt.init  = atena_xxx_init(); // 这个函数是驱动里面的,XXX是天线的型号
devices[DEV_ATENA].opt.open = atena_xxx_open(); // 不用多说了吧
// 第二步,完成初始化:
for(i=0; i<sizeof(DEV_NUM_MAX); i++)
{
if(devices == NULL) continue;
devices.opt.init();
}
// 第三步,驱动设备,一个支持多个天线的系统,很常见的情况:
#ifdef ATENA_TYPE == XXX:
devices[DEV_ATENA].opt.read(...);
...
#else if
...
#endif

OSAL和OS都有一个非常核心的部分,那就是进程调度。前面timer也在设备初始化后设置好了心跳频率,每1ms之后,就会进行调度,但是在具体调度之前,会做一次异步处理,比如某个进程阻塞在访问flash资源上,它此时在阻塞队列里面安静地呆着,那么当占用该资源的进程释放了flash资源后,会设置某信号值,OSAL就会发现,然后将阻塞进程从阻塞进程队列拉入就绪进程队列(PS:这里只说一下其中的道理,进程还有很多其他状态)。之后就按照自己的调度算法在就绪队列里面选择一个进程执行。全局的异步处理都是在调度前进行的,也是为了调整进程状态和进程队列。而局部的异步处理,比如消息通信,每个进程都有一个消息邮箱,A进程向B进程发送消息,就是向B进程的消息邮箱写数据,然后等到调度到B进程,B首先接收消息,然后对消息进行处理。每个进程都应该这么写,接收消息,处理消息。往往一个系统都有几个后台进程和一个前台进程,前台用于绘制图形,后台进程发送消息给前台,前台基于此弹出消息框或各种字幕等。

开这个帖子就是想补充这点内容。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表