FreerTOS系统中OSA 操作系统抽象层介绍

OSA 抽象层是位于嵌入式操作系统内核上层。OSA 封装了操作系统内核,比恩向上层应用程序提供独立与特定操作系统内核的API 接口。

可以说OSA 是操作系统内核API 的二次封装

这些API 向上层提供的模块:断言,事件,IRQ中断,内存管理,收发消息,线程,定时器,信号量(互斥,计数),时间,日志,服务器-客户端通信

断言

函数原型:Void SCI_ASSERT(void *_EXP);

【函数功能】

这是第一个宏,先计算表达式EXP 的值,结果为0(FALSE) 打印错误信息,中断程序

实例

char *dest_ptr;

//分配一块内存

dest_ptr = (char *)SCI_ALLOC(100);

//如果分配直白就中断程序

SCI_ASSERT(SCI_NULL != dest_ptr);

事件

SCI_CreatEvent(const char *name_ptr);

【函数功能】

创建一个事件标记组

实例

SCI_EVENT_GROUP_PTR  event_prt;

const char name[]="My name";

......

//创建一个32 位的事件标记组,其名称为“My name”

event_prt = SCI_CreatEvent(name);

SCI_ASSERT(SCI_NULL != event_ptr);

....

uint32_t SCI_SetEvent( SCI_EVENT_GROUP_PTR group_ptr, uint32 flags_to_set, uint32 set_option);

【函数功能】

创建一个事件标记组

【参数说明】

group_ptr :已经创建好的时间标记组指针

flags_to_set: 用来设置时间标记组的值

set_option: 描述如何设置该事件标记组

  • SCI_AND: 将flag_to_set 和已有的事件标记组与运算
  • SCI_OR;  将flag_to_set 和已有的事件标记组或运算

实例

SCI_EVENT_GROUP_PTR event_ptr;

......

status = SCI_SetEvent(event_ptr, 0x0103, SCI_AND);

if (SCI_SUCCESS != status)

{

      //错误处理

}

IRQ 中断

实例

//禁止IRQ 中断

SCI_DisableIRQ(); 

...

//恢复中断

SCI_RestoreIRQ();

SCI_DisableIRQ() 和 RestoreIRQ() 一定要配对使用,否则会造成死锁

系统内存管理

编写代码是动态分配的pool 和 heap存储空间

void *SCI_ALLOC_CONST(uint32 _SIZE);

【函数功能】

宏:分配一块指定长度的系统内存,失败后返回SCI_NULL

void *SCI_ALLOC_APP(uint32 _SIZE);

【函数功能】

分配一块指定长度的动态内存,分配失败后assert

实例

char  *dest_ptr;

dest_ptr = (char * )SCI_ALLOC_APP(100);

if (SCI_NULL == dest_ptr)

{

     //操作失败,错误处理

}

....

//释放内存

SCI_FREE(dest_ptr);

SCI_ALLOC_BASE, SCI_ALLOC 和 SCI_ALLOC_CONST类似应用实例相同

SCI_ALLOCA 和 SCI_ALLOC_APP 函数相同,应用实例相同

void *SCI_MEM16CPY (uint16 *_DEST_PTR, const uint16 *_SRC_PTR,  uint16 _SIZE)

以16bit 为单位内存拷贝。

void SCI_MEM16SET(uint16 *_DEST_PTR,  int16 _VALUE, uint16 _SIZE);

这是一个宏,以16bit 为单位设置内存块,

委托内存管理

RTOS为了省去模块自身管理内存的复杂性, 专门提供一套针对指定空间的内存进行重新管理的接口

常用的函数接口

MPOOL_HANDLE SCI_CreatMemPool(const char* mem_name, uint8 * mem_addr, uint32 mem_size, APP_MEM_CUFG_T * mem_cfg_ptr) 返回被托管的内存的指针。

被托管的内存信息包括:内存名字,内存地址,内存大小, 内存管理配置信息

#define MAX_MEM_SIZE (100*1024)

uint8 s_mem_buf[MAX_MEM_SIZE];

MPOOL_HANDLE g_mem_handle = 0;

