首页 > 系统相关 >4-petalinux2018.3摸索记录-linux驱动(交叉编译)

4-petalinux2018.3摸索记录-linux驱动(交叉编译)

时间:2024-10-27 19:24:19浏览次数:7  
标签:SLCR led 0000 linux unsigned 编译 GPIO gpio petalinux2018.3

4-petalinux2018.3摸索记录-linux驱动(交叉编译)

  前面通过petalinux-build完成了镜像的编译生成,通过命令行完成了GPIO的驱动,接下来记录如何使用C语言在Linux通过交叉编译的方式完成xilinx-linux设备驱动的开发。

  学习过程中发现,大部分厂商的教程都是提供一套带脚本的环境,然后大家跟着把文件放到对应的文件夹,执行对应的脚本就可以得到镜像,完成开发等等,但是咱们学习还是需要了解一下来龙去脉的,如果开发板是非定制的,那么我们就需要知道哪里要更改并且怎么更改。

一、内核Kernel

  根据开发方法,内核分为两种,一种是使用petalinux内部的,另一种是使用外部导入的。外部导入后面再整理一篇放出来,这里主要记录怎么使用petalinux内部的内核来进行驱动开发。

  按照网上的一些资料描述这个内核的路径应该是{petalinux_prj}/build/tmp/work/plnx_zynqmp-xilinx-linux/linux-xlnx/4.14-xilinx-v2018.3+gitAUTOINC+eeab73d120-r0/linux-plnx_zynqmp-standard-build​,但是没找到,需要先输入了petalinux-config -c kernel​完成一些配置或者默认,然后执行petalinux-build​即可在这个路径下可以看到出现了。

  我的路径是:/home/tzh/workspace/petalinux_prj/xczu2cg/build/tmp/work/plnx_zynqmp-xilinx-linux/linux-xlnx/4.14-xilinx-v2018.3+gitAUTOINC+eeab73d120-r0/linux-plnx_zynqmp-standard-build

二、Makefile编写

#内核路径
KERNEL_DIR = /home/tzh/workspace/petalinux_prj/xczu2cg/build/tmp/work/plnx_zynqmp-xilinx-linux/linux-xlnx/4.14-xilinx-v2018.3+gitAUTOINC+eeab73d120-r0/linux-plnx_zynqmp-standard-build
#编译链
export ARCH = arm64
export CROSS_COMPILE = aarch64-linux-gnu-
#当前路径
CURRENT_DIR = $(shell pwd)

all:
	make -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
clean:
	make -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean

#指定编译哪个文件
obj-m = hello_world.o

三、驱动程序编写

1、HelloWorld

#include <linux/module.h>
#include <linux/kernel.h>

