基于Zynq-Zybo开发板及rtl8188无线网卡的远程舵机控制系统设计(三)——驱动设计及编译

在开始本章叙述之前,先声明嵌入式Linux系统的挂载流程不会在这个系列中详细说明。仅说明用到的相关材料的版本信息。
Linux内核源码:Xilinx-Linux-4.19
uboot源码:xilinx-v2018.3
根文件系统:linaro-precise-ubuntu-desktop-20120923-436
FSBL文件,比特流文件,设备树文件:在Vivado18.2中用相关工具基于上一章得到的硬件工程生成
交叉编译工具:vivado SDK2018.2附带的交叉编译工具arm-linux-gnueabihf-
8G SD卡:boot分区0-512M,用于放置BOOT.bin文件,设备树文件,Linux内核
root分区512M-8G,用于放置文件系统

回顾

在上一章中,我们进行了FPGA电路设计,得到了一个将USB接口以及FPGA内的PWM波模块与ARM核相连的电路。

而在本次系统设计中,在Zybo开发板上需要用到舵机驱动芯片和rtl8188无线网卡这两块外部设备。而在嵌入式Linux系统中需要控制外部设备,就需要使用对应不同硬件的“驱动”了。在本章,笔者将详细介绍本次设计中Linux系统中的舵机驱动和rtl8188驱动的生成原理及流程。

何谓“驱动”?

驱动程序全称“设备驱动程序”,是添加到操作系统中的特殊程序。其中包含有关硬件设备的信息。此信息能够使计算机与相应的设备进行通信。驱动程序是硬件厂商根据操作系统编写的配置文件,可以说没有驱动程序,计算机中的硬件就无法工作。一般驱动的源码使用的语言是汇编、C等比较偏底层的语言。

Linux系统下的驱动

一般情况下,Linux系统通过Linux内核来驱动硬件,在编译内核的流程中可以看到生成了很多代表硬件驱动的.ko文件,最后被整合到了内核文件uImage中。此外,也可以对文件系统中的.ko文件使用insmod指令来驱动对应的硬件。在本次设计中,会同时用到这两种驱动方式。将rtl8188的驱动源码放入Linux内核源码中共同编译后整合到内核文件中,而舵机驱动单独编译生成.ko文件,使用insmod指令来驱动舵机。

设计流程

rtl8188无线网卡驱动编译

1.修改驱动源码的编译设置

首先在网上查询并下载到了适用于4.x版本Linux内核的rtl8188驱动源码,将其解压后放入内核文件夹的/driver/net/wireless子目录中。该源码包含驱动相关的C语言头文件和源文件,以及编译时使用的makefile文件等。首先,针对本次编译,需要修改驱动源码文件夹内的makefile文件,主要目的是指明正确的交叉编译工具以及内核源码文件夹的位置。具体修改内容如下:
在宏定义部分找到这样一组宏定义,如下图:
makefile文件宏
这些宏的命名都对应了不同的硬件架构及操作系统。在编译时,若宏的值为y,则按照该宏指定的编译代码进行编译,若为n,则跳过该宏指定的编译代码。这里为了便于区分,我定义一个新宏如下:

CONFIG_PLATFORM_ARM_ZYBO = y

并将其他的对应了编译目标平台的宏的值修改为n。
然后,再依照这个makefile文件的格式,添加我新定义的宏对应的编译方式,如下:

