嵌入式学习小阶段小总结

来源:互联网 发布:有道词典无法连接网络 编辑:程序博客网 时间:2024/06/11 16:09

接触嵌入式以来,虽然毕业设计的内容只是研究应用开发,但是还是研究了一段时间的底层内容

Linux网络:
桥接模式:主机能够提供多种IP.
主机模式:没有外部网络,只能在VM和主机通讯。
NAT模式:网络只能提供一个IP地址。但是虚拟机不能被外部所发现的。
Ifconfig查看网卡情况
Eth0:第一个以太网卡
Lo:虚拟的回环网卡
Virbr0:虚拟网桥






开发板:(处理器,NOR,nand flash,RAM,LCD)
NOR:容量小,运行快,价格高
Nand:容量大,价格低,运行不快。
开发板启动模式:NAND启动,NOR启动。
安装开发板:1.pc和NOR通过JTAG连接起来,再通过USB下载线下载到内存中,然后把内存的操作系统烧写到NAND中去。
串口连接:在PC机以及开发之间输入输出。
开发板软件:Bootloader,嵌入式操作系统,嵌入式文件系统(应用程序,配置文件)。
交叉开发模型:
JTAG(并口,USB接口):十一张国际标准测试协议,现在主要是对FLASH烧写。
宿主机:产生嵌入式软件的平台
目标机:运行嵌入式软件


安装过程(红帽linux):
1.FLASH选择开关拨到NOR的位置
2.连接好Jlink与开发板连接起来,串口线连上,usb下载线连上。
3.打开开发板电源
嵌入式linux:BOOTLOADDER(启动.s ARM代码提供),linux内核(驱动)文件系统。


安装210步骤:将SD卡插在PC上,利用win上面的软件,把安装引导程序烧到SD,复制到SD上,按到sd上,设置在sd开启。
Dd命令、windows烧写到sd(linux命令,win烧写软件),把sd卡插到开发板,从SD卡启动,再利用USB下载线,利用SD卡里的安装软件。
Dd iflag=dysnc oflag=dysnc if=xx.bin of=/dev/sds seek=1
Dd:命令名(可以格式转化,cp不行)
Iflag=dsync 读取文件,同步方式
Oflag=dysnc 写入文件,同步
If=xx.bin 要复制的文件名
Of=/dev/sdb 被复制到的设备,/dev/sdb表示sd卡
Seek=1:SD卡的第一扇区
Fdisk可以确定位置
SD卡启动2,3口打开,1,4关闭。


裸机ARM(很少使用裸机程序)
Bootloader的设计(大型的裸机程序):内存初始化,看门狗,LCD,网口。
设计linux驱动
学习驱动5步:基本原理,读手册,思维导图设计,程序设计,在线调试程序
Windows xp:ads,rvds(makefile产生,链接)
Linux:makefile,lds脚本,调试eclipse
裸机开发流程:编写裸机程序,调试裸机程序,生成2进制映像文件,烧写到开发板(需要用到不一样的驱动test里面,要加一个头文件mv210,才能运行   mv210 led.bin led-210.bin)
首先 arm-linux-gcc -g -c led.s (交叉工具链)
    Arm-linux-ld -Tled.lds -o led.elf led.o (链接器脚本)
Arm-linux-objcopy -O  binary  led.elf  led.bin
Makefile 可以简单起来,自动的完成
三个工具


烧写过程:先连上NOR/SD,接着通过USB烧到NAND
串口别接错,USB下载连接线,电源。
先格式化NAND选择6,选择下载到NAND选择1,
210要加头
关闭电源,拨到nand,打开开发板电源




常用交叉工具:
交叉编译器,交叉链接器,交叉转换器,交叉ELF文件工具,交叉反汇编器。
(gcc) (ld) (readelf) (objdump)
Arm-linux-gcc hello.c  [option] ..与gcc不同之处:寻找头文件的地方不一样。
..交叉链接器:-T 链接连接器脚本
交叉ELF文件工具:-a大小端是否正确,与处理器大小相符
 File 可以看到文件处理平台。
