参考
蚂蚁S9矿板引脚定义.csdn
PS GPIO 测试
# 内核配置CONFIG_GPIO_SYSFS=yCONFIG_GPIO_ZYNQ=ygpio子系统测试
Zynq Linux GPIO 编号计算
GPIO编号=GPIO_BASE + MIO编号 当前: GPIO_BASE=906所以:
| LED | MIO | Linux GPIO |
|---|---|---|
| RED | MIO37 | 943 |
| GREEN | MIO38 | 944 |
# 查看 GPIO 控制器root@antbase:~# cat /sys/class/gpio/gpiochip906/labelzynq_gpio# 导出红灯root@antbase:~# echo 943 > /sys/class/gpio/exportroot@antbase:~# ls /sys/class/gpio/exportgpio943 gpio953 gpio957 gpiochip906 unexport root@antbase:~# echo out > /sys/class/gpio/gpio943/direction# 红灯亮root@antbase:~# echo 1 > /sys/class/gpio/gpio943/value# 红灯灭root@antbase:~# echo 0 > /sys/class/gpio/gpio943/value# 导出绿灯root@antbase:~# echo 944 > /sys/class/gpio/exportroot@antbase:~# echo out > /sys/class/gpio/gpio944/direction# 绿灯亮root@antbase:~# echo 1 > /sys/class/gpio/gpio944/value# 绿灯灭root@antbase:~# echo 0 > /sys/class/gpio/gpio944/valueled.ko 驱动测试
led.c
#include<linux/types.h>#include<linux/kernel.h>#include<linux/init.h>#include<linux/module.h>#include<linux/fs.h>#include<linux/uaccess.h>#include<asm/io.h>/* * 字符设备 */#defineLED_MAJOR200#defineLED_NAME"led"/* * Zynq-7000 PS GPIO寄存器 * * GPIO: * * Bank0: * MIO0 ~ MIO31 * * Bank1: * MIO32 ~ MIO53 * */#defineZYNQ_GPIO_REG_BASE0xE000A000/* * Bank1 GPIO寄存器偏移 * * DATA: * Bank0 0x40 * Bank1 0x44 * * DIRM: * Bank0 0x204 * Bank1 0x244 * * OUTEN: * Bank0 0x208 * Bank1 0x248 * * INTDIS: * Bank0 0x214 * Bank1 0x254 */#defineDATA_OFFSET0x44// GPIO 数据寄存器偏移地址#defineDIRM_OFFSET0x244// GPIO 方向控制寄存器偏移地址#defineOUTEN_OFFSET0x248// GPIO 输出使能寄存器偏移地址#defineINTDIS_OFFSET0x254// GPIO 中断禁止寄存器偏移地址/* * PS GPIO时钟 * * APER_CLK_CTRL bit22 */#defineAPER_CLK_CTRL0xF800012C/* * LED GPIO定义 * * 注意: * * MIO编号 != GPIO寄存器bit * * Bank1: * * MIO32 -> bit0 * MIO33 -> bit1 * ... * * MIO37 -> bit5 * MIO38 -> bit6 * */#defineRED_PIN5// MIO37#defineGREEN_PIN6// MIO38/* * GPIO虚拟地址 */staticvoid__iomem*data_addr;staticvoid__iomem*dirm_addr;staticvoid__iomem*outen_addr;staticvoid__iomem*intdis_addr;staticvoid__iomem*aper_clk_addr;/* * 打开设备 */staticintled_open(structinode*inode,structfile*filp){printk(KERN_INFO"led open\n");return0;}/* * 读取 * * 未实现 */staticssize_tled_read(structfile*filp,char__user*buf,size_tcnt,loff_t*offt){return0;}/* * 写LED控制 * * 命令: * * 0x01 RED ON * 0x02 RED OFF * * 0x03 GREEN ON * 0x04 GREEN OFF * */staticssize_tled_write(structfile*filp,constchar__user*buf,size_tcnt,loff_t*offt){charcmd;u32 val;printk(KERN_INFO"led_write cnt=%ld\n",cnt);/* * 只接受一个字节 */if(cnt!=1){printk(KERN_ERR"invalid count=%ld\n",cnt);return-EINVAL;}/* * 用户空间复制到内核 */if(copy_from_user(&cmd,buf,1)){printk(KERN_ERR"copy_from_user failed\n");return-EFAULT;}printk(KERN_INFO"LED cmd=0x%02x\n",(unsignedchar)cmd);/* * 读取当前GPIO状态 */val=readl(data_addr);switch(cmd){/* * RED ON * * MIO37 = 1 */case0x01:val|=(1U<<RED_PIN);printk(KERN_INFO"RED ON\n");break;/* * RED OFF * * MIO37 = 0 */case0x02:val&=~(1U<<RED_PIN);printk(KERN_INFO"RED OFF\n");break;/* * GREEN ON * * MIO38 = 1 */case0x03:val|=(1U<<GREEN_PIN);printk(KERN_INFO"GREEN ON\n");break;/* * GREEN OFF * * MIO38 = 0 */case0x04:val&=~(1U<<GREEN_PIN);printk(KERN_INFO"GREEN OFF\n");break;default:printk(KERN_WARNING"unknown cmd=0x%02x\n",(unsignedchar)cmd);return-EINVAL;}/* * 更新GPIO输出 */writel(val,data_addr);/* * 等待写入完成 */readl(data_addr);returncnt;}/* * 关闭设备 */staticintled_release(structinode*inode,structfile*filp){printk(KERN_INFO"led release\n");return0;}staticstructfile_operationsled_fops={.owner=THIS_MODULE,.open=led_open,.read=led_read,.write=led_write,.release=led_release,};staticint__initled_init(void){u32 val;intret;/* * 映射GPIO寄存器 */data_addr=ioremap(ZYNQ_GPIO_REG_BASE+DATA_OFFSET,4);dirm_addr=ioremap(ZYNQ_GPIO_REG_BASE+DIRM_OFFSET,4);outen_addr=ioremap(ZYNQ_GPIO_REG_BASE+OUTEN_OFFSET,4);intdis_addr=ioremap(ZYNQ_GPIO_REG_BASE+INTDIS_OFFSET,4);aper_clk_addr=ioremap(APER_CLK_CTRL,4);if(!data_addr||!dirm_addr||!outen_addr||!intdis_addr||!aper_clk_addr){printk(KERN_ERR"ioremap failed\n");return-ENOMEM;}/* * 开启GPIO时钟 */val=readl(aper_clk_addr);val|=(1<<22);writel(val,aper_clk_addr);/* * 禁止GPIO中断 * * Bank1: * * MIO37 bit5 * MIO38 bit6 */val=readl(intdis_addr);val|=(1<<RED_PIN)|(1<<GREEN_PIN);writel(val,intdis_addr);/* * 设置输出方向 * * 1 输出 */val=readl(dirm_addr);val|=(1<<RED_PIN)|(1<<GREEN_PIN);writel(val,dirm_addr);/* * 开启输出 */val=readl(outen_addr);val|=(1<<RED_PIN)|(1<<GREEN_PIN);writel(val,outen_addr);/* * 默认关闭LED * * 当前假设: * * GPIO=0 灭 * * 如果硬件低有效, * 这里需要改成置1 */val=readl(data_addr);val&=~((1<<RED_PIN)|(1<<GREEN_PIN));writel(val,data_addr);/* * 注册字符设备 */ret=register_chrdev(LED_MAJOR,LED_NAME,&led_fops);if(ret<0){printk(KERN_ERR"register_chrdev failed\n");iounmap(data_addr);iounmap(dirm_addr);iounmap(outen_addr);iounmap(intdis_addr);iounmap(aper_clk_addr);returnret;}printk(KERN_INFO"Zynq PS GPIO LED driver loaded\n");printk(KERN_INFO"RED=MIO37(GPIO943) GREEN=MIO38(GPIO944)\n");return0;}staticvoid__exitled_exit(void){u32 val;/* * 关闭LED */val=readl(data_addr);val&=~((1<<RED_PIN)|(1<<GREEN_PIN));writel(val,data_addr);unregister_chrdev(LED_MAJOR,LED_NAME);iounmap(data_addr);iounmap(dirm_addr);iounmap(outen_addr);iounmap(intdis_addr);iounmap(aper_clk_addr);printk(KERN_INFO"LED driver unloaded\n");}module_init(led_init);module_exit(led_exit);MODULE_AUTHOR("ming");MODULE_DESCRIPTION("Zynq7010 PS GPIO MIO37 MIO38 LED Driver");MODULE_LICENSE("GPL");test_led.py
#!/usr/bin/env python# -*- coding: utf-8 -*-importtimeimportos DEV_PATH="/dev/led"defled_write(cmd):try:withopen(DEV_PATH,"wb")asf:f.write(chr(cmd))exceptExceptionase:print("LED write error:",e)defred_on():print("RED ON")led_write(0x01)defred_off():print("RED OFF")led_write(0x02)defgreen_on():print("GREEN ON")led_write(0x03)defgreen_off():print("GREEN OFF")led_write(0x04)if__name__=="__main__":red_on()time.sleep(2)red_off()green_on()time.sleep(2)green_off()测试
root@antbase:~# insmod led.koZynq PS GPIO LED driver loadedRED=MIO37GREEN=MIO38# 红灯亮root@antbase:~# printf "\x01" > /dev/ledledopenled_writecnt=1LEDcmd=0x01 RED ON led release# 红灯灭root@antbase:~# printf "\x02" > /dev/ledledopenled_writecnt=1LEDcmd=0x02 RED OFF led release# 绿灯亮root@antbase:~# printf "\x03" > /dev/ledledopenled_writecnt=1LEDcmd=0x03 GREEN ON led release# 绿灯灭root@antbase:~# printf "\x04" > /dev/ledledopenled_writecnt=1LEDcmd=0x04 GREEN OFF led release# python 测试root@antbase:~# python test_led.pyRED ON ledopenled_writecnt=1LEDcmd=0x01 RED ON led release RED OFF ledopenled_writecnt=1LEDcmd=0x02 RED OFF led release GREEN ON ledopenled_writecnt=1LEDcmd=0x03 GREEN ON led release GREEN OFF ledopenled_writecnt=1LEDcmd=0x04 GREEN OFF led release