Drive homework

#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_mother;

// 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)

{

    // copy to user

    int ret;

    // If the size the user wants to write is larger than the memory size of the kernel, correct the size written by the user

    if (size > sizeof(kbuf))

        size = sizeof(kbuf);

    ret = copy_to_user(ubuf, kbuf, size);

    if (ret) // success returns 0, failure returns the number of uncopied bytes

    {

        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)

{

    // copy from user

    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__);

    // Realize the light on and off control according to the instructions sent from the user space

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

    {

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

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

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

    }

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

    {

        (*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;

}

// Define an operation method structure variable and initialize it

struct file_operations fops = {

    .open = mycdev_open,

    .read = mycdev_read,

    .write = mycdev_write,

    .release = mycdev_close,

};

static int __init mycdev_init(void)

{

    // character device driver registration

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

    if (major < 0)

    {

        printk("Character device driver registration failed\n");

        return major;

    }

    printk("Character device driver registered successfully major=%d\n", major);

    // LED related register address mapping

    vir_led1_moder = ioremap(PHY_led1_MODER, 4); // 4 32 bytes

    if (for_led1_moder == NULL)

    {

        printk("Physical memory mapping failed\n");

        return -EFAULT;

    }

    vir_led2_moder = ioremap(PHY_led2_MODER, 4); // 4 32 bytes

    if (vir_led2_moder == NULL)

    {

        printk("Physical memory mapping failed\n");

        return -EFAULT;

    }

    // vir_led3_moder = ioremap(PHY_led2_MODER, 4); // 4 32 bytes

    // if (vir_led3_moder == NULL)

    // {

    // printk("Physical memory mapping failed\n");

    //     return -EFAULT;

    // }

    vir_led1_odr = ioremap(PHY_led1_ODR, 4); // 4 32 bytes

    if (vir_led1_odr == NULL)

    {

        printk("Physical memory mapping failed\n");

        return -EFAULT;

    }

    vir_led2_odr = ioremap(PHY_led2_ODR, 4); // 4 32 bytes

    if (vir_led2_odr == NULL)

    {

        printk("Physical memory mapping failed\n");

        return -EFAULT;

    }

    // vir_led3_odr = ioremap(PHY_led2_ODR, 4); // 4 32 bytes

    // if (vir_led3_odr == NULL)

    // {

    // printk("Physical memory mapping failed\n");

    //     return -EFAULT;

    // }

    vir_rcc = ioremap(RCC_MP_AHB4ENSETR, 4); // 4 32 bytes

    if (vir_rcc == NULL)

    {

        printk("Physical memory mapping failed\n");

        return -EFAULT;

    }

    printk("Physical memory mapped successfully\n");

    // Initialize PE10 PF10 PE8

    *vir_rcc |= (0x3 << 4); // enable 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)); // off by default

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

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

    printk("Initialization succeeded\n");

    return 0;

}

static void __exit mycdev_exit(void)

{

    ionmap(for_rcc);

    iounmap(vir_led1_odr);

    iounmap(vir_led1_moder);

    iounmap(vir_led2_odr);

    iounmap(vir_led2_moder);

    // ionmap(vir_led3_odr);

    // ionmap(vir_led3_moder);

    // character device driver logout

    unregister_chrdev(major, "myled");

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

head File

#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

 

Guess you like

Origin blog.csdn.net/m0_53451387/article/details/131195116