嵌入式技术之RAlarm接口说明

在实际的开发项目中,很多时候我们需要定时的做一些事情,举例:
①路上的路灯,每天晚上6:00准时打开,每天早上6:00准时关闭;
②定时闹钟,起床上班。这些行为其实都是定时任务--闹钟。
大部分单片机都提供了rtc alarm硬件闹钟,但是实际很少人使用,就举个简单的例子,rt-thread的bsp中也没有几个芯片适配了alarm硬件闹钟。但是我们要使用怎么办??
我受到rtos的调度的启发,像m3/m4这种内核都是systick产生时钟节拍,以供系统处理所有和时间有关的事情,如线程延时,线程的时间片轮转,以及定时器超时等。
有了第3点的经验,那么我们可以写一个软件闹钟功能就容易多了,只需要提供一个刷新节拍,定时查看哪一个闹钟需要唤醒,就可以解决闹钟的管理了。
闹钟组件名字:ralarm(全称rice alarm)。
ralarm
ralarm接口说明:
跨平台
rtos的种类很多,接口差异性大,所以ralarm为了解决这个问题,统一为上层提供一整套接口。
线程接口。
typedef void *ralarm_task_id;struct ralarm_task_attr{    const char *name;       // name of the task    uint32_t stack_size;     // size of stack    uint8_t priority;       // initial task priority};typedef void(*ralarm_task_func)(void *arg);ralarm_task_id ralarm_task_create(ralarm_task_func func, void *arg, const struct ralarm_task_attr *attr);void ralarm_task_delete(ralarm_task_id thread); 互斥量接口。
typedef void *ralarm_mutex_id;ralarm_mutex_id ralarm_mutex_create(void);ralarm_err_t ralarm_mutex_lock(ralarm_mutex_id mutex);ralarm_err_t ralarm_mutex_unlock(ralarm_mutex_id mutex);void ralarm_mutex_delete(ralarm_mutex_id mutex); 事件接口。
typedef void *ralarm_event_id;ralarm_event_id ralarm_event_create(void);uint32_t ralarm_event_recv(ralarm_event_id event, uint32_t flags);ralarm_err_t ralarm_event_send(ralarm_event_id event, uint32_t flags);void ralarm_event_delete(ralarm_event_id event); ralarm目前已经提供了两个环境的适配,如cmsis,rtthread。
接口使用简单
接口 说明
ralarm_init 初始化
ralarm_deinit 去初始化
ralarm_create 创建闹钟
ralarm_start 启动闹钟
ralarm_stop 停止闹钟
ralarm_modify 修改闹钟
ralarm_delete 删除闹钟
闹钟初始化接口:初始化闹钟的链表,闹钟任务,事件,互斥锁;去初始化接口:注销闹钟组
/* 闹钟初始化 */ralarm_err_t ralarm_init(void);/* 闹钟去初始化 */void ralarm_deinit(void); 闹钟创建:
参数说明:
参数 描述
setup 闹钟的时间和标志,flag可为:ralarm_oneshot(只设置一次)和ralarm_daily(每天都设置)
cb 闹钟时间到了,唤醒的回调函数指针:typedef void (*ralarm_response_cb)(ralarm_t alarm)
userdata 设置闹钟时,自带的用户数据的指针
返回 ——
ralarm_t 闹钟创建成功,放回闹钟句柄
null 闹钟创建失败
函数说明:
①申请闹钟控制块的空间。
②设置闹钟参数到控制块中。
③将闹钟加入到闹钟链表中。
struct ralarm_setup {    ralarm_flag flag;    struct ralarm_time time;};typedef struct ralarm_setup *ralarm_setup_t;struct ralarm {    ralarm_state state;    struct ralarm_setup setup;    ralarm_response_cb cb;    void *userdata;    ralarm_list_t list;};typedef struct ralarm *ralarm_t;ralarm_t ralarm_create(ralarm_setup_t setup, ralarm_response_cb cb, void *userdata){    ralarm_t alarm = null;        if(setup == null) {        ralarm_loge(create alarm failed, setup param is null);        return null;    }    alarm = ralarm_malloc(sizeof(struct ralarm));                           // ----①    if(alarm == null) {        ralarm_loge(malloc alarm memory failed);        return null;    }    ralarm_list_init(&alarm->list);                                         // ----②    memset((void *)alarm, 0, sizeof(struct ralarm));    memcpy((void *)&alarm->setup, setup, sizeof(struct ralarm_setup));    alarm->cb = cb;    alarm->userdata = userdata;    ralarm_mutex_lock(g_container.mutex);    ralarm_list_insert_after(&g_container.list, &alarm->list);              // ----③    ralarm_mutex_unlock(g_container.mutex);    return alarm;} 闹钟启动:将闹钟的状态的start bit置为1。
ralarm_err_t ralarm_start(ralarm_t alarm){    if(alarm == null) {        return ralarm_error;    }    ralarm_mutex_lock(g_container.mutex);    alarm->state |= ralarm_state_start;    ralarm_mutex_unlock(g_container.mutex);    return ralarm_eok;} 闹钟停止:将闹钟的状态的start bit置为0。
ralarm_err_t ralarm_stop(ralarm_t alarm){    if(alarm == null) {        return ralarm_error;    }    ralarm_mutex_lock(g_container.mutex);    alarm->state &= ~ralarm_state_start;    ralarm_mutex_unlock(g_container.mutex);    return ralarm_eok;} 闹钟修改:修改闹钟的标志和闹钟的时间
参数说明:
参数 描述
alarm 闹钟的句柄
setup 要修改闹钟的时间和标志参数
返回 ——
ralarm_eok 修改成功
ralarm_error 修改失败
ralarm_err_t ralarm_modify(ralarm_t alarm, ralarm_setup_t setup)
{    if(alarm == null) {        return ralarm_error;    }    ralarm_mutex_lock(g_container.mutex);    memcpy((void *)&alarm->setup, setup, sizeof(struct ralarm_setup));    ralarm_mutex_unlock(g_container.mutex);    return ralarm_eok;} 删除闹钟:
函数说明:
①将闹钟的状态的start bit置为0。
②将闹钟从闹钟链表中移除。
③释放闹钟的内存。
ralarm_err_t ralarm_delete(ralarm_t alarm)
{    if(alarm == null) {        return ralarm_error;    }    ralarm_mutex_lock(g_container.mutex);    alarm->state &= ~ralarm_state_start;        // ---①    ralarm_list_remove(&alarm->list);           // ---②    ralarm_free(alarm);                         // ---③    alarm = null;    ralarm_mutex_unlock(g_container.mutex);    return ralarm_eok;} 适配简单
根据系统能力,提供获取时间方法,创建ralarm的ops并注册获取时间接口。
struct ralarm_ops{    ralarm_err_t (*time_get)(ralarm_time_t time);};ralarm_err_t ralarm_register_ops(struct ralarm_ops *ops); 提供刷新节拍,然后调用刷新接口。
void ralarm_refresh(void);
ralarm运行逻辑:
闹钟的refresh接口需要用户提供一个刷新节拍,以提供闹钟的生命。
refresh根据闹钟链表是否存在已设置的闹钟,选择发送事件给更新任务,更新检测闹钟的状态。
如下图:当检测闹钟链表无设置的闹钟,则不会发送事件给更新任务
如下图:
当用户创建了闹钟,则会将闹钟挂在闹钟量表中。
刷新节拍调用refresh之后,发送事件给更新任务,然后调用wakeup检测闹钟的状态。
如果某个闹钟时间到,则会调用对应闹钟的回调函数。
ralarm的使用
在rt-thread下使用ralarm组件:
① 闹钟的处理函数,当闹钟时间到了,则会调用这个函数。
② 提供给ralarm组件时间接口。
③ 创建ops,提供时间接口。
④ 软件定时器的处理函数,调用ralarm的刷新函数,提供刷新节拍。
⑤ ralarm组件初始化,注册ops。
⑥ 创建闹钟。
⑦ 创建一个软件定时器,为ralarm组件提供刷新节拍。
static rt_timer_t timer;ralarm_t alarm_test = null;static void alarm_handler(ralarm_t alarm)                               // ---①{    rt_kprintf(time: %02d:%02d:%02d, alarm->setup.time.hour,                      alarm->setup.time.minute, alarm->setup.time.second);    ralarm_stop(alarm);    ralarm_dump();}static ralarm_err_t alarm_time_get(ralarm_time_t timer)                 // ---②{    time_t current;    struct tm *local;        time(¤t);    local = localtime(¤t);    timer->hour = local->tm_hour;    timer->minute = local->tm_min;    timer->second = local->tm_sec;    return ralarm_eok;}static struct ralarm_ops ops = {                                        // ---③    .time_get = alarm_time_get,};static void time_handler(void *param)                                   // ---④{    ralarm_refresh();}int main(void){    ralarm_init();                                                      // ---⑤    ralarm_register_ops(&ops);    struct ralarm_setup setup;    setup.flag = ralarm_daily;    setup.time.hour = 15;    setup.time.minute = 0;    setup.time.second = 0;    alarm_test = ralarm_create(&setup, alarm_handler, null);            // ---⑥    ralarm_start(alarm_test);    ralarm_dump();    timer = rt_timer_create(timer, time_handler,                      // ---⑦                             rt_null, 800,                             rt_timer_flag_periodic);    if (timer != rt_null)         rt_timer_start(timer);} 验证结果:


智能家电系统的基本组成结构是怎样的
ADAS摄像头+77G毫米波雷达或将上市?
多串口数据采集网关有什么功能
Gfk推“每日家价监控器”系统,用于电信行业的数据分析等
美国可能重组芯片等关键供应链
嵌入式技术之RAlarm接口说明
无线充电的魅力 镭射无线充电法相隔4米也无所谓
以色列医学影像技术公司开发基于AI云的软件Nanox.CLOUD”的系统
曝英特尔将入门级处理器和芯片组外包给台积电
移动电源技术参数大介绍
如何推动电动汽车更加安全、高效的发展
华为NOVA8系列消息曝光
补盲激光雷达的兴起
2G/3G/4G终端对手机PA的不同需求
富士康与美国电动车公司Fisker签署合作备忘录
线性电路基础知识
同样是对上代产品的升级,苹果iPhone8与一加5有何不同之处?
高性能 Sub-GHz无线芯片及应用方案
Qualcomm将全力推动5G全球统一标准的制定
intel官方数据库更新上线i3-8100F 属于8代酷睿CoffeeLake家族