目录

底层知识

芯片启动过程

树莓派Linux源码目录树分析

ARM树莓派高级开发——linux内核源码、树莓派源码编译、SD卡挂载

编译移植条件

树莓派Linux源码配置

如何配置树莓派的Linux内核

树莓派Linux内核编译

树莓派本地编译

Linux基础 ——“文件系统” 走进一切皆文件的体系中(文件系统目录结构、磁盘分区、虚拟文件系统)

1. 什么是文件系统?

2. 文件系统(文件管理系统的方法)的种类有哪些?

3. 什么是分区?

4. linux目录结构

5.详细说明目录作用

3、etc

什么虚拟文件系统Virtual File System ?

Linux中级——“内核” 硬核的体系结构,衔接工作

shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。

Linux中级——“驱动” 控制硬件必须学会的底层知识

驱动认知

应用到驱动流程

基于框架编写驱动代码:

驱动框架执行流程:

驱动模块代码编译

树莓派高级开发——“IO口驱动代码的编写“ 包含总线地址、物理/虚拟地址、BCM2835芯片手册知识

总线

地址总线

数据总线

数据总线的宽度对CPU的性能的影响:

物理地址(PA)

虚拟地址(VA)


参考博文 原文链接:https://blog.csdn.net/qq_44333320/article/details/125555867

底层知识

芯片启动过程

C51、STM32(裸机)是C直接操控底层寄存器实现相关业务,属于业务流程型的裸机代码。比如:
遥控灯: while(1)
垃圾桶:WemosD1 LOOP
恩智浦智能车: stm32

X86、Intel、windows
启动过程: 电源——> BIOS——>windows内核——>C,D盘——> 程序启动(QQ)

嵌入式产品: 树莓派,mini2440, mini6410,nanopi,海思,RK(瑞芯微)
启动过程: 电源——>BootLoader(引导操作系统启动)——>Linux内核——>文件系统(根据功能性来组织文件夹,带访问权限)——>KTV点歌机、人脸识别打卡器、智能家居主控。

安卓
启动过程: 电源——>fastBoot/Bootloader——>linux内核——>文件系统——>虚拟机——>HOME应用程序——>点某图标打开某APP

BootLoader:
Bootloader启动大多数都分为两个阶段。第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现。第二阶段通常用C语言完成,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。

一阶段:让CPU 跟内存、FLASH、串口、IIC、IIS、数据段打交道,驱动这些设备(汇编和C结合)

二阶段:引导Linux内核启动 (纯C)


树莓派Linux源码目录树分析

arch:包含和硬件体系结构相关的代码,每种平台占一个相应的目录。和32位PC相关的代码存放在i386目录下,其中比较重要的包括kernel(内核核心部分)、mm(内存管理)、math-emu(浮点单元仿真)、lib(硬件相关工具函数)、boot(引导程序)、pci(PCI总线)和power(CPU相关状态)。

block:部分块设备驱动程序。

crypto:常用加密和散列算法(如AES、SHA等),还有一些压缩和CRC校验算法。

Documentation:关于内核各部分的通用解释和注释。

drivers:设备驱动程序,每个不同的驱动占用一个子目录。

fs:各种支持的文件系统,如ext、fat、ntfs等。

include:头文件。其中,和系统相关的头文件被放置在linux子目录下。

init:内核初始化代码(注意不是系统引导代码)。

ipc:进程间通信的代码。

kernel:内核的最核心部分,包括进程调度、定时器等,和平台相关的一部分代码放在arch/*/kernel目录下。

lib:库文件代码。

mm:内存管理代码,和平台相关的一部分代码放在arch/*/mm目录下。

net:网络相关代码,实现了各种常见的网络协议。

scripts:用于配置内核文件的脚本文件。

security:主要是一个SELinux的模块。

sound:常用音频设备的驱动程序等。

usr:实现了一个cpio。

