查看: 1334|回复: 0

正点原子ARM Linux开发板I.MX6ULL - 6、linux LED驱动程序

[复制链接]
  • TA的每日心情
    开心
    前天 08:07
  • 签到天数: 1053 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2020-3-4 00:07:39 | 显示全部楼层 |阅读模式
    分享到:
        参考手册测试linux下LED驱动程序开发。

        一、硬件电路


        1.1、硬件电路图
        1.png
        2.png

        3.png
        1.2、LED连接MCU的GPIO1_IO03引脚


        二、配置寄存器
       
        2.1、CCGR1寄存器
        打开GPIO1时钟。
        4.png
        5.png
       
        2.2、IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO3寄存器
        选择GPIO模式
        6.png


        2.3、IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
        配置GPIO
        7.png


        2.4、GPIOx_GDIR寄存器
        配置GPIO方向
        8.png
       
        2.5、GPIOx_DR寄存器
        数据寄存器
        9.png


        三、驱动程序
       
        3.1、LED驱动程序
       
    1. #include <linux/types.h>
    2. #include <linux/kernel.h>
    3. #include <linux/delay.h>
    4. #include <linux/ide.h>
    5. #include <linux/init.h>
    6. #include <linux/module.h>
    7. #include <linux/errno.h>
    8. #include <linux/gpio.h>
    9. #include <asm/mach/map.h>
    10. #include <asm/uaccess.h>
    11. #include <asm/io.h>

    12. #define LED_MAJOR                200               
    13. #define LED_NAME                "myled"        

    14. #define LEDOFF         0                                 
    15. #define LEDON         1                                 

    16. #define CCM_CCGR1_BASE                                (0X020C406C)       
    17. #define SW_MUX_GPIO1_IO03_BASE                (0X020E0068)
    18. #define SW_PAD_GPIO1_IO03_BASE                (0X020E02F4)
    19. #define GPIO1_DR_BASE                                (0X0209C000)
    20. #define GPIO1_GDIR_BASE                                (0X0209C004)

    21. static void __iomem *IMX6U_CCM_CCGR1;
    22. static void __iomem *SW_MUX_GPIO1_IO03;
    23. static void __iomem *SW_PAD_GPIO1_IO03;
    24. static void __iomem *GPIO1_DR;
    25. static void __iomem *GPIO1_GDIR;

    26. void led_switch(u8 sta)
    27. {
    28.         u32 val = 0;
    29.         if(sta == LEDON) {
    30.                 val = readl(GPIO1_DR);
    31.                 val &= ~(1 << 3);       
    32.                 writel(val, GPIO1_DR);
    33.         }else if(sta == LEDOFF) {
    34.                 val = readl(GPIO1_DR);
    35.                 val|= (1 << 3);       
    36.                 writel(val, GPIO1_DR);
    37.         }       
    38. }

    39. static int led_open(struct inode *inode, struct file *filp)
    40. {
    41.         return 0;
    42. }
    43. static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
    44. {
    45.         return 0;
    46. }
    47. static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
    48. {
    49.         int retvalue;
    50.         unsigned char databuf[1];
    51.         unsigned char ledstat;

    52.         retvalue = copy_from_user(databuf, buf, cnt);
    53.         if(retvalue < 0) {
    54.                 printk("kernel write failed!\r\n");
    55.                 return -EFAULT;
    56.         }

    57.         ledstat = databuf[0];               

    58.         if(ledstat == LEDON) {       
    59.                 led_switch(LEDON);
    60.         } else if(ledstat == LEDOFF) {
    61.                 led_switch(LEDOFF);         
    62.         }
    63.         return 0;
    64. }

    65. static int led_release(struct inode *inode, struct file *filp)
    66. {
    67.         return 0;
    68. }

    69. static struct file_operations led_fops = {
    70.         .owner = THIS_MODULE,
    71.         .open = led_open,
    72.         .read = led_read,
    73.         .write = led_write,
    74.         .release =         led_release,
    75. };

    76. static int __init led_init(void)
    77. {
    78.         int retvalue = 0;
    79.         u32 val = 0;

    80.           IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
    81.         SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
    82.           SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
    83.         GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
    84.         GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);

    85.         val = readl(IMX6U_CCM_CCGR1);
    86.         val &= ~(3 << 26);         
    87.         val |= (3 << 26);         
    88.         writel(val, IMX6U_CCM_CCGR1);   //gpio clk enable
    89.        
    90.         writel(5, SW_MUX_GPIO1_IO03);
    91.         writel(0x10B0, SW_PAD_GPIO1_IO03);

    92.         val = readl(GPIO1_GDIR);
    93.         val &= ~(1 << 3);         
    94.         val |= (1 << 3);         
    95.         writel(val, GPIO1_GDIR);
    96.        
    97.         val = readl(GPIO1_DR);
    98.         val |= (1 << 3);       
    99.         writel(val, GPIO1_DR);
    100.        
    101.         retvalue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
    102.         if(retvalue < 0){
    103.                 printk("register chrdev failed!\r\n");
    104.                 return -EIO;
    105.         }else{
    106.                 printk("led init!\r\n");
    107.         }
    108.         return 0;
    109. }

    110. static void __exit led_exit(void)
    111. {
    112.         iounmap(IMX6U_CCM_CCGR1);
    113.         iounmap(SW_MUX_GPIO1_IO03);
    114.         iounmap(SW_PAD_GPIO1_IO03);
    115.         iounmap(GPIO1_DR);
    116.         iounmap(GPIO1_GDIR);
    117.         unregister_chrdev(LED_MAJOR, LED_NAME);
    118.         printk("led exit!\r\n");
    119. }

    120. module_init(led_init);
    121. module_exit(led_exit);
    122. MODULE_LICENSE("GPL");
    123. MODULE_AUTHOR("alpha.imx led");
    复制代码


        3.2、测试程序
       
    1. #include "stdio.h"
    2. #include "unistd.h"
    3. #include "sys/types.h"
    4. #include "sys/stat.h"
    5. #include "fcntl.h"
    6. #include "stdlib.h"
    7. #include "string.h"

    8. #define LEDOFF         0
    9. #define LEDON         1

    10. int main(int argc, char *argv[])
    11. {
    12.         int fd, retvalue;
    13.         char *filename;
    14.         unsigned char databuf[1];
    15.        
    16.         if(argc != 3){
    17.                 printf("Error Usage!\r\n");
    18.                 return -1;
    19.         }

    20.         filename = argv[1];

    21.         fd = open(filename, O_RDWR);
    22.         if(fd < 0){
    23.                 printf("file %s open failed!\r\n", argv[1]);
    24.                 return -1;
    25.         }

    26.         databuf[0] = atoi(argv[2]);

    27.         retvalue = write(fd, databuf, sizeof(databuf));
    28.         if(retvalue < 0){
    29.                 printf("LED Control Failed!\r\n");
    30.                 close(fd);
    31.                 return -1;
    32.         }

    33.         retvalue = close(fd);
    34.         if(retvalue < 0){
    35.                 printf("file %s close failed!\r\n", argv[1]);
    36.                 return -1;
    37.         }
    38.         return 0;
    39. }
    复制代码



        四、编译
       
        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
        >查看编译工具
        11.png
        编译环境配置完成。
       
        4.3、文件复制到linux下。
        10.png
         

        4.4、修改Makefile文件
        修改linux内核目录
        12.png    


        4.5、编译驱动程序
        编译驱动程序生成LED的驱动程序模块。
        13.png
         
        4.6、编译测试程序
        执行命令:arm-linux-gnueabihf-gcc ledApp.c -o ledtest
        14.png


        五、测试
       
        5.1、复制文件
        将led.ko 和ledtest复制到开发板的/lib/modules/4.1.15-g52f6b26目录下
        15.png
        复制到开发板
        16.png
        17.png


        5.2、打开模块
        18.png
       
         5.3、创建设备节点
        19.png
       
        5.4、开关LED灯
        执行指令前,先关闭之前的LED灯状态
        > echo 0 > /sys/class/leds/sys-led/brightness


        打开LED灯命令:./ledtest /dev/myled 1
        关闭LED灯命令:./ledtest /dev/myled 0


         
        六、结果


        执行指令正常开关LED灯。






    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-4-20 05:47 , Processed in 0.109846 second(s), 16 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.