跳过正文
  1. 所有文章/

字符设备驱动开发实验

· loading · loading ·
Linux 驱动 硬件
Seraphique
作者
Seraphique
目录

GPIO之MIO的使用
#

Bank0: 32-bit bank controlling MIO pins[31:0] Bank1: 22-bit bank controlling MIO pins[53:32]

除 Bank1 之外的 Bank 都具有 32bit, Bank1 只具有 22bit 是因为总共只有 54 个 MIO,其中 32bit 的 Bank0控制了 MIO[031],剩下的 MIO[3153]就由 22bit 的 Bank1 控制。 Bank2 和 Bank3 用于控制扩展的 MIO 即EMIO,也就是说总共可以有 32+32=64 个 EMIO。 PS-MIO:

  Bank0:MIO[31:0] GPIO PIN 脚号: MIO31~MIO0

  Bank1:MIO[53:32] GPIO PIN 脚号: MIO53~MIO32

PS-EMIO:

  Bank2:EMIO[ 0:31] 可以分配到任意的 FPGA IO

  Bank3:EMIO[32:63] 可以分配到任意的 FPGA IO

查看硬件原理图以及数据手册
#

搜索AXU4EVB-E_UG.pdf发现目标led连接在开发板PS端的MIO40引脚上。 在xilinx 官网搜索ug1087就可以找到。搜索关键词MIO,找到GPIO Module。

GPIO 寄存器的基地址为0xFF0A0000,控制GPIO我们需要三步:使能、设置方向、控制输出。MIO40在GPIO BANK1中。对应找到使能寄存器OEN_1:0xFF0A0248、方向寄存器DIRM_1:0xFF0A0244、控制寄存器DATA_1:0xFF0A0044。

led-ps 源码
#

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ide.h>
#include <linux/types.h>

#define GPIO_BASE 0x00FF0A0000
#define GPIO_BASE_LEN 0x300
static unsigned int *gpio_addr_vir = 0;

#define GPIO_OEN1 (unsigned int *)(0x248 + (unsigned long)gpio_addr_vir)
#define GPIO_DIRM1 (unsigned int *)(0x244 + (unsigned long)gpio_addr_vir)
#define GPIO_DATA1 (unsigned int *)(0x044 + (unsigned long)gpio_addr_vir)

#define CHAR_DEV_MAJOR 200
#define CHAR_DEV_NAME "led_dev"

static int char_dev_open(struct inode *inode_p, struct file *file_p)
{
    printk(KERN_ERR "char dev open\n");
    return 0;
}

static int char_dev_release(struct inode *inode_p, struct file *file_p)
{
    printk("char dev release\n");
    return 0;
}

static ssize_t char_dev_write(struct file *file_p, const char __user *buf, size_t len, loff_t *loff_t_p)
{
    int ret = 0;
    char lc_buf = 0;

    ret = copy_from_user(&lc_buf, buf, len);
    if (ret != 0)
    {
        printk("copy_from_user failed\n");
        return -1;
    }

    if (len != 1)
    {
        printk("len err\n");
        return -2;
    }

    if (1 == lc_buf)
    {
        *GPIO_DATA1 |= 0x00004000;
    }
    else if (0 == lc_buf)
    {
        *GPIO_DATA1 &= 0xFFFFBFFF;
    }
    else
    {
        printk("data err\n");
    }

    return 0;
}

static struct file_operations char_dev_opt = {
    .owner = THIS_MODULE,
    .open = char_dev_open,
    .write = char_dev_write,
    .release = char_dev_release,
};

static int __init char_drv_init(void)
{
    int ret = 0;

    ret = register_chrdev(CHAR_DEV_MAJOR, CHAR_DEV_NAME, &char_dev_opt);
    if (ret < 0)
    {
    }
    else
    {
        gpio_addr_vir = ioremap_wc(GPIO_BASE, GPIO_BASE_LEN);
        *GPIO_DIRM1 |= 0x00004000;
        *GPIO_OEN1 |= 0x00004000;
    }

    return ret;
}

static void __exit char_drv_exit(void)
{
    iounmap(gpio_addr_vir);
    unregister_chrdev(CHAR_DEV_MAJOR, CHAR_DEV_NAME);
}

module_init(char_drv_init);
module_exit(char_drv_exit);

MODULE_AUTHOR("Alinx");
MODULE_ALIAS("gpio_led");
MODULE_DESCRIPTION("GPIO LED driver");
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL");

使用petalinux编译
#

进入工作目录(/peta/peta_prj/linuxPsBase/petalinux)启动docker

docker run -ti -v "$PWD":"$PWD" -w "$PWD" --rm -u petalinux docker_petalinux2:2020.1 $@

输入下面的命令添加新的驱动:

petalinux-create  -t  modules  --name  ps-led  --enable

查看petalinux工程中目录/peta/peta_prj/linuxPsBase/petalinux/project-spec/meta-user/recipes-modules,下面有了名为 ps-led 的文件夹,再进入petalinux工程中目录/peta/peta_prj/linuxPsBase/petalinux/project-spec/meta-user/recipes-modules/ps-led/files,目录下名为 ps-led.c 的文件就是 petalinux 帮我们新建的驱动文件。
将代码写入该c文件 在终端输入命令petalinux-build 编译petalinux工程
编译完成后在petalinux工程目录下搜索“ps-led.ko”,就是对应的驱动模块文件。

使用 makefile单独编译驱动
#

修改c文件第一行添加一个语法错误用于寻找KERNELDIR

所以我的KERNELDIR为

/peta/peta_prj/linuxPsBase/petalinux/build/tmp/work-shared/zynqmp-generic/kernel-build-artifacts

创建Makefile

modname:=ps-led 
obj-m:=$(modname).o 
PWD :=$(shell pwd) 
MAKE :=make 
KERNELDIR = /peta/peta_prj/linuxPsBase/petalinux/build/tmp/work-shared/zynqmp-generic/kernel-build-artifacts 
CROSS_COMPILE=aarch64-linux-gnu-ARCH=arm64 
all: 
    $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules 
clean: 
    rm -rf $(modname).ko *.o *mod* \.*cmd *odule* .tmp_versions 
.PHONY: all clean 

将其和c放置在同一文件夹时使用make即可编译

首次编译需要安装 gcc-aarch64-linux-gnu

sudo apt-get install gcc-aarch64-linux-gnu

相关文章

使用Petalinux定制Linux系统 1
· loading · loading
Petalinux Linux 硬件
使用Petalinux定制Linux系统 1
Petalinux 2020.1安装记录
· loading · loading
Petalinux Docker-Petalinux2 硬件
Petalinux 2020.1安装记录
支持Page Bundle的MarkDown编辑器
· loading · loading
软件 Hugo VSCode 插件 Markdown
VSCode + Front Matter