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

myled.c

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/uaccess.h>

#include <linux/io.h>

#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 <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

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;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值