第001节:辅线1_硬件知识_LED原理图
- 实现点亮LED的步骤:
- 1.看原理图,确定控制led的引脚
- 通过主芯片使用引脚输出:3.3V点亮led;0V熄灭led。
-接法:
- 引脚驱动能力不足:使用三极管,
- 接法介绍:
-接法1:
-接法2:
- 通过主芯片使用引脚输出:3.3V点亮led;0V熄灭led。
- 2.看主芯片手册,确定如何设置/控制引脚
- 3.写程序
- 1.看原理图,确定控制led的引脚
第002节:辅线1_硬件知识_s3c2440启动流程与GPIO操作
知识点:
- 网络net,同名的net表示连接在一起
- 网络中的n,常表示低电平有效
- 怎么让GPF4输出1/0
- 先配置为输出引脚
- 设置状态
- 设置GPFCON[9:8]=0b01(0b表示二进制,9为0,8为1),GPF4配置为输出
- 设置GPFDAT[4]=1:输出高电平,led熄灭
- 设置GPFDAT[4]=0:输出低电平,led点亮
S3C2440框架与启动过程:
- S3C2440框架图:
- 启动过程:大多数ARM芯片从0地址启动
- Nor启动时候,Nor Flash基地址为0;片内RAM地址为0x4000,0000
- cpu读出Nor上第一个指令(前4字节),执行,
- cpu继续读出其他指令执行。
- Nand启动,片内4kRAM基地址为0; Nor Flash不可以访问
- 2440硬件把Nand前4k内容复制到片内RAM,
- 然后cpu从0地址取出第一条指令执行。
- S3C2440框架图:
第003节:编写第一个程序点亮LED
怎么让GPF4输出1/0的方法:
- 先配置为输出引脚
- 设置状态
- 设置GPFCON[9:8]=0b01(0b表示二进制:9为0,8为1),GPF4配为输出
-==>把0x100写入GPFCON,即写到地址0x5600,0050上 - 设置GPFDAT[4]=1:输出高电平,led熄灭
-==>把0x10写到地址0x5600,0054上 - 设置GPFDAT[4]=0:输出低电平,led点亮
-==>把0写到地址0x5600,0054上
- 补充知识:
- 补充知识:
- 设置GPFCON[9:8]=0b01(0b表示二进制:9为0,8为1),GPF4配为输出
几条汇编代码:
- LDR(load):读内存命令,
- LDR RO,[R1]:假设R1的值为x,则读取地址x上的数据(4字节),保存到R0中
- STR(store):写内存命令
- STR R0,R[1]:假设R1的值为x,把R0的值写入地址x(4字节)
- B:跳转
- MOV(move):
- MOV R0, R1:把R1的值赋给R0,即R0=R1
- MOV R0,#0x100:即把R0=0x100
- LDR R0, =0X12345678:伪指令,它会被拆分为几条真正的RAM指令
- 引入伪指令, “LDR R0,=任意值”的原因:
-ARM指令一共32位,会有部分字节表示指令,某些存储R0,其余剩余的不足32位,不能表示任意值,只能表示简单值(被称为立即数)。
- LDR(load):读内存命令,
安装arm-linux-gcc注意事项以及相关重点:
第004节:汇编与机器码
- CPU寄存器及其别名:
寄存器名 | 别名 | 全称 |
---|---|---|
R1 | ||
R2 | ||
R3 | ||
R4 | ||
R5 | ||
R6 | ||
R7 | ||
R8 | ||
R9 | ||
R10 | ||
R11 | ||
R12 | ||
R13 | sp | stack point:栈指针 |
R14 | lr | link register:保存返回地址 |
R15 | pc | program counter:程序计数器 |
- 详细介绍:
- program counter:程序计数器=当前指令+8
- 流水线:当前执行地址A的指令,已经在对地址A+4的指令进行译码,已经在读取地址A+8(即PC的值)的指令
- program counter:程序计数器=当前指令+8
- 反汇编指令理解:
0: e59f1014 ldr r1, [pc, #20] ; 1c <halt+0x4>
- r1=[pc+20]=[8+20]=[0x1c]=0x56000050
8: e5810000 str r0, [r1]
- 把r0即0x100,写入r1对应的内存,0x100–>[0x56000050]:即GPFCON寄存器
c: e59f100c ldr r1, [pc, #12] ; 20 <halt+0x8>
- r1=[pc+12]=[0xc+8+12]=[32]=[0x20]=0x56000054:即GPFDAT寄存器
- GPFCON/GPFDAT在CPU中,都是作为内存
- 完整代码:
led_on.elf: file format elf32-littlearm
Disassembly of section .text:
00000000 <_start>:
0: e59f1014 ldr r1, [pc, #20] ; 1c <halt+0x4>
4: e3a00c01 mov r0, #256 ; 0x100
8: e5810000 str r0, [r1]
c: e59f100c ldr r1, [pc, #12] ; 20 <halt+0x8>
10: e3a00000 mov r0, #0
14: e5810000 str r0, [r1]
00000018 <halt>:
18: eafffffe b 18 <halt>
1c: 56000050 undefined instruction 0x56000050
20: 56000054 undefined instruction 0x56000054
Disassembly of section .ARM.attributes:
00000000 <.ARM.attributes>:
0: 00001941 andeq r1, r0, r1, asr #18
4: 61656100 cmnvs r5, r0, lsl #2
8: 01006962 tsteq r0, r2, ror #18
c: 0000000f andeq r0, r0, pc
10: 00543405 subseq r3, r4, r5, lsl #8
14: 01080206 tsteq r8, r6, lsl #4
18: Address 0x00000018 is out of bounds.
- 练习题:
- 修改len_on.s到点亮LED2
- 直接修改led_on.bin点亮LED2
- mov指令机器码:
4: e3a00c01 mov r0, #256 ; 0x100
- 故:当代码为mov r0,#0x400,即修改最后的12位立即数(=immed_8循环右移(2*rotate)位)
- 12位立即数中高4位,表示rotate,低8位:immed_8
- 具体介绍:
- 举一反三:
第005、006节:编程知识_进制-字节序
进制:
- 如何快四转化2/8/16进制:
- 8421
- 0b开头:2进制
- 0开头:8进制
- 0x开头:16进制
字节序:
- 低位存放低地址:小字节序(little endian)
- 高位存在低地址:大字节序(big endian)
位操作:
- 移位:
- 左移:int a=0x123; int b=a<<2=?
-通过8421来转化为二进制,即a=0001,0010,0011,故b=0100,1000,1100=8421=0x48C=0x123*(2^2)=0x123*4 - 右移:int a=0x123; int b=a>>2=?
-故a=0001,0010,0011; 则b=00,0100,1000=0x48=0x123/4=0x48
- 左移:int a=0x123; int b=a<<2=?
- 取反: 原来为0的位变为1;原来为1的位变为0
- int a=0x123; int b=~a=0xfffffedc???
- 位与: c=a&b
- 1 and 1 = 1;
- 1 and 0 = 0;
- 0 and 1 = 0;
- o and 0 = 0;
- 位或:c=a|b
- 1 or 1 = 1;
- 1 or 0 = 1;
- 0 or 1 = 1;
- o or 0 = 0;
- 置位:
- int a=0x123,把bit7,8置位
- int b=a|(1<<7)|(1<<8)
- 移位:
清位:
- int a=0x123,把bit7,8清除
- int b=a&(~(1<<7))&(~(1<<8))
第007节:编写C程序控制LED
- C指针操作:
1.所有的变量在内存中都有一块区域
可以通过变量/指针来操作内存
第008节:
几条汇编代码:
- LDR(load):读内存命令,
- LDR RO,[R1]:假设R1的值为x,则读取地址x上的数据(4字节),保存到R0中
- STR(store):写内存命令
- STR R0,R[1]:假设R1的值为x,把R0的值写入地址x(4字节)
- B:跳转
- MOV(move):
- MOV R0, R1:把R1的值赋给R0,即R0=R1
- MOV R0,#0x100:即把R0=0x100
- LDR R0, =0X12345678:伪指令,它会被拆分为几条真正的RAM指令
- 引入伪指令, “LDR R0,=任意值”的原因:
-ARM指令一共32位,会有部分字节表示指令,某些存储R0,其余剩余的不足32位,不能表示任意值,只能表示简单值(被称为立即数)。
- add:
- add r0,r1, #4==>r0=r1+4
- sub:
- sub r0, r1,#4==>r0=r1-4
- sub r0, r1,r2==>r0=r1-r2
BL(branch and link):
- bl * * *:
-跳转到* * *;
-并将返回地址(下一条指令的地址)保存在lr寄存器中
- bl * * *:
ldm(many):读内存,写入多个寄存器
- ldmia:
- stm: 把多个寄存器的值写入内存
- stmdb:
- 过后增加(Increment After)、预先增加(Increment Before)、过后减少(Decrement After)、预先减少(Decrement Before)。
- 举例:
- LDR(load):读内存命令,