驱动 课后作业

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/uaccess.h>

#include <linux/io.h>

#include "led.h"

unsigned int major;

char kbuf[128] = "";

unsigned int *vir_led1_moder;

unsigned int *vir_led1_odr;

unsigned int *vir_led2_moder;

unsigned int *vir_led2_odr;

// unsigned int *vir_led3_moder;

// unsigned int *vir_led3_odr;

unsigned int *vir_rcc;

int mycdev_open(struct inode *inode, struct file *file)

{

    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);

    return 0;

}

ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *offs)

{

    // 向用户拷贝

    int ret;

    // 如果用户想写的大小大于内核的内存大小,更正用户写的大小

    if (size > sizeof(kbuf))

        size = sizeof(kbuf);

    ret = copy_to_user(ubuf, kbuf, size);

    if (ret) // 成功返回0,失败返回未拷贝的字节的个数

    {

        printk("copy to user filed\n");

        return -EIO;

    }

    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);

    return 0;

}

ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *off)

{

    // 从用户拷贝

    int ret;

    if (size > sizeof(kbuf))

        size = sizeof(kbuf);

    ret = copy_from_user(kbuf, ubuf, size);

    if (ret)

    {

        printk("copy from user filed\n");

        return -EIO;

    }

    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);

    // 根据用户空间发送来的指令实现灯的亮灭控制

    if (kbuf[0] == '1') // led1亮

    {

        (*vir_led1_odr) |= (0x1 << 10);

        (*vir_led2_odr) |= (0x1 << 10);

        (*vir_led1_odr) |= (0x1 << 8);

    }

    else if (kbuf[0] == '0') // led1灭

    {

        (*vir_led1_odr) &= (~(0x1 << 10));

        (*vir_led2_odr) &= (~(0x1 << 10));

        (*vir_led1_odr) &= (~(0x1 << 8));

    }

    return 0;

}

int mycdev_close(struct inode *inode, struct file *file)

{

    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);

    return 0;

}

// 定义一个操作方法结构体变量并初始化

struct file_operations fops = {

    .open = mycdev_open,

    .read = mycdev_read,

    .write = mycdev_write,

    .release = mycdev_close,

};

static int __init mycdev_init(void)

{

    // 字符设备驱动注册

    major = register_chrdev(0, "mycdev", &fops);

    if (major < 0)

    {

        printk("字符设备驱动注册失败\n");

        return major;

    }

    printk("字符设备驱动注册成功 major=%d\n", major);

    // LED相关寄存器地址映射

    vir_led1_moder = ioremap(PHY_led1_MODER, 4); // 4  32字节

    if (vir_led1_moder == NULL)

    {

        printk("物理内存映射失败\n");

        return -EFAULT;

    }

    vir_led2_moder = ioremap(PHY_led2_MODER, 4); // 4  32字节

    if (vir_led2_moder == NULL)

    {

        printk("物理内存映射失败\n");

        return -EFAULT;

    }

    // vir_led3_moder = ioremap(PHY_led2_MODER, 4); // 4  32字节

    // if (vir_led3_moder == NULL)

    // {

    //     printk("物理内存映射失败\n");

    //     return -EFAULT;

    // }

    vir_led1_odr = ioremap(PHY_led1_ODR, 4); // 4  32字节

    if (vir_led1_odr == NULL)

    {

        printk("物理内存映射失败\n");

        return -EFAULT;

    }

    vir_led2_odr = ioremap(PHY_led2_ODR, 4); // 4  32字节

    if (vir_led2_odr == NULL)

    {

        printk("物理内存映射失败\n");

        return -EFAULT;

    }

    // vir_led3_odr = ioremap(PHY_led2_ODR, 4); // 4  32字节

    // if (vir_led3_odr == NULL)

    // {

    //     printk("物理内存映射失败\n");

    //     return -EFAULT;

    // }

    vir_rcc = ioremap(RCC_MP_AHB4ENSETR, 4); // 4  32字节

    if (vir_rcc == NULL)

    {

        printk("物理内存映射失败\n");

        return -EFAULT;

    }

    printk("物理内存映射成功\n");

    // 初始化   PE10 PF10 PE8

    *vir_rcc |= (0x3 << 4); // 使能GPIOE,F

    *vir_led1_moder &= (~(0x3 << 20));

    *vir_led1_moder |= (0x1 << 20);

    *vir_led2_moder &= (~(0x3 << 20));

    *vir_led2_moder |= (0x1 << 20);

    *vir_led1_moder &= (~(0x3 << 16));

    *vir_led1_moder |= (0x1 << 16);

    *vir_led1_odr &= (~(0x1 << 10)); // 默认灭

    *vir_led2_odr &= (~(0x1 << 10));

    *vir_led1_odr &= (~(0x1 << 8));

    printk("初始化成功\n");

    return 0;

}

static void __exit mycdev_exit(void)

{

    iounmap(vir_rcc);

    iounmap(vir_led1_odr);

    iounmap(vir_led1_moder);

    iounmap(vir_led2_odr);

    iounmap(vir_led2_moder);

    // iounmap(vir_led3_odr);

    // iounmap(vir_led3_moder);

    // 字符设备驱动注销

    unregister_chrdev(major, "myled");

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

头文件

#ifndef __MYLED_H__

#define __MYLED_H__

//PE10 PF10 PE8

#define PHY_led1_MODER   0x50006000

#define PHY_led2_MODER   0x50007000

// #define PHY_led3_MODER   0x50006000

#define PHY_led1_ODR     0x50006014

#define PHY_led2_ODR     0x50007014

// #define PHY_led3_ODR     0x50006014

#define RCC_MP_AHB4ENSETR     0x50000A28

// #include "stm32mp1xx_rcc.h"

// #include "stm32mp1xx_gpio.h"ss


 

#endif

猜你喜欢

转载自blog.csdn.net/m0_53451387/article/details/131195116