......

APP_MEM_CFG_T  mem_cfg = {0};

mem_cfg.min_pool_size = 4;

mem_cfg.pool_space_size = MAX_MEM_SIZE >> 2;

mem_cfg.heap_mem_watermark = 20 * 1024;

g_mem_handle = SCI_CreatMemPool("XXX Memory", s_mem_buf, MAX_MEM_SIZE, &mem_cfg);

if (0 == g_mem_handle)

{

     //错误处理

}

消息

Uint32 SCI_SendSignal(xSignalHeader signal_ptr, BLOCK_ID dest_id)

【函数功能】

向ID 为dest_id 的线程发送消息signal_ptr

【参数说明】

signal_ptr :待发送的消息指针,dest_id目标线程

实例

xSignalHeader    sig_ptr;

BLOCK_ID          dest_id;

uint32                  status;

......

//创建消息,并赋值

sig_ptr = SCI_ALLOC(sizeof(xSignalHeaderRec));

SCI_ASSERT(SCI_NULL != sig_ptr);

sig_ptr->SignalCode = 0x1234;

sig_ptr->SignalSize = sizeof(xSignalHeaderRec);

sig_ptr->Sender = 0;

sig_ptr->pre = SCI_NULL;

sig_ptr->suc  =SCI_NULL;

//发送消息

status = SCI_SendSignal(sig_ptr, dest_id);

if (SCI_SUCCESS != status)

{

      //发送失败错误处理

}

......

SCI_GetSignal(BLOCK_ID thread_id) 和 SCI_PeekSignal(BLOCK_ID thread_id);

【函数功能】

获取发送ID为thread_id 的线程消息,如果没消息,调用该函数的线程就被挂起知道有消息;

实例

xSignalHeader sig_ptr;

BLOCK_IDthread_id;

......

//接收消息

sig_ptr = SCI_GetSignal(thread_id);

if (sig_ptr == SCI_NULL)

{
      //接收失败,进行出错处理

}

线程

BLOCK_ID SCI_CreateThread(const char *thread_name, const char *queue_name, void (*entry)(uint32, void*),  uint32 argc, void *argy, uint32 queue_num, uint32 priority, uint32 preempt, uint32 auto_start);

【函数功能】

创建一个线程,使用指定的参数线程。//线程创建后所用的资源常驻系统。

【参数说明】

thread_name :线程名称, queue_name: 消息队列名称

entry:线程实体函数, argc:线程实体函数第一个参数,argy: 线程实体函数第二个参数

stack_size:堆栈大小(单位字节),queue_num:消息队列大小(单位:消息个数)

priority:线程优先级

preempt: 线程是否可以抢占

auto_start:线程创建后是否可以自动运行

实例

#define MY_STACK_SIZE 2048

#define MY_QUEUE_SIZE 10

BLOCK_ID thread_id;

....

//创建一个动态线程

thread_id = SCI_CreatThread("my thread", "my queue", my_thread_entry, 0, 0,MY_STACK_SIZE, MY_QUEUE_SIZE, 31,SCI_PREEMPT,SCI_AUTO_START);

if (SCI_INVALID_BLOCK_ID == thread_id)

{

     //创建失败,错误处理

}

//线程实体函数

void my_thread_entry(uint32 argc, void*argy)

{

    uint32 i = 0;

   while(1)

  {

    i++;

  }

}

uint32 SCI_DeleteThread(BLOCK_ID thread_id)

【函数功能】

删除已经创建的ID 为thread_id线程,并释放相关资源,删除后不能对线程进行操作

注意:SCI_CreateStaticThread, SCI_CreateAppThread和SCI_CreateBaseThread 接口所创建的线程可以使用此接口进行删除

实例

BLOCK_ID thread_id;

uint32 status;

....

status = SCI_DeleteThread(thread_id);

if (SCI_SUCCESS != status)

{

      //删除失败,进行出错处理

}

  uint32 SCI_SupendThread(BLOCK_ID thread_id);

【函数功能】

挂起ID为thread_id  线程

【参数说明】

thread_id: 待挂起的线程的ID

