内容参考于《抽象接口技术和组件开发规范及其思想》、《面向ametal框架和接口的C编程》
六.面向对象的嵌入式底层开发-LED
Ametal中LED的实现
资源图

1. demo_std_led.c
demo属于应用层。am_led_on和am_led_off属于通用接口,通用接口的第一个参数表示要操作的具体对象。一个系统可能有多颗LED,为每一颗LED分配一个ID号。通过ID形式隐藏了底层的对象和指针,对APP层更加友好,不被非业务的逻辑所影响。通过ID能查找到对象,但是,ID和对象并非是一对一的,一个对象可以拥有几个ID,可以理解为,主设备号(对象)下拥有这多个次设备号(ID)。
#include "ametal.h"
#include "am_led.h"
#include "am_delay.h"
void demo_std_led_entry (int led_id)
{
while (1) {
am_led_on(led_id);
am_mdelay(500);
am_led_off(led_id);
am_mdelay(500);
}
}
2. am_led.h(LED标准接口)
demo_std_led.c依赖于am_led.h
#ifndef __AM_LED_H
#define __AM_LED_H
#ifdef __cplusplus
extern "C" {
#endif
#include "am_common.h"
int am_led_set(int led_id, am_bool_t state);
int am_led_on(int led_id);
int am_led_off(int led_id);
int am_led_toggle(int led_id);
#ifdef __cplusplus
}
#endif
#endif /* __AM_LED_H */
3. am_led_dev.c(通用LED设备管理器)
通用接口的实现
- 先看看int am_led_on (int led_id)和int am_led_off (int led_id),发现其实整个的核心代码是int am_led_set (int led_id, am_bool_t state) 和 int am_led_toggle (int led_id),这两个函数屏蔽了底层的差异,无论底层如何变化(GPIO或者HC595),其使用p_dev->p_funcs->pfn_led_set 和 p_dev->p_funcs->pfn_led_toggle即可,这部分下面再进行细讲。
- am_led_dev_t * __led_dev_find_with_id(int id),其通过ID号查找到对象,将对象屏蔽在底层。
- 一般来说,在嵌入式底层,对象都是确定的,有几个LED,有几个UART,在硬件设计那一刻就确定了,代码通过宏进行声明。应用层启动前会对对象进程初始化,再进入应用。把LED对象,挂在 *static am_led_dev_t __gp_head 这个链表下面,这部分下面再进行细讲。
#include "ametal.h"
#include "am_led.h"
#include "am_led_dev.h"
#include "am_int.h"
static am_led_dev_t *__gp_head;
static am_led_dev_t * __led_dev_find_with_id (int id)
{
am_led_dev_t *p_cur = __gp_head;
int key = am_int_cpu_lock();
while (p_cur != NULL) {
if ((id >= p_cur->p_info->start_id) &&
(id <= p_cur->p_info->end_id)) {
break;
}
p_cur = p_cur->p_next;
}
am_int_cpu_unlock(key);
return p_cur;
}
static int __led_dev_add (am_led_dev_t *p_dd)
{
int key = am_int_cpu_lock();
/* add the device to device list */
p_dd->p_next = __gp_head;
__gp_head = p_dd;
am_int_cpu_unlock(key);
return AM_OK;
}
static int __led_dev_del (am_led_dev_t *p_dd)
{
int ret = -AM_ENODEV;
am_led_dev_t **pp_head = &__gp_head;
am_led_dev_t *p_prev = AM_CONTAINER_OF(pp_head, am_led_dev_t, p_next);
am_led_dev_t *p_cur = __gp_head;
int key = am_int_cpu_lock();
while (p_cur != NULL) {
if (p_cur == p_dd) {
p_prev->p_next = p_dd->p_next;
p_dd->p_next = NULL;
ret = AM_OK;
break;
}
p_prev = p_cur;
p_cur = p_cur->p_next;
}
am_int_cpu_unlock(key);
return ret;
}
int am_led_dev_lib_init (void)
{
__gp_head = NULL;
return AM_OK;
}
int am_led_dev_add (am_led_dev_t *p_dev,
const am_led_servinfo_t *p_info,
const am_led_drv_funcs_t *p_funcs,

&spm=1001.2101.3001.5002&articleId=109284343&d=1&t=3&u=373333238bec4f24af7d5135e1d0232c)
994

被折叠的 条评论
为什么被折叠?



