3.3.2 设备注册 以I2C设备为例: #define OS_DEVICE_INFO static OS_SECTION("device_table") const os_device_info_t
OS_DEVICE_INFO asr1603_i2c1_device = {
.name = "i2c1",
.driver = "ASR1603_I2C_DRIVER",
.info = OS_NULL,
};
OS_DEVICE_INFO asr1603_i2c2_device = {
.name = "i2c2",
.driver = "ASR1603_I2C_DRIVER",
.info = OS_NULL,
};
所有的设备信息存在device_table段,只是分配设备驱动类型和名称。 OS_DRIVER_INFO asr1603_i2c_driver = {
.name = "ASR1603_I2C_DRIVER",
.probe = asr1603_i2c_probe, //I2C设备初始化和注册
};
OS_DRIVER_DEFINE(asr1603_i2c_driver, "2");
#define OS_DRIVER_DEFINE(_driver_, sequence) \
static os_err_t __driver_##_driver_##_init(void) \
{ \
return driver_match_devices(&_driver_); \
} \
OS_INIT_EXPORT(__driver_##_driver_##_init, sequence)
//OS_INIT_EXPORT即为前面提到的开机自启动定义宏
开机后自动执行_asr1603_i2c_driver_driver__init,也就是自动将device_table段设备对应的驱动程序asr1603_i2c_probe自动执行,实现了所有设备的初始化, static int asr1603_i2c_probe(const os_driver_info_t *drv, const os_device_in
fo_t *dev)
{
...
//所有的 I2C 设备(一种设备有多个)进行初始化
if(!strcmp(dev->name, "i2c1"))
{
g_i2c1.id = ASR1603_DEV_I2C1;
i2c_p = &g_i2c1;
}
else if(!strcmp(dev->name, "i2c2"))
{
g_i2c2.id = ASR1603_DEV_I2C2;
i2c_p = &g_i2c2;
}
....
asr1603_wrap_i2c_init(i2c_p->id);
i2c_p->i2c_bus.ops = &i2c_bus_ops; //底层操作 I2C 的接口,与实际硬件绑定
i2c_p->i2c_bus.priv = i2c_p;
ret = os_i2c_bus_device_register(&(i2c_p->i2c_bus), dev->name, OS_DEVICE
_FLAG_RDWR, &(i2c_p->i2c_bus));
return ret;
}
os_i2c_bus_device_register将I2C设备注册到系统设备列表os_device_list,包括其对外接口i2c_ops。 struct os_device_ops
{
os_err_t (*init) (os_device_t *dev);
os_err_t (*open) (os_device_t *dev, os_uint16_t oflag);
os_err_t (*close) (os_device_t *dev);
os_size_t (*read) (os_device_t *dev, os_off_t pos, void *buffer, os_size_t size);
os_size_t (*write) (os_device_t *dev, os_off_t pos, const void *buffer, os_size_t size);
os_err_t (*control)(os_device_t *dev, os_int32_t cmd, void *args);
};
所有设备对外提供接口都类似,部分不支持的为NULL,风格和linux设备驱动一致,这些接口是封装前面i2c_bus_ops提供的硬件特有驱动,这样完成了I2C设备框架与硬件驱动绑定以及自动初始化。
|