在i386体系下,系统引导将从arch/i386/kernel/head.s开始执行,并进而转移到init/main.c中的main()函数初始化内核。


ARM树莓派高级开发——linux内核源码、树莓派源码编译、SD卡挂载

编译移植条件

对应开发板内核linux内核源码、对应开发板交叉编译工具、 SD卡

树莓派Linux源码配置

驱动代码的编译需要一个提前编译好的内核,而编译内核就必须配置,配置最终会生成 .config文件,该文件指导Makefile去把有用的东西组织成内核。

linux源码中有很多工程:
树莓派1的工程是bcmrpi_defconfig;
树莓派2、3的工程是bcm2709_defconfig。

厂家配给linux内核源码,比如说买了树莓派,配给树莓派linux内核源码,一般我们有三种方法配置。

第一种方式:
cp 厂家给的.config .config
将我们厂家给的.config完全copy到自己的.config上。

第二种方式:
make menuconfig 一项项配置,通常是基于厂家的config来配置

第三种方式:
完全自己来

tips:find -name *_defconfig查看config

如何配置树莓派的Linux内核

驱动两种加载方式:
* -----编译进内核 zImage包含了驱动
M-----模块方式生成驱动文件xxx.ko 系统启动后,通过命令inmosd xxx.ko 加载

内核配置:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
其中参数:
1、ARCH=arm指定ARM架构
2、CROSS_COMPILE=arm-linux-gnueabihf-指定编译器工具链
3、KERNEL=kernel7树莓派
4、make bcm2709_defconfig主要核心指令

树莓派Linux内核编译

安装必要的库:
sudo apt-get install bc
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install zlib1g:i386
sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5

编译:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
指定用多少电脑资源进行编译
其中参数:
zImage生成内核镜像
modules要生成驱动模块
dtbs生成配置文件

2、编译成功后,看到源码树目录多了vmlinux,失败则无此文件
成功后,目标zImage镜像arch/arm/boot底下

3、打包zImage成树莓派可用的xxx.img
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img

挂载树莓派sd卡,并安装编译出的DIRECTLY 到sd卡
4、数据拷贝
dmesg命令查看底层硬件数据
4.1、mkdir data1 data2创建两个文件夹用于挂载
4.2、挂载U盘

sudo mount /dev/sdb1 data1 一个fat分区,是boot相关的内容,kernel的img
sudo mount /dev/sdb2 data2 一个是ext4分区,也就是系统的根目录分区。

4.3、安装modules, 设备驱动文件: hdmi usb wifi io …
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/sxh/data2 modules_install
4.4、安装更新 kernel.img 文件,注意镜像名字是kernel7.img
先备份
cd /home/sxh/data1
cp kernel7.img kernel7Old.img
再把编译新生成的拷贝到data1,起名kernel7.img
cp kernel_new.img /home/sxh/data1/kernel7.img

4.5、拷贝配置文件

cp arch/arm/boot/dts/.*dtb* /home/sxh/data1
cp arch/arm/boot/dts/overlays/.*dtb* /home/sxh/data1/overlays/
cp arch/arm/boot/dts/overlays/README /home/sxh/data1/overlays/

更新完成后插回树莓派即可开机,开机后可以用 uname -r 命令查看kernel信息已经改变。


树莓派本地编译

1、配置编译环境
在ubuntu里交叉编译时需要配置的环境变量有:

PATH: 添加交叉工具链的目录
ARCH: 配置成arm
CROSS_COMPILE: 配置成ubuntu上使用的交叉工具链arm-linux-gnueabihf- KERNEL=kernel7
KERNEL: 配置成kernel7
而在树莓派本地编译:
关于交叉工具链,本身的编译工具就可以编译给自己使用,所以不用配置;
只需要配置 KERNEL=kernel7 即可。

和上面相同,可以用 export KERNEL=kernel7,一次设置之后此终端里所有命令都带有此环境变量。
也可以更进一步写成脚本,不过这里这一行命令很简单,不写脚本也可以。

