首发:Rice 嵌入式开发技术分享
作者:RiceDIY
简介
- rt-smart相关文章
- 《rt-smart的第一个应用程序,imx6ull用户态点灯》
- 《rt-smart用户态通过IPC通信玩转传感器数据》
- rt-thread驱动相关文章
- 《rt-thread驱动框架分析》-pin驱动
- 《rt-thread驱动框架分析》-i2c驱动
- 对于imx6ull这个平台,目前RT-Thread是没有对应的BSP,已经相关的硬件驱动,所以通过这个平台来学习RT-Thread的驱动框架也是非常好的,而且又能玩rt-smart,两全其美。
- 100ask\_imx6ull带有7寸的屏幕,有屏幕不玩起来还是挺无聊的,所以花了点时间对接一下相关驱动,LCD驱动和touch驱动,我分成两篇。
- 为了把屏幕跑起来,中间走了不少路,屏幕出现一闪一闪的(时钟配置错了),屏幕错位等,下面讲解的是我个人的做法,不对的地方,请指出。。。。
- 关于RT-Smart对接屏幕,后面我会重新更新一篇文章,并对比一个rt-thread和rt-smart的不同之处。
- 基于100ask\_imx6ull的rt-thread和rt-smart仓库:
- rt-thread的仓库:https://gitee.com/RiceChen0/imx6ull_rt_rthread
- rt-smart的厂库:https://gitee.com/RiceChen0/imx6ull_rt_smart
LCD驱动:
- imx6ull这款芯片自带LCD控制器,所以比较方便。
- 关于LCD驱动,从RTT的代码是没有对应的驱动框架的,所以直接对接设备驱动框架中。而且只需要实现通用设备接口的init和control接口。
/* common device interface */
rt_err_t (*init) (rt_device_t dev);
rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag);
rt_err_t (*close) (rt_device_t dev);
rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
rt_err_t (*control)(rt_device_t dev, int cmd, void *args);
init接口:
我主要做了以下四个步骤(详情实现请clone代码):
- framebuffer清0,
- LCD控制器的相关GPIO初始化
- LCD控制器的相关时钟初始化
- LCD控制器的相关配置初始化(这里要结合屏幕手册进行配置)
- 时钟配置,控制配置需要参考LCD的手册。
control接口:
- rtt提供了如下6条命令:
/**
* graphic device control command
*/
#define RTGRAPHIC_CTRL_RECT_UPDATE 0
#define RTGRAPHIC_CTRL_POWERON 1
#define RTGRAPHIC_CTRL_POWEROFF 2
#define RTGRAPHIC_CTRL_GET_INFO 3
#define RTGRAPHIC_CTRL_SET_MODE 4
#define RTGRAPHIC_CTRL_GET_EXT 5
- 因为我使用的是单个FB,所以实际只实现了3条命令:RTGRAPHIC\_CTRL\_POWERON、RTGRAPHIC\_CTRL\_POWEROFF、RTGRAPHIC\_CTRL\_GET\_INFO
static rt_err_t imx6ull_lcd_control(rt_device_t dev, int cmd, void *args)
{
struct imx6ull_lcd *lcd_dev = (struct imx6ull_lcd *)dev;
switch(cmd)
{
case RTGRAPHIC_CTRL_RECT_UPDATE:
{
break;
}
case RTGRAPHIC_CTRL_POWERON:
{
rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_HIGH);
break;
}
case RTGRAPHIC_CTRL_POWEROFF:
{
rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_LOW);
break;
}
case RTGRAPHIC_CTRL_GET_INFO:
{
struct rt_device_graphic_info *info = (struct rt_device_graphic_info*)args;
RT_ASSERT(info != RT_NULL);
rt_memcpy(info, &lcd_dev->info, sizeof(lcd.info));
break;
}
}
return RT_EOK;
}
注册设备
- 前面也说道LCD没有独立的驱动框架,所以以一个通用设备驱动框架来实现:
int rt_hw_lcd_init(void)
{
rt_err_t ret;
lcd.device.type = RT_Device_Class_Graphic;
#ifdef RT_USING_DEVICE_OPS
lcd.device.ops = &lcd_ops;
#else
lcd.device.init = imx6ull_lcd_init;
lcd.device.open = RT_NULL;
lcd.device.close = RT_NULL;
lcd.device.read = RT_NULL;
lcd.device.write = RT_NULL;
lcd.device.control = imx6ull_lcd_control;
#endif
lcd.device.user_data = (void *)&lcd.info;
ret = rt_device_register(&lcd.device, "lcd", RT_DEVICE_FLAG_RDWR);
return ret;
}
INIT_BOARD_EXPORT(rt_hw_lcd_init);
效果(通过刷屏演示)
- 在代码中,我提供了测试样例,命令:lcd\_test
关注微信公众号『Rice嵌入式开发技术分享』,后台回复“微信”添加作者微信,备注”入群“,便可邀请进入技术交流群。
推荐阅读
更多嵌入式技术干货请关注Rice 嵌入式开发技术分享