当前位置: 首页 > news >正文

Rk3568驱动开发_点亮led灯(手动挡)_5

1.MMU简介

完成虚拟空间到物理空间的映射
内存保护设立存储器的访问权限,设置虚拟存储空间的缓冲特性

stm32点灯可以直接操作寄存器,但是linux点灯不能直接访问寄存器,linux会使能mmu

在这里插入图片描述

linux中操作的都是虚拟地址,要想访问物理地址0x0a就得先搞清楚0xa对应的虚拟地址

获得物理地址对应的虚拟地址使用ioremap函数,本质是个宏,参数分别是物理地址启始大小,要转换的字节数量

卸载驱动的时候用iounmap()卸载映射

stm32没有这个MMU其控制gpio直接操作寄存器就行,在linux上由于这个内存映射在,需要知道真实物理地址,反推其虚拟地址才能像stm32一样操作寄存器

linux做驱动有配置设备树更高级的操作方式,像这种操作寄存器的好似手动档

2.代码:

驱动:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>

#define LED_MAJOR 200
#define LED_NAME "led"

#define PMU_GRF_BASE						      (0xFDC20000)
#define PMU_GRF_GPIO0C_IOMUX_L				(PMU_GRF_BASE + 0x0010)
#define PMU_GRF_GPIO0C_DS_0					  (PMU_GRF_BASE + 0X0090)
#define GPIO0_BASE						        (0xFDD60000)
#define GPIO0_SWPORT_DR_H				      (GPIO0_BASE + 0X0004)
#define GPIO0_SWPORT_DDR_H				    (GPIO0_BASE + 0X000C)

/* 映射后的寄存器虚拟地址指针 */
static void __iomem *PMU_GRF_GPIO0C_IOMUX_L_PI;
static void __iomem *PMU_GRF_GPIO0C_DS_0_PI;
static void __iomem *GPIO0_SWPORT_DR_H_PI;
static void __iomem *GPIO0_SWPORT_DDR_H_PI;

static int led_open(struct inode* inode, struct file* filp){

  return 0;
}

static int led_release(struct inode* inode, struct file* filp){

  return 0;
}

static ssize_t led_write(struct file* filp, const char __user* buf, size_t count, loff_t* ppos){

  return 0;
}

/* 字符设备操作集*/
static const struct file_operations led_fops = {
  .owner = THIS_MODULE,
  .write = led_write,
  .open = led_open,
  .release = led_release,
};

/*注册驱动加载卸载*/

static int __init led_init(void){ // 入口

  // 初始化led灯

  int ret = 0;
  u32 val = 0;

  PMU_GRF_GPIO0C_IOMUX_L_PI = ioremap(PMU_GRF_GPIO0C_IOMUX_L, 4);
	PMU_GRF_GPIO0C_DS_0_PI = ioremap(PMU_GRF_GPIO0C_DS_0, 4);
	GPIO0_SWPORT_DR_H_PI = ioremap(GPIO0_SWPORT_DR_H, 4);
	GPIO0_SWPORT_DDR_H_PI = ioremap(GPIO0_SWPORT_DDR_H, 4);
  // 初始化

  // 设置GPIO0_c0为GPIO功能
  val = readl(PMU_GRF_GPIO0C_IOMUX_L_PI);
  val &= ~(0x7 << 0); //最低三位置0
  val |= ((0x7 << 16) | (0x0 << 0)); // 16 17 18位置1其他不变,bit2:0:0,用作GPIO0_C0
  writel(val, PMU_GRF_GPIO0C_IOMUX_L_PI);

  // 设置GPIO_C0驱动能力为level5
  val = readl(PMU_GRF_GPIO0C_DS_0_PI);
  val &= ~(0x3f << 0);  // 0 ~ 5置0
  val |= ((0x3f << 16) | (0x3f << 0)); // 16 ~ 21置1,0~5置1同时用作GPIO0c0
  writel(val, PMU_GRF_GPIO0C_DS_0_PI);

  // 设置GPIOO0_c0为输出
  val = readl(GPIO0_SWPORT_DDR_H_PI);
  val &= ~(0x1 << 0); // 0置0
  val |= ((0x1 << 16) | (0x1 << 0)); // 16置1,0置1
  writel(val, GPIO0_SWPORT_DDR_H_PI);

  // 设置GPIO_c0为低电平,关闭LED
  val = readl(GPIO0_SWPORT_DR_H_PI);
  val &= ~(0x1 << 0);
  val |= ((0x1 << 16) | (0x0 << 0));
  writel(val, GPIO0_SWPORT_DR_H_PI);

  // 开灯

  val = readl(GPIO0_SWPORT_DR_H_PI);
  val &= ~(0X1 << 0); /* bit0 清零*/
  val |= ((0X1 << 16) | (0X1 << 0));	/* bit16 置1,允许写bit0,
                         bit0,高电平*/ 
  writel(val, GPIO0_SWPORT_DR_H_PI);  
  
  // 注册字符设备
  ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);

  if(ret < 0){
    printk("register chrdev failed!\r\n");
    return -EIO;
  }

  printk("led_init\r\n");
  return 0;
}

