华清远见上海中心22071班--11.16作业

题目:使用结构体映射,实现LED1、LED2、LED3循环点亮

实现代码:

#ifndef __LED_H__
#define __LED_H__

/*#define PHY_GPIO_MODER 0x50006000
#define PHY_GPIO_ODR 0x50006014
#define PHY_RCC 0x50000A28*/
typedef struct{
    volatile unsigned int MODER;
    volatile unsigned int OPTYPER;
    volatile unsigned int OSPEEDR;
    volatile unsigned int PUPDR;
    volatile unsigned int IDR;
    volatile unsigned int ODR;
}gpio_t;
#define GPIOE (gpio_t *)0x50006000
#define GPIOF (gpio_t *)0x50007000
#define PHY_RCC 0x50000A28
#endif
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "led.h"


#define CNAME "myled"

int major;
char kbuf[128]={0};
volatile unsigned int* virt_rcc;
volatile unsigned int* virt_gpioe;
volatile unsigned int* virt_gpiof;

//#define VIRT_RCC ((gpio_t *)virt_rcc)
#define VIRT_GPIOE ((gpio_t *)virt_gpioe)
#define VIRT_GPIOF ((gpio_t *)virt_gpiof)
//打开
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 *loffs)
{
    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 error\n");
        return -EIO;
    }
    printk("copy to user ubug =%s\n",ubuf);
    return 0;
}
//写入
ssize_t mycdev_write(struct file* file,const char __user *ubuf,size_t size,loff_t *loffs)
{
    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 error\n");
        return -EIO;
    }
    switch (kbuf[0])
    {
    case '1':   //PE10
        if('1'== kbuf[1])
        {
            VIRT_GPIOE->ODR |= (0x1 << 10); //led1输出高电平
        }
        else if('0' == kbuf[1])   //熄灭
        {
             VIRT_GPIOE->ODR &= (~(0x1 << 10));//led1输出低电平
        }
        break;
    case '2':   //PF10
        if('1'== kbuf[1])
        {
            VIRT_GPIOF->ODR |= (0x1 << 10); //led1输出高电平
        }
        else if('0' == kbuf[1])   //熄灭
        {
             VIRT_GPIOF->ODR &= (~(0x1 << 10));//led1输出低电平
        }
        break;
    case '3':   //PE8
        if('1'== kbuf[1])
        {
            VIRT_GPIOE->ODR|= (0x1 << 8); //led1输出高电平
        }
        else if('0' == kbuf[1])   //熄灭
        {
             VIRT_GPIOE->ODR &= (~(0x1 << 8));//led1输出低电平
        }
        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 demo_init(void)
{
    //注册字符设备驱动
    major = register_chrdev(0,CNAME,&fops);
    if(major <0)
    {
        printk("registe chrdec is error\n");
        return major;
    }
    printk("major=%d\n",major);
    //映射3个物理地址
    virt_rcc = ioremap(PHY_RCC,4);
    if(NULL == virt_rcc)
    {
        printk("rcc ioremap is error\n");
        return -ENOMEM;
    }
    virt_gpioe = ioremap(GPIOE,sizeof(GPIOE));
    if(NULL == virt_gpioe)
    {
        printk("gpio moder ioremap is error\n");
        return -ENOMEM;
    }
    virt_gpiof = ioremap(GPIOF,sizeof(GPIOF));
    if(NULL == virt_gpiof)
    {
        printk("gpio odr ioremap is error\n");
        return -ENOMEM;
    }

    //将rcc、gpio初始化   PE10\PF10\PE8
    *virt_rcc |= (0x3<<4);
    //PE10初始化
    VIRT_GPIOE->MODER &= (~(0x3<<20));
    VIRT_GPIOE->MODER |= 0x1<<20;
    VIRT_GPIOE->ODR &= (~(0x1<<10));
    //PE8初始化
    VIRT_GPIOE->MODER &= (~(0x3<<16));
    VIRT_GPIOE->MODER |= 0x1<<16;
    VIRT_GPIOE->ODR &= (~(0x1<<8));
    //PF10初始化
    VIRT_GPIOF->MODER &= (~(0x3<<20));
    VIRT_GPIOF->MODER |= 0x1<<20;
    VIRT_GPIOF->ODR &= (~(0x1<<10));
    return 0;
}
static void __exit demo_exit(void)
{
    //注销字符设备驱动
    iounmap(virt_rcc);
    iounmap(virt_gpioe);
    iounmap(virt_gpiof);
    unregister_chrdev(major,CNAME);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");

代码实现原理:

1、使用结构体对GPIO需要使用到的寄存器进行封装;

2、对整个结构体进行映射,返回结构体的首物理地址的虚拟地址A;

3、将该A虚拟地址强转为结构体指针类型;

4、在write函数中使用A指针访问结构体成员变量GPIO的各个寄存器;

5、用switch和if语句判断哪个灯应该被点亮,执行相应操作

测试现象:

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值