码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 驱动开发(三):内核层控制硬件层


     驱动开发相关文章:

    驱动开发(一):驱动代码的基本框架

    驱动开发(二):创建字符设备驱动

    驱动开发(三):内核层控制硬件层

    驱动开发(四):Linux内核中断

    驱动开发(五):Linux内核定时器

    驱动开发(六):应用层通过文件系统与内核层交互

    驱动开发(应用):设计一个社区饮水机控制系统

    目录

    驱动是如何操作寄存器的

    地址映射函数

    物理地址映射为虚拟地址

    取消映射

    实际操作流程演示


    驱动是如何操作寄存器的

    驱动操作寄存器可以通过以下步骤实现:

    1. 获取寄存器的地址:首先需要确定要操作的寄存器的地址。这可以通过查阅芯片的数据手册或者使用芯片提供的寄存器映射文档来获得。

    2. 设置寄存器的值:使用编程语言提供的位操作或者寄存器操作函数,将需要设置的值写入到寄存器中。可以使用位掩码来确定要设置的位或者位域。

    3. 读取寄存器的值:使用编程语言提供的位操作或者寄存器操作函数,读取寄存器的当前值。可以使用位掩码来获取特定位或者位域的值。

    需要注意的是,在操作寄存器时,要确保对寄存器的访问是合法的,遵循芯片厂商的规定,避免对未定义或者只读的寄存器进行写操作。此外,还要考虑并发访问的问题,如果多个驱动同时操作同一个寄存器,可能会引发竞争条件或者数据不一致的问题,需要进行同步或者互斥操作。

    以点亮一盏灯为例,控制rgb_led灯的寄存器是物理地址,但是在Linux内核启动之后,在使用地址的时候,操作的全是虚拟地址。需要将物理地址转换为虚拟地址。在驱动代码中操作的虚拟地址就相当于操作的实际物理地址。

    地址映射函数

    物理地址映射为虚拟地址

    1. void * ioremap(phys_addr_t offset, unsigned long size)
    2. 功能:将物理地址映射成虚拟地址
    3. 参数:
    4. @offset :要映射的物理地址
    5. @size :大小(字节)
    6. 返回值:成功返回虚拟地址,失败返回NULL;

    取消映射

    1. void iounmap(void *addr)
    2. 功能:取消映射
    3. 参数:
    4. @addr :虚拟地址
    5. 返回值:无

    实际操作流程演示

    1、以S5P6818的U21引脚输出高电平熄灭LED灯为例

    2、在手册芯片搜索U21引脚

     GPIOXOUT寄存器:控制高低电平

    GPIOXOUTENB寄存器:输入/输出模式 对应位置1设置为输出模式

     GPIOXALTFN寄存器:功能模式寄存器(配置引脚是哪种功能),刚刚查询引脚时可以看到,功能0为GPIO,选择功能0,

     GPIOA28 (0XC001A000)----> red_base   //起始地址

    *(red_base) |= 1<<28;    //操作GPIOXOUT寄存器,控制引脚电平

    *(red_base+1) |= 1<<28;   //操作GPIOXOUTENB寄存器,设置为输出模式

    *(red_base+9) &= ~(3<<24);  //操作GPIOXALTFN寄存器,选择GPIO功能模式

     3、根据查询到的信息编写驱动代码

    1. #include <linux/init.h>
    2. #include <linux/module.h>
    3. #include <linux/printk.h>
    4. #include <asm/io.h>
    5. #define RED 0XC001A000 //起始物理地址
    6. unsigned int *red_base = NULL;
    7. static int __init hello_init(void)
    8. {
    9. red_base = ioremap(RED,40); //将物理地址映射成虚拟地址
    10. if (NULL == red_base )
    11. {
    12. printk("ioremap err\n");
    13. }
    14. *(red_base) &= ~(1<<28); //操作寄存器
    15. *(red_base+1) |= 1<<28;
    16. *(red_base+9) &= ~(3<<24);
    17. return 0;
    18. }
    19. static void __exit hello_exit(void)
    20. {
    21. *(red_base) |= (1<<28); //还原LED状态
    22. iounmap(red_base); //取消映射
    23. }
    24. module_init(hello_init); //入口
    25. module_exit(hello_exit); //出口
    26. MODULE_LICENSE("GPL"); //许可证

  • 相关阅读:
    c入门第二十四篇: 学生成绩管理系统优化(可执行文件传参)
    Python-爬虫(基础概念、常见请求模块(urllib、requests))
    ElasticSearch异常情况监控处理
    Flink部署之Yarn
    CiteSpace的介绍、重要调整参数及其重要术语
    Nacos源码系列—关于服务注册的那些事
    【Spring Boot】实战:实现Session共享
    Monaco Editor教程(十二):使用Marker来增加分词注释,标记,优化编辑器交互体验
    rust持续学习 Fn FnMut FnOnce
    Java后端开发——实现登录验证程序
  • 原文地址:https://blog.csdn.net/a1547998353/article/details/139661593
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号