2、配置config
和上面一样,
树莓派1使用的是 bcmrpi_defconfig,
树莓派2、3使用的是 bcm2709_defconfig。
例:KERNEL=kernel7 make bcm2709_defconfig

如果要使用树莓派自带的config的话:
sudo modprobe configs # 加载模块
zcat config.gz > .config # 获取配置

3、编译
安装必要的库:
sudo apt-get install bc
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install zlib1g
sudo apt-get install libc6

3.1、执行menuconfig
KERNEL=kernel7 make menuconfig
没什么要改的话就不用执行这一步。

3.2、编译
KERNEL=kernel7 make -j4 zImage modules dtbs 2>&1 | tee build.log
以n进程编译。不指明几进程的话则默认以单进程编译。

3.3、打包zImage文件
直接用linux源码包里的工具:
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
在本目录生成一个kernel_new.img文件,这个文件就是要放到sd卡中的文件。

4、更新系统
4.1、安装模块
sudo make modules_install

4.2、复制dtb文件
sudo cp arch/arm/boot/dts/.dtb /boot/ sudo cp arch/arm/boot/dts/overlays/.dtb* /boot/overlays/ sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/

4.3、更新kernel.img文件
sudo cp arch/arm/boot/zImage /boot/$KERNEL.img


Linux基础 ——“文件系统” 走进一切皆文件的体系中(文件系统目录结构、磁盘分区、虚拟文件系统)

1. 什么是文件系统?

常规认知: 根目录
        文件系统 :是操作系统用于明确存储设备组织文件的方法。
        以上说的方法:就是文件管理系统(程序),简称文件系统

2. 文件系统(文件管理系统的方法)的种类有哪些?

FAT VFAT NTFS EXT1/2/3/4 HFS ....
        树莓派查看文件系统的命令: df -T
        vfat  :  boot(bootloader, kernel)
        ext4  :  根目录
        tmpfs : 内存文件系统

3. 什么是分区?

windows: 随意(面向普通用户PC),目录即分区
            C(装系统的位置)也可以随意在C盘存放文件.    D盘(用户随意发挥)

Linux: 按照功能来分区,每个分区严格存放文件(开发者)   
            嵌入式系统可以分为4个区,分别是
            bootloader、  启动代码
            para、        启动代码向内核传递参数的位置
            kernel、         内核分区
            根分区等      文件系统结构

4. linux目录结构

5.详细说明目录作用

  • /bin      

是Binary(二进制)的缩写,这个目录存放着最经常使用的命令

  • /sbin    

s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序 

  • /lib     

  统开机所需要最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。

  • /home  

存放普通用户的主目录,在Linux中每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。不会有root管理员用户的文件夹

  • /root     

该目录为系统管理员,也称作超级权限者的用户主目录

/usr      
这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于windows下的program files目录。

/lost+found 
当系统非法关机后,这里就存放了一些文件这个目录一般情况下是空的

/etc     
  所有的系统管理所需要的配置文件和子目录

3、etc

  • etc下面是配置文件,若想要开机启动某个程序可以在/etc/init这个文件夹下去配置某些文件,使之开机自启。比如打开bootmisc.sh.conf:vi /etc/init/bootmisc.sh.conf然后将指令添加到脚本的最后即可。
  • 但是一般不那么做,一般是在init文件夹下去模仿这个文件夹下面的文件自己去新建一个文件,然后再文件里面写入相关的指令,只需文件以.conf结尾即可。
    除此之外还可以修改etc下面的rc .local也是添加相关的指令即可。
    比如智能家居,智能小车,就可以运用这个,总不能一上电,我们还要打开电脑配置一下。我们要一上电就自动配置了。

/boot    
这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件,自己的安装别放这里。

/proc    
这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。

Isrv      
service缩写,该目录存放一些服务启动之后需要提取的数据

