前言

I.MX6ULL的板子未选配RGB的屏幕,无法在板子上进行GUI的开发调试,不过手头上有块控制器为ST7789V3的LCD屏幕(1.3inch),通过简易接线后可以很方便进行驱动的移植

如有异议,欢迎留言指正

ST7789 LCD控制器

ST7789是一款单芯片TFT-LCD控制器,支持并口与SPI通信方式

特性
  • 控制器支持显示区域340x320(LCD屏幕实际为240X240)
  • RGB565、16bit、65K真彩
  • 支持SPI通信
  • LCD控制引脚
NO. 引脚 描述
1 BLK 背光调节亮度
2 CS 片选
3 RES 复位
4 SDA 数据引脚
5 SCL 串行时钟
6 DC 数据命令选择

修改设备树

修改&ecspi1
  • 板子上通过SPI1接到LCD上,设备树路径 arch/arm/boot/dts/100ask_imx6ull-14x14.dts,修改&ecspi1,增加 cs-gpiosdc-gpiosrst-gpio引脚(dc与rst也可以单独放到root节点下)
&ecspi1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_ecspi1>;fsl,spi-num-chipselects = <1>;cs-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;dc-gpios = <&gpio4 21 GPIO_ACTIVE_HIGH>;rst-gpio = <&gpio4 23 GPIO_ACTIVE_HIGH>;status = "okay";spidev: st7789s@0{compatible = "100ask, st7789s";spi-max-frequency = <25000000>;reg = <0>;};
};
修改pinctrl
  • 修改设备树中pinctrl_ecspi1,增加dcrst的IO配置(dc与rst的配置也可以单独放到root节点下,需要屏蔽掉其他地方复用防止引起的冲突)
pinctrl_ecspi1: spi_st7789s {fsl,pins = <MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK          0x000010B1/*sclk*/MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI          0x000010B1/*mosi*/MX6UL_PAD_CSI_DATA07__ECSPI1_MISO          0x000010B1/*miso*/MX6UL_PAD_CSI_DATA03__GPIO4_IO24           0x000010B0/*cs*/MX6UL_PAD_CSI_DATA00__GPIO4_IO21           0x000010B0/*dc*/MX6UL_PAD_CSI_DATA02__GPIO4_IO23           0x000010B0/*rst*/>;};

SPI驱动框架

注册spi
  • Linux内核使用spi_driver标识spi设备驱动(匹配方式、probe、remove函数),通过 spi_register_driver向内核进行注册
/* SPI驱动结构体 */
static struct spi_driver st7789s_driver = {.probe = st7789s_probe,.remove = st7789s_remove,.driver = {.owner = THIS_MODULE,.name = ST7789S_NAME,.of_match_table = st7789s_of_match,},.id_table = st7789s_id,
};
/** @description : 驱动入口函数* @param       : 无* @return      : 无*/
static int __init st7789s_init(void)
{return spi_register_driver(&st7789s_driver);
}
数据发送
  • 将待发送数据添加到spi_message队列中,并使用同步(堵塞方式)发送
static int st7789_write_regs(struct st7789_dev *dev,unsigned char *buf, int len)
{int ret;struct spi_message m;struct spi_transfer *t;struct spi_device *spi = (struct spi_device *)dev->private_data;t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);   /* 申请内存 */t->tx_buf = buf;            /* 要写入的数据 */t->len = len;               /* 写入的字节数 */spi_message_init(&m);       /* 初始化spi_message */spi_message_add_tail(t, &m);/* 将spi_transfer添加到spi_message队列 */ret = spi_sync(spi, &m);    /* 同步发送 */kfree(t);                   /* 释放内存 */return ret;
}

probe函数

  • 设备与驱动匹配成功后,在probe中注册设备并进行刷屏