【实例】

BLOCK_ID thread_id;

uint32 status;

......

//挂起线程

status = SCI_SuspendThread(thread_id);

if (SCI_SUCCESS != status)

{

      //挂起失败,进行出错处理

}

uint32 SCI_ResumeThread(BLOCK_ID thread_id);

【函数功能】

  恢复ID 为thread_id的线程,是该项成转到就绪状态

【参数说明】

thread_id 是线程id

void SCI_Sleep(uint32 time_in_ms);

【函数功能】

挂起当前线程

【参数说明】

挂起时长为time_in_ms

SCI_GetThreadEvent(BLOCK_ID thread_id, uint32 requested_flags, uint32 get_option, uint32 *actual_flags_ptr, uint32 wait_option)

获取指定线程的事件标记组的值。每个事件标记组包含32个事件标记,每个事件标记有一位无符号位表示,该函数可以获取根据输入参数指定的多种不同的事件标记组合。

xSignalHeader SCI_GetSaveQ(BLOCK_ID thread_id)

【函数功能】

获取指定线程的SaveQ

OS 为线程提供消息备份功能,SaveQ指向一个被备份的消息,如果没有备份消息,SaveQ 为NULL,该函数返回指定线程的SaveQ

定时器

SCI_TIMER_PTR SCI_CreateTimer( const char  *timer_name, TIMER_FUN timer_fun, uint32 input, uint32 timer_expire, uint32 auto_activate);

【函数功能】

创建一个一次性定时器,当定时器时间到时,调佣超时回调函数timer_fun,该定时器不在运行,但它仍然存在,知道用户调用SCI_DeleteTimer将其删除

【参数说明】

timer_name: 定时器名称

timer_fun:定时器超时回调函数

input:超时回调函数的输入参数

timer_expire:定时器超时时间(单位毫秒)

auto_activate: 定时器创建后是否生效开始计时,SCI_AUTO_ACTIVATE:自动生效, SCI_NO_ACTIVATE:不生效,知道用户调用SCI_ActiveTimer使能后生效

实例

SCI_TIMER_PTR  my_timer;

const char my_timer_name[] = "My timer";

....

//创建一次性定时器,超时时间为100ms

my_timer = SCI_CreateTimer(my_timer_name, my_timer_func,0, 100, SCI_SUTO_ACTIVATE);

if (SCI_NULL == my_timer)

{

      //创建失败,进行出错处理

}

....

//超时回调函数

void my_timer_func(uint32 param)

{

   //定时器超时后,做的处理

......

}

SCI_CreatePeriodTimer(const char * timer_name, TIMER_FUN timer_fun, uint32 input, uint32 timer_expier, uint32 auto_activate)

【函数功能】

创建一个周期性的定时器,当定时器时间到,调用超时回调函数timer_fun, 该定时器自动重新开始计时;

【函数参数】

同SCI_CreateTimer

实例

同SCI_CreateTimer

SCI_ActiveTimer(SCI_TIMER_PTR timer_ptr)

【函数功能】

启动定时器

【参数说明】

timer_ptr:已创建的待启动的定时器的指针

实例

SCI_TIMER_PTR my_timer;

uint32 status;

.....

//启动my_timer, 该定时器my_timer 必须已经创建了

status = SCI_ActiveTimer(my_timer);

if (SCI_SUCCESS != status)

{

      //操作失败,进行出错处理

}

uint32 SCI_DeactiveTimer(SCI_TIMER_PTR timer_ptr);

【函数功能】

暂停定时器,定时器站定是保存剩余的时间,当再次启动时,从剩余的时间开始计时;

【参数说明】

timer_ptr: 已经创建的定时器的指针

BOOLEAN  SCI_IsTimerActive(SCI_TIMER_PTR timer_ptr);

【函数功能】

检查定时器是否处于有效状态

【参数说明】

timer_ptr : 已创建的定时器的指针

SCI_DeleteTimer(SCI_TIMER_PTR timer_ptr);

【函数功能】

删除定时器,删除后应使定时器指针为空

实例

SCI_TIMER_PTR   my_timer;