/sys     
这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新出现的一个文件系统 sysfs

/tmp    
这个目录是用来存放一些临时文件的
/dev    
类似于windows的设备管理器,把所有的硬件用文件的形式存储.

/media(CentOS6)
linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后linux会把识别的设备挂载到这个目录下
CentOS7迁移到 /run/media
 /mnt
系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将外部的存储挂载在/mnt/上,然后进入该目录就可以查看里的内容了。

/opt
这是给主机额外安装软件所摆放的目录。比如你安装一个mysql数据库则就可以放到这个目录下。默认是空的。

/var
这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件

什么虚拟文件系统Virtual File System ?

vfs就是对各种文件系统的一个抽象,它为各种文件系统提供了一个通用的接口,
    
    3. 虚拟文件系统有什么作用?
        简化应用程序员的开发
            不管是什么文件类型,不管文件是磁盘还是设备,都只用open read write统一操作

Linux中级——“内核” 硬核的体系结构,衔接工作

其中用户应用程序由基础C和程序库组成,程序库提供应用程序支配内核干活的接口,程序库通过系统调用接口然后操控底层各种东西,比如:程序里面调用open、read、write函数,通过程序库到达系统调用,然后会在系统调用那里会调用sys_open、sys_read、sys_write等函数,然后sys_open、sys_read、sys_write等函数会根据程序里面函数的参数判断你要打开什么类型的文件会产生不一样的指令信息,然后系统调用那里的函数会去分析打开文件的类型(磁盘上的文或者串口等设备文件),然后进行操作。

shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。

shell也是一种应用程序 
它接收用户输入的命令并把它送入内核去执行,是一个命令解释器。
另外,shell编程语言具有普通编程语言的很多特点,用这种编程语言编写的shell程序与其他应用程序具有同样的效果。


Linux中级——“驱动” 控制硬件必须学会的底层知识

驱动认知

1. 什么是驱动
驱动就是对底层硬件设备的操作进行封装,并向上层提供函数接口。

设备分类:
linux系统将设备分为3类:字符设备、块设备、网络设备。

字符设备:指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后顺序。字符设备是面向流的设备,常见的字符设备有鼠标、键盘、串口、控制台和LED设备等,字符设备驱动程序通常至少要实现open、close、read和write的系统调用,字符终端(/dev/console)和串口(/dev/ttyS0以及类似设备)就是两个字符设备,它们能很好的说明“流”这种抽象概念。
块设备: 指可以从设备的任意位置读取一定长度数据的设备。块设备包括硬盘、磁盘、U盘和SD卡等。
网络设备: 网络设备可以是一个硬件设备,如网卡; 但也可以是一个纯粹的软件设备,
比如回环接口(lo).一个网络接口负责发送和接收数据报文。

应用到驱动流程

我们来举一个例子来说一下整体的调用过程

在上层我们调用 c语言 open函数 open("/dev/pin4",O_RDWR); 调用/dev下的pin4以可读可写的方式打开,对于上层open调用到内核时会发生一次软中断中断号是0X80,从用户空间进入到内核空间
open会调用到system_call(内核函数),system_call会根据/dev/pin4设备名,去找出你要的设备号。
再调到虚拟文件VFS (为了上层调用到确切的硬件统一化),调用VFS里的sys_open,sys_open会找到在驱动链表里面,根据主设备号和次设备号找到引脚4里的open函数,我们在引脚4里的open是对寄存器操作

我们写驱动无非就是做添加驱动
添加驱动做哪些事呢?

  1. 设备名
  2. 设备号
  3. 设备驱动函数 (操作寄存器 来驱动 IO口)