-d 查看库,确定库对不对.
交叉反汇编器arm-linux-objdump -D -S hello.c >mdump


Makefile:规则,变量
目标:依赖
命令
Make 目标:就能得到想要的文件
Makefile中第一条规则为最终目标
$^代表所有依赖文件
$@代表目标
$<代表依赖第一个文件
当命令一模一样,目标名和依赖一模一样时,就能简化为:%.o:%.s
在命令前面加上一个@就能消除回显:@gcc -c hello.c -o hello
Make -f file 就能make file这个文件


链接器脚本的起了至关重要的作用


脚本的组成:基本构成 段,起始链接地址,对齐,变量,代码段首文件
段:有代码段,数据段,bss段
SECTIONS{
        .=30000000;
        .text:
        { 
        *(.text)
        }


        .data:
        {
        *(.data)
        }
      
        .bss:
        {
        *(.bss)
        }


对齐:4字节对齐
变量:
首文件:第一个代码段十分重要
SECTIONS{
        .=30008000;
        .=ALIGN(4);


        .text:
        { 
        start.o(.text)//首文件
        *(.text)
        }
        .=ALIGN(4);
        .data:
        {
        *(.data)
        }
        .=ALIGN(4);
        bss_start= . ;
        .bss:
        {
        *(.bss)
        }
        bss_end= . ;
ECLIPSE:能在线调试,编程。通过GDB和SEVER与开发板相互香炉
准备工作,从sd/nor flash 格式化nand
拨到nand,线连好
安装GDB SEVER


ARM:芯片:2440,210
ARM核:ARM8,ARM9
ARM架构:ARMV7
 ARM   CORTEX(M系列,R系列,A系列)


Svc模式表示保护模式
Abort异常模式
System模式v4以上才有
Linux用户运行在user上
Linux内核在svc模式


寄存器(37个):R0-R7不分组寄存器
  R8-R14分组寄存器
  R15程序寄存器


程序状态字寄存器:CPSR
  SPSR
特殊的寄存器:R13,R14,R15
R13用于堆栈
R14用于链接寄存器(返回调用的函数,记录地址)
R15用于程序计数寄存器
程序状态字寄存器:只有在异常情况下,有两种。Spsr记录异常时上一个函数的地址。


CPSR 的状态寄存器:N比较大小,a-b,结果为负数则0,0或正数,为1
Z 结果为0则为1
IF 中断置1
M 5位,标明处理器的工作模式


寻址方式:处理器根据给出的信息通过指令找到所需的操作数
立即数寻址 ADD R0,R0,#0X2F;R0=R0+0X2F
寄存器寻址:ADD R0,R1,R2;
寄存器间接寻址:LDR R0,[R1];   R0<-R1
基址变址寻址: LDR R0,[R1,#4]  R0<-R1+4
相对寻址:BL NEXT 跳转NEXT
......
NEXT
.......


协处理器:ARM 11 ,ARM9 A8 中CP15是协处理器。主要是用于执行特定的处理任务。
ARM最多支持16个协处理器。
CP15是最重要的一个
CP15:系统控制协处理器,配置与控制MMU,以及时钟模式。
如何访问CP15:MCR指令以及MRC指令。通过16组寄存器来访问协处理器。
CP15提供了16组寄存器。
MainID:32位,5个段..(看一下)
MCR{cond} P15,<Opcode_1>, <Rd>,<CRn>,<CRm>,<Op_2>
MRC{cond} P15,<Opcode_1>, <Rd>,<CRn>,<CRm>,<Op_2>
ARM手册有详细的参数表
使用时,尽量查看参数表
目的寄存器在前面,源寄存器在后面


伪指令
ARM机器码:与汇编原理十分像
是为了让超出指令架构格式而形成的
伪指令分为定义类伪指令,操作类伪指令
(编译时)定义类伪指令:global ascii int byte word data equ align
伪指令本身没有对应的机械码,它只是在编译的时候起作用,或者转化为其他的实际指令来运行。
. Global _statrt :声明全局变量的符号
.Data 定义的数据使用byte,word,ascii 
比如:
.data
Hello:
.ascii ”helloword”
Gn:
.byte 0x1
Add:
.word 0xff


.equ DA 89 
(宏变量)


操作类伪指令:LDR NOP
当操MOV转移的立即数超过8位,就要使用LDR
MOV R0, #0XFF(#是立即数)
LDR R0,=0X1FF(这里是用=使用立即数)
实际上:ldr r0,[PC,-4] 
NOP:控制时序,延时。实际上:mov r0,r0


ARM分类:
算术和逻辑指令
比较指令
跳转指令
移位指令
程序状态字访问指令
存储器访问指令
加注释是用@
算术和逻辑类指令:MOV MVN(传送取反值)  SUB  ADD AND BIC  
SUB <DUST> ,<OP1>, <OP2>
AND <DUST>, <OP1>, <OP2>
BIC(位清除)<DUST>,<OP1>,<OP2>  哪一位为1,哪一位清零
兼优汇编:二进制0b #立即数
标准汇编:二进制#
比较指令:CMP TST
CMP<OP1>,<OP2> OP1-OP2 会影响程序状态寄存器 N, Z两位被影响
TST(测试位与)<OP1>,<OP2>影响CPSR寄存器 看结果,还是影响了N Z两位
TSQ(测试等价)<op1>,<op2> 


跳转指令:b ,bl
又叫做分支指令
Bgt branch1
Add r3,r2,r1
B end
Branch1:
Sub r3,r2,r1
End:
Nop


Bl 带链接返回的跳转
想要返回自己想要的地方,就要修改PC指针
Mov r1,#2
Cmp r1,#1
B func1
Mov r1,#2
cmp R1,#3
Func1
Movr1,#2
Mov r2,#3
Mov pc,lr(关键在于LR寄存器里面,但是lr没有相应的地址,会飞掉)
所以,B要变成BL才能运行
可以回到函数调用的原来的地址


位移指令:LSL,ROR
LSL:逻辑或者算术左移
MOV R0,R1,LSL#2
ROR(循环右移):溢出去的1会到前面去


程序状态字访问指令:msr mrs
要修改要借助其他的寄存器
存储器访问指令:LDR STR
内存和寄存器之间的互通
Str<R1><R2> 
LDR<R1><R2>


ARM概述:
ARM汇编的分类:ADS只是使用于ARM公司开发的标准汇编
GNU适用于Linux平台GNU汇编
细微的区别:.text GNU ADS没有点


ARM汇编程序的框架:
.sections .data
<初始化数据>
.section .bss
<未初始化的数据>
.section .text
.global _start(声明)
_start:(代码入口)
<代码>
.section可以取消
链接器脚本能够锁定起始地址,同时arm-linux-ld -T 也可以锁定起始地址






BOOTLODER 的设计
BootLoader:Bootloader作用:起引导作用
去模仿U-Boot
U-Boot:第一支持多种嵌入式CPU,不仅指出LINUX还支持其他操作系统
自主模式:先运行U-BOOT,再自动的启动linux内核
开发模式:内核的开发工作。


安装sourceinsight,解压缩到linux里面去,访问
原因:windows下不区分文件名大小写,会导致文件被覆盖。


ARM处理器启动流程
重要三点:启动方式,地址布局,启动流程
2440:NOR启动(2M),NAND启动(256M)
地址布局:从0地址处取第一条指令。
NAND不能直接访问,需要使用寄存器间接访问,无法统一编制。0地址处,BootSARM。
启动1:BootSARM(4KB stepping stone)先上电之后,NAND把4KB复制到bootsarm。
启动2:BOOTLODAER剩下的部分从NAND里面复制到内存,BOOTSARM接着运行剩下的 BOOTLODAER。
第三步,将4KB的复制到内存当中去。
2440的(SDRAM)内存开始地址:0x30000000


6410:启动方式:NOR启动,ONENAND(有NOR,NAND的特性),MODEN,IROM(处理器INTERNAL存储器不是垫脚石,NAND启动,SD启动)
通过设置引脚来配置启动方式。
地址布局:BOOTLODAER从0C开始,内存从50000000开始,0地址处是通过XOM设置的booting驱动区域。(一个镜像区域)
镜像区域没有东西,只是被映射的。把IROM映射到镜像或者NOR映射过去,相当于每一种启动方式都到0地址开始。
上电之后,先运行IROM,映射到0地址,里面放的是固化的软件,Boot0(0阶段)。把NAND里面的Boot1(8K)拷贝到steppings stone里面,剩下的BL送到SDRAM里面。SDRAM送到控制口运行。


210(表2.6.4):支持IROM启动(SD,NAND),USB,串口
IROM(64KB,0XD开始),垫脚石IRAM(0XD002_0000),0地址处BootAREA(映射方式),内存(DRAM 0X20000000)
NAND启动:IROM(固化软件)先启动 BL0(初始化),(BL1)NAND将BL1和BL2传到ISRAM(在这里是垫脚石,大小96KB,界限:B1 16KB,BL2 80KB),假如不够放就放到SDRAM里面。操作系统接下来到SDRAM里面。


U-Boot工作流程
程序入口,第一阶段分析,第二阶段分析


2440:还是一样的,用makefile去找,在三星发现了lds,找start.o先运行,ENTRY为入口。
        1.先做一个中断向量表(跳转向量表)
2.先将处理器设置为SVC模式
3.刷新ID CACHE
4.关闭MMU和CACHE
5.BL LOWLEVEL_INIT(都在BORAD目录下面):初始化时钟(关闭看门狗,关中断),初始化串口,对NAND简单初始化,判断U-Boot是否在内存当中(不是,就要初始化内存),
6.检查是NAND还是NOR,是那个就是哪一个拷贝。
7.设置堆栈。
8.清除BSS段
拷贝进去的是start.S(4kb)
第三步:实际上就是把PC指针跳转到内存运行
B:首先算出一个相对值,再在赋值加给pc
LDR:绝对跳转,直接修改PC指针的值。


BL2:初始化硬件(主要),软件
先一个循环初始化串口,初始化LCD,网卡初始化,初始化LED,对用户输入的命令进行解析。


6410:1.先做一个中断向量表(跳转向量表)
    2.先将处理器设置为SVC模式
            3.刷新ID CACHE
4.关闭MMU和CACHE
5.外设基地址初始化
LOWLEVEL_INIT 的调用(LED的初始化,点亮,关闭看门狗,关闭中断,)初始化串口,对NAND简单初始化,判断U-Boot是否在内存当中(不是,就要初始化内存)。
6.复制NAND到内存去
7.设置堆栈
8.清除BSS
9.跳转到START_ARMBOOT
接着一样


210:ARM处理器流程:IROM通过映射到0地址处,上电后IROM固化程序运行,把BL1复制到IRAM里面16KB,BL2复制到IRAM(小于80KB),大了就复制到内存。
210使用高版本U-BOOT,出现了两个bin文件。


1.先做一个中断向量表(跳转向量表)
2.先将处理器设置为SVC模式
3.让L1的I/D CAHCE失效
4.关闭MMU和CACHE
5.LOWLEVEL_INIT:保存LR寄存器,检查reset的状态,I/O引脚恢复为默认值,关闭看门狗,SRAM和SROM的初始化,判断是否在内存中运行。时钟初始化,,内存初始化,串口初始化,取消存储保护区。NAND简单初始化,关闭ABB
6.返回函数两次
7.设置堆栈,判断是否在内存运行,是就跳到BOOT_IN_RAM
8.复制BL2到内存当中去
9.PC跳转到U-BOOT
实际上,FLASH写入时,BL1与BL2之间的间距相差24KB因此可以轻易额找到下一段BL。
BL2采用指针跳转地址,运行BL2。


BL2:在内存中运行,跳转上面函数。
Board_init_f才是新的开始
弱函数遇到同名函数,自己就失效。

0 0
原创粉丝点击