资讯详情

嵌入式学习笔记-2022.2.22

ARM裸机(学习外设)

ARM版本号

  • ARM基本都是RISC哈佛结构的结构 内存和地址统一编写

ARM内核版本号--------ARM SoC版本号-芯片型号

ARMv1

ARMv6 ------------------ARM11--------------------S3C6410…

ARMv7-----Cortex-M(微控制器/单片机)/Cortex-A(应用级,手机,平板)/Cortex-R(实时的、工业航天…)…

ARMv8-------Cortex-A30、ARM Cortex-A50、ARM Cortex-A70

ARMv9

########################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################

核版本号和SoC版本由ARM分为三个系列,有64个架构

SoC&CPU

SoC:System on Chip 包含外设(Peripheral)内外设备

CPU:中央处理器=运算器 控制器

RISC&CISC

  • CISC:复杂指令集

编译器很容易用最少的指令设计任务。

  • RISC:精简指令集

编译器设计难以提供基本指令集

IO与内存 统一编址|独立编址

  • 统一编址:IO访问地址与内存地址相同

RISC访问方式。CPU地址空间有限IO也有限。CPU内存数据需要在寄存器中加载

  • 独立编址:专用CPU与访问内存不同,指令访问特定外设

CISC访问方式。CPU设计复杂

冯诺伊曼&哈佛

  • 冯诺伊曼结构:程序和数据都放在内存中,存在安全性和稳定性问题

  • 哈佛结构:程序放置ROM、FLASH中;数据放置RAM中

多采用单片机和嵌入式;软件复杂,需要规划链接地址

寄存器是软件控制硬件的关键

寄存器是CPU可编程开关外设硬件的一部分

在哈佛结构中,寄存器操作与访问内存相似。单个寄存器的位宽一般与CPU同样的位宽有利于最佳效率

  • 通用寄存器:在CPU通用寄存器
  • 特殊功能寄存器(SFR):不在CPU中

内存地址映射

210属于A8架构,32位,32条地址线和32条数据线。搜索空间为4G

  • 见:UM-P25

内存:RAM CPU可直接访问(地址总线) 数据总线)速度快

外存:ROM 通过控制器接口连接访问

支持的外部存储器

常见的外部存储器:

FLASH:电存储     NorFlash:   接至SROM bank,总线访问(类似内存访问)昂贵可靠,一般用于启动     NANDFLASH:         NandFlash: (分SLC、MLC和TLC)价格便宜         eMMC/iNand(闪迪)/moviNand(三星):类似SD卡的芯片,均为eMMC         SD卡/TF卡/MMC卡:         eSSD:嵌入式MLC硬盘 SATA接口硬盘:磁存储 

*启动过程

SRAM:无需初始化即可使用(容量小) DRAM:使用软件需要初始化内存 NORFLASH:总线访问(启动介质) NANDFLASH:不能总线访问,需要初始化 210启动模式:内置966K SRAM(IRAM),64K NORFLASH(IROM) 
启动过程见IROM_API-P5     1.CPU读取IROM实施基本初始化(IROM代码BL0由SOC厂家内置),硬件选择启动模式读取启动代码(第一部分BL1,16K)至SRAM并校验。     2.SRAM中运行读取到的启动代码(UBOOT-BL1)。搬运剩余UBOOT(BL2)至SRAM的BL2     3.SRAM中的BL2初始化SDRAM并加载OS至SDRAM     4.跳转至OS的地址运行 

ARMv7 32位 通用寄存器相关

ARM32位约定:Byte=8bit Halfword=16bit=2Byte Word=32bit ARM32位指令集:

ARM指令集32bit、Thumb2指令集 

-1.ARMv7处理器工作模式(stm32基本没有那么多模式)

非特权模式:     User:大多数任务执行模式 特权模式:        异常模式:         FIQ:快速中断         IRQ:普通中断         Supervisor:管理模式(复位,软中断进入,引导)         Abort:异常模式         Undef:指令模式没有定义     System: 与User使用相同寄存器的特权模式 

写CPSR或者切换寄存器CPU自行切换

*如此设计由OS与安全要求有关

-2.ARMv7通用寄存器

模式    ABORT   User    FIQ     IRQ     SVC     UNDEF r0  通用 r1  通用 r2  通用 r3  通用 r4  通用 r5  通用 r6  通用 r7  通用 r8  部分不通用          r8-F r9  部分不通用          r9-F r10 部分不通用          r10-F r11 部分不通用          r11-F r12 部分不通用          r12-F (sp)    r13-A   r13-U   r13-F   r13-I   r13-S   r13-D (lr)    r14-A   r14-U   r14-F   r14-I   r14-S   r14-D r15(pc) 通用 cpsr    通用         spsr-A   无     spsr-F  spsr-I  spsr-S  spsr-D --------------------------------------------------------- 总计:37 @:SYSTEM模式使用USER模式寄存器 
sp:堆栈指针保护现场使用 lr:存储当前模式的返回地址 pc:当前程序执行的指针,pc指向哪里,CPU执行哪个指令。程序跳转是将目标代码地址放在目标代码上。pc中 cpsr:记录程序状态寄存器CPU状态 spsr:用于保存以前的模式CPSR 

-3.详解CPSP

32-28   27  24  23-16   15-8    7   6   5   4-0 NZCV    Q   J   Undef   ined    I   F   T   mode *条件位:发生时结果自动位置1(ALU为运算器)     N:ALU Negative 结果为负     Z:ALU Zero     运算结果为0     C:ALU Carried out  ALU计算结果有进位     V: ALU oVerflowed  ALU计算结果溢出     --------------------------------------------     Q:指示饱和状态(仅)ARMv5支持)     J:=1时JAVA加速使用(仅)ARMv5支持) 禁止中断:     I: =1时禁止IRQ     F: =1时禁止FIQ     --------------------------------------------     T:仅ARM xT架构支持,=0为ARM状态,=1为Thumb状态     mode:ARM的模式位 

-4.CPU异常处理

异常发生时,CPU自动将PC跳异常向量表跳转到异常地址。(CPU提前设置的异常中断地址)决定。CPU提供二级向量表 VECTOR TABLE:

  • 异常发生时CPU做的事:
  • 1.拷贝CPSR在新模式下SPSR
  • 2.设置新的CPSR
  • 3.保存返回地址lr
  • 4.设置PC指针为异常向量表(跳转执行)
  • 5.中断结束,从SPSR恢复CPSR,从lr恢复PC指针。

ARMv7 32位指令

  • GNU编程风格:指令全小写

指令: 编译后得到机器码

伪指令:编译器提供,指导编译过程,不生成机器码 load 内存加载至寄存器 store 寄存器内容存入内存