综上所述
如果想要打开dev下面的pin4引脚,过程是:用户态调用open(“/de/pin4”,O_RDWR),对于内核来说,上层调用open函数会触发一个软中断(系统调用专用,中断号是0x80,0x80代表发生了一个系统调用),系统进入内核态,并走到system_call,可以认为这个就是此软中断的中断服务程序入口,然后通过传递过来的系统调用号来决定调用相应的系统调用服务程序(在这里是调用VFS中的sys_open)。sys_open会在内核的驱动链表里面根据设备名和设备号查找到相关的驱动函数(每一个驱动函数是一个节点),驱动函数里面有通过寄存器操控IO口的代码,进而可以控制IO口实现相关功能。

主设备号用来区分不同种类的设备,而次设备号用来区分同一类型的多个设备。

主设备号用来表示一个特定的驱动程序。          主设备类似于品牌
次设备号用来表示使用该驱动程序的各设备。   次设备类似于型号

驱动链表

管理所有设备的驱动,添加或查找
添加是发生在我们编写完驱动程序,加载到内核。
查找是在调用驱动程序,由应用层用户空间去查找使用open函数。

驱动插入链表的顺序由设备号检索,就是说主设备号和次设备号除了能区分不同种类的设备和不同类型的设备,还能起到将驱动程序加载到链表的某个位置,在下面介绍的驱动代码的开发无非就是添加驱动(添加设备号、设备名和设备驱动函数)和调用驱动。

基于框架编写驱动代码:

  • 上层调用代码:
    操作驱动的上层代码(pin4test.c):
  • #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>void main()
    {int fd,data;fd = open("/dev/pin4",O_RDWR);if(fd<0){printf("open fail\n");perror("reson:");}else{printf("open successful\n");}fd=write(fd,'1',1);
    }
    

-内核驱动
最简单的字符设备驱动框架

#include <linux/fs.h>       //file_operations声明
#include <linux/module.h>    //module_init  module_exit声明
#include <linux/init.h>      //__init  __exit 宏定义声明
#include <linux/device.h>  //class  devise声明
#include <linux/uaccess.h>   //copy_from_user 的头文件
#include <linux/types.h>     //设备号  dev_t 类型声明
#include <asm/io.h>          //ioremap iounmap的头文件static struct class *pin4_class;
static struct device *pin4_class_dev;static dev_t devno;                //设备号,devno是用来接收创建设备号函数的返回值,销毁的时候需要传这个参数
static int major =231;            //主设备号
static int minor =0;              //次设备号
static char *module_name="pin4";   //模块名//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{printk("pin4_open\n");  //内核的打印函数和printf类似   return 0;
}//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{printk("pin4_write\n");  //内核的打印函数和printf类似return 0;
}
//将上面的函数赋值给一个结构体中,方便下面加载到到驱动链表中去
static struct file_operations pin4_fops = {
//static防止其他文件也有同名pin4_fops
//static限定这个结构体的作用,仅仅只在这个文件。.owner = THIS_MODULE,.open  = pin4_open,.write = pin4_write,
};
/*
上面的代码等同于以下代码(但是在单片机keil的编译环境里面不允许以上写法):
里面的每个pin4_fops结构体成员单独赋值
static struct file_operations pin4_fops;  pin4_fops.owner = THIS_MODULE;pin4_fops.open  = pin4_open;pin4_fops.write = pin4_write;
*/
//static限定这个结构体的作用,仅仅只在这个文件。int __init pin4_drv_init(void)   //真实的驱动入口
{int ret;devno = MKDEV(major,minor);  //2. 创建设备号ret   = register_chrdev(major, module_name,&pin4_fops);  //3. 注册驱动  告诉内核,把这个驱动加入到内核驱动的链表中pin4_class=class_create(THIS_MODULE,"myfirstdemo");//由代码在dev下自动生成设备,创建一个类pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name); //创建设备文件,先有上面那一行代码,创建一个类然后这行代码,类下面再创建一个设备。return 0;
}void __exit pin4_drv_exit(void)
{device_destroy(pin4_class,devno);//先销毁设备class_destroy(pin4_class);//再销毁类unregister_chrdev(major, module_name);  //卸载驱动}module_init(pin4_drv_init);  //入口,内核加载驱动的时候,这个宏(不是函数)会被调用,去调用pin4_drv_init这个函数
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");

手动创建设备名

上面这个字符设备驱动代码里面有让代码自动的在dev下面生成设备除此之外我们还可以手动创建设备名。 使用指令:sudo mknod +设备名字 +设备类型(c表示字符设备驱动) +主设备号+次设备号 b : create a block
(buffered) pecial file。 c, u: create a character (unbuffered)
special file。 p: create a FIFO, 删除手动创建的设备名直接rm就好。

 驱动框架执行流程:

通过上层程序打开某个设备,如果没有驱动,执行就会报错,
在内核驱动中,上层系统调用open,wirte函数会触发sys_call、sys_call会调用sys_open,和sys_write、sys_open,和sys_write通过主设备号在内核的驱动链表里把设备驱动找出来,执行里面的open和write、我们为了整个流程顺利进行,我们要先准备好驱动(设备驱动文件)。
设备驱动文件有固定框架:
module_init(pin4_drv_init); //入口 去调用 pin4_drv_init函数
int __init pin4_drv_init(void) //真实的驱动入口
驱动入口devno = MKDEV(major,minor); // 创建设备号
register_chrdev(major, module_name,&pin4_fops); //注册驱动 告诉内核,把上面准备好的结构体加入到内核驱动的链表中
pin4_class=class_create(THIS_MODULE,"myfirstdemo");//由代码在dev下自动生成设备,创建一个类
pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name); //创建设备文件。
主要是要让/dev下多了个文件供我们上层可以open
如果没有,也可以手动sudo mknod +设备名字 +设备类型(c表示字符设备驱动) +主设备号+次设备号的去创造设备

