TA的每日心情 | 开心 5 小时前 |
---|
签到天数: 1056 天 连续签到: 3 天 [LV.10]以坛为家III
|
参考手册测试linux下LED驱动程序开发。
一、硬件电路
1.1、硬件电路图
1.2、LED连接MCU的GPIO1_IO03引脚
二、配置寄存器
2.1、CCGR1寄存器
打开GPIO1时钟。
2.2、IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO3寄存器
选择GPIO模式
2.3、IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
配置GPIO
2.4、GPIOx_GDIR寄存器
配置GPIO方向
2.5、GPIOx_DR寄存器
数据寄存器
三、驱动程序
3.1、LED驱动程序
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/errno.h>
- #include <linux/gpio.h>
- #include <asm/mach/map.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
- #define LED_MAJOR 200
- #define LED_NAME "myled"
- #define LEDOFF 0
- #define LEDON 1
-
- #define CCM_CCGR1_BASE (0X020C406C)
- #define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
- #define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
- #define GPIO1_DR_BASE (0X0209C000)
- #define GPIO1_GDIR_BASE (0X0209C004)
- static void __iomem *IMX6U_CCM_CCGR1;
- static void __iomem *SW_MUX_GPIO1_IO03;
- static void __iomem *SW_PAD_GPIO1_IO03;
- static void __iomem *GPIO1_DR;
- static void __iomem *GPIO1_GDIR;
- void led_switch(u8 sta)
- {
- u32 val = 0;
- if(sta == LEDON) {
- val = readl(GPIO1_DR);
- val &= ~(1 << 3);
- writel(val, GPIO1_DR);
- }else if(sta == LEDOFF) {
- val = readl(GPIO1_DR);
- val|= (1 << 3);
- writel(val, GPIO1_DR);
- }
- }
- static int led_open(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
- {
- return 0;
- }
- static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
- {
- int retvalue;
- unsigned char databuf[1];
- unsigned char ledstat;
- retvalue = copy_from_user(databuf, buf, cnt);
- if(retvalue < 0) {
- printk("kernel write failed!\r\n");
- return -EFAULT;
- }
- ledstat = databuf[0];
- if(ledstat == LEDON) {
- led_switch(LEDON);
- } else if(ledstat == LEDOFF) {
- led_switch(LEDOFF);
- }
- return 0;
- }
- static int led_release(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- static struct file_operations led_fops = {
- .owner = THIS_MODULE,
- .open = led_open,
- .read = led_read,
- .write = led_write,
- .release = led_release,
- };
- static int __init led_init(void)
- {
- int retvalue = 0;
- u32 val = 0;
- IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
- SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
- SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
- GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
- GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
- val = readl(IMX6U_CCM_CCGR1);
- val &= ~(3 << 26);
- val |= (3 << 26);
- writel(val, IMX6U_CCM_CCGR1); //gpio clk enable
-
- writel(5, SW_MUX_GPIO1_IO03);
- writel(0x10B0, SW_PAD_GPIO1_IO03);
- val = readl(GPIO1_GDIR);
- val &= ~(1 << 3);
- val |= (1 << 3);
- writel(val, GPIO1_GDIR);
-
- val = readl(GPIO1_DR);
- val |= (1 << 3);
- writel(val, GPIO1_DR);
-
- retvalue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
- if(retvalue < 0){
- printk("register chrdev failed!\r\n");
- return -EIO;
- }else{
- printk("led init!\r\n");
- }
- return 0;
- }
- static void __exit led_exit(void)
- {
- iounmap(IMX6U_CCM_CCGR1);
- iounmap(SW_MUX_GPIO1_IO03);
- iounmap(SW_PAD_GPIO1_IO03);
- iounmap(GPIO1_DR);
- iounmap(GPIO1_GDIR);
- unregister_chrdev(LED_MAJOR, LED_NAME);
- printk("led exit!\r\n");
- }
- module_init(led_init);
- module_exit(led_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("alpha.imx led");
复制代码
3.2、测试程序
- #include "stdio.h"
- #include "unistd.h"
- #include "sys/types.h"
- #include "sys/stat.h"
- #include "fcntl.h"
- #include "stdlib.h"
- #include "string.h"
- #define LEDOFF 0
- #define LEDON 1
- int main(int argc, char *argv[])
- {
- int fd, retvalue;
- char *filename;
- unsigned char databuf[1];
-
- if(argc != 3){
- printf("Error Usage!\r\n");
- return -1;
- }
- filename = argv[1];
- fd = open(filename, O_RDWR);
- if(fd < 0){
- printf("file %s open failed!\r\n", argv[1]);
- return -1;
- }
- databuf[0] = atoi(argv[2]);
- retvalue = write(fd, databuf, sizeof(databuf));
- if(retvalue < 0){
- printf("LED Control Failed!\r\n");
- close(fd);
- return -1;
- }
- retvalue = close(fd);
- if(retvalue < 0){
- printf("file %s close failed!\r\n", argv[1]);
- return -1;
- }
- return 0;
- }
复制代码
四、编译
4.1、交叉编译环境
按照前面章节安装
启动交叉编译环境
命令:
# source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
4.2、应用程序编译环境
编译应用程序需要\5、开发工具\1、交叉编译器\1、交叉编译器\gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
文件gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz复制到linux下,并配置环境。
>命令:
xz -d gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
tar xvf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar
>编辑 /etc/profile
在文件的后面添加
export PATH=/opt/ALPHA.IMX/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/binPATH
>执行 source /etc/profile
>查看编译工具
编译环境配置完成。
4.3、文件复制到linux下。
4.4、修改Makefile文件
修改linux内核目录
4.5、编译驱动程序
编译驱动程序生成LED的驱动程序模块。
4.6、编译测试程序
执行命令:arm-linux-gnueabihf-gcc ledApp.c -o ledtest
五、测试
5.1、复制文件
将led.ko 和ledtest复制到开发板的/lib/modules/4.1.15-g52f6b26目录下
复制到开发板
5.2、打开模块
5.3、创建设备节点
5.4、开关LED灯
执行指令前,先关闭之前的LED灯状态
> echo 0 > /sys/class/leds/sys-led/brightness
打开LED灯命令:./ledtest /dev/myled 1
关闭LED灯命令:./ledtest /dev/myled 0
六、结果
执行指令正常开关LED灯。
|
|