IO口操控:orangepi zero 2

微机总线地址、物理地址、虚拟地址

推荐书籍:unix设计与实现

总线地址

  1. CPU能够访问内存的范围
  2. 如:装了32位的win7系统,内存条位8G,但是系统只识别了3.8G,装了64位,才能识别到8G
    1. 2^32=4G

物理地址

  1. 硬件的实际地址或绝对地址

虚拟地址

  1. 逻辑地址称为虚拟地址:基于算法的地址,软件层面的地址是假的

全志H616芯片是Cortex-A53的处理器,是ARMv8-A架构

编写IO口驱动

假设我要使用名字为PC9的引脚
image.png

阅读手册如下

基础物理地址如下:

image.png

功能选择寄存器

image.png
image.png
则PC9_SELECT的物理地址为 0x0300B000 + 0x004C
默认值为0x7777 7777,需要用到第4~6位

设置电平寄存器

image.png
则物理地址PC_DAT = 0x0300B000 + 0x0058
由于我们使用PC9,显然的第9位(从0开始数起)

实例代码

API

  1. ioremap(实际物理地址,大小):将实际物理地址,映射为指定大小的虚拟地址
  2. void iounmap(volatilevoid __iomem *addr);:解除映射
  3. unsigned long copy_from_user(void*to, constvoid__user*from, unsignedlong n);:从用户空间复制数据到内核空间,也就是将from的数据复制n个字节到to中,返回未能复制的字节数

驱动代码

#include <linux/fs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/types.h>
#include <asm/io.h>


static struct class *pin4_class;
static struct device *pin4_class_dev;

static dev_t devno;            //设备号
static int major =231;       //主设备号
static int minor =0;          //次设备号
static char *module_name="pin4";   //模块名

volatile unsigned int* PC9_SELECT = NULL;
volatile unsigned int* PC9_DAT = NULL;

static int pin4_open(struct inode *inode,struct file *file)
{

    printk("pin4_open\n");

    *PC9_SELECT &= ~(0x7 << 4);
    *PC9_SELECT |= (0x1 << 4);

    return 0;

}


static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{
    int userCmd=0;

    printk("pin4_write\n");

    copy_from_user(&userCmd,buf,count);
    printk("getValue\n");

    if(userCmd == 1){
         *PC9_DAT |= (0x1 << 9);

     }else if(userCmd == 0){
         *PC9_DAT &= ~(0x1 << 9);
     }else {
         printk("undo\n");
     }

    return 0;
}

static struct file_operations pin4_fops = {
    .owner = THIS_MODULE,
    .open  = pin4_open,
    .write = pin4_write,
};
//static int __init
static int  pin4_drv_init(void)
{
    int ret;

    devno = MKDEV(major,minor);
    ret   = register_chrdev(major, module_name,&pin4_fops);
    pin4_class=class_create(THIS_MODULE,"myfirstdemo");
    pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);

    PC9_SELECT = (volatile unsigned int* )ioremap(0x0300B04C,4);
    PC9_DAT = (volatile unsigned int *)ioremap(0x0300B058,4);
    //0x0300B000 

    return 0;
}

static void pin4_drv_exit(void)
{

    iounmap(PC9_SELECT);
    iounmap(PC9_DAT);

    device_destroy(pin4_class,devno);
    class_destroy(pin4_class);
    unregister_chrdev(major, module_name);
}

module_init(pin4_drv_init);
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL");

测试代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
 {
     int fd;
     fd = open("/dev/pin4",O_RDWR);
     if(fd < 0){
         printf("open fail\n");
     }else {
         printf("open success\n");
     }

     int cmd = 0;
     printf("cin cmd 1/0\n");

     scanf("%d",&cmd);

     if(cmd == 0){
         write(fd,&cmd,1);
     }else if(cmd == 1) {
         write(fd,&cmd,1);
     }
     printf("cmd=%d\n",cmd);
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值