驱动模块代码编译

驱动模块代码编译

驱动模块代码编译(模块的编译需要配置过的内核源码,编译、连接后生成的内核模块后缀为.ko,编译过程首先会到内核源码目录下,读取顶层的Makefile文件,然后再返回模块源码所在目录。):

在导入虚拟机的内核代码中找到字符设备驱动的那一个文件夹:/SYSTEM/linux-rpi-4.19.y/drivers/char将以上代码复制到一个文件中,然后下一步要做的是就是:将上面的驱动代码编译生成模块,再修改Makefile。(你放那个文件下,就改哪个文件下的Makefile)
文件内容如下图所示:
(-y表示编译进内核,-m表示生成驱动模块,CONFIG_表示是根据config生成的)
所以只需要将obj-m += pin4drive.o添加到Makefile中即可。
下图:Makefile文件图

加载内核驱动
然后使用指令:sudo insmod pin4drive.ko加载内核驱动(相当于通过insmod调用了module_init这个宏,然后将整个结构体加载到驱动链表中)
加载完成后就可以在dev下面看到名字为pin4的设备驱动(这个和驱动代码里面static char *module_name=“pin4”; //模块名这行代码有关),设备号也和代码里面相关。

为什么生成驱动模块需要在虚拟机上生成
为什么生成驱动模块需要在虚拟机上生成?树莓派不行吗?

生成驱动模块需要编译环境(linux源码并且编译,需要下载和系统版本相同的Linux内核源代码),也可以在树莓派上面编译,但在树莓派里编译,效率会很低,要非常久。这篇文章有讲树莓派驱动的本地编译。


树莓派高级开发——“IO口驱动代码的编写“ 包含总线地址、物理/虚拟地址、BCM2835芯片手册知识

总线

总线地址用于在总线上传输数据和指令的地址。总线是计算机系统中不同组件(如CPU、内存、IO设备等)之间进行通信和数据传输的通道。
总线地址用于在总线上进行数据的读取和写入操作。物理地址和虚拟地址可以被转换为总线地址,以便在总线上进行数据传输。

地址总线

地址总线 = cpu能够访问内存的范围:
用一个现象来解释地址总线:
装了32位的win7系统,明明内存条8G,可是系统只识别了3.8G,装了64位,才能识别到8G。
32位能表示/访问 4,294,967,296 bit

数据总线

CPU通过地址总线寻址,然后通过数据总线与外部设备互换信息。
是CPU与内存或其他器件之间的数据传送的通道。
数据总线的宽度决定了CPU和外界的数据传送速度。
每条传输线一次只能传输1位二进制数据。eg: 8根数据线一次可传送一个8位二进制数据(即一个字节)。
数据总线是数据线数量之和,数据总线的位数决定CPU单次通信能交换的信息数量。

数据总线的宽度对CPU的性能的影响:

首先,总线的速度(即:CPU的主频,CPU的性能指标之一)决定CPU和外设互换信息的速度。
其次,数据总线的宽度也是表示CPU性能的参数之一(通常,我们说“64位的CPU”是指CPU的数据总线的宽度是64位)。
如:64位数据总线的CPU一次就能取出64bit的数据,8位数据总线的CPU一次只能取出8bit的数据,在相同频率的情况下,8位数据总线的CPU就得连续取8次数据,数据量才能和64位数据总线一次取出的数据量相同,单就比较取数据的性能就相差8倍。况且,通常CPU中的寄存器的位数与数据总线的宽度一样,所以在数据处理方面,64位的CPU又比8位的CPU快很多。
CPU的地址总线位数和数据总线可以不同(典型代表就是51单片机),但是一般都相同。16位机有16根数据总线,20根地址总线,能访问1M(2的20次方),32位机有32根数据总线,32根地址总线,能访问4G(2的32次方),64位机确实有64根数据总线。

物理地址(PA)

百度百科解释:
物理地址存储器中存储单元对应实际地址称物理地址

这里说的 物理地址是内存中的内存单元实际地址,不是外部总线连接的其他电子元件的地址!物理地址属于比较好理解的,物理地址就是内存中每个内存单元的编号,这个编号是顺序排好的,物理地址的大小决定了内存中有多少个内存单元,物理地址的大小由地址总线的位宽决定!
物理地址是硬件实际地址或绝对地址

虚拟地址(VA)

基于算法的地址[软件层面的地址:假地址])称为虚拟地址,与实地址模式下的分段地址类似,虚拟地址也可以写为“段:偏移量”的形式,这里的段是指段选择器。而linux没有各种保护模式,本来用的就是虚拟地址。

MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权,多用户多进程操作系统。作用有两点,地址翻译和内存保护。MMU将虚拟地址翻译为物理地址。

wiringPi库pin4编写 和驱动编写移植差不多  
参考博文:树莓派高级开发——“IO口驱动代码的编写“ 包含总线地址、物理/虚拟地址、BCM2835芯片手册知识_树莓派 内核 io开发_Refuel.CONG的博客-CSDN博客

树莓派02 ------ 内核编译、移植相关推荐

  1. 香橙派内核编译/移植 和 驱动编译

    OrangeZero2 内核编译/移植 和 驱动编译 为什么要选它?(买不起树莓派 : /(ㄒoㄒ)/~~) 当然是学习下内核编译 , 内核移植,驱动的编译啦. 1. 准备工作 工具 Ubuntu18 ...

  2. Liunx树莓派(ARM)开发篇—第十四章、树莓派Linux内核编译步骤(超详细、图文结合)

    对树莓派内核源码进行配置后,下一步要进行树莓派Linux内核编译 以下步骤均在PC端虚拟机上完成 准备材料:PC端虚拟机.树莓派交叉编译工具.树莓派内核(交叉编译工具.内核下载步骤见树莓派内核源码) ...

  3. 树莓派-linux内核编译

    树莓派-linux内核编译 装虚拟机[^1] 配置共享文件夹 配置交叉编译工具 下载树莓派linux系统内核[^3] 树莓派等芯片带操作系统的启动过程 树莓派linux源码目录树 树莓派linux源码 ...

  4. 树莓派镜像备份/内核编译和更换/EC200U上网

    树莓派镜像备份/内核编译和更换/EC200U上网 操作涉及树莓派linux内核替换,由于我的树莓板子里跑了ROS,以免环境破坏,所以先进行镜像备份. 备份本机树莓派img 工具:win32diskim ...

  5. 树莓派交叉编译 内核编译 - HQ

    树莓派交叉编译 & 内核编译 - HQ 文章目录 树莓派交叉编译 & 内核编译 - HQ @[toc] 注意 树莓派交叉编译 引入 交叉编译工具链的安装 交叉编译使用举例 树莓派源码分 ...

  6. 树莓派Linux内核编译、文件系统、Linux内核驱动基础框架、驱动测试步骤、总线地址

    树莓派高阶开发课程 1. ubuntu18.04版本安装          让程序猿搭建环境太搞笑了,轻松easy! ========================================= ...

  7. 树莓派Linu内核编译

    可做参考:树莓派Linux内核配置.编译以及烧录详细步骤_是光哥呀的博客-CSDN博客_linux内核烧录 1编译: ARCH=arm CROSS_COMPILE=arm-linux-gnueabih ...

  8. 树莓派Linux内核源码配置、编译、挂载(boot/kernal/根文件)、开启新内核

    目录 一.树莓派Linux源码配置(适合树莓派) 总体概述 配置的三种方式 1.照搬厂家的配置(使用这种方式) 2.参考厂家的配置(感受一下) 3.完全自主配置(需要一定工作经验) 二.树莓派Linu ...

  9. 树莓派内核编译(5)

    树莓派高阶开发课程 ========================================================= 1. ubuntu18.04版本安装 让程序猿搭建环境太搞笑了, ...

