2023.2.7作业【字符设备驱动点灯实验】

myled.c

#include

#include

#include

#include

#include

#include "myled.h"

unsigned int major = 0;

gpio_t* gpioe_virt_base = NULL;

gpio_t* gpiof_virt_base = NULL;

unsigned int* rcc_ahb4_base = NULL;

char kbuf[128] = {0};

#define LED1_ON (gpioe_virt_base->ODR |= (0x1 << 10))

#define LED1_OFF (gpioe_virt_base->ODR &= (~(0x1 << 10)))

#define LED2_ON (gpiof_virt_base->ODR |= (0x1 << 10))

#define LED2_OFF (gpiof_virt_base->ODR &= (~(0x1 << 10)))

#define LED3_ON (gpioe_virt_base->ODR |= (0x1 << 8))

#define LED3_OFF (gpioe_virt_base->ODR &= (~(0x1 << 8)))

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 *loff)

{

    int ret;

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

    if(size > sizeof(kbuf)) size = sizeof(kbuf);

    ret = copy_to_user(ubuf,kbuf,size);

    if(ret)

    {

        printk("copy to user is error\n");

        return -EIO;

    }

    return size;

}

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

{

    int ret;

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

    if(size > sizeof(kbuf)) size = sizeof(kbuf);

    ret = copy_from_user(kbuf,ubuf,size);

    if(ret)

    {

        printk("copy from user is error\n");

        return -EIO;

    }

    //kbuf[0] 代表哪一盏灯 kbuf[0] = 0  kbuf[1] = 1 kbuf[2] = 2

    //kbuf[1] 代表灯的状态 kbuf[1] = 0  kbuf[1] = 1

    switch(kbuf[0])

    {

        case 0:

            kbuf[1]?LED1_ON:LED1_OFF;

            break;

        case 1:

            kbuf[1]?LED2_ON:LED2_OFF;

            break;

        case 2:

            kbuf[1]?LED3_ON:LED3_OFF;

            break;

    }

    return size;

}

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

{

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

    return 0;

}

const struct file_operations fops ={

    .open = mycdev_open,

    .read = mycdev_read,

    .write = mycdev_write,

    .release = mycdev_close,

};

static int __init mycdev_init(void)

{

    //1.注册字符设备驱动

    major = register_chrdev(0,CNAME,&fops);

    if(major < 0)

    {

        printk("register_chrdev is error\n");

        return major;

    }

    //2.将GPIOE、GPIOF、RCC地址进行映射

    gpioe_virt_base = ioremap(GPIOE_BASE_ADDR,sizeof(gpio_t));

    if(gpioe_virt_base == NULL)

    {

        printk("gpioe ioremap is error\n");

        return -ENOMEM;

    }

    gpiof_virt_base = ioremap(GPIOF_BASE_ADDR,sizeof(gpio_t));

    if(gpiof_virt_base == NULL)

    {

        printk("gpiof ioremap is error\n");

        return -ENOMEM;

    }

    rcc_ahb4_base = ioremap(RCC_PHY_ADDR,4);

    if(rcc_ahb4_base == NULL)

    {

        printk("rcc ioremap is error\n");

        return -ENOMEM;

    }

    //3.将led1灯进行初始化

    *rcc_ahb4_base |= (0x3 << 4);

    //1>设置GPIOE--->PE10引脚为输出模式

    gpioe_virt_base->MODER &= (~(0x3 << 20));

    gpioe_virt_base->MODER |= (0x1 << 20);

    //2>设置GPIOE_ODR--->PE10引脚输出低电平

    gpioe_virt_base->ODR &= (~(0x1 << 10));

    //4.将led2灯进行初始化  

    //1>设置GPIOF--->PF10引脚为输出模式

    gpiof_virt_base->MODER &= (~(0x3 << 20));

    gpiof_virt_base->MODER |= (0x1 << 20);

    //2>设置GPIOF_ODR--->PF10引脚输出低电平

    gpiof_virt_base->ODR &= (~(0x1 << 10));

    //3.将led3灯进行初始化

    //1>设置GPIOE--->PE8引脚为输出模式

    gpioe_virt_base->MODER &= (~(0x3 << 16));

    gpioe_virt_base->MODER |= (0x1 << 16);

    //2>设置GPIOE_ODR--->PE8引脚输出低电平

    gpioe_virt_base->ODR &= (~(0x1 << 8));

    return 0;

}


 

static void __exit mycdev_exit(void)

{

    iounmap(gpioe_virt_base);

    iounmap(gpiof_virt_base);

    iounmap(rcc_ahb4_base);

    unregister_chrdev(major,CNAME);

}

module_init(mycdev_init);

module_exit(mycdev_exit);

MODULE_LICENSE("GPL");

 myled.h

#ifndef __MYLED_H__

#define __MYLED_H__

#define CNAME "myled"

typedef struct {

        volatile unsigned int MODER;   // 0x00

        volatile unsigned int OTYPER;  // 0x04

        volatile unsigned int OSPEEDR; // 0x08

        volatile unsigned int PUPDR;   // 0x0C

        volatile unsigned int IDR;     // 0x10

        volatile unsigned int ODR;     // 0x14

        volatile unsigned int BSRR;    // 0x18

        volatile unsigned int LCKR;    // 0x1C

        volatile unsigned int AFRL;    // 0x20

        volatile unsigned int AFRH;    // 0x24

        volatile unsigned int BRR;     // 0x28

        volatile unsigned int res;

        volatile unsigned int SECCFGR; // 0x30

}gpio_t;

#define RCC_PHY_ADDR 0x50000A28

#define GPIOE_BASE_ADDR 0x50006000

#define GPIOF_BASE_ADDR 0x50007000

#endif

test.c

#include

#include

#include

#include

#include

#include

int main(int argc, char const *argv[])

{

    int fd;

    char ubuf[128] = {0};

    fd = open("/dev/myled",O_RDWR);

    if(fd == -1)

    {

        perror("open is error");

        exit(1);

    }

    while(1)

    {

        //LED1灯操作

        ubuf[0] = 0;

        ubuf[1] = 1;

        write(fd,ubuf,sizeof(ubuf));

        sleep(1);

        ubuf[1] = 0;

        write(fd,ubuf,sizeof(ubuf));

        sleep(1);

        //LED2灯操作

        ubuf[0] = 1;

        ubuf[1] = 1;

        write(fd,ubuf,sizeof(ubuf));

        sleep(1);

        ubuf[1] = 0;

        write(fd,ubuf,sizeof(ubuf));

        sleep(1);

        //LED3灯操作

        ubuf[0] = 2;

        ubuf[1] = 1;

        write(fd,ubuf,sizeof(ubuf));

        sleep(1);

        ubuf[1] = 0;

        write(fd,ubuf,sizeof(ubuf));

        sleep(1);

    }

    close(fd);

    return 0;

}

你可能感兴趣的:(作业,嵌入式硬件)