赞
踩
轻量化,大小为10KB;面向IoT;支持功能静态裁剪;使用make文件可支持动态加载、分散加载。
与正常的操作系统内核一样,包括任务管理、内存管理、时间管理、通信机制、中断管理、队列管理、事件管理、定时器等操作系统基础组件,可以单独运行。
LiteOS SDK 是 Huawei LiteOS 软件开发工具包(Software Development Kit),包括端云互通组件,FOTA,JS引擎、传感器框架等内容。
Huawei IoT Link SDK(下文统一简称SDK)是部署在具备广域网能力、对功耗/存储/计算资源有苛刻限制的终端设备上的轻量级互联互通中间件.
Huawei IoT Link SDK 的底层拥有OS适配层,可以适配Linux、MacOS、LiteOS,以及其它第三方OS(需要自行适配),笔者适配的OS是LiteOS。
为了用户开发方便,SDK的代码不会出现在 IoT Studio 中,IoT Studio中只有用户的目标工程代码(target),但是,SDK的代码会在编译的时候被编译进工程。
SDK代码位置:C:\Users\XXXXX\.iotlink
SDK使用 arm-none-eabi-gcc
工具链进行编译,使用 make
工具构建编译,使用*.mk
文件留给用户配置一些 makefile
中的选项。
LiteOS 内核提供任务的创建、删除、延迟、挂起、恢复等功能,以及锁定和解锁任务调度,支持任务按优先级高低的抢占调度及同优先级时间片轮转调度。
在 LiteOS 中,一个任务就是一个线程,多个任务按照优先级进行抢占式调度,达到多个任务“同时”运行的目的。
每个任务都有多种运行状态。当系统初始化完成并启动调度器后,系统中所有创建的任务就由内核进行调度,在不同运行状态之间切换,同时在系统中竞争一定的资源。
任务的状态有以下四种:
任务 ID 在任务创建时通过参数返回给用户,作为任务的一个非常重要的标识。
用户可以通过任务ID对指定任务进行任务挂起、任务恢复、查询任务名等操作。
优先级表示任务执行的优先顺序。任务的优先级决定了在发生任务切换时即将要执行的任务,在就绪列表中的最高优先级的任务将得到执行。
Huawei LiteOS 的任务一共有 32 个优先级 (0-31),最高优先级为 0,最低优先级为 31。
因为是LiteOS的内核是抢占式调度内核,所以:
高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度。
Liteos由用户实现每个新任务得到调度后将执行的函数,该函数称为任务入口函数。
在多任务操作系统的内核中,为了方便对每个任务进行管理,每一个任务都有一个任务控制块(TCB),其中包含了任务上下文栈指针(stack pointer)、任务状态、任务优先级、任务ID、任务名、任务栈大小等信息,TCB 相当于每个任务在内核中的身份证,可以反映出每个任务运行情况。
每个任务相当于一个裸机程序,每个任务之间相互独立,这个“独立”指的是每个任务都有自己的运行环境 —— 栈空间,称为任务栈,栈空间里保存的信息包含局部变量、寄存器、函数参数、函数返回地址等。
用户创建任务时,系统会先申请任务控制块需要的内存空间,申请成功后,系统会将任务栈进行初始化,预置上下文。此外,系统还会将“任务入口函数”地址放在相应位置。这样在任务第一次启动进入运行态时,将会执行“任务入口函数”。
LiteOS 任务管理提供的 API 都是以 LOS 开头,但是这些 API 使用起来比较复杂,所以Huawei IoT Link SDK 提供了统一API接口,这些接口底层已经使用 LiteOS 提供的API实现,对用户而言更为简洁,API列表如下:
接口名 | 功能描述 |
---|---|
osal_task_create | 创建任务 |
osal_task_kill | 删除任务(非自身) |
osal_task_exit | 任务退出 |
osal_task_sleep | 任务休眠 |
osal的api接口声明在osal.h
中,使用相关的接口需要包含该头文件,关于函数的详细参数请参考该头文件的声明。
任务相关的接口定义在osal.c
中,基于LiteOS的接口实现在 liteos_imp.c
文件中.
void* osal_task_create(const char *name,int (*task_entry)(void *args),\
void *args,int stack_size,void *stack,int prior)
{
void *ret = NULL;
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->task_create))
{
ret = s_os_cb->ops->task_create(name, task_entry,args,stack_size,stack,prior);
}
return ret;
}
int osal_task_kill(void *task)
{
int ret = -1;
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->task_kill))
{
ret = s_os_cb->ops->task_kill(task);
}
return ret;
}
void osal_task_exit()
{
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->task_exit))
{
s_os_cb->ops->task_exit();
}
return ;
}
void osal_task_sleep(int ms)
{
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->task_sleep))
{
s_os_cb->ops->task_sleep(ms);
}
return ;
}
在多任务操作系统中,不同的任务之间需要同步运行,信号量功能可以为用户提供这方面的支持。信号量(Semaphore)是一种实现任务间通信的机制,实现任务之间同步或临界资源的互斥访问。
信号量可以被任务获取或者申请,不同的信号量通过信号量索引号来唯一确定,每个信号量都有一个计数值和任务队列。
通常一个信号量的计数值用于对应有效的资源数,表示剩下的可被占用的互斥资源数,其值的含义分两种情况:
当任务申请(Pend)信号量时,如果申请成功,则信号量的计数值递减,如若申请失败,则挂起在该信号量的等待任务队列上,一旦有任务释放该信号量,则等待任务队列中的任务被唤醒开始执行。
用作互斥时,信号量创建后记数是满的,在需要使用临界资源时,先申请信号量,使其变空,这样其他任务需要使用临界资源时就会因为无法申请到信号量而阻塞,从而保证了临界资源的安全。
用作同步时,信号量在创建后被置为空,任务1申请信号量而阻塞,任务2在某种条件发生后,释放信号量,于是任务1得以进入 READY 或 RUNNING 态,从而达到了两个任务间的同步。
用作资源计数时,信号量的作用是一个特殊的计数器,可以递增或者递减,但是值永远不能为负值,典型的应用场景是生产者与消费者的场景。
用作中断与任务的同步时,可以在中断未触发时将信号量的值置为0,从而堵塞断服务处理任务,一旦中断被触发,则唤醒堵塞的中断服务处理任务进行中断处理。
信号量有三种申请模式:非阻塞模式、永久阻塞模式、定时阻塞模式,用 timeout 参数的值选择。
任务需要申请信号量,若当前信号量的任务数没有到信号量设定的上限,则申请成功。否则,立即返回申请失败
任务需要申请信号量,若当前信号量的任务数没有到信号量设定的上限,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,直到有其他任务释放该信号量,阻塞任务才会重新得以执行
任务需要申请信号量,若当前信号量的任务数没有到信号量设定的上限,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该信号量,或者用户指定时间超时后,阻塞任务才会重新得以执行
由于中断不能被阻塞,因此在申请信号量时,阻塞模式不能在中断中使用。
API相关文件与任务管理相同。API列表如下:
接口名 | 功能描述 |
---|---|
osal_semp_create | 信号量创建 |
osal_semp_del | 信号量删除 |
osal_semp_pend | 信号量申请 |
osal_semp_post | 信号量释放 |
bool_t osal_semp_create(osal_semp_t *semp,int limit,int initvalue)
{
bool_t ret = false;
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->semp_create))
{
ret = s_os_cb->ops->semp_create(semp,limit,initvalue);
}
return ret;
}
bool_t osal_semp_del(osal_semp_t semp)
{
bool_t ret = false;
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->semp_del))
{
ret = s_os_cb->ops->semp_del(semp);
}
return ret;
}
bool_t osal_semp_pend(osal_semp_t semp,unsigned int timeout)
{
bool_t ret = false;
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->semp_pend))
{
ret = s_os_cb->ops->semp_pend(semp,timeout);
}
return ret;
}
bool_t osal_semp_post(osal_semp_t semp)
{
bool_t ret = false;
if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->semp_post))
{
ret = s_os_cb->ops->semp_post(semp);
}
return ret;
}
在多任务环境下,往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。互斥锁(mutex)又称互斥型信号量,是一种特殊的二值信号量,用于实现对共享资源的独占式处理。另外,Huawei LiteOS提供的互斥锁通过优先级继承算法,解决了优先级翻转问题。 互斥锁操作与信号量类似,不再赘述。
LiteOS动态内存支持 DLINK 和 BEST LITTLE 两种标准算法。
LiteOS动态内存管理的方法使用宏定义的方法使能,在用户工程目录下的OS_CONFIG中的target_config.h文件中配置。
在该文件中,找到下面这两项宏定义,置为 YES 则表示使能:
#define LOSCFG_MEMORY_BESTFIT YES
#define LOSCFG_KERNEL_MEM_SLAB YES
此处不对算法进行赘述,直接看API。
API相关文件与任务管理相同。API列表如下:
接口名 | 功能描述 |
---|---|
osal_malloc | 按字节申请分配动态内存空间 |
osal_free | 释放已经分配的动态内存空间 |
osal_zalloc | 按字节申请分配动态内存空间,分配成功则初始化这块内存所有值为0 |
osal_realloc | 重新申请分配动态内存空间 |
osal_calloc | 申请分配num个长度为size的动态内存空间 |
无论选择使用哪种动态内存管理算法,都使用该API。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。