常见ARM32位指令:
    寻址方式:
        1.寄存器寻址    mov r1,r2       r2值赋给r1
        2.立即数寻址    mov r0,#0xffff
        3.寄存器移位寻址 mov r0,r1,lsl #3 r1左移3位赋值给r0
        4.寄存器间接寻址 ldr r1,[r2]    将r2为地址的内容赋值给r1
        5.基址变址寻址  ldr r1,[r2,#4]  r2地址+4的地址 的内容给r1
        6.多寄存器寻址  ldmia r1!,{r2-r7,r12}    以r1为地址,依次将内容放入多个寄存器中(弹栈)
        7.堆栈寻址(压栈)stmfd sp!,{r2-r7,lr}    将栈连续访问,放入大括号内的寄存器中
        8.相对寻址 beq xxx  跳转到xxx标号。实质为pc指针相对偏移量
    指令后缀:指令族
        指令+B  功能不变,由操作32位变为操作8位
        指令+H  功能不变,由操作32位变为操作16位
        指令+S  功能不变,操作有符号数/影响CPSR标志条件位
    条件执行后缀:条件的成立由上句代码结果,只影响本句代码的执行。(根据CPSR判断)
        标志    标志位      含义
        ---------------------------------------
        EQ      Z=1     运算结果为0
        NE      Z=0     运算结果不为0(不相等)
        ---------------------------------------
        CS/HS   C=1     无符号大于等于
        CC/LO   C=0     无符号小于
        MI      N=1     负数
        PL      N=0     正数或0
        VS      V=1     溢出
        VC      V=0     未溢出
        HI      C=1,Z=0 无符号数大于
        LS      C=0,Z=1 无符号小于等于
        GE      N=V     有符号数大于等于
        LT      N!=V   有符号数小于
        GT      Z=0,N=V 有符号数大于
        LE      Z=1,N!=V有符号数小于等于
        AL      无条件执行,指令默认条件
        NV      从不执行
常见指令
    数据传输
        *mov 寄存器     mvn 按位取反后赋值
        算术运算    add sub rsb adc sbc rsc
        *逻辑指令   and orr eor(异或) bic(位清除)
        *比较指令,自动影响CPSR:   cmp(比较相等) cmn tst teq
        乘法指令    mvl mla umull   umlal   smull smlal
        前导0计数   clz
    *cpsr访问指令:cpsr需要专门指令访问
        mrs 读cpsr/spsr
        msr 写cpsr/spsr
    跳转指令:
        *b:直接跳转
        *bl:保存返回地址到lr然后跳转 //bx:跳转同时切换为ARM模式
    访问内存指令:
        *ldr/str:
        *ldm/stm:多字访问
            后缀    ia   increase after 先传输,地址+
                    ib  increase before 先地址+,传输
                    da  decrease after 传输,地址-
                    db
                    ---------------------------------
                *   fd  满减
                    ed  空减
                    fa  满增
                    ea  空增
        swp:内存与寄存器互换指令
    立即数(普通数字):带#。立即数有合法、非法。非0部分8位内即合法
    软中断指令:swi软件模拟中断,实现OS系统调用
    协处理器指令:一般SoC只实现CP15协处理器.协处理器和MMUC、cache、TLB等处理有关
        mrc&mcr
    ^:目标寄存器有PC寄存器时,会同时将spsr写入到cpsr
*伪指令:不同编译环境的伪指令不同,以下为GNU环境
    @ 注释
    // 注释
    /*注释 */
    # 注释
    :标号,标记指令地址
    .点代表当前指令地址
    --------------------------------------------------
    .global xxx @声明为外部的链接属性,声明为全局变量,让别的文件可用
    .section .text @将当前段指定为代码段
    .ascii .byte .shrt .long .word .quad .float .string变量类型
    .align X 以2的X次方对齐
    .balignl x,0xnnnnn  @对齐,填充:b表示位填充,l表示为long4字节为单位填充 ,以16字节对齐
    .equ @类似宏定义
    .end 文件结束   .include 包含头文件 .arm/.code32 声明代码为ARM指令  .thumb/.code16声明为thumb指令
    * ldr   大范围地址加载指令(伪指令不用考虑合法立即数)不使用#而是=,绝对地址
    * adr   小范围地址加载,以PC为基准表示地址(相对地址)
    * adrl
    * nop   空操作

ARM指令流水线(CPU自动处理,了解即可)

三级流水线:    取值-->解码-->执行
    ARM       PC    PC-4  PC-8
PC指针实际指向被取址的指令,并非正在执行的指令
流水线越多速度越快,但跳转会重置流水线

刷机

步骤

使用串口做控制台
    1.选择启动方式 0xd0020010(usb启动地址)下载BL1
    2.下载、烧写 运行bootloader(uboot)
    3.下载、烧写 OS(使用uboot中的fastboot,通过USB进行,需要驱动)
        -1.分区fdisk -c 0
        -2.fastboot flash bootloader分区 uboot镜像
        -3.fastboot flash kernel分区 内核文件(linux kernel)
        -4.fastboot flash system分区 文件系统(rom)
    fastboot常用命令
        fastboot devices 查看当前连接设备
        fastboot flash xxx  用于烧录
        fastboot reboot 重启设备
    uboot的参数:bootcmd    bootargs
        set bootcmd 'movi read kernel 30008000;bootm 30008000'
        set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuuxrc rootfsype=ext3
        save

elf文件&bin文件

elf文件:OS下的 可执行文件,包含了整个文件的基本属性,如文件版本,目标机器型号,程序入口等等。是带格式的映象
hex文件:包含地址信息,因此无需指定地址信息
bin文件:只包含可执行二进制,可顺序执行,内部没有地址标记是直接的内存映象的表示。需要指定地址信息
(mkv210_image.c)用于给生成的bin文件添加ECC头校验。根据MCU特性,USB\UART启动无需使用校验,因此可直接使用生成的bin文件

BL0

BL0(内置的IROM代码)无需编写了,210内置
1.关看门狗
2.从初始化cache指令
3.初始化栈
4.初始化堆内存
5.初始化块设备的 复制函数
6.初始化PLL相环和系统时钟
7.复制BL1至SRAM中
8.校验BL1,如果失败尝试二次启动
9.是否安全启动&安全启动相关内容
10.跳转至BL1的起始地址

BL1(uboot方式与推荐手册不同)

    //1.关看门狗(210BL0已经做)
    // 初始化时钟(210默认初始化为1G)
    //2.设置栈(210BL0已做)(C语言环境:c语言的局部变量使用栈实现)IROM-API:P13memory map
        :SVC栈0xD003_7780-0xD003_0xD003_7D80 ARM使用满减栈,故sp=0xD003_7D80
    //3.开指令cache (210BL0已做):UM-P
        icache是内部自动的,打开即可
    4.重定位和链接脚本
    5.初始化ddr
    6.搬运uboot到ddr
    7.从iram长跳转到ddr中继续执行uboot(使用ldr修改PC指针)

初始化ddr-见具体的bord

内存相关见NT5TU64M16GG-P10:BLOCK DIAGRAM 128Mb*8  UM-P598:memory
其中,要清楚内存是分Bank的,每个bank寻址由行地址和列地址组成
	bl sdram_asm_init

重定位

1.链接脚本中指定目标地址
2.下载时运行在非目标地址
3.使用PIC将代码搬运至链接地址处
4.长跳转到目标地址中执行(以目标地址为起始,链接脚本为偏移的地址)
    伪指令:adr短加载(加载运行时相对地址)
            ldr长加载(加载相对链接脚本的地址)
    adr r0, _start      //_start为起始地址,短加载 运行时地址
    ldr r1, =_start     //长加载 链接地址,因此与上面的地址不一定相同
    ldr r2, =bss_start  //重定位代码的结束地址
    cmp r0, r1      // 比较_start的运行时地址和链接地址是否相等,是否需要重定位
    beq clean_bss   //如果相等,不需要重定位,跳转至clean_bss函数,否则继续下面的代码
//搬运
copy_loop:
    ldr r3,[r0],#4  //将r0地址的内容放至r3中,地址加4字节
    str r3,[r1],#4  //将r3内容放至r1地址中
    cmp r1,r2       //目标地址==重定位结束地址
    bne copy_loop   //如果不等,没有复制完成,继续
clean_bss:
	ldr r0, =bss_start					
	ldr r1, =bss_end
	cmp r0, r1				// 如果r0等于r1,说明bss段为空,直接下去
	beq run_on_dram			// 清除bss完之后的地址
	mov r2, #0          //不等,,则清除

UBOOT&OS移植

SHELL&MAKEFILE

Shell

shell脚本语言:一类语言。可自动化执行shell命令,一般用于配置
    无需编译链接,可直接解释运行。解析器逐行解释代码
常用shell语言:sh、bash、python...
执行方法:1:    ./xx.sh     需要可执行权限
        2:      source xx.sh    无需可执行权限
        3:     bash xx.sh        bash解释器执行
注意:应注意语法严格
变量引用:使用$xxx  有时仅可以${xxx}
#!/bin/sh #!开始,加上解释器的pathname
# #为行注释
echo "hello word"
shell中为弱变量类型,`xx`反引号的作用是调用命令的返回内容
if的参数[ -参数前后都要有空格 ]:
    -f  :判断文件是否存在
    -d  :判断目录是否存在
    -eq 是否相等    -gt大于  -lt小于  -ge大于等于   -le小于等于
    -z  :字符串是否为空    -o  逻辑或      ||和&&用于简写的if表达式
echo中可使用>创建文件并添加echo的内容,>>用于已存在的文件添加内容
shell传参: $#调用传参个数  $0、$1、$2以此表示传参各参数。命令本身不算参数。$x可用shift移出一个
    break作用与c语言不同,用于跳出循环

Makefile

引用其他makefile:   include(原地展开)
#用来做注释
@命令前加这个表示静默执行(不显示命令本身)
=   引用最后一次赋值
:= 此句之前的值
?= 如果已被定义,此句略过
+= 给已经赋值的变量接续赋值
export导出环境变量,给其他makefile使用

通配符:

*   匹配多个任意字符
?  匹配单个任意字符
[xy]将括号内字符挨个匹配
%   类似*,一般只用于规则中

常见自动变量:

$@  规则的目标文件名
$<  规则的依赖文件名
$^  依赖的文件集合

UBOOT

	0.就是一个裸机程序
    1.自身可开机直接启动-uboot-start.S      :根据SOC启动介质
    2.引导内核启动,给内核传参(用于引导系统)
    3.拥有部署系统的能力。能够使用uboot完成OS的下载(uboot/kernel/rootfs...)
    4.能够初始化并控制一部分硬件(如:NAND/LCD/USART)
    5.提供人机交互,如命令行shell

生命周期:uboot本质是一个裸机程序(单线程),从start.S到OS内核启动结束

部署操作系统:fastboot方式/ftp方式
    tftp:uboot作为客户端,pc的ftp作为服务器,需设置ip&severip(此处传到了内存中)
    movi命令将内存中的镜像写到flash中
    环境变量bootcmd:自动运行命令的设置movi read kernel 30008000;bootm 30008000
    环境变量,内核约定好的参数:bootargs:console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3

UBOOT命令

x210uboot发现,无相同命令时可省略后边的命令,如printenv可为pri/prin/...
有空格的单个参数使用单引号将参数作为一个参数
    printenv- print environment variables
        打印环境变量,可简化为print
    setenv  - set environment variables 设置环境变量
    *saveenv - save environment variables to persistent storage整体覆盖保存内存的环境变量到flash
    tftpboot- boot image TFTP下载镜像
        tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
    nfs     - boot image via network using NFS protocol
    movi(mmc)    SD/inand相关操作
        movi init - Initialize moviNAND and show card info
        movi read  {u-boot | kernel|分区名|分区地址} {addr} - Read data from sd/mmc
        movi write {fwbl1 | u-boot | kernel} {addr} - Write data to sd/mmc
        movi read  rootfs {addr} [bytes(hex)] - Read rootfs data from sd/mmc by size
        movi write rootfs {addr} [bytes(hex)] - Write rootfs data to sd/mmc by size
        movi read  {扇区sector#} {bytes(hex)} {addr} - instead of this, you can use "mmc read"
        movi write {扇区sector#} {bytes(hex)} {addr} - instead of this, you can use "mmc write"
    内存操作:注意防止越界
        mw       - memory write (fill)写内存
        md       - memory display显示内存内容
        mm       - memory modify (auto-incrementing)修改内存
    启动内核
        bootm   - boot application image from memory从内存某地址启动程序镜像同时给内核传参
        go      - start application at address 'addr'从某地址启动应用/裸机程序
    -----------------------------------------------------------------
    autoscr - run script from memory
    base     - print or set address offset
    bdinfo  - print Board Info structure
    boot    - boot default, i.e., run 'bootcmd'
    bootd   - boot default, i.e., run 'bootcmd'
    bootelf - Boot from an ELF image in memory

    bootp   - boot image via network using BootP/TFTP protocol
    bootvx  - Boot vxWorks from an ELF image
    cmp      - memory compare
    coninfo - print console devices and information
    cp       - memory copy
    crc32    - checksum calculation
    dcache  - enable or disable data cache
    dhcp    - invoke DHCP client to obtain IP/boot params
    dnw     - initialize USB device and ready to receive for Windows server (specific)
    echo    - echo args to console
    erase   - erase FLASH memory
    exit    - exit script
    ext2format - disk format by ext2
    ext2load- load binary file from a Ext2 filesystem
    ext2ls  - list files in a directory (default /)
    ext3format - disk format by ext3
    fastboot- use USB Fastboot protocol
    fatformat - disk format by FAT32
    fatinfo - print information about filesystem
    fatload - load binary file from a dos filesystem
    fatls   - list files in a directory (default /)
    fdisk   - fdisk for sd/mmc.
    flinfo  - print FLASH memory information
    help    - print online help
    icache  - enable or disable instruction cache
    iminfo  - print header information for application image
    imls    - list all images found in flash
    imxtract- extract a part of a multi-image
    itest   - return true/false on integer compare
    loadb   - load binary file over serial line (kermit mode)
    loads   - load S-Record file over serial line
    loady   - load binary file over serial line (ymodem mode)
    loop     - infinite loop on address range
    MMC sub systemprint MMC informationmovi - sd/mmc r/w sub system for SMDK board
    mtest    - simple RAM test
    nm       - memory modify (constant address)
    ping    - send ICMP ECHO_REQUEST to network host
    protect - enable or disable FLASH write protection
    rarpboot- boot image via network using RARP/TFTP protocol
    reset   - Perform RESET of the CPU
    reginfo - print register information
    run     - run commands in an environment variable
    sdfuse  - read images from FAT partition of SD card and write them to booting device.
    sleep   - delay execution for some time
    test    - minimal test like /bin/sh
    version - print monitor version

UBOOT环境变量(系统的全局变量&自定义环境变量)

UBOOT文件&文件夹分析

uboot-jiuding
    文件:  
        CHANGELOG       :   修改日志      记录每个版本的修改记录 ,git管理工具也可以生成
        arm_config.mk   :   .mk类文件     makefile中调用的某个文件
        config.mk
    *   rules.mk       :  uboot的makefile使用的规则
        COPYING         :   GPL许可版权
        CREDITS         :   感谢目录
        -image_split    :  分割uboot的脚本
        MAINTAINERS     :  维护者名单
        -MAKEALL        :   可能是帮助uboot编译的脚本
*       Makefile        :   主makefile文件
        -mk             :  快速编译脚本
*       mkconfig        :   uboot主要配置脚本,可移植性主要由此文件实现
        -mkmovi         :  和启动介质相关
        README          :  说明文档
    目录:
        api             :  硬件无关的功能函数API,uboot本身使用的
        -api_examples   :   API示例代码
+       arch                :   新版uboot中的:架构相关
*       board           :   开发板相关信息,已移植的板/厂家
+       boot                :   新版uboot中的:可能与启动顺序有关
+       cmd                 :   新版uboot中的:
*       common          :   与具体硬件无关的普遍适用的代码。主要是uboot的命令与env环境变量相关的
+       configs             :   新版uboot中的:可能与soc相关的
*       cpu-            :  新uboot无,SOC相关代码,需要移植的。包括SOC初始化、控制代码、start.S
        disk            :   磁盘相关的
        doc             :   文档文件,uboot相关文档、资料
+       dts                 :   ??
*       drivers         :   从linux中拿出的uboot必须使用的设备驱动
+       env                 :   ??
        examples        :   示例代码
*       fs              :  文件系统,从linux中移植的
*       include         :   头文件目录集合
*       lib_ xx-        :   架构相关的库文件
        lib_generic-    :   架构通用库文件
        libfdt-         :   设备树相关的
+       lib                 :   ?可能修改了以上的文件夹
        -nand_spl       :   nand相关的
        net             :   网络相关代码,如tftp nfs sntp ...
        -onenand_xxx    :   三星的flash相关的
        post            :   ??
*       -sd_fusing      :   烧录uboot镜像到sd卡
+       scripts             :  脚本
+       test                :  ?测试代码
        tools           :  工具类代码

UBOOT-1.3.4配置、编译

/makefile

版本信息:
    U_BOOT_VERSION = $(VERSION主版本).$(PATCHLEVEL补丁版本).$(SUBLEVEL次级补丁版本)$(EXTRAVERSION附加信息)   "1.3.4xxx"
    VERSION_FILE =$(obj)include/version_autogenerated.h         编译后生成的版本宏定义
环境变量:
    HOSTARCH := i386/sparc64/arm/ppc/其他----   主机架构:这里我的x86_64不会被替换
    HOSTOS :=   linux/...                       操作系统:linux,本来应该是Linux
    export	HOSTARCH HOSTOS
静默编译:		findstring s 		XECHO=echo:如果MAKEFLAGS中有s则静默编译。可以只输出编译过程信息,没有makefile信息
build编译方法:	 	1.原地编译:默认将当前目录.c编译的.o放在同一文件夹。	
					2.输出文件夹编译方式:linux kernel也是如此。
						-1. make O=/指定路径
						-2.	export BULLD DIR=/路径	然后make
	配置脚本目录变量:NO.101	MKCONFIG	:= $(SRCTREE)/mkconfig
	标志远程编译变量并导出环境变量
加载配置	include $(obj)include/config.mk 	未编译的源码目录没有此文件,由配置过程生成。此文件的值和配置有关。
CROSS_COMPILE	编译器前缀全路径
导入其他配置文件:NO.185			include $(TOPDIR)/config.mk
U-Boot objects、LIB集合:NO.188
ALL目标:NO.286

x210_sd_config :NO.2589配置目标
	@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110		#执行$(SRCTREE)/mkconfig脚本并传参
	将_config替换为空	$1=x210_sd 	$2=arm 	$3=s5pc11x 	$4=x210 	$5=samsung 	$6=s5pc110 $#=6

/config.mk

主要是编译环境相关
包含自动配置生成的board configs		sinclude $(OBJTREE)/include/autoconf.mk指导条件编译、可移植性的。
		由include/configs/xx.h文件生成(宏定义)因此移植时需要修改此文件
根据环境ARCH、CPU...包含不同的编译配置信息
根据CONFIG_NAND_U_BOOT配置LDSCRIPT变量	$(TOPDIR)/board/$(BOARDDIR)/xxx.lds链接脚本的路径
CPPFLAGS:NO.157 += -DTEXT_BASE=$(TEXT_BASE)		用于指定链接地址0xc
		TEXT_BASE在主makefile配置时编写,编译后在.obj/board/samsung/x210/config.mk编译前在主makefile配置目标中
		这里TEXT_BASE=0xc3e0 0000	uboot使用了虚拟地址映射,实际地址在:0x23e0 0000
自动推导规则编译:NO.239

/mkconfig

	BOARD_NAME  = x210_sd 	$#要为4-6
	NO.33-181:	创建符号链接,选择需要移植代码创建符号链接
		include/ 创建asm ->	asm-arm
		include/asm-arm/创建arch ->	arch->s5pc110--------被后面删掉了
		include/ 创建regs.h ->	include/s5pc110.h
		include/asm-arm/创建arch ->	arch->s5pc11x
		include/asm-arm	创建proc 	-> /include/proc-armv
	创建/include/config.mk文件---》为了让主makefile使用
	创建、追加配置头文件	/include/config.h 		包含了x210_sd.h,用来生成autoconfig.mk,然后用于指导编译

链接脚本: ( T O P D I R ) / b o a r d / (TOPDIR)/board/ (TOPDIR)/board/(BOARDDIR)/xxx.lds

ENTRY(_start) 	:程序入口,类似c中的main
	-Ttext的链接地址和.lds链接脚本中都指定链接地址时,以-Ttext地址优先
代码段中,应注意排列顺序。BL1前16k的文件必须排列在前

/include/configs/xxx.h

uboot1.3.4源码分析

	BL1:汇编阶段、SRAM中,主要操作Soc内部
	寻找第一个入口:lds链接脚本的ENTRY声明的地方的符号,为入口/cpu/s5pc11x/start.S
	头文件包含
		config.h 	配置后生成的,实际指向x210_sd.h
		version.h  	指向version_autogenerated.h 	定义了U_BOOT_VERSION值来自makefile的修改
		如果定义CONFIG_ENABLE_MMU 	包含 <asm/proc/domain.h>
		<regs.h>	指向s5pc110.h
	条件编译
		CONFIG_EVT1=1 	CONFIG_FUSED未定义	则定义校验头16字节占位
    start.S:
		复位跳转到reset,设置SVC32模式,并关闭普通中断与快速中断
		构建异常向量表
		16字节对齐,TEXT_BASE由配置makefile时指定的
		reset
		-cpu_init_crit:
			disable_l2cache		禁止l2cache
			set_l2cache_auxctrl_cycle	设置l2cache
			enable_l2cache		使能l2cache
			刷新L1 I / D 	cache
			禁止MMU和缓存	disable MMU stuff and caches
		Read booting information:
			R2-->PRO_ID_BASE=0xE0000000	OMR_OFFSET=0x04 包含了OM_PIN信息
			R3-->根据启动信息,加载启动介质方式MMC/NAND...
		设置栈	0xd0036000--》sram中
		lowlevel_init	进行底层初始化-->uboot-9d/board/samsung/x210/lowlevel_init.S
				压栈,防止再次调用函数
				-check reset status 检查复位状态:如冷启动、热启动、复位...
				-IO Retention release	IO恢复。。。
				*关看门狗
				-外部SRAM&SROM初始化
				*PS_HOLD pin(GPH0_0) set to high	锁定开关
				判断在SRAM还是DDR,是否需要重新初始化时钟、内存
				如果SRAM中,
					初始化时钟
					初始化内存控制器(DDR)---cpu_init.S 	uboot中,256内存地址设置为0x3000..裸机中设为0x20...都可工作
					uboot整体物理地址设置为DMCO(0X3000..-0X3FFF..)DMC1(0X4000..-0X4FFF)	512MB
				初始化串口,打印‘O’
				tzpc_init...打印‘K’
		再次供电锁存,无意义,但不影响
		再次设置栈,此时DDR已初始化,设置ddr中的栈。//33e0 0000
		再次判断代码运行在SRAM还是DDR,如果是SRAM则重定位代码至DDR
		判断启动介质,最终调用相应copy函数movi_bl2_copy--uboot-9d/cpu/s5pc11x/movi.c
			将启动设备中完整的uboot复制到DDR中了
		enable_mmu虚拟地址映射:MMU(内部外设,实现虚拟地址和物理地址转换),建立虚拟地址映射表
			MMU在CP15协处理器控制:映射、访问控制、	
			1.设置cp15-c3,实现控制域访问
			2.转换表基地址设置TTB:cp15-c2,即设置转换表:表索引对应虚拟地址,表项对应物理地址。
					内存映射与管理以块为单位,块大小取决于设置和mmu支持。
					虚拟地址映射实际就是建立映射表,放置时要求xx位对齐 
				-lowlevel_init.S
					->mmu_table:粗表映射按1MB
			3.使能mmu-cp15-c1:bit0控制
		设置栈,将栈放置在较安全的地方,紧凑而不浪费内存
		ldr清bss-start到end
		ldr远跳转加载uboot/lib_arm/bord.c start_armboot:UBOOT的第二阶段(BL2,DDR中)
--------------------------------------------------------------------------------------------
	BL2:C阶段、DRAM中、注重Soc外部
	uboot/lib_arm/bord.c 	-start_armboot(418):外部硬件初始化、uboot本身初始化
		init_fnc_t **init_fnc_ptr;	//函数指针 数组
		gd_base:
				gd(全局变量,指向gd_t类型的指针),
				gd_t(include/asm-arm/global_data.h,uboot使用的全局变量,包含一个bd_t硬件参数)
				分配gd、bd的内存
				内存间隔(内嵌汇编),防止gcc优化
		init_sequence定义同时初始化。包含的board相关的初始化函数的指针
		遍历以上的函数指针数组
				uboot/cpu/s5pc11x.c 	->	cpu_init();
				uboot/board/samsung/x210/x210.c 	->	board_init();
						网卡初始化(不是驱动,硬件相关的)
						配置开发板的机器码
				cpu/s5pc11x/interrupts.c ->	interrupt_init()	不是中断初始化,而是定时器4初始化(10ms)用来做delay
				common/env_movi.c(有很多启动介质,选择相应版本) 	->	env_init	环境变量初始化
				init_baudrate	波特率初始化
				cpu/s5pc11x/serial.c	serial_init 	//这里什么都没做,估计是uboot框架
				common/console.c 	console_init_f	控制台初始化(_f表示first第一阶段初始化,r为第二部分初始化)  
				display_banner串口显示uboot第二部分,版本信息(此时串口未被初始化,使用putc,调用serial_putc操作寄存器发送)
					控制台是软件虚拟的设备,最终映射到硬件实现。中间件可以实现缓冲
				print_cpuinfo	打印cpu信息	时钟
				checkboard 	//检查板信息
				init_func_i2c	//初始化软件/硬件IIC	(X210中未使用)
				dram_init		//dram初始化,初始化dram软件信息
				display_dram_config 	//打印显示dram信息
		CFG_NO_FLASH相关 	//NorFLASH的配置信息(实际中没有)
		CONFIG_VFD			//uboot自带虚拟显示(未开启)
		CONFIG_LCD			//uboot自带LCD显示相关(未开启)
		CONFIG_MEMORY_UPPER_CODE	//uboot堆管理器初始化,实现malloc/free
		-Board Specific开发板独有的初始化
			mmc_initialize...
		--CONFIG_HAS_DATAFLASH 串行存储设备(这里没有)
		env_relocate环境变量SD卡重定位到ddr。如果SD卡没有,则从代码中使用默认一套ENV
		IP Address赋值
		MAC Address赋值
		devices_init 	硬件驱动设备初始化
		jumptable_init	跳转表(未使用)
		console_init_r	控制台第二阶段初始化(纯软件初始化)
		enable_interrupts 	中断初始化(未使用中断、空的)
		loadaddr、bootfile 	环境变量初始化读出全局变量
		board_late_init 	板级最后的初始化。实际是空的
		eth_initialize		网卡相关初始化(网卡本身的初始化)
		*x210_preboot_init 	启动前初始化(LCD相关初始化)
		check_menu_update_from_sd	检查自动更新
		main_loop----------最终到这里

UBOOT环境变量

	作用:掉电保存全局变量,不用修改源码。环境变量优先级大于代码中的硬编码值。
	工作方式:	1.刚烧录时,无环境变量,加载代码中的默认环境变量。-/common/env_common.c
			2.SAVE时将DDR环境变量保存至SD卡中,下次启动时,	\
			uboot第二阶段env_relocate环境变量会被加载至DDR
				getenv()UBOOT内部获取环境变量使用

UBOOT与linux驱动

	uboot与linux驱动:
		linux下MMU是开启的,驱动使用虚拟地址
			linux驱动本身做了模块化设计
		uboot/裸机,使用物理地址。uboot移植了linux的源代码。
			uboot硬件驱动比linux简单
	iNand/sd驱动解析:
		从start_armboot:
			/drivers/mmc/mmc.c	-mmc_initialize	
				mmc初始化:Soc的mmc控制器初始化、时钟、GPIO的SFR初始化,芯片的初始化
				1.cpu_mmc_init 
					/cpu/s5pc11x/setup_hsmmc.c 开启mmc时钟,
					/cpu/s5pc11x/setup_hsmmc.c 初始化mmc相关gpio
					smdk_s3c_hsmmc_init(); 	//三星开发板的mmc通道初始化
						建立mmc结构体,调用mmc_register进行驱动注册,链表链接到mmc_devices
						mmc_init()	
				2.mmc_init() 	mmc卡、芯片的初始化
				由于函数以函数指针形式存在于结构体中,具体的操作函数是需要被绑定的
	驱动框架思想:
			每个驱动的关键数据结构(结构体),包含了成员属性、函数指针(成员函数)
			即驱动就被抽象为了一个结构体。包含:驱动(构建一个结构体)初始化、驱动工作时操作函数和变量
		分离思想:
			驱动中将操作方法(函数)、数据(变量)分开:不同的位置来存储管理驱动的操作方法和变量
		分层思想:分成不同的层次如soc层、bord层、软件层等

uboot210从三星移植

1.复制uboot,修改makefile中交叉编译工具,配置编译,可使用sd_fuing脚本烧录sd卡(注意参数) 2.看现象,失败,未打印"O",屏蔽start.s中的PMIC电源管理。uboot可工作 3.修改配置目标xxx_config,对应一个include/configs/xxx.h文件 修改xx.h的信息,lowleveinit.s-system_clock_init修改时钟配置(根据配置头文件) 修改ddr配置(配置文件):内存地址、内存大小 修改ddr为0x30000000 256MB+0x40000000 256MB 修改ddr寄存器 宏修改, ddr相关uboot宏修改,虚拟地址映射修改 SD(INAND驱动)问题: 问题现象-》定位错误代码-》错误需要修改的代码 网卡:DM9000-总线式,复用数据线地址线,接至SROMC1 配置网卡初始化函数,配置相关config宏

网卡驱动工作方式简介

linux中网卡生成的设备名一般是eth x/wlan x
linux使用专用命令来操作网卡
linux应用程序通过socket接口实现上网,应用层->socket接口 和驱动层->网络驱动框架 是完全分离的。由框架承接上下层。
uboot中操作网络相关的命令实际是直接操作驱动的,上下层并不完全分离。

uboot从uboot官方移植

版本差异:
	新版uboot使用了linux kernel配置体系(kbuild.kconfig.menuconfig)
工作中一般不需要从uboot移植,而是soc厂商配套开发板移植

UBOOT启动内核

	1.uboot本身是一个裸机程序:
		-1.从启动角度看,操作系统内核本身也是一个裸机程序,OS可以分为内核层、应用层,操作权限不同。
		-2.嵌入式系统,bootloader、kernel、rootfs都以镜像形式存在于介质中。运行时在DDR内存中
		-3.启动过程就是由ROM到RAM启动硬件、软件达到运行状态的过程
		-4.分区:预先设定的存储位置,以便指导启动(uboot\kernel\实际分区表必须一致)
		-5.内核启动需要放置在预定链接地址,内核需要bootloader重定位到内存运行。需要启动参数
	2.启动内核
		从哪里加载:Flash、服务器...kernel分区(raw分区)
		怎么加载:使用uboot命令读取 如movi(读写inand)	bootm启动内核--实际是do_bootm函数
				tftp 内存地址 镜像名--远程tftp下载(一般用于开发)
	3.do_bootm函数 /common/Cmd_bootm.c
		-1.条件编译执行secureboot(签名认证)
		-2.CONFIG_ZIMAGE_BOOT宏控制zImage格式内核启动
		-3.uboot 的ELF可执行程序使用objcopy生成bin可烧录镜像文件
		-4.kernel生成vmlinux/vmlinuz ELF可执行程序 objcopy生成bin可烧录镜像image
			将image压缩+解压代码(自解压)=zImage
			zImage加工(64字节头信息)=uImage
				zImage不是uboot原生支持的方式
				uImage方式因设备树原因成为了历史版本:校验uImage得到kernel启动地址
			bootm.c lib_arm/bootm.c
				调用检查机器码,配置传参tag数据结构,启动
	4.main_loop:获取、解析、执行命令
		获取:console_buffer -> lastcommand
			命令结构体数组放在自定义段中(开始结束地址即段的开始结束地址)
		解析:parse_line将命令解析为argv	find_cmd在命令集合中搜索命令
		执行:run_command(const char *cmd, int flag)

UBOOT配置编译

uboot来源:uboot官方、SoC厂商、开发板供应商

-1.from 开发板供应商:九鼎

    1.配置config
        make xxx_config
        得到:Configuring for x210_sd board...  配置完成
    2.编译得到bin文件
        检查arm-linux-gcc是否合适正确
        主makefile中编译工具链路径名称是否正确
        make -j4    多线程编译

分区

uboot   :必须从flash起始地址(SoC的启动地址)存放。
        一般设置512KB-1MB左右
var     :uboot的环境变量表,紧挨uboot分区。32kB-1MB
kernel  :大小一般3、5MB-N
rootfs
自由空间    :一般挂载到rootfs

分区在系统移植前应确定好,uboot与kernel使用同一个分区表,部署时按照系统代码的分区方法进行

DDR分区和FLASH分区不同。注意不要内存冲突即可

linux内核

操作系统:本质是一个程序,用来管理硬件,给应用程序提供运行环境

操作系统的核心功能: 内存管理、进程调度(多任务实现宏观并行)、硬件设备管理(OS控制硬件,APP不用管)、文件系统(管理存储设备) 操作系统的扩展功能:协议栈、有用的应用程序包 内核与发行版的区别: 内核仅实现核心功能,不包含应用程序:www.kernel.org 发行版(普通意义的操作系统):包含内核、协议栈、应用程序包… ------------------------------------------ 应用0|应用2|…|应用层-用户态 … kernel-内核态 … ------------------硬件---------------------

内核与驱动的关联

要有整体的认识,层次的作用清楚、层次关联互相调用要清楚。
 驱动 (是内核的一部分、与硬件接轨)
内核中的硬件设备管理模块----驱动工作在内核态
内核权限高(无限制)、驱动故障可能导致内核崩溃、驱动漏洞会使内核不安全

内核、APP、rootfs系统的关联

应用程序不属于内核,工作在用户态,资源受限制,应用故障不会导致内核崩溃
应用程序-----调用----->内核API接口--内核驱动----->硬件
APP是最终目标,内核是为APP提供资源管理服务的
------------------------------------------
rootfs为操作系统提供根目录,进程1存放在根文件系统中
内核启动后会装载根文件系统,启动根目录的进程1

linux内核的模块化设计

内核各功能的代码是彼此独立的,如调度系统和内存管理系统没有全局变量的互相引用,函数调用也是遵循接口规范的(低耦合)
模块化体现:配置时可裁剪(源码级,静态变化)、模块化编译和安装(无需修改系统,动态变化)、源码中条件编译
模块化好处:可裁剪、灵活、可扩展性、利于协作,是一种普遍性的系统设计原则。

linux内核选择

版本:
    linux0.01(初版)--0.11(适合阅读,较成熟)--2.4x(经典书籍多)--2.6早期(类似2.4晚期)--2.6晚期(驱动、头文件位置修改了)
    linux3.x 4.x---linux5.16(2021.12最新版本)

linux目录结构

.linux5.15 ├── arch ***架构,如arm ├── block *块设备管理代码(逻辑代码),以块为整体,如sd卡、SSD、inand ├── certs ?证书处理? ├── COPYING -f -版权声明 ├── CREDITS -f -贡献名单 ├── crypto 校验、加密算法… ├── Documentation -文档 ├── drivers ***驱动文件夹 | ├──firmware 固件,原来在根文件目录,固化到IC里的代码,像IROM代码 ├── fs *filesystem,linux支持的文件系统的实现 ├── include ***各种架构的cpu,共用文件,特有的在arch/arm/include目录下 ├── init 内核的初始化 ├── ipc linux进程间通信代码实现 ├── Kbuild -f ├── Kconfig -f ├── kernel *makfile编译 ├── mm *内存管理相关代码 ├── net *网络相关代码(如TCP/IP协议) ├── README ├── samples -示例代码 ├── scripts 脚本文件,辅助linux内核配置编译生成的脚本文件 ├── security 安全相关代码 ├── sound *音频处理相关代码 ├── tools linux用到的工具 ├── usr *initramfs和linux内核启动有关 └── virt 内核虚拟机

linux内核配置、编译

步骤体验

1.make distclean检查makefile的CROSS_COMPILE和ARCH?= 
2.第一步配置make 合适的.config make xxx_defconfig
3.第二步配置make menuconfig
4.make--make后的镜像在arch/arm/boot zImage

内核配置原理

配置是为了得到.config文件(可看作一个脚本),类似与uboot/include/configs/xxx_xx.h
内核用此文件指导整个编译、链接
make 合适的_defconfig解决大部分的配置项-可以避开很多不懂的配置项
    相当于cp arch/arm/configs/合适的_defconfig ./.config
make menuconfig调整开发板细节
linux内核编译方法:编入,直接编译链接到zImage,去除即不编译链接,模块化即只编译单独链接到.ko文件进行动态加载卸载

menuconfig工具

menuconfig本身是一套软件支持,ncuress库实现文字图像界面
menuconfig本身读取Kconfig文件
    显示菜单内容是由源码树各目录文件下的Kconfig提供支持,即能看到哪些菜单
menuconfig读取/写入.config
    每个菜单的选择结果是保存到.config中的,即哪个=y哪个为注释..

Kconfig的格式

注释:#xxx
menuconfig (这是一个菜单)
config (菜单的项目)XXX (构成.config文件中的CONFIG_XXX=?)
tristate (三种选择状态)"菜单显示的名字"
bool (两种选择状态)"菜单显示的名字"
source (引用子Kconfig)"(path)/Kconfig"
depends on XXX (此配置项依赖于XXX配置项,也可进行逻辑运算)
select XXX(会自动选择的项目)
default x(默认配置值)
help 按下?后显示的帮助信息
=y =m =空 选项会导致CONFIG_XXX宏的值,最终导致makefile进行编译或内核makefile中将其链接为模块或不编译

内核分析(x210)

1.内核MIKEFILE 版本号定义 内核支持O=xxx,编译到一个文件夹 ARC\CROSS_COMPILE变量 2.lds链接脚本分析-找到程序入口 kernel链接脚本提供一个arch/($arch)/kernel/vmlinux.lds.S,真正得到的是vmlinux.lds,因此是动态的(可以借用预处理器)。 程序入口,编译后的lds中找到了ENTRY(stext) arch/arm/kernel/head-nommu.S arch/arm/kernel/head.S 3.head.S文件(校验,建立粗页表,c运行环境,b start_kernel) KERNEL_RAM_VADDR:虚拟内存地址=(KERNEL_OFFSET + TEXT_OFFSET) (5.x版本中)arch/arm/include/asm/memory.h中KERNEL_OFFSET=内核映像开始的虚拟地址 =PAGE_OFFSET= lowmem开始的虚拟地址,内存在上面=CONFIG_PAGE_OFFSET 在.config中定义为CONFIG_PAGE_OFFSET=0xC0000000 $(textofs-y)控制偏移 应该是0x8000 0000 但目前没找到在哪里定义,lds也+了这个偏移量 KERNEL_RAM_PADDR(新版内核已取消这个定义) XIP_KERNEL:原地执行 ENTRY(stext):kernel真正的入口,一般被解压代码调用的。需要MMU是关的,D-cache是关的。。UBOOT传递的参数:r0=0,r1=machine nr(机器码), r2 =atags pointer(参数所在的地址) ARM的函数调用传参是通过寄存器(还有一种是栈内存传参) MMU关的,没有页表,因此我们链接内核到了虚拟地址,但是又不可以用物理地址,因此内核开始运行时,没有虚拟地址,因此要用位置无关码。__pa(0x虚拟地址) 可以转换为物理地址。 linux kernel分配的mach id在/arch/arm/tools/mach-types文件 禁用中断,设置SVC模式 读出cp15,c0寄存器,读出processor id(cpu id),校验cpu id的合法性 machine id(机器码)的校验 _vet_atages uboot通过tage给内核传参的校验:内存分布memtag,uboot的bootargs… create_page_tables:建立段式页表(开启虚拟地址映射) -1-先建立一个段式页表(粗页表,以MB区分,每个页表用四个字节表示,总共需要16K).-2-再建立一个细页表(以4kb为单位),启动新的页表,废除段式页表 调用switch_data:存了一些地址和全局变量、函数 mmap_switched:复制数据段、清bss段(构建c运行环境),保存一些id号、atage… b start_kernel:跳转到c运行阶段 4.start_kernel–kenel/init/main.c文件 处理smp相关的:对称多处理器(相同的多核cpu) 锁定依赖处理:内核调试模块,处理内核自旋锁死锁。 cgroup:control groups内核提供用来处理进程组的技术 printk(内核用来从console打印调试信息,不同于printf的是可在参数前加一个打印级别的宏): linux控制台有消息过滤器,可根据设置来显示不同等级消息 linux_banner:字符串信息:版本、环境… setup_arch (处理cmdline-uboot给kernel传的bootargs)cpu架构的初始化过程,确定当前的架构,硬件平台相关的定义… default_command_line默认分配的全局命令 默认=CONFIGXXXX 定义一些描述硬件的结构体指针 setup_processor:查找cpu的类型,并打印cpu的相关信息 setup_machine:通过机器码查到这个板子machine_desc的描述符 __lookup_machine_type:内核链接时将各种cpu信息组成machine_desc结构体实例,使用.arch.info.init段属性链接在一起。 打印Machine:板的名字 如果传参atages不是空,则打印个信息 旧版风格的tage分析…并且将参数加载到内核的变量中 经过处理后,打印cmdline.(稍后会解析cmdline) 内存初始化相关 一些command_line处理:具体以后再说 多处理器相关:nr_cpu_ids、per_cpu_areas、smp_prepare_boot_cpu 打印kernel command line parse_early_param&parse_args:解析cmdline传参和其他传参,到字符串数组。目前没执行 内核初始化相关 trap_init:设置异常向量表 mm_init:内存管理模块初始化 sched_init:调度系统初始化 禁止抢占 中断初始化、定时器、软中断、时间系统… console_init:控制台初始化-在此前的打印信息是存在缓冲区的,控制台初始化后才能打印出 …等 构建内核环境、****加载驱动 rest_init:剩下的比较重要的初始化 rest_init:启动了两个kernel线程、cpu_idle进程 kernel_init线程(kernel_thread函数运行)进程1:最重要的进程,init进程 kthreadd线程(kernel_thread函数运行)进程2:内核守护进程,保证内核本身正常工作 schedule:开启内核的调度系统. 最终调用:cpu_idle-进程0(不返回):无任务时,执行空闲进程 进程和线程:应用层运行的程序构成一个进程/线程。内核运行一个函数,就是一个线程 进程:一个独立运行的程序任务(与其他程序独立,可被内核单独调用)用ps命令可以查看 进程0(空闲进程)是内核进程不是用户进程,故ubutu下看不到 线程:linux中,线程类似于进程,不同在于,线程是容易通讯 kernel_init-进程1:内核态向用户态转变。 这个进程有两个状态,init开始时是内核线程,运行了用户态程序后,将自己强转为用户态,后续进程都工作在用户态了。 内核态时:挂载根文件系统,试图找到用户态init程序。内核源码的所有函数都是内核态的,因此应用程序只能独立于内核源码。因此根文件系统是给内核提供用户态环境的。 用户态时:init大部分有意义的工作都在用户态下进行的。其他的用户进程都是由init进程派生的 如何从内核态转到用户态:init进程在内核态通过kernel_execve执行一个用户空间编译链接的init应用程序,就跳跃到了用户态。进程号未改变,跳跃过程是单向的。用户态要调用内核只能通过API。 init进程在用户态:构建用户交互功能。linux进程的创建是从父进程创建来的。 init启动了login进程(登录)、命令行进程、shell进程(解析执行命令行) shell进程启动其他用户进程 init源码: kenel_thead->kernel_init … 打开控制台设备,得到文件描述符编号。(linux中,设备也以文件形式存在,如/dev/buzzer代表蜂鸣器设备【真实设备】,console代表控制台设备【虚拟设备】) 复制了2次文件描述符。得到了三个文件描述符,分别为0、1、2,即标准输入、标准输出、标准输出。因此后续进程都默认具有这三个文件描述符(子进程会继承父进程的文件描述符)。 prepare_namespace:->mount_block_root挂载根文件系统 根文件系统位置、文件类型:bootloader会通过传参告诉kernel根文件系统的信息 root=/dev/mmcblk0p2 rw ->根文件系统的位置 rootfstype=ext3 ->根文件系统的类型 挂载rootfs成功后会打印出:VFS:Mounted root (xxx) on device xxx 如果挂载失败:uboot bootargs参数错误、根文件系统烧录失败(fastboot烧录不容易出错,代码烧录方式容易出错)、根文件系统本身有问题。 init_post->run_init_process(调用kernel_execve执行用户态进程1) 进入rootfs寻址init程序并执行 init程序确定方法:uboot cmdline指定(init=/xxx)/代码预先指定的(如:/sbin/init|/etc/init|/bin/init|/bin/sh) cmdline常用参数: 格式:xxx=yyyy【空格】->内核解析,影响内核启动 root=[根文件系统位置:/dev/mmcblk0p2(支持nfs网络文件系统)]->设备名可以在哪看? rootfstype=[文件系统类型:ext3] console=[控制台设备声明/dev/ttySAC0,115200->串口0,波特率115200] mem=[指定内存有多少] init=[进程1的pathname:/linuxrc] 产品出厂:rootfs会在物理存储器上 开发时:rootfs可以在nfs上 root=/dev/nfs nfsroot=[IP]:/pathname ip=[HOST IP]:[server IP]:[网关]:[子网]::[网卡]:[DHCP状态] 内核架构相关代码 arch:硬件架构有关代码 mach:machine architecture->一类machine定义,即相同soc。一个开发板对应一个.c文件 plat:平台设备驱动[可能类似于stm32的HAL],SOC(内部外设)硬件相关数据代码 include:架构相关头文件,不是通用的 头文件包含格式:xxx/yyy.h ->kernel/include/xxx/yyy.h drivers:硬件驱动 OTHERS:硬件无关代码,一般不会修改的

x210内核移植初体验

构建移植环境:
	设置makefile: CROSS_COMPILE  ARCH
	make xx_defconfig
	make/make O=xxx -jxx
运行kernel:
	1.解压部分代码没有运行:
		可能原因:解压地址应==链接地址对应的物理地址
			解压地址在哪看:(物理地址).config ->0x3000 8000
			链接地址在哪看:(虚拟地址).config ->0xc000 8000
			查看自解压部分代码:/mach/makefile.boot
				zreladdr-y:自解压的地址
				param_phys-y:uboot参数地址
	2.解压后没有正确运行
		可能原因:某些地址不正确
	3.内核中,机器码的确定
		arch/arm/mach-xxx/mach-xxx.c 具体的文件要看makefile和.config文件
		MACHINE_START宏&MACHINE_END;定义了一个结构体变量,会被链接到一个特定段
			MACHINE_START(type,name)
				.nr->mach id:xxx,对应uboot定义的值,对应一个开发板
				.init_machine = xxx ->机器硬件初始化函数->绑定了内核初始化过程中的硬件信息
	4.内核启动过程中的错误信息:
		Oops信息-》内核错误的致命信息
		kernel panic:内核抱怨信息
	5.设备驱动问题
	6.分区
		UBOOT的->fdisk -c 0对iNand分区.已经写死了。分区信息是由iNAND本身的MBR传递的
		如果是NAND,则分区表要在内核中构建->要与uboot中构建的一致
	7.网卡
		.config开启网卡
		硬件由mach文件的结构体中.init_machine调用初始化 
			SOC的硬件配置
			设备本身的配置
			驱动数据配置
内核调试方法:
	第0阶段:没打印信息
		1.自解压代码
		2.在第一阶段汇编开头操作LED操作代码,注意r0-r2被用作uboot传参
		用于判断内核有没有被正常运行
	第一阶段:
		校验(CPU ID、板的机器码、传参tag)
		创建页表
		start_kernel

根文件系统

根文件系统存在的原因: init应用程序需要一个位置,存在根文件系统 根文件系统给内核提供了根目录/ 内核启动后应用层配置在根文件系统(/etc/) shell命令程序、cd程序… 只有内核没有配置文件、库文件、程序,是不能工作的。 根文件系统实质: 特殊用途的文件系统 根文件系统本身也属于某种文件系统格式 文件系统作用:存储设备是分 块/扇区 的,底层访问存贮设备是按块号/扇区号 访问。文件系统是一套对存储设备扇区管理的软件。将对扇区的访问变为对目录和文件名的访问。我们对pathname的访问会被文件系统转换为扇区号的访问。不同文件系统的差异在于对扇区的管理策略和方法不同。如坏块、碎片

标签: utc2025集成电路l925b冷接子光纤快速连接器mmc集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台