ifeq ($(CONFIG_PLATFORM_ARM_ZYBO), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH:=arm
CROSS_COMPILE:=$CROSS_COMPILE$
KVER:=
KSRC:= /opt/Linux-kernel

其中,ARCH代表目标架构,CROSS_COMPILE代表交叉编译工具,KVER代表内核版本,KSRC代表内核源码目录。如果要编译到其他平台上,可以通过修改这些参数来修改编译设置。

2.修改内核源码的编译设置

刚刚修改完了驱动源码的编译配置。但是,在编译内核时,并不会自动把这个驱动编译后整合到内核中。
我们知道,在编译内核的时候使用menuconfig,会进入内核设置界面,在这个界面可以配置内核需要的相关驱动。然而,这个界面中显示的内容,都是由内核源码里大量的Kconfig和makefile文件实现的。所以,我们现在要修改内核源码内的Kconfig文件和makefile文件,使rtl8188的驱动选项出现在menuconfig产生的界面中。之前把rtl8188的驱动源码放到了内核源码的/driver/net/wireless子目录中,所以现在就修改这个子目录下的Kconfig和makefile文件。

在makefile文件中,添加:

obj-$(CONFIG_RTL8188EU) = rtl8188eu/

其中rtl8188/表示驱动源码在/driver/net/wireless目录中的路径。如果源码文件夹修改命名,则这里也需要一起变化。

在Kconfig文件中,添加:

source "drivers/net/wireless/rtl8188eu/Kconfig"

该路径/drivers/net/wireless/rtl8188eu/Kconfig代表了驱动源码的Kconfig文件路径。
修改了这两个文件之后,再次使用menuconfig打开内核编译配置,就可以在/drivers/net/wireless下看到rtl8188eu驱动的选项,如下图所示:
Menuconfig
然后,在编译内核的时候选择这个选项,就可以使得得到的内核文件可以驱动rtl8188了。测试方法就是挂载Linux系统后插入无线网卡,无线网卡亮灯时就代表驱动成功(可能有的无线网卡没有灯,那就要通过别的方法判断是否驱动成功)。博主测试时的驱动效果如下图:
在这里插入图片描述

舵机驱动编写及编译

之前提到过,会用insmod指令驱动舵机的.ko文件来让Linux内核能够驱动舵机。现在就来介绍一下舵机的.ko文件的生成过程。

1.舵机驱动源码编写

使用C语言来编写驱动源码。
首先为设备起名字:

#define DEVICE_NAME "zrcar_servo_dev"

之后宏定义设备树中的舵机外设地址,这个地址由vivado的硬件工程决定:

#define SERVO_BASEADDR 0x43c30000

舵机驱动函数介绍如下:

static int __init zrcar_servo_module_init(void) //初始化舵机设备信息,注册舵机设备
static void __exit zrcar_servo_module_exit(void)//退出使用舵机设备
static long servo_ioctl(struct file *file, unsigned int cmd, unsigned long arg) //为应用程序提供的控制舵机的接口函数(即“写”操作)
static int servo_open(struct inode *inode, struct file *filp)//打开舵机设备(此时设备抽象为”文件”)

接口函数需要注册才可以使用,接口注册函数如下:

static struct file_operations servo_fops =
{
    
    
            .owner = THIS_MODULE,
            .unlocked_ioctl = servo_ioctl,
            .open = servo_open,
};//包含接口函数的结构体
register_chrdev(0, DEVICE_NAME, &servo_fops);//注册接口函数,以及设备名字。
servo_baseaddr = (unsigned long)ioremap(SERVO_BASEADDR, 16);//注册舵机外设地址
module_init(zrcar_servo_module_init);//注册初始化函数
module_exit(zrcar_servo_module_exit);//注册退出设备函数

至此,舵机驱动源码编写完毕。

2.舵机驱动编译

编写完驱动源文件后,编写Makefile
在与源代码所在目录下新建Makefile文件,输入以下内容:

CROSS_COMPLIE = arm-linux-gnueabihf-
ARCH = arm
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld

ifneq ($(KERNELRELEASE),)
    obj-m := servo_driver.o
else
    KERNEL_DIR := /home/liukaixin/vivado_zynq/linux-digilent-master/
    PWD := $(shell pwd)
all:              
    $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules ARCH=arm
clean:
    rm *.o *.ko *.mod.c Module* module*
endif

其中,CROSS_COMPLIE为交叉编译工具的名字,ARCH为开发板CPU架构,KERNEL_DIR为linux内核源码所在的路径。servo_driver.o与舵机驱动程序servo_driver.c对应。
编写完Makefile文件后,在源码目录使用make指令编译,便可生成驱动文件,将驱动文件servo_driver.ko保存,备用。
此外,在源码目录使用make clean指令,可以按照makefile中clean的指示清除生成的.o,.c,.ko文件等。
当驱动运行后,设备所抽象的文件可在 /dev/ zrcar_servo_dev 处找到。应用程序通过访问文件/dev/ zrcar_servo_dev,对舵机外设进行操作。

最终成果

通过rtl8188驱动以及舵机驱动的编译,最终生成了可以驱动rtl8188的Linux内核以及可以驱动上一章设计的PWM输出模块的.ko文件。在之后的测试中,打开嵌入式系统之后,插入rtl8188后即可成功驱动。再用insmod指令注册舵机的驱动.ko文件,就可以在嵌入式系统内对该端口进行控制。

附录

rtl8188eu驱动源码下载

下章预告

成功驱动硬件之后,就可以基于无线网卡和舵机来做软件开发了。下一章将主要介绍Zybo开发板上的socket接收应用,通过该应用,将接收到的socket包转化成舵机的具体旋转角度信息,用于控制舵机进行旋转。

猜你喜欢

转载自blog.csdn.net/qq_36745999/article/details/92787674