| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> WK2124下linux驱动分析与移植 -> 正文阅读 |
|
[嵌入式]WK2124下linux驱动分析与移植 |
WK系列 SPI拓展4串口驱动移植参考文档 V2.4 1、概述本文档主要适用于SPI拓展UART 驱动移植的参考。本文档基于V2.4版本的驱动来进行说明的,其它版本的驱动也可以参考。 1.1?WK系列串口扩展芯片简介? ? ??? ? ? 目前WK系列能实现SPI扩展UART的芯片包括 WK2124、WK2204、WK2168、WK2132。目前WK2124、WK2204、WK2168能实现SPI扩展4路UART,WK2132能实现扩展2路UART。目前这几款芯片使用的都是相同的linux驱动。 WK系列扩展的子通道的UART具备如下功能特点: 每个子通道UART的波特率、字长、校验格式可以独立设置,最高可以提供2Mbps的通信速率。 每个子通道具备收/发独立的256 级FIFO,FIFO的中断可按用户需求进行编程触发点且具备超时中断功能。 2、SPI拓展串口驱动简介2.1??硬件连接示意图? ? ? ? ? ? ?
2.2?linux ??串口驱动基本框架简介? 1、WK驱动工作在linux 内核层,向上提供4个串口设备节点供应用层用户调用。也就是说WK驱动注册成功以后,在/dev/ 目录下会生成 ttysWK0、ttysWK1、ttysWK2、ttysWK3 ?共4个串口设备节点,应用层就可以按照操作普通串口节点的方式操作。 2、WK驱动需要和WK芯片进行数据交互,数据交互是通过SPI总线进行的,所以WK驱动会调用SPI总线驱动接口进行数据收发。 3. WK SPI拓展UART驱动简介3.1?开平台简介3.1.1 硬件平台本驱动在开发的时候使用了Firefly-RK3399和IMX8这款开发板。该开发板接口丰富,开发驱动很方便。 3.1.2?软件平台简介该驱动是在Ubuntu16.04系统上开发。内核版本4.4.具体见下图: 3.2 驱动介绍??驱动源文件wk2xxx_spi.c 下面对驱动作一些基本介绍 3.2.1??串口驱动信息描述和数据结构?? ?3.2.1.1 串口驱动描述鉴于芯片的相关特性和驱动编写的需要,定义了结构体 wk2xxx_port用于对WK的SPI转串口驱动进行描述。程序清单入下所示。
3.2.1.2 串口端口描述 定义一个结构体wk2xxx_one来描述WK2xxx芯片的串口端口进行描述,实际上是对uart_port的进一步封装,增加了两个内核队列和芯片子串口一些寄存器。程序如下:
3.2.2 串口驱动的底层基本操作3.2.2.1 读全局寄存器描述 该函数调用SPI接口,实现读WK2XXX芯片的全局寄存器,全局寄存器通常包括GENA 、GRST、GIER、GIFR、GMUT、GPDIR、GPDAT等
3.2.2.2 写全局寄存器 该函数调用SPI接口,实现对WK2XXX芯片的全局寄存器写操作,全局寄存器通常包括GENA 、GRST、GIER、GIFR、GMUT、GPDIR、GPDAT等
3.2.2.3 读子串口寄存器函数描述 该函数调用SPI接口实现读子串口的相关寄存器。Uint8_t port 这个参数表示对应的子串口编号。
3.2.2.4 写子串口寄存器函数描述 ??该函数调用SPI接口,实现写子串口的寄存器。
3.2.2.5 读fifo函数描述? 该函数通过调用SPI接口实现读子串口的FIFO(也就是子串口的接收缓存区)。具体函数如下:
3.2.2.6 写FIFO函数描述 该函数通过调用SPI接口实现写子串口FIFO(也就是子串口发送缓存区)。具体函数如下:
3.2.3?驱动架构与应用层(用户空间)之间的分析本驱动遵循标准的tty驱动的架构。tty 架构如下图所示: ? 一般来说tty架构可以分成两层:一层是下层我们的串口驱动层,直接操作WK2XXX芯片,同时向上提供一组标准的接口,这组接口通过结构体struct uart_ops来实现,该结构体涵盖了驱动对串口的所有操作。还有一层是上层tty层,包括tty_core、line_discipline.他们各自实现实现一个ops结构,用户空间通过tty注册的字符设备节点来访问驱动。 Wk2xxx 驱动的struct uart_ops结构体如下:
3.2.3.1 驱动注册 在驱动编译完成以后。驱动加载成功以后,驱动会向系统注册4个串口设备节点,我们可以在/dev/ 目录下找到ttysWK0 、ttysWK1、ttysWK2、ttysWK3这4个节点。 用户空间可以通过这个4个节点访问4个不同的串口。通常用户空间通过 3.2.3.2? ?用户空间Open()\close()串口设备节点 用户空间通常通过open()\close()函数打开或者关闭设备节点。 1、如下用户空间打开串口设备节点: ? 注意:Dev为设备节点指针(设备节点的路径如下) 当用户空间打开串口的时候,驱动层会调用如下函数: static?int?wk2xxx_startup(struct?uart_port?*port) 该函数主要是来初始化wk2xxx芯片当前子串口的寄存器和设置子串口的初始波特率(115200)。示意图入下: ??????? ?2. 用户空间关闭串口设备节点 ?????? 用户关闭设备节点如下:????close(fd); ?????? 注意:fd 是open串口时获得的。 ???? 当用户空间调用close()串口的时候。驱动主要是调用static?void?wk2xxx_shutdown(struct?uart_port?*port) 函数来实现关闭串口。 ???? 该函数主要实现关闭子串口的时钟、中断等操作。 3.2.3.3 设置子串口波特率和数据格式 ? 应用层设置波特率和数据格式有专 驱动层设置波特率是通过如下的函数来实现的: static?void?wk2xxx_termios(?struct?uart_port?*port,?struct?ktermios?*termios,struct?ktermios?*old) 3.2.3.4 通过串口读写数据 应用层通过write() /read()函数来实现子串口的收发。那么驱动层是怎么来实现的:
??????? ?用户空间和驱动层之间在数据传递上并不是直接传递的。当write()写数据时,用户空间仅仅是把数据传递给tty缓冲区,然后驱动程序收到发送数据的指令,然后按照一定的流程去发送数据;当接收数据的时候,驱动层首先把接收的数据放入tty缓冲区,用户空间read()去读数据,那么就能从tty缓冲区读出子串口接收的数据。 2.驱动层接收和发送数据的实现 驱动层接收和发送数据都依赖于中断。具体的示意图如下: ? 发送数据:用户空间需要发送数据,首先调用write(),并把需要发送的数据传递到tty缓存区.驱动层调用wk2xxx_start_tx()告诉驱动有数据需要发送,WK2xxx芯片产生中断,中断函数通过wk2xxx_tx_chars()函数把tty缓存区的数据取出来,并把数据写入wk2xxx芯片的发送fifo,芯片再自动发送发送fifo中的数据。 接收数据:当WK2xxx芯片接收的数据都是暂时存在子串口的接收fifo,当接收fifo中数据个数到达设置的接收中断触点,芯片产生接收中断,中断函数通过wk2xxx_rx_chars()函数,从接收fifo中读出接收的数据,然后传递给tty缓存区。那么用户空间就可以通过read()函数读到接收的数据。 4.驱动的移植驱动的移植一般过程就是修改内核端的DTS配置,然后编译驱动,加载驱动,最后就是测试。 4.1????????配置DTS节点在DTS文件当中添加SPI驱动节点描述。如下图所示: ? 本驱动使用的是SPI1,
4.2????????驱动修改驱动当中有些差异配置,是需要根据具体的硬件使用情况去修改的。 4.2.1 晶振频率值修改如下中WK_CRASTAL_CLK是芯片外部的实际晶振值,目前我们在测试中使用的是24Mhz的晶振,所以晶振值是24000000.如果用的是12Mhz晶振就修改为12000000. 4.2.2 调试接口开启如下的宏,可以在驱动运行的时候增加打印信息。方便调试 ?4.2.3 功能接口通常下面的这些功能,按照默认设置就可以,除非有相应需求才开启 ? ?上面的宏定义是一些功能接口:
4.2.4 芯片型号修改WK2XXX系列芯片在主接口相同的情况下,驱动是可以兼容的,但是还有还是存在一些差异,比如扩展子串口的数量,我们可以通过修改芯片类型结构体去实现,入下图红色框中的 可以按照下面的方式去修改
?4.3 驱动的编译驱动可以和内核编译到一起,也可以单独编译成模块加载。我们就按照编译成模块的方式分享一遍驱动的编译过程。 4.3.1编译前的准备工作编译驱动以前需要搭建好交叉编译环境。其次就是要准备好编译工具(编译器),最后就是先要编译好开发平台内核。以上这些网上都有详细的资料,这里再在介绍。 其次准备驱动源文件和makefile文件。 驱动配套的Makefile文件如下,请参考:
注意下面通常是需要修改的:编译器路径和内核文件路径 MVTOOL_PREFIX?:指向编译器的路径 KDIR:内核文件路径 4.3.2 编译驱动正常情况下,把驱动和Makefile文件放交叉编译环境中,执行make指令,就会成功编译出对应的驱动模块文件wk2xxx_spi.ko文件。 ?但是编译过程当中通常都会遇见一些问题,这些问题主要是和平台差异相关的问题。下面就把我们遇见过的一些问题分享一下。 4.3.2.1????????Kthread_work相关定义问题 ?在头文件#include?<linux/kthread.h> 下,定义了相关的函数和结构体。入下图 ? 在实际调试中,我们发现不同平台下,对于这些函数定义存在差异。所以我们在头文件中定义了宏定义 #define?WK_WORK_KTHREAD 通过条件编译的方式来切换。 如果在编译的时候,出现如下的一些编译错误,就可以通过宏定义 #define WK_WORK_KTHREAD来调整。 4.3.2.2?????????Port.flags 赋值问题 ? struct uart_port 在函数static?int?wk2xxx_probe(struct?spi_device?*spi)中给struct ?uart_port初始化的时候。可能会出现如下代码编译不过的情况。 如果出现port.flags这个标志位编译不过,那么可以如下操作: 1.替换。如下图 用红色框中的标志代替上面的。 2.用UPF_BOOT_AUTOCONF 替换 ASYNC_BOOT_AUTOCONF,如下所示 ???????? ???s->p[i].port.flags????=?UPF_BOOT_AUTOCONF; ????//s->p[i].port.flags????=?ASYNC_BOOT_AUTOCONF; 3.方法1不行,那么只有参考平台串口驱动中该标志位的赋值。 说明:struct uart_port该结构体定义在include/linux/serial_core.h ?4.3.2.3????????MAX_RT_PRIO无定义问题 ? const?struct?sched_param?sched_param?=?{?.sched_priority?=?MAX_RT_PRIO?/?2?}; MAX_RT_PRIO这个参数有可能定义的头文件找不到,导致编译不过,可以直接用100代替该参数。如下图所示: ?4.4 驱动调试在驱动编译完成以后,会生成wk2xxx_spi.ko文件。 4.4.1 加载驱动把wk2xxx_spi.ko 文件push到开发板。执行如下命令加载驱动模块 insmod wk2xx_spi.ko如下: ? 驱动加载成功,会在/dev/目录下出现对应的串口节点,如图: ttysWK* 这些节点就可以当做标准串口设备节点编程使用。 4.4.2 测试驱动我们下面介绍一些简单的测试方法.简单的测试数据发送和数据接收。 我们在linux开发板端采用命令的方式操作串口设备节点。然后用USB转串口工具,一端连接WK2XXX芯片的UART1,一端连接到PC端,PC端用串口助手接收和发送数据。硬件连接示意图如下
在开发板端使用命令echo “123456abcdefg”>/dev/ttysWK1 该命令的默认波特率是9600。演示结果如下。 2、串口接收字符和发送字符 首先是cat设备节点,如下图。Cat 设备节点入下图。 ? cat? 设备节点有如下功能。首先是会打开对应的串口设备节点(波特率9600),准备接收字符数据。其次是把接收的字符数据然后通过串口设备节点发送出来,这一点是需要注意的。所以cat命令不光有数据的接收,也有数据的发送。 演示操作截图如下: ? ?如上图所示:该测试过程的数据流向与过程如下:PC上的USB串口通过TX发送出数据------>开发板上的WK2xxx接收到数据,并传给系统------》开发板系统把收到的数据,然后通过WK2xxx芯片发送出来-------》PC接收到返回的数据。示意图如下: ? ? ? |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 22:39:32- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |