IO设备模型
IO设备的理解,比如我们使用了一款传感器,但是RTT并没有提供软件包给我们使用,并且我们不需要使用HAL库进行开发,而是想使用RTT给我们的函数,比如下面的rt_device_find()等,那么我们就需要将该设备注册到驱动中,类似于linux的驱动开发,并且基本上我们不会涉及到设备驱动层开发,我们一般只需要涉及到I/0设备管理层即可
下面的图我们只需要涉及到应用程序和IO设备管理器即可了,至于设备驱动框架和设备驱动,一般是不会让我们写的,跟linux一样
模拟添加设备驱动以及如何使用
添加drv.demo.c文件成为我们的驱动文件
在该文件中写驱动文件,在main函数中直接使用应用程序对该设备进行操作即可
驱动代码编写
模拟其他驱动进行编写即可,先不写init函数,并且使用INIT_BOARD_EXPORT把该初始化函数注册到内核中去,那样内核就会调用我们写的initial函数,而我们在init的操作就是赋值多个函数比如close、open等函数
static rt_err_t rt_stm32_eth_open(rt_device_t dev, rt_uint16_t oflag)
{
LOG_D("emac open");
return RT_EOK;
}
static rt_err_t rt_stm32_eth_close(rt_device_t dev)
{
LOG_D("emac close");
return RT_EOK;
}
static rt_size_t rt_stm32_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
LOG_D("emac read");
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_size_t rt_stm32_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
LOG_D("emac write");
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
{
switch (cmd)
{
case NIOCTL_GADDR:
/* get mac address */
if (args) rt_memcpy(args, stm32_eth_device.dev_addr, 6);
else return -RT_ERROR;
break;
default :
break;
}
return RT_EOK;
}
static int rt_hw_stm32_eth_init(void)
{
rt_err_t state = RT_EOK;
stm32_eth_device.dev_addr[0] = 0x00;
stm32_eth_device.dev_addr[1] = 0x80;
stm32_eth_device.dev_addr[2] = 0xE1;
/* generate MAC addr from 96bit unique ID (only for test). */
stm32_eth_device.dev_addr[3] = *(rt_uint8_t *)(UID_BASE + 4);
stm32_eth_device.dev_addr[4] = *(rt_uint8_t *)(UID_BASE + 2);
stm32_eth_device.dev_addr[5] = *(rt_uint8_t *)(UID_BASE + 0);
stm32_eth_device.parent.parent.init = rt_stm32_eth_init;
stm32_eth_device.parent.parent.open = rt_stm32_eth_open;
stm32_eth_device.parent.parent.close = rt_stm32_eth_close;
stm32_eth_device.parent.parent.read = rt_stm32_eth_read;
stm32_eth_device.parent.parent.write = rt_stm32_eth_write;
stm32_eth_device.parent.parent.control = rt_stm32_eth_control;
stm32_eth_device.parent.parent.user_data = RT_NULL;
}
INIT_DEVICE_EXPORT(rt_hw_stm32_eth_init);
#endif /* BSP_USING_ETH */
rt_device_t My_device = RT_NULL;
rt_err_t My_device_open(rt_device_t dev, rt_uint16_t oflag)
{
rt_kprintf("My_device_open Enter\r\n");
return RT_EOK;
}
rt_err_t My_device_close(rt_device_t dev)
{
rt_kprintf("My_device_close Enter\r\n");
return RT_EOK;
}
rt_err_t My_device_init(rt_device_t dev)
{
rt_kprintf("My_device_init Enter\r\n");
My_device = rt_device_create(RT_Device_Class_Char, 32);
My_device->close = My_device_close;
My_device->open = My_device_open;
rt_device_register(My_device, "My_device",RT_DEVICE_FLAG_RDWR);
return RT_EOK;
}
INIT_BOARD_EXPORT(My_device_init);//初始化函数,等设备运行时,内核会调用rt_demo_init
//如果这一条代码不存在的话,则下面的find设备是会出问题的
rt_device_t My_dv;
int main(void)
{
My_dv = rt_device_find("My_device"); //形参为设备名字,返回值为设备对象
if(My_dv != RT_NULL)
rt_kprintf("find is success\r\n");
thread23_sample();
return 0;
}
串口设备使用
#define SAMPLE_UART_NAME "uart2" /* 串 口 设 备 名 称 */
rt_device_t serial_device; /* 串 口 设 备 句 柄 */
int main(void)
{
serial_device = rt_device_find(SAMPLE_UART_NAME);
if(serial_device != RT_NULL)
rt_kprintf("serial is success\r\n");
thread23_sample();
return 0;
}
出现的问题,找不到设备,原因是rtconfig.h没有配置
rtconfig.h的作用相当于freertos上的config.h,因此我这里只定义了串口2,而并没有定义串口1
串口在RTT中是存在初始化设置的,因此如果我们不配置串口的波特率的话,它存在默认选择 ,或者说当我们使用串口的时候,我们可以直接在这里修改即可,无需通过函数进行改变
#define SAMPLE_UART_NAME "uart2" /* 串 口 设 备 名 称 */
static rt_device_t serial; /* 串 口 设 备 句 柄 */
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初 始 化 配 置 参 数 */
/* step1: 查 找 串 口 设 备 */
serial = rt_device_find(SAMPLE_UART_NAME);
/* step2: 修 改 串 口 配 置 参 数 */
config.baud_rate = BAUD_RATE_9600; //修 改 波 特 率 为 9600
config.data_bits = DATA_BITS_8; //数 据 位 8
config.stop_bits = STOP_BITS_1; //停 止 位 1
config.bufsz = 128; //修 改 缓 冲 区 buff size 为 128
config.parity = PARITY_NONE; //无 奇 偶 校 验 位
/* step3: 控 制 串 口 设 备。 通 过 控 制 接 口 传 入 命 令 控 制 字, 与 控 制 参 数 */
rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
/* step4: 打 开 串 口 设 备。 以 中 断 接 收 及 轮 询 发 送 模 式 打 开 串 口 设 备 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);