Linux驱动学习之第二个驱动程序(LED点亮关闭驱动程序-分层设计思想,使其能适应不同的板子-驱动程序模块为多个源文件怎么写Makefile)

目录

看这篇博文前请先掌握下面这些博文中的知识

https://blog.youkuaiyun.com/wenhao_ir/article/details/144888989
https://blog.youkuaiyun.com/wenhao_ir/article/details/144901797
https://blog.youkuaiyun.com/wenhao_ir/article/details/144881830

需要的PDF资料

开发板的原理图文件:
https://pan.baidu.com/s/1CEwPbcNUIicA1HVGwG6e5A?pwd=m9wb
IMX6ULL-CPU芯片的操作手册:
https://pan.baidu.com/s/1hZWmgmvYAA9mvzAHsPiw4g?pwd=eiuh

完整源代码

board_fire_imx6ull-pro.c中的代码

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <asm/io.h>

#include "led_opr.h"

static volatile unsigned int *CCM_CCGR1                              ;
static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
static volatile unsigned int *GPIO5_GDIR                             ;
static volatile unsigned int *GPIO5_DR                               ;

static int board_demo_led_init (int which) /* 初始化LED, which-哪个LED */       
{
   
    unsigned int val;

    //printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);
    if (which == 0)
    {
   
        if (!CCM_CCGR1)
        {
   
            CCM_CCGR1                               = ioremap(0x20C406C, 4);
            IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(0x2290014, 4);
            GPIO5_GDIR                              = ioremap(0x020AC000 + 0x4, 4);
            GPIO5_DR                                = ioremap(0x020AC000 + 0, 4);
        }
        
        /* GPIO5_IO03 */
        /* a. 使能GPIO5的时钟信号
         * set CCM to enable GPIO5
         * CCM_CCGR1[CG15] 0x20C406C
         * bit[31:30] = 0b11
         */
        *CCM_CCGR1 |= (3<<30);
        
        /* b. 设置GPIO5_IO03用于GPIO
         * set IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3
         *      to configure GPIO5_IO03 as GPIO
         * IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3  0x2290014
         * bit[3:0] = 0b0101 alt5
         */
        val = *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
        val &= ~(0xf);
        val |= (5);  //5的二进制表示为0101
        *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = val;
        
        
        /* b. 设置GPIO5_IO03作为output引脚
         * set GPIO5_GDIR to configure GPIO5_IO03 as output
         * GPIO5_GDIR  0x020AC000 + 0x4
         * bit[3] = 0b1
         */
        *GPIO5_GDIR |= (1<<3);
    }
    
    return 0;
}

static int board_demo_led_ctl (int which, char status) /* 控制LED, which-哪个LED, status:1-亮,0-灭 */
{
   
    //printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");
    if (which == 0)
    {
   
        if (status) /* on: output 0*/
        {
   
            /* d. 设置GPIO5_DR输出低电平
             * set GPIO5_DR to configure GPIO5_IO03 output 0
             * GPIO5_DR 0x020AC000 + 0
             * bit[3] = 0b0
             */
            *GPIO5_DR &= ~(1<<3);
        }
        else  /* off: output 1*/
        {
   
            /* e. 设置GPIO5_IO3输出高电平
             * set GPIO5_DR to configure GPIO5_IO03 output 1
             * GPIO5_DR 0x020AC000 + 0
             * bit[3] = 0b1
             */ 
            *GPIO5_DR |= (1<<3);
        }
    
    }
    return 0;
}

static int board_demo_led_close(int which) /* whice表示具体是要操作哪个LED*/
{
   
    if (which == 0)
    {
   
        if (CCM_CCGR1) {
   
            iounmap(CCM_CCGR1);
            CCM_CCGR1 = NULL;
        }
        if (IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3) {
   
            iounmap(IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3);
            IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = NULL;
        }
        if (GPIO5_GDIR) {
   
            iounmap(GPIO5_GDIR);
            GPIO5_GDIR = NULL;
        }
        if (GPIO5_DR) {
   
            iounmap(GPIO5_DR);
            GPIO5_DR = NULL;
        }
    }
    
    return 0;
}


static struct led_operations board_demo_led_opr = {
   
    .num  = 1,
    .init = board_demo_led_init,
    .ctl  = board_demo_led_ctl,
    .close = board_demo_led_close,
};

struct led_operations *get_board_led_opr(void)
{
   
    return &board_demo_led_opr;
}


leddrv.c中的代码

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

#include "led_opr.h"


/* 1. 确定主设备号                                                                 */
static int major = 0;
static struct class *led_class;
struct led_operations *p_led_opr;


#define MIN(a, b) (a < b ? a : b)

/* 3. 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
   
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

/* write(fd, &val, 1); */
static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
   
	int err;
	char status;
	struct inode *inode = file_inode(file);
	int minor = iminor(inode)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值