最新文章

  1. 查看Linux系统中某目录的大小
  2. ONAP — Overview
  3. 初识tmux---编译安装tmux
  4. Windows内核实验005 Inline Hook
  5. Android 如何实现带滚动条的TextView,在更新文字时自动滚动到最后一行
  6. jrtplib 打包做了哪些事_30岁前就实现财务自由的人,都做了哪些事
  7. 人家android博客地址
  8. 易鲸捷数据库常用优化方法
  9. 华为轮值董事长郭平新年致辞:不经艰难困苦,何来玉汝于成
  10. Cesium|xt3d 兼容西部世界模型压平效果
  11. VendorNPC.lua --随身商人
  12. 春晚宫女唐奕霖被爆背景深厚 可携助手出入央视排练场享有特权
  13. mysql mha etcd_postgresql 高可用 etcd + patroni 之四 failover
  14. 计算机一级考试PPT部分几分,计算机一级考试PPT幻灯片和最后一题(就是自己输网址)各有多少分啊...
  15. 职场分享:职场生涯中我们经常面临的一些困惑
  16. 基于ETH创建自己的代币
  17. web前端性能优化与SEO
  18. ElastAlert规则
  19. V891-Z3735F重做系统,驱动修复汇总
  20. 她力量系列六丨杨笛一:女孩长大后数理化可以很好,科研可以很鲜活

热门文章

  1. 保护自己电脑绝对不做黑客肉鸡
  2. 一款名为VirLock的敲诈者病毒来袭
  3. javascript自动判断15位和18为身份证号计算年龄的解决方案
  4. 如何用CRM做售后管理
  5. 3秒搭建第一个人工智能对话引擎——青云客
  6. Touch事件分发 九宫格解锁
  7. DM创建DBLINK连接oracle
  8. 网站建设如何选择专业的网站建设公司
  9. 【分享】Java集合求交集、并集、差集
  10. 玲珑杯oj-1126咸鱼旅行