static int st7789s_probe(struct spi_device *spi)
{int ret = 0;printk("st7789 probe \n");/* 1、构建设备号 */if (st7789sdev.major) {st7789sdev.devid = MKDEV(st7789sdev.major, 0);register_chrdev_region(st7789sdev.devid, ST7789S_CNT, ST7789S_NAME);} else {alloc_chrdev_region(&st7789sdev.devid, 0, ST7789S_CNT, ST7789S_NAME);st7789sdev.major = MAJOR(st7789sdev.devid);}/* 2、注册设备 */cdev_init(&st7789sdev.cdev, &st7789s_ops);cdev_add(&st7789sdev.cdev, st7789sdev.devid, ST7789S_CNT);/* 3、创建类 */st7789sdev.class = class_create(THIS_MODULE, ST7789S_NAME);if (IS_ERR(st7789sdev.class)) {return PTR_ERR(st7789sdev.class);}/* 4、创建设备 */st7789sdev.device = device_create(st7789sdev.class, NULL, st7789sdev.devid, NULL, ST7789S_NAME);if (IS_ERR(st7789sdev.device)) {return PTR_ERR(st7789sdev.device);}/* 获取设备树中cs片选信号 */st7789sdev.nd = of_find_node_by_path("/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02008000");if(st7789sdev.nd == NULL) {printk("ecspi1 node not find!\r\n");return -EINVAL;}/* 2、 获取设备树中的gpio属性,得到BEEP所使用的BEEP编号 */st7789sdev.cs_gpio = of_get_named_gpio(st7789sdev.nd, "cs-gpios", 0);if(st7789sdev.cs_gpio < 0) {printk("can't get cs-gpio");return -EINVAL;}st7789sdev.res_gpio = of_get_named_gpio(st7789sdev.nd, "rst-gpios", 0);if(st7789sdev.res_gpio < 0) {printk("can't get res-gpio");return -EINVAL;}st7789sdev.dc_gpio = of_get_named_gpio(st7789sdev.nd, "dc-gpios", 0);if(st7789sdev.dc_gpio < 0) {printk("can't get dc-gpio");return -EINVAL;}/* 3、设置GPIO为输出,并且输出高电平 */ret = gpio_direction_output(st7789sdev.cs_gpio, 1);//if(ret < 0) {printk("can't set cs gpio!\r\n");}gpio_set_value(st7789sdev.cs_gpio,1);ret = gpio_direction_output(st7789sdev.res_gpio, 1);if(ret < 0) {printk("can't set res gpio!\r\n");}ret = gpio_direction_output(st7789sdev.dc_gpio, 1);if(ret < 0) {printk("can't set dc gpio!\r\n");}/*初始化spi_device */spi->mode = SPI_MODE_2; /*MODE0,CPOL=0,CPHA=0 */spi_setup(spi);st7789sdev.private_data = spi; /* 设置私有数据 *//* 初始化st7789s内部寄存器 */st7789s_reginit(&st7789sdev);     return 0;
}

编译运行

模块拷贝到板子中,由于在加载内核驱动中增加了刷图代码,所以加载驱动后LCD会显示如下图

后续章节贴完整源码