static int __init hello_init(void) {
    printk(KERN_INFO "Hello, World!\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, World!\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple Hello World Module");
MODULE_AUTHOR("Your Name");

2、GPIO

//添加头文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>

static int led_major;
static struct class *led_cls;

/* gpio 内存映射地址 */
static unsigned long *gpio_addr = NULL;
static unsigned long *iou_slcr = NULL;

/* gpio 寄存器物理基地址 */
#define GPIO_BASE_ADDR 0xFF0A0000
#define IOU_SLCR_ADDR 0xFF180000
/* gpio 寄存器所占空间大小 */
#define GPIO_BASE_SIZE 0x368
#define IOU_SLCR_SIZE 0x714

/* gpio 引脚设置GPIO功能*/
#define GPIO_PIN_40 (unsigned int *)((unsigned long)iou_slcr + 0x000000A0)
#define GPIO_PIN_42 (unsigned int *)((unsigned long)iou_slcr + 0x000000A8)

/* gpio 控制电流0*/
#define IOU_SLCR_BANK1_CTRL0 (unsigned int *)((unsigned long)iou_slcr + 0x00000154)
/* gpio 控制电流1*/
#define IOU_SLCR_BANK1_CTRL1 (unsigned int *)((unsigned long)iou_slcr + 0x00000158)
/* gpio 输入引脚选择Schmitt或CMOS*/
#define IOU_SLCR_BANK1_CTRL3 (unsigned int *)((unsigned long)iou_slcr + 0x0000015C)
/* gpio 设置上下拉*/
#define IOU_SLCR_BANK1_CTRL4 (unsigned int *)((unsigned long)iou_slcr + 0x00000160)
/* gpio 使能上下拉*/
#define IOU_SLCR_BANK1_CTRL5 (unsigned int *)((unsigned long)iou_slcr + 0x00000164)
/* gpio 引脚速率选择*/
#define IOU_SLCR_BANK1_CTRL6 (unsigned int *)((unsigned long)iou_slcr + 0x00000168)

/* gpio 方向寄存器 */
#define GPIO_DIRM_1 (unsigned int *)((unsigned long)gpio_addr + 0x00000244)
/* gpio 使能寄存器 */
#define GPIO_OEN_1 (unsigned int *)((unsigned long)gpio_addr + 0x00000248)
/* gpio 输出数据寄存器 */
#define GPIO_DATA_1 (unsigned int *)((unsigned long)gpio_addr + 0x00000044)
/* gpio 输出数据控制寄存器1 */
#define GPIO_MASK_DATA_1_LSW (unsigned int *)((unsigned long)gpio_addr + 0x00000008)
/* gpio 输出数据控制寄存器2 */
#define GPIO_MASK_DATA_1_MSW (unsigned int *)((unsigned long)gpio_addr + 0x0000000C)

const struct file_operations led_fops = {};

//实现装载入口函数和卸载入口函数
static __init int led_drv_v1_init(void)
{
	printk("-------^v^-------\n");
	printk("-led drv v1 init-\n");
	//申请主设备号
	led_major = register_chrdev(0, "led_drv_v1", &led_fops);
	if (led_major < 0)
	{
		printk("register chrdev faile!\n");
		return led_major;
	}
	printk("register chrdev ok!\n");

	//创建设备节点
	//创建设备的类别
	led_cls = class_create(THIS_MODULE, "led_class");
	printk("class create ok!\n");

	//创建设备
	device_create(led_cls, NULL, MKDEV(led_major, 0), NULL, "Myled%d", 0);
	printk("device create ok!\n");


	//1.内存映射
	gpio_addr = ioremap(GPIO_BASE_ADDR, GPIO_BASE_SIZE);
	iou_slcr = ioremap(IOU_SLCR_ADDR, IOU_SLCR_SIZE);
	printk("gpio_addr init over!\n");


	//2.MIO40 MIO42 设置成GPIO,参考手册设置
	iowrite32((ioread32(GPIO_PIN_40) & 0x0), GPIO_PIN_40);
	printk("gpio MIO40 init over!\n");
	iowrite32((ioread32(GPIO_PIN_42) & 0x0), GPIO_PIN_42);
	printk("gpio MIO42 init over!\n");

	// //3.MIO40 MIO42设置输出驱动电流大小
	// // 将 0x3FFFFFF 和 0x0 转换为二进制。
	// // 0011 1111 1111 1111 1111 1111 1111
	// // 0000 0000 0000 0000 0000 0000 0000
	// // 参考手册,可以知道每一位的地址都是由 CTRL0 和 CTRL1 控制的,在这里都是 10, 查看手册得 8 mA。
	iowrite32((ioread32(IOU_SLCR_BANK1_CTRL0) | 0x3FFFFFF), IOU_SLCR_BANK1_CTRL0);
	iowrite32((ioread32(IOU_SLCR_BANK1_CTRL1) & 0x0), IOU_SLCR_BANK1_CTRL1);

	//4.选择引脚是Schmitt还是CMOS
	iowrite32((ioread32(IOU_SLCR_BANK1_CTRL3) & 0x0), IOU_SLCR_BANK1_CTRL3);

	//5.输出管脚上下拉及使能
	iowrite32((ioread32(IOU_SLCR_BANK1_CTRL4) | 0x3FFFFFF), IOU_SLCR_BANK1_CTRL4);
	iowrite32((ioread32(IOU_SLCR_BANK1_CTRL5) | 0x3FFFFFF), IOU_SLCR_BANK1_CTRL5);

	//6.MIO速率的选择
	iowrite32((ioread32(IOU_SLCR_BANK1_CTRL6) & 0x0), IOU_SLCR_BANK1_CTRL6);

	//7.MIO40 MIO42 设置成输出
	// 40 - 26 = 14, 42 - 26 = 16
	// 0000 0000 000|0 0|000 0000 0000 0000
 	//              |16 |14   
	// 0000 0000 000 1 0 100 0000 0000 0000
	// 0000 0000 0001 0100 0000 0000 0000
	// 0x00014000
	iowrite32((ioread32(GPIO_DIRM_1) | 0x00014000), GPIO_DIRM_1);
	//MIO40 MIO42 使能
	iowrite32((ioread32(GPIO_OEN_1) | 0x00014000), GPIO_OEN_1);

	/* MASK_DATA方式按灭LED1,LED2,这个需要自己修改相关参数 */
	//iowrite32((ioread32(GPIO_MASK_DATA_0_LSW ) & 0xFEFFEFFF), GPIO_MASK_DATA_0_LSW );
	//printk("GPIO_MASK_DATA_0_LSW = 0x%x\n", *GPIO_MASK_DATA_0_LSW);
	//iowrite32((ioread32(GPIO_MASK_DATA_0_MSW ) & 0xFEFFEFFF), GPIO_MASK_DATA_0_MSW );
	//printk("GPIO_MASK_DATA_0_MSW = 0x%x\n", *GPIO_MASK_DATA_0_MSW);

	//8.DATA方式按灭LED1,LED2
	// 1111 1111 1111 111|1 1|111 1111 1111 1111
	//                   |0  |0
	// 1111 1111 1111 1110 1011 1111 1111 1111
	// 0xFFFEBFFF
	// iowrite32((ioread32(GPIO_DATA_1) & 0xFFFEBFFF), GPIO_DATA_1);
	iowrite32((ioread32(GPIO_DATA_1) & 0xFFFEFFFF), GPIO_DATA_1);

	printk("GPIO_DATA_1 = 0x%x\n", *GPIO_DATA_1);

	return 0;
}

static __exit void led_drv_v1_exit(void)
{
	iowrite32((ioread32(GPIO_DATA_1) | 0xFFFFFFFF), GPIO_DATA_1);
	//9.内存释放
	iounmap(gpio_addr);
	iounmap(iou_slcr);
	//删除设备
	device_destroy(led_cls, MKDEV(led_major, 0));
	//删除类
	class_destroy(led_cls);
	//注销主设备号
	unregister_chrdev(led_major, "led_drv_v1");

	printk("-------^v^-------\n");
	printk("-led drv v1 exit-\n");
}

//申明装载入口函数和卸载入口函数
module_init(led_drv_v1_init);
module_exit(led_drv_v1_exit);

//添加GPL协议
MODULE_LICENSE("GPL");
MODULE_AUTHOR("msxbo");

四、交叉编译上板实现

1、HelloWorld

  ‍

2、GPIO

  ‍

补充

  交叉编译链的命名

  arch-core-kernel-system

  arch: 用于哪个目标平台
core: 使用的是哪个CPU Core,如Cortex A8,但是这一组命名好像比较灵活,在其它厂家提供的交叉编译链中,有以厂家名称命名的,也有以开发板命名的,或者直接是none或cross的
kernel: 所运行的OS,见过的有Linux,uclinux,bare(无OS)
system:交叉编译链所选择的库函数和目标映像的规范,如gnu,gnueabi等。其中gnu等价于glibc+oabi;gnueabi等价于glibc+eabi

标签:SLCR,led,0000,linux,unsigned,编译,GPIO,gpio,petalinux2018.3
From: https://www.cnblogs.com/popepy/p/18508791/4petalinux20183-fleeing-recordlinux-driver-cross

相关文章

  • 3-petalinux2018.3摸索记录-命令驱动_交叉编译链
    3-petalinux2018.3摸索记录-命令驱动_交叉编译链一、命令行控制GPIO对于ps端设备,在板卡的linux系统中,切换到/sys/class/gpio​路径下可以看到目前挂载的gpio设备。export:导入用户空间gpiochip:系统中gpio寄存器信息unexport:移除用户空间​​以MIO40......
  • 2-petalinux2018.3摸索记录-petalinux rootfs
    2-petalinux2018.3摸索记录-petalinuxrootfs​​1FilesystemPackages文件系统软件包2PetalinuxPackageGroupsPetalinux软件包组3ImageFeatures镜像特性4apps应用程序5userpackages用户软件包6PetalinuxRootFSSettingsPetalinux根......
  • 1-petalinux2018.3摸索记录-petalinux-config
    1-petalinux2018.3摸索记录-petalinux-config一、petalinux-config的具体配置-ZYNQMPConfiguration​​1、LinuxCompomentSelection​​LinuxCompomentSelection,Linux组件选择.FirstStageBootloader和Autoupdateps_init勾选会自动生成fsbl.elf,自动更新ps_i......
  • linux都有哪些认证
    linux都有以下认证:一、LPI认证;二、RedHat认证;三、LinuxFoundation认证;四、CompTIALinux+认证;五、SUSE认证;六、OracleLinux认证;七、红旗Linux认证。LPI认证是业界公认的证明个人在Linux系统管理和开发领域专业能力的标准之一。一、LPI认证LPI(LinuxProfessionalInstitute......
  • 高效自动化运维:Python在Linux与Windows环境下的应用
    高效自动化运维:Python在Linux与Windows环境下的应用目录......
  • Linux学习_7
    第六章文件的其他操作命令主要包括文本内容统计(wc),复制移动文件,查找文件,压缩和解压缩,tar归档文本内容统计(wc)wc------用于统计指定文本文件的行数、字数或字节数wc-参数文件名复制移动文件复制文件cp-参数源文件目标文件移动文件mv命令用于剪切或重命名......
  • Linux练习_2账户管理
    题目描述1建立用户组[root@localhost~]#groupadd-g2000shengchan[root@localhost~]#groupadd-g2001caiwu[root@localhost~]#groupadd-g2002jishu[root@localhost~]#tail-3/etc/groupshengchan:x:2000:caiwu:x:2001:jishu:x:2002:[root@localhost......
  • Linux多ip地址如何删除多余ip
    问题场景:linux支持多个ip连接一个节点,但是ifconfig往往只列出其中一个ip,而ip命令能够显示所有ip,这可能会在某些场景造成一定问题,比如对本机有多ip不知情但又管理多客户机者,可能造成寻找困难的问题。比如:我一台俩ip机子执行ifconfig结果如下执行ipa可以看到如果只执行ifco......
  • Openwrt编译后生成的固件区别
    Openwrt编译后生成的固件区别2024-07-02固件格式:kernel:内置最简文件系统的Linux内核,适用于首次安装或故障恢复sysupgrade:从本来就是openwrt的固件基础上升级,或者无刷机引导限制的机器上直接刷入此格式文件factory:用于从设备的原厂固件刷入factory,再刷入breed之类不死......
  • 如何在Linux系统中进行服务器迁移
    ​服务器迁移是一项关键任务,尤其在Linux环境下。以下步骤将指导您完成迁移:1.备份原始数据;2.为迁移选择合适的工具;3.准备新的服务器环境;4.传输数据并确保数据的完整性;5.测试新环境并完成迁移。首先,确保对当前服务器进行全面的备份。1.备份原始数据在开始任何迁移过程之前,始终备......