1 API 概述
1.1. 简介
bl_mcu_sdk 代码层次结构主要分为以下几层
应用层:由用户自己编写的代码
组件层:开源的一些组件,接口则是调用 HAL 层的接口,使用到无线功能则是调用 Wireless 层的接口
为适配不同 MCU 提供的 HAL 层和无线层,其中 HAL 层又分为两层
设备驱动管理层:提供一套标准的接口,具体实现由外设驱动适配层实现
外设驱动适配层:实现设备驱动管理层的标准接口,并且拓展自己的独特的接口
基于寄存器封装的标准驱动层
硬件层,也就是寄存器层
1.2. 设备驱动管理层实现
设备驱动管理层主要针对芯片外设实现,目的是不影响用户应用层代码因为芯片驱动的不同而频繁修改。
设备驱动管理层的实现采用了面向对象的思想,首先我们将外设看成是一个设备或者是文件,秉承 一切皆文件 的理念,而文件又都具有标准的调用接口:open、close、ctrl、write、read、callback,不同文件类别不同(比如串口设备、ADC设备、SPI设备),并且打开的方式也不同(比如轮询、中断、DMA),由此,我们可以构建出一个对象的基类(父类)。
基类
struct device
{
char name[NAME_MAX];
dlist_t list;
enum device_status_type status;
enum device_class_type type;
uint16_t oflag;
int (*open)(struct device *dev, uint16_t oflag);
int (*close)(struct device *dev);
int (*control)(struct device *dev, int cmd, void *args);
int (*write)(struct device *dev, uint32_t pos, const void *buffer, uint32_t size);
int (*read)(struct device *dev, uint32_t pos, void *buffer, uint32_t size);
void (*callback)(struct device *dev, void *args, uint32_t size, uint32_t event);
void *handle;
};
基类成员:name
给设备取名,后面会使用 device_find 找到这个设备。
基类成员:type
type 记录当前设备的类别,可以选择的 type 类型如下。
enum device_class_type
{
DEVICE_CLASS_NONE = 0,
DEVICE_CLASS_GPIO,
DEVICE_CLASS_UART,
DEVICE_CLASS_SPI,
DEVICE_CLASS_I2C,
DEVICE_CLASS_ADC,
DEVICE_CLASS_DMA,
DEVICE_CLASS_TIMER,
DEVICE_CLASS_PWM,
DEVICE_CLASS_SDIO,
DEVICE_CLASS_USB,
DEVICE_CLASS_I2S,
DEVICE_CLASS_CAMERA,
DEVICE_CLASS_SEC_HASH,
} ;
基类成员:status
status 用来记录当前设备的状态,当前提供 4 种状态。
enum device_status_type
{
DEVICE_UNREGISTER = 0,
DEVICE_REGISTERED,
DEVICE_OPENED,
DEVICE_CLOSED
} ;
基类成员:oflag
oflag 记录 注册时填入的 flag 信息以及使用 device_open 时填入的 oflag 信息。
基类成员:list
设备的增加和删除使用双向链表进行存储,节省内存。
基类成员:标准的函数指针
为不同的外设提供了标准的函数接口,当外设实现此类接口并赋值给该成员,便能达到重写的功能。
1.3. 设备驱动管理层标准接口
1.3.1. device_register
device_register 用于设备标准驱动的注册,并将设备信息注册到链表当中。
int device_register(struct device *dev, const char *name);
dev 设备句柄。
name 设备名称。
return 返回错误码,0 表示注册成功,其他表示错误。
1.3.2. device_unregister
device_unregister 用于设备的删除,将设备信息从链表中删除。
int device_unregister(const char *name);
dev 设备句柄
name 要删除的设备名称
return 错误码,0 表示删除,其他表示错误
1.3.3. device_find
device_find 用于根据 name 从链表中寻找设备,并返回设备句柄的首地址。
struct device *device_find(const char *name);
dev 设备句柄
name 要查找的设备名称
return 错误码,不为 0 表示找到的设备句柄,NULL 表示未找到该设备。
1.3.4. device_open
device_open 用于设备的打开,oflag 表示以何种方式打开,目前提供 6 种打开方式。底层调用 dev 句柄中的 open 成员。
int device_open(struct device *dev, uint16_t oflag);
dev 设备句柄
oflag 设备的打开方式
return 错误码,0 表示打开成功,其他表示错误
oflag 可以写入以下参数:
#define DEVICE_OFLAG_STREAM_TX 0x001
#define DEVICE_OFLAG_STREAM_RX 0x002
#define DEVICE_OFLAG_INT_TX 0x004
#define DEVICE_OFLAG_INT_RX 0x008
#define DEVICE_OFLAG_DMA_TX 0x010
#define DEVICE_OFLAG_DMA_RX 0x020
1.3.5. device_close
device_close 用于设备的关闭。底层调用 dev 句柄中的 close 成员。
int device_close(struct device *dev);
dev 设备句柄
return 错误码,0 表示关闭成功,其他表示错误
1.3.6. device_control
device_control 用于根据命令对设备进行控制和参数的修改。底层调用 dev 句柄中的 control 成员。
int device_control(struct device *dev, int cmd, void *args);
dev 设备句柄
cmd 设备控制命令
args 控制参数
return 不同的控制命令返回的意义不同。
cmd 提供了以下标准命令,除此之外,不同外设还具有自己的命令
#define DEVICE_CTRL_SET_INT 0x01
#define DEVICE_CTRL_CLR_INT 0x02
#define DEVICE_CTRL_GET_INT 0x03
#define DEVICE_CTRL_RESUME 0x04
#define DEVICE_CTRL_SUSPEND 0x05
#define DEVICE_CTRL_CONFIG 0x06
#define DEVICE_CTRL_GET_CONFIG 0x07
#define DEVICE_CTRL_ATTACH_TX_DMA 0x08
#define DEVICE_CTRL_ATTACH_RX_DMA 0x09
#define DEVICE_CTRL_TX_DMA_SUSPEND 0x0a
#define DEVICE_CTRL_RX_DMA_SUSPEND 0x0b
#define DEVICE_CTRL_TX_DMA_RESUME 0x0c
#define DEVICE_CTRL_RX_DMA_RESUME 0x0d
#define DEVICE_CTRL_RESVD1 0x0E
#define DEVICE_CTRL_RESVD2 0x0F
1.3.7. device_write
device_write 用于数据的发送,发送方式根据打开方式可以是轮询、中断、dma。底层调用 dev 句柄中的 write 成员。
int device_write(struct device *dev, uint32_t pos, const void *buffer, uint32_t size);
dev 设备句柄
pos 不同的设备 pos 的意义不同
buffer 要写入的 buffer 缓冲区
size 要写入的长度
return 错误码,0 表示写入成功,其他表示错误
1.3.8. device_read
device_read 用于数据的接收,接收方式根据打开方式可以是轮询、中断、dma。底层调用 dev 句柄中的 read 成员。
int device_read(struct device *dev, uint32_t pos, void *buffer, uint32_t size);
dev 设备句柄
pos 不同的设备 pos 的意义不同
buffer 要读入的 buffer 缓冲区
size 要读入的长度
return 错误码,0 表示读入成功,其他表示错误
1.3.9. device_set_callback
device_set_callback 用于中断回调函数的注册。底层调用 dev 句柄中的 callback 成员。
int device_set_callback(struct device *dev, void (*callback)(struct device *dev, void *args, uint32_t size, uint32_t event));
dev 设备句柄
callback 要注册的中断回调函数
dev 设备句柄
args 不同外设意义不同
size 传输长度
event 中断事件类型
1.4. 外设驱动适配层实现
子类继承父类
不同的外设首成员为 struct device ,这就相当于父类的继承,从而可以使用子类来访问父类成员,当使用子类修改父类成员时,便拥有了子类自己的功能。实现原理是不同结构体的首地址是该结构体中首个成员的地址。
typedef struct xxx_device
{
struct device parent;
} xxx_device_t;
重写标准接口
每个外设都有一个 xxx_register 函数,用来重写标准接口。
dev->open = xxx_open;
dev->close = xxx_close;
dev->control = xxx_control;
dev->write = xxx_write;
dev->read = xxx_read;
原作者:BL_MCU_SDK 开发指南