uint32 status;

//删除定时器my_timer 该定时器my_timer 必须已经创建

status = SCI_DeleteTimer(my_timer);

if (SCI_SUCCESS != status)

{

       //操作失败,进行出错处理

}

my_timer = SCI_PNULL;

互斥信号量

SCI_MUTEX_PTR SCI_CreateMutex( const char *name_ptr, uint32 priority_inherit)

【函数功能】

创建互斥信号量

【参数说明】

name_ptr: 互斥信号量名称

priority_inherit:互斥信号量是否支持优先级继承

实例

const char my_mutex_name[] = "My Mutex";

SCI_MUTEX_PTR  my_mutex = SCI_PNULL;

//创建互斥信号量

my_mutex = SCI_CreateMutex(my_mutex_name, SCI_INHERIT);

if (my_mutex == SCI_PNULL)

{

      //创建失败,进行出错处

      ......

}

uint32 SCI_DeleteMutex(SCI_MUTEX_PTR mutex_ptr);

【函数功能】

删除互斥信号量

计数信号量

SCI_SEMAPHORE_PTR SCI_CreateSemaphore(const char *name_ptr , uint32 initial_count)

【函数功能】

创建计数信号量

【参数说明】

name_ptr:计数信号量名称

initial_count:计数信号量初始值

实例

const char my_sem_name[] = "My_Sem";

SCI_SEMAPHORE_PTR my_sem = SCI_PNULL;

....

//创建计数信号量

my_sem = SCI_CreateSemaphore(my_sem_name,10);

if (SCI_PNULL == my_name)

{

      //创建失败,出错处理

}

uint32 SCI_GetSemaphore(SCI_SEMAPHORE_PTR sem_ptr, uint32 wait_option);

【函数功能】

获取计数信号量,该信号量的计数值减少1

【参数说明】

sem_ptr:已经创建好的计数信号量指针

wait_option:等待时间(ms)

uint32 SCI_PutSemaphore(SCI_SEMAPHORE_PTR  sem_ptr);

【函数功能】

释放计数信号量,该信号量的计数值增加1

【参数说明】

sem_ptr:已经创建好的计数信号量指针

uint32 SCI_DeleteSemaphore(SCI_SEMAPHORE_PTR sem_ptr);

【函数功能】

删除计数信号量

【参数说明】

待删除的计数信号量指针

服务器与客户端

一个服务器可以提供多个事件服务,客户端向服务器注册需要的事件,注册时可以提供回调函数

当事件发生时,服务器会调用客户端注册的回调函数对该事件进行相应的处理。由于该回调函数是在服务器所在的线程中运行的所以该回调函数中不能太耗时,禁止中断等操作。一般是向客户端发送一个消息,然后由客户端所在线程进行进一步处理。

uint32 SCI_CreateClientList(uint32 server_ID, uint8 total_event_num, REG_CALLBACK default_fun);

【函数功能】

创建一个事件服务器

【参数说明】

server_ID: 事件服务器ID

total_event_num: 该服务器提供的事件总数

default_fun: 缺省的回调函数

uint32 SCI_DeleteClientList(uint32 server_ID)

【函数功能】

删除事件服务器

【参数说明】

server_ID :要删除的事件服务器

uint32 SCI_SendEventToClient(uint32  server_ID, uint32 ui_event_type, void *signal_ptr)

通过调用回调函数或者缺省函数将事件发送给客户端

uint32 SCI_RegisterMsg(uint32 server_ID, uint8 start_event, uint8 end_event, REG_CALLBACK fun);

【函数功能】

客户端向服务器注册需要的事件。本函数注册的是事件范围,一次可以注册多个事件

【参数说明】

server_ID:事件服务器ID

start_event: 待注册的事件范围的起始ID;

end_event:待注册的事件范围的上限ID

fun: 注册事件的回调函数指针,当这些事件发生时,服务器调用该函数

uint32 SCI_UnregisterMsg(uint32 server_ID, uint8 start_event, uint8 end_event, REG_CALLBACK fun);

【函数功能】

客户端向服务器取消之前注册的事件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值