static void __exit led_exit(void){ // 出口

  u32 val = 0;

  // 关灯

  val = readl(GPIO0_SWPORT_DR_H_PI);
  val &= ~(0X1 << 0); /* bit0 清零*/
  val |= ((0X1 << 16) | (0X0 << 0));	/* bit16 置1,允许写bit0,
                         bit0,低电平	*/
  writel(val, GPIO0_SWPORT_DR_H_PI); 

  // 取消地址映射
  iounmap(PMU_GRF_GPIO0C_IOMUX_L_PI);
  iounmap(PMU_GRF_GPIO0C_DS_0_PI);
  iounmap(GPIO0_SWPORT_DR_H_PI);
  iounmap(GPIO0_SWPORT_DDR_H_PI);
  // 注销
  unregister_chrdev(LED_MAJOR, LED_NAME);
  printk("led_exit\r\n");

}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Narnat");

ioremap(PMU_GRF_GPIO0C_IOMUX_L, 4);将物理地址转虚拟内存

在程序挂载时初始化一些寄存器,并点亮led灯,卸载时关闭led灯

3.现象:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

相关文章:

  • 文件上传漏洞学习笔记
  • 【SRC实战】搜索功能泄露订单号+用户定位
  • 自学c++之类、对象、封装
  • 【语法】C++的string
  • 解决应用程序 0xc00000142 错误:完整修复指南
  • 记录Liunx安装Jenkins时的Package ‘jenkins‘ has no installation candidate
  • 全星QMS软件系统:制造业质量管理的全面优化与创新研究
  • 开源基准测试模拟器:BlueROV2 水下机器人的控制(更改Z方向控制器)
  • JAVA面试常见题_基础部分_Dubbo面试题(上)
  • 2025/2/25,字节跳动后端开发一面面经
  • 深入理解Tomcat与Web应用部署:C/S与B/S架构下的实践指南
  • 冒泡排序(Bubble Sort)
  • 第13周:LSTM实现糖尿病探索与预测
  • UE 播放图像序列
  • 学习记录:初次学习使用transformers进行大模型微调
  • Docker镜像面试题及参考答案
  • 计算机毕业设计 ——jspssm513Springboot 的小区物业管理系统
  • HTML+CSS
  • 什么是数据治理?如何从数据治理中获得价值?
  • 【新人系列】Python 入门专栏合集
  • 几天洗一次头发最好?终于有答案了...
  • 安徽六安特色产品将“组团”入沪,借力五五购物节开拓市场
  • 上海浪琴环球马术冠军赛明日启幕!五一假期在这里感受精彩
  • 49:49白热化,美参议院对新关税政策产生巨大分歧
  • 王毅:时代不容倒退,公道自在人心
  • 北大深圳研究生院成立科学智能学院:培养交叉复合型人才