linux驱动开发 ST7789 LCD驱动移植(I.MX6ULL平台)相关推荐

  1. 【Linux驱动开发】LCD 驱动实验

    一.简介 Framebuffer 设备,Framebuffer(帧缓冲),简称 fb. LCD 对应的设备文件是 /dev/fbX(X=0~n). 在 Linux 中应用程序也是通过操作 RGB LC ...

  2. 【i.MX6ULL】驱动开发11——LCD驱动实践

    之前在Linux系统移植时提到过LCD驱动,本篇来看下Linux设备树如何配置LCD驱动. 1 知识点 首先需要了解一个新的概念:Framebuffer 1.1 Framebuffer Framebu ...

  3. <Linux开发>驱动开发 -之-platform 驱动

    <Linux开发>驱动开发 -之-platform 驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: < ...

  4. <Linux开发>--驱动开发-- 字符设备驱动(3) 过程详细记录

    <Linux开发>–驱动开发-- 字符设备驱动(3) 过程详细记录 驱动开发是建立再系统之上的,前面作者也记录了系统移植的过程记录,如果有兴趣,可进入博主的主页查看相关文章,这里就不添加链 ...

  5. Linux 设备驱动开发 —— platform设备驱动应用实例解析

    前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 -- platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platfor ...

  6. Linux驱动开发1:驱动开发与裸机开发的区别

    Linux驱动开发1:驱动开发与裸机开发的区别 1.裸机驱动开发回顾: 裸机驱动开发是非常底层的,跟寄存器打交道,有些MCU为了方便我们开发,提供了一些库,让我们通过调用API函数来间接的实现利用寄存 ...

  7. Linux驱动开发—内核I2C驱动详解

    Linux驱动开发--内核I2C驱动 I2C驱动文件结构 I2C数据传输过程 i2c_transfer i2c_msg I2C通讯常用的接口函数(老版本) 快速读写接口函数:(连续读写) 常用的读操作 ...

  8. Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)

    文章目录 全系列传送门 1. 在/arch/arm/boot/dts/imx6q-pinfunc.h查找 2. 在设备树配置文件中添加设备节点定义以及其引脚定义 3. 修改设备树文件添加配置 4. d ...

  9. STM32MP157驱动开发——USB设备驱动

    STM32MP157驱动开发--USB设备驱动 一.简介 1.电气属性 2.USB OTG 3.STM32MP1 USB 接口简介 4.Type-C 电气属性 二.USB HOST 驱动开发 1.US ...

  10. STM32MP157驱动开发——4G通信模块驱动

    STM32MP157驱动开发--4G通信模块驱动 一.简介 二.驱动开发 1.高新兴 ME3630 驱动开发 驱动修改 添加 ECM 支持程序 配置 Linux 内核 ppp拨号功能测试 ECM 联网 ...

最新文章

  1. 即学即用的30段Python实用代码
  2. 1357篇ECCV 2020论文打包下载!奖项公布:李飞飞高徒获最佳论文奖
  3. WordPress更新时提示无法连接到FTP服务器的解决方案
  4. VisualStudio2017中新建项目没有Asp.Net项目
  5. 王爽 16 位汇编语言学习记录
  6. 快搜浏览器_opera、Google、firefox三个浏览器的选择
  7. 防止Ddos攻击脚本
  8. Jmeter远程启动负载机
  9. DataFrame基础操作
  10. 对象 复制构造函数
  11. 如何使用代码获取电脑内存_代码实战 | 如何在 Android 开发中使用协程
  12. caffe安装系列——综述
  13. 编写SQL语句,从Orders表中检索顾客ID(cust_id)和订单号(order_num),并先按顾客ID对结果进行排序,再按订单日期倒序排列
  14. Ubuntu 16 NFS的安装与使用
  15. 区块链项目ICO注意事项
  16. 【网络编程】一、如何记住OSI七层协议模型,看完还记不住的来打我。
  17. java山地车火山_2019“JAVA(佳沃)杯”第十届凤凰山山地自行车挑战赛
  18. 转载: windows硬盘默认是NTFS文件格式
  19. everything增强神器,文档搜索效率何止翻倍!
  20. 深海迷航创造模式火箭怎么飞_深海迷航火箭怎么发射说什么没关 | 手游网游页游攻略大全...

热门文章

  1. Adam:大规模分布式机器学习框架
  2. 使用ViewPage + Fragment,ViewPage所在的activity重建时的问题
  3. python与数据思维基础网课答案_智慧树知到_Python数据分析与数据可视化_答案免费查询...
  4. 离散数学7__第2章命题逻辑的推理理论__主析取范式和主合取范式
  5. python隐藏窗口_python中隐藏Console窗口
  6. 电子技术基础(三)_第3章集成运算放大器及其应用__基本运算电路
  7. 关于交换机端口的Trunk和Access模式的分析与验证
  8. ☆☆☆Windows服务器部署及原理☆☆☆
  9. 联想l430主板图纸_【有图】Thinkpad L430升级内存,点亮,成功实现双通道!附详细教程及评测!!!...
  10. 常见电容器图片_最强汇总:燃油锅炉常见故障分析与解决方法简单粗暴!编辑不易!...