微机总线地址、物理地址、虚拟地址
推荐书籍:unix设计与实现
总线地址
- CPU能够访问内存的范围
- 如:装了32位的win7系统,内存条位8G,但是系统只识别了3.8G,装了64位,才能识别到8G
- 2^32=4G
- 2^32=4G
物理地址
- 硬件的实际地址或绝对地址
虚拟地址
- 逻辑地址称为虚拟地址:基于算法的地址,软件层面的地址是假的
全志H616芯片是Cortex-A53的处理器,是ARMv8-A架构
编写IO口驱动
假设我要使用名字为PC9的引脚
阅读手册如下
基础物理地址如下:
功能选择寄存器
则PC9_SELECT的物理地址为 0x0300B000 + 0x004C
默认值为0x7777 7777,需要用到第4~6位
设置电平寄存器
则物理地址PC_DAT = 0x0300B000 + 0x0058
由于我们使用PC9,显然的第9位(从0开始数起)
实例代码
API
ioremap(实际物理地址,大小)
:将实际物理地址,映射为指定大小的虚拟地址void iounmap(volatilevoid __iomem *addr);
:解除映射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);
}