PC:Windows 10
虚拟机:ubuntu 16.04
vivado:2017.04
PetaLinux:2017.04
开发板:黑金AX7010
根文件系统:debian8
-------------------------------------------------- --------------------传说中的分割线------------------------- -------------------------------------------------- ------
新建vivado工程
配置PS部分:
过程略.....
添加AXI GPIO,改名为leds
配置AXI GPIO数据方向和位宽:
执行这两步:
打开顶层文件找到刚才添加的LED的名字:
根据顶层文件里找到的引脚名字添加约束文件:
执行生成位文件
漫长的等待...........................................
导入SDK,找到AXI GPIO的基地址:
把这个文件夹拷贝到Ubuntu的的里:
使用petalinux编译fsbl,u-boot,kernel,设备树文件(这里设备树文件单独拿出来编译成dtb文件,为下一章做准备):
过程略.....
用的PetaLinux制作BOOT.BIN文件,将BOOT.BIN,image.ub,system.dtb文件拷贝到SD卡的胖分区里(这里没有用的PetaLinux生成的根文件系统,用的是debian8)
开发板上电,查看一下系统版本(4.9.0)
在的的PetaLinux的工程目录下
find -name "kernel"
进入这个目录
发现这个貌似就是内核的源码,用VIM打开的Makefile文件查看一下
确实是4.9的内核
然后把这个里面的所有文件全部拷贝出去,我这里是拷贝到〜/ work / kernel / linux-4.9里
cd arch/arm/configs
ls
确认有xilinx_zynq_defconfig文件
cd -
回到内核目录
用VIM打开的Makefile文件
找到ARCH和CROSS_COMPILE,大概是在255行
修改
ARCH = arm
CROSS_COMPILE = arm-linux-gnueabihf-
PS: 这里是 gnu 不是 gun
PS: 这里是 gnu 不是 gun
PS: 这里是 gnu 不是 gun
保存退出
make xilinx_zynq_defconfig
make -j8
(我这里CPU是8核的)
等待.....
编译完成.....其实这个不是重点......
接下来切入重点,来看驱动,按照传统方法来写
先来看驱动:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// 定义设备文件名
#define DEVICE_NAME "leds"
#define LEDS_BASE_ADDR (0x41200000)
typedef struct{
volatile unsigned int ODR;
}LEDS_T;
LEDS_T* leds;
static int leds_drv_open(struct inode *Inode, struct file *File)
{
leds->ODR = 0xf;
return 0;
}
static ssize_t leds_drv_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t leds_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
unsigned int ret = 0;
unsigned int tmp_val;
ret = copy_from_user(&tmp_val, buf, count);
leds->ODR = (~tmp_val) & 0xf;
return ret;
}
// 描述与设备文件触发的事件对应的回调函数指针
static struct file_operations dev_fops =
{
.owner = THIS_MODULE,
.open = leds_drv_open,
.read = leds_drv_read,
.write = leds_drv_write,
};
// 描述设备文件的信息
static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops
};
// 初始化Linux驱动
static int __init leds_drv_init(void)
{
int ret;
leds = ioremap(LEDS_BASE_ADDR, sizeof(LEDS_T));
// 建立设备文件
ret = misc_register(&misc);
// 输出日志信息
if(ret)
{
printk("leds_drv_init faiitrt!\n");
}
else
{
printk("leds_drv_init success!\n");
}
return ret;
}
// 卸载Linux驱动
static void __exit leds_drv_exit(void)
{
iounmap(leds);
// 删除设备文件
misc_deregister(&misc);
// 输出日志信息
printk("leds_drv_exit success!\n");
}
// 注册初始化Linux驱动的函数
module_init( leds_drv_init);
// 注册卸载Linux驱动的函数
module_exit( leds_drv_exit);
MODULE_LICENSE("Dual BSD/GPL");
Makefile文件:
export ARCH=arm
KERN_DIR = /home/zynq/work/kernel/linux-4.9
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += leds_drv.o
执行一下
make
开发板挂接一下NFS文件系统,然后加载驱动
编写一个测试程序:
#include
#include
#include
#include
#include
int main(int argc, char** argv)
{
int fd;
fd = open("/dev/leds", O_RDWR);
if(fd < 0)
{
printf("fd = %d open fialed!\n", fd);
}
unsigned int leds = 0;
while(1)
{
write(fd, &leds, 4);
leds++;
leds %= 0xf;
sleep(1);
}
close(fd);
return 0;
}
编译一下
arm-linux-gnueabihf-gcc -o leds leds.c
换到开发板执行./leds
就能看到4个LED做加法了
下一篇:zynq linux驱动之使用设备树开发