完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
2个回答
|
|
1、ARM相关的概念
1.4 ARM相关的概念 内核:ARM公司授权给芯片设计厂家 内核=运算器 + 控制器 + 存储器(寄存器) 存储器的分类 1.主存储器即内存。程序中待处理的数据和处理的结果都存储在内存中。 2.外存储器是用来长期保存数据的大容量存储器。 3.寄存器是CPU内部的高速存储器,速度快,数目少。 CPU(Central Processing Unit),是一台计算机的运算核心和控制核心。CPU由运算器、控制器和寄存器及实现它们之间联系的数据、控制及状态的总线构成。所谓的计算机的可编程性主要是指对CPU的编程。 处理器 SOC(CPU) 内核 架构 麒麟9000 cortex-A774 ARM-v8 cortex-a554 ARM-v8 骁龙888 cortex-x1 1 ARM-v8 cortex-A783 ARM-v8 cortex-a554 ARM-v8 Exynos4412 cortex-a94 ARM-v7 stm32MP157 cortex-A72 ARM-v7 cortex-M41 SOC(System Of Chip):片上系统 芯片的内部集成了内核和很多的外设,这样的芯片可以统称SOC。 ## 1.5 ARM产品线 ```c ARM体系 ARMv4 ARMv5 ARMv6 ARMv7 ARM CPU arm7 arm9/arm10 arm11 arm_cortex_a8 cortex-A: 高端处理器,可以运行linux系统,消费类电子产品( 手机、平板等) cortex-R:主要针对的实时处理,汽车电子,摄像机,照相机 cortex-M:低端电子产品,运行裸机程序,物联网设备开发,stm32/stm8(意法半导体公司),可以运行实时的操作系统(FreeRTOS LiteOS AliOS ucos II) arm内核命令的规范: 早期:ARM7 ARM9 ARM10 ARM11 从ARM11之后ARM内核的命名调整为Cortex-A X86——32位架构 X64——64位架构 ARMv7——32位架构 ARMv8——64位架构 ARM-v8架构是arm64的架构及支持arm64位的汇编指令 ARM-v8架构向下兼容ARM-v7的架构 ARM-v7架构是arm32的架构及支持arm32位的汇编指令 架构:汇编指令集的集合 ARM汇编指令集:一些汇编指令的集合 ARM汇编指令:具有某个特殊功能的指令 指令本身是通过CMOS设计的硬件电路图 不同ARM体系采用的是不同的指令集 哈佛结构是数据和指令分开存储并行 冯诺依曼(普林斯顿)结构是混合存储的 1.6 RISC和CISC指令集的区别 RISC: 精简指令集 (ARM,8051,MIPS,PowerPC) 精简指令集是在复杂指令集中提取一些比较简单和使用频率较高的指令作为精简指令,精简指令集的指令的周期和指令的宽度固定。ARM指令集是精简指令集 指令周期:执行1一条指令所需要的时间 指令宽度:1条指令所占用的内存空间 CISC: 复杂指令集(电脑CPU) 复杂指令集更加注重指令的功能和处理能力,复杂指令集的周期和宽度不固定。X86指令集是复杂指令集 从汇编代码的角度分析复杂指令集合精简指令集的区别? 复杂指令集: // 作用:将elf文件生成反汇编文件 // objdump是GNU工具集中的一个命令 objdump -D a.out > 1.dis 内存地址 机器码 反汇编指令 8048154: 2f das 8048155: 6c in*** (%dx),%es:(%edi) 8048156: 69 62 2f 6c 64 2d 6c imul $0x6c2d646c,0x2f(%edx) 804815d: 69 6e 75 78 2e 73 6f imul $0x6f732e78,0x75(%esi) 8048164: 2e 32 00 xor %cs:(%eax),%al 精简指令集: 交叉编译工具链:将源文件编译生成支持ARM架构的可执行程序 arm-none-linux-gnueabi-gcc 1.c arm-none-linux-gnueabi-objdump -D a.out > 1.dis 内存地址 机器码 反汇编指令 8134: 62696c2f r***vs r6, r9, #12032 ; 0x2f00 8138: 2d646c2f stclcs 12, cr6, [r4, #-188]! ; 0xffff 813c: 756e696c strbvc r6, [lr, #-2412]! ; 0x96c 8140: 6f732e78 svcvs 0x00732e78 反汇编分析: 拓展: ELF与BIN文件区别 gcc 编译出来的是elf文件。通常gcc –o test test.c,生成的test文件就是ELF格式的,在linuxshell下输入 ./test就可以执行。 bin 文件是经过压缩的可执行文件,去掉elf格式的东西。是直接的内存映像的表示。在系统没有加载操作系统的时候可以执行。 elf(executable and link format)文件里面包含了符号表,汇编等。 bin文件是将elf文件中的代码段,数据段,还有一些自定义的段抽取出来做成的一个内存的镜像。 在Embedded中,如果上电开始运行,没有OS系统,如果将ELF格式的文件烧写进去,包含一些ELF格式的东西,arm运行碰到这些指令,就会导致失败,如果用arm-softfloat-linux-gnu-objcopy生成纯粹的汇编 bin文件,程序就可以一步一步运行。 两种文件都可以运行 机器最终只认BIN,之所以有ELF格式是在有操作系统时,操作系统会根据ELF解析出代码、数据等等,最终仍是以BIN运行。由于elf文件的信息比较全,所以可以用来以单步跟踪的方式运行。关键是看loader。 嵌入式开发的时候,我们的编译一个*.S文件,并最终生成bin文件,编译命令大致如下: CC=arm-softfloat-linux-gnu-gcc LD=arm-softfloat-linux-gnu-ld OBJCOPY=arm-softfloat-linux-gnu-objcopy $(CC) -g$(CFLAG) -c boot.S #先将boot.S文件生成boot.o $(LD) -g-Bstatic -T$(LDFILE) -Ttext 0x12345600 boot.o --start-group -Map boot.map -oboot.elf #再将boot.o生成boot.elf,boot.elf通常就是可执行文件,类似于gcc-o test test.c 中的test文件,在LinuxShell下输入./test就可以执行。 $(OBJCOPY)-O binary boot.elf boot.bin #接着将boot.elf->boot.bin,这样可以缩小代码尺寸。 运行arm-softfloat-linux-gnu-objdump-h boot.elf 可以查看该文件的信息,但是如果变成 arm-softfloat-linux-gnu-objdump-h boot.bin会提示错误,为了看boot.bin文件信息,输入: arm-softfloat-linux-gnu-objdump-h -b binary -m arm boot.bin就可以了。哈哈我也是现学了一招,其中参数-h可以被替换成为-D, -S,-s等等,请用arm-softfloat-linux-gnu-objdump--help查看器中表示的意义。 1.7 ARM数据的约定 ARM-V7约定: char :8bits half word:16bits word:32bits double word :64bits(cortex-a系列才支持) ARM-V8约定: char :8bits half word:16bits word:32bits double word :64bits(cortex-a系列才支持) quad word:128bits(ARM-V8架构才支持) 2、ARM工作模式和寄存器 2.1 ARM处理器的工作模式 |--特权模式--|--异常模式--|-快速中断模式(FIQ) | | |-普通中断模式(IRQ) | | |-管理模式(SVC):当复位或软中断指令执行时进入此种模式 | | |-未定义指令异常模式(Und) 工 | | |-中止异常模式(Abort):当存取异常时会进入此模式 作 | | |-安全监控模式(Monitor) --| | (cortex-A系列内核支持,所以会比armv系列多3个寄存器) 模 | | 式 | |--非异常模式 -->System | (属于用户模式的特权模式) | |--非特权模式-->user -> 执行用户空间的代码 普通中断模式(IRQ):当发生一个外部中断的事件,进入到IRQ模式,执行IRQ模式下对应的代码。 外部中断事件:按键,定时器等 2.2 ARM处理器的寄存器组织(重点) ARM内核 = 运算器 + 控制器 + 存储器 存储器 = cache + 寄存器 存储器:flash 内存(Memory) cache(i-cache,d-cache), 寄存器(Register) 寄存器 cache 内存 flash 快 <-------------------慢 读写速度 小 -------------------->大 容量 贵 <-------------------贱 价格 寄存器/cache/内存 : 掉电数据丢失 Flash:掉电不丢失 2.3 特殊寄存器 r13 -> 别名sp (the stack pointer) 栈指针寄存器,存放栈的地址 r14 -> 别名lr (the link Register) 链接寄存器, 保存的是返回地址 r15 -> 别名pc (the program counter) 程序计数寄存器, 保存当前取指指令的地址 cpsr -> (current program status register) 当前程序状态寄存器:存储的程序运行状态 每条指令执行的状态 处理器的工作模式 spsr -> (saved program status register) 保存程序状态寄存器:专门用于保存cpsr寄存器 2.4 CPSR寄存器的详解 2.5 ARM指令集 和 Thumb指令集 ARM指令集: 一条指令占32位宽度, ARM指令集的功能性更强,指令密度较低 PC取指每次自动加4 Thumb指令集: 一条指令占16位宽度 Thumb指令集的密度大。 PC取指每次自动加2 2.6 PC寄存器详解 PC寄存器中存放的是当前取指指令的地址 ARM指令集: 每条ARM指令占32bits的宽度 所有的指令必须4字节对齐, pc寄存器中的值[31:2]位有效,[1:0]位未定义(无效) 0000 0000 0000 0100 0000 1000 0000 1100 pc = 0x3 @ 由于第[1:0]位未定义,永远当0处理 @ 因此从0x00地址开始进行取指 ARM指令集: 每条ARM指令占16bits的宽度 所有的指令必须2字节对齐, pc寄存器中的值[31:1]位有效,[0]位未定义(无效)。 0000 0000 0000 0010 0000 0100 0000 0110 2.7 指令的三级流水线 取指器 :根据PC寄存器中的值进行取指 译码器 :翻译机器码,给到对应的执行器 执行器 :执行指令,并将结果返回到寄存器 取指器,译码器,执行器是三个独立的硬件, 都是单周期的器件,工作互不影响。 指令1 指令2 指令3 指令4 指令5 指令6 1 取指 2 译码 取指 3 执行 译码 取指 4 执行 译码 取指 5 执行 译码 取指 6 执行 译码 取指 7 执行 译码 取指 8 执行 译码 取指 一条指令的执行时间 : 8 / 6 = 1 跳转和中断都会打断指令的流水线。 arm7 三级流水线 arm9 五级流水线 arm11 七级流水线 cortex-A9 13级流水线 (未知) cortex-a53 8级流水线 (?) |
|
|
|
3、汇编
3.1 汇编代码中的主要符号
.text //将定义符开始的代码编译到代码段(只读) .data //将定义符开始的代码编译到数据段(可读写) .end //文件结束 .equ //GPG3CON,0xE03001C0 定义宏(即用GPG3CON代替0xE03001C0) .byte //定义变量1字节 .byte 0x11,'a',0定义字节数组 .word //定义word变量(4字节,32位机) .word 0x12344578, 0x33445566 .string //定义字符串 .string "abcd " .global _start //声明_start为全局符号
(opcode){cond}{S} Rd, Rn, oprand2 opode : 指令的名字 {cond} : 条件码 {S} : 状态标志位 指令名后边加S,指令的执行结果影响CPSR寄存器的NZCV位,否则不影响CPSR的NZCV位 movs adds subs Rd : 目标寄存器 Rn : 第一个操作寄存器 oprand2 : 第二个操作数 1> 可以是一个普通的寄存器 2> 可以是一个立即数或有效数 3> 可以是一个经过移位操作的寄存器 一条汇编指令占一行,指令名和目标寄存器之间使用空格隔开;寄存器之间使用逗号隔开; (opcode){cond}{S}连到一起写。 汇编中,指令不区分大小写,举例如下 MOV R0, #0xFF ==== mov r0, #0xff 拓展:条件码 3.3 指令分类 3.3.1 数据操作指令 3.3.1.1 数据搬移指令 mov mvn ldr @== mov/mvn{cond}{s} Rd, oprand2== mov r0, #0xff @ r0 = 0xff mov r1, r0 @ r1 = r0 mvn r2, #0xff @ r2 = ~0xff mvn r3, r2 @ r3 = ~r2 @ mov pc, #0x3 错 //pc寄存器的0,1两位无效 mov r0, #0xFF000000 @ mov r1, #0xFFF 错 @ mov r2, #0xFFFF 错 mov r3, #0xFFFFFF 拓展:立即数和有效数 3.3.1.2 移位操作指令 lsl lsr asr ror @ 语法格式: @ opcode{cond}{S} Rd, Rn, Oprand2 mov r0, #0xFF @ lsl 逻辑左移 :高位移出,低位补0 lsl r1, r0, #0x4 @ r1 = r0 << 4 @ lsr 逻辑右移 :低位移出,高位补0 lsr r2, r0, #0x4 @ r2 = r0 >> 4 @ asr 算数右移 :低位移出,高位符号位 @ ror 循环右移 :低位移出补到高位 mov r3, r0, lsl #4 √ mov r4, #(0xFF << 4) √ mov r4,0xFF,lsl #4 × 3.3.1.3算数运算指令 add adc sub ***c mul @ 语法格式: @ opcode{cond}{S} Rd, Rn, Oprand2 @ add/sub: 普通的加减法指令 @ adc/***c: 待进位借位的加减法指令 @ 案例: /* 实现两个64位数据的加法运算 第1个64位数,r0表示低32位,r1表示高32位 第2个64位数,r2表示低32位,r3表示高32位 结果,r4存低32位,r5存高32位 */ mov r0, #0xFFFFFFFE mov r1, #4 mov r2, #5 mov r3, #3 @ s:指令的执行结果影响cpsr的nzcv位 adds r4, r0, r2 @ r4 = r0 + r2 = 0x3 @ 判断C位的值 adc r5, r1, r3 @ r5 = r1 + r3 + C =0x8 @ 案例: /* 实现两个64位数据的减法运算 第1个64位数,r0表示低32位,r1表示高32位 第2个64位数,r2表示低32位,r3表示高32位 结果,r4存低32位,r5存高32位 */ mov r0, #4 mov r1, #8 mov r2, #5 mov r3, #3 subs r4, r0, r2 @ r4 = r0 - r2 ***c r5, r1, r3 @ r5 = r1 - R3 - !C @ mul mov r7, #3 mov r8, #4 mul r6, r7, r8 r6=r7*r8 √ mul r6, r7,#4 × @ mul指令的第二个操作数只能是一个寄存器 3.3.1.4位运算指令 and(与) orr(或) eor(异或) bic(位清除) @ 语法格式: @ opcode{cond}{S} Rd, Rn, Oprand2 ldr r0, =0x87654321 @ 1> 将R0寄存器中的值,第[3]位置1,保证其他位不变 @ r0 = r0 | 0x8; 方法1:orr r0, r0, #0x8 方法2:@ orr r0, r0, #(0x1 << 3) 方法3:@ mov r1, #1 @ orr r0, r0, r1, lsl #3 @ 2> 将R0寄存器中的值,第[10]位清0,保证其他位不变 @ r0 = r0 & (~(0x1 << 10)); 方法1:and r0, r0, #0xFFFFFBFF 方法2:and r0, r0, #(~0x400) 方法3:and r0, r0, #(~(0x1 << 10)) @ 3> 将R0寄存器中的值,第[7:4]位置1,保证其他位不变 @ r0 = r0 | (0xF << 4); orr r0, r0, #(0xF << 4) @ 4> 将R0寄存器中的值,第[23:20]位清0,保证其他位不变 @ r0 = r0 & (~(0xF << 20)) and r0, r0, #(~(0xF << 20)) @ 5> 将R0寄存器中的值,第[15:10]位设置为0b101010,保证其他位不变 1) 全部清0 r0 = r0 & (~(0x3F << 10)) and r0, r0, #(~(0x3F << 10)) 2) 把相应的位置1 r0 = r0 | (0x3F << 10) orr r0, r0, #(0x2A << 10) @ 6> 将R0寄存器中的值,第[20]位取反,保证其他位不变 @ r0 = r0 ^ (0x1 << 20) eor r0, r0, #(0x1 << 20) @ bic 位清除指令 @ 将R0寄存器中的值,第[23:20]位清0,保证其他位不变 @ 本质: r0 = r0 & (~(0xF << 20)) bic r0, r0, #(0xF << 20) 3.3.1.5比较指令 cmp @ 语法格式: @ cmp{cond} Rn, oprand2 @ 注:1. 没有目标寄存器 @ 2. 执行的执行结果影响的是cpsr的nzcv位,不需要加s @ 3. 本质:减法运算 @ 4. 比较指令和条件码结合使用 @ 案例:if (r0>r1) r0 = r0 - r1 @ else r1 = r1 - r0 mov r0, #15 mov r1, #9 cmp r0, r1 subhi r0, r0, r1 subcc r1, r1, r0 //无进位无符号小于 3.3.2 跳转指令 b/bl @ 语法格式: @ b/bl{cond} Label(函数名) @ 汇编中的函数 Label: 指令 @ b : 不保存返回地址到lr寄存器,有去无回 @ bl : 保存返回地址到lr寄存器,有去有回,C语言函数的调用 @ 1. 调用汇编的函数 .if 0 mov r0, #1 mov r1, #2 b add_func add_func: add r2, r0, r1 .endif @ 2. 实现一个0-100相加,结果保存到r0 mov r1, #0 func: cmp r1, #100 bhi loop //无符号大于 add r0, r0, r1 add r1, r1, #1 b func mov r6,#3 bl add_100 @ 保存返回地址到lr中 b loop add_100: mov r1, #0 stop: cmp r1, #101 addcc r0, r0, r1 addcc r1, r1, #1 bcc stop mov pc, lr @ 必须手动返回 loop: b loop @ 案例: 求两个数的最大公约数 mov r0, #25 mov r1, #10 mm: cmp r0, r1 beq loop subhi r0, r0, r1 subcc r1, r1, r0 bne mm loop: b loop 3.3.3 内存读写的操作指令 load/store 2> 多寄存器操作指令 3> 栈操作指令 load/store指令 单寄存器的操作指令 ldr str @ r : Register @ 语法格式: ldr{cond} Rn, [Rm] //从Rm的地址中下载数据到Rn str{cond} Rn, [Rm] //把Rn的值存到Rm地址里面 Rn : Rn寄存器中的数当成数据处理 [Rm] : Rm寄存器中的数当成内存的地址处理 == ldr : 将[Rm]执向的地址空间中的内容读到Rn寄存器中 str : 将Rn寄存器中的值,写到[Rm]指向的地址空间中。== ldr r0, =0x40000800 //伪指令 ldr r1, =0x12345678 //伪指令 str r1, [r0] ldr r2, [r0] @ int *p = &a @ p =r0 / *p = [r0] @ (*p = a) = str @ (a = *p) =ldr @ ldrh/strh : 半字内存读写指令 @ h : half @ strb/ldrb : 单字节内存读写指令 @ b : Byte @ ldr/str的寻址方式 ldr r0, =0x40000800 ldr r1, =0x11111111 ldr r2, =0x22222222 ldr r3, =0x33333333 //将r1中的值写到r0+4指向的地址空间中,r0指向的地址空间不变 str r1, [r0, #4] //将r2中的值写到r0执行的地址空间中,同时更新r0指向的地址空间:r0=r0+4 str r2, [r0], #4 //将r3中的值写到r0+4指向的地址空间中,同时更新r0指向的地址空间:r0=r0+4 str r3, [r0, #4]! //同样ldr strh ldrh strb ldrb也支持以上三种不同的内存寻址方式 //注意:地址偏移量应该是load/store指令所操作内存的最小值的整数倍 2> 多寄存器操作指令 stm ldm @ m : mutil @ 语法格式: stm/ldm{cond} Rm, {寄存器列表} Rm : Rm中存放的是内存地址 {寄存器列表}:寄存器连续使用"-“隔开 寄存器不连续使用”,"隔开。 ldr r0, =0x40000800 ldr r1, =0x11111111 ldr r2, =0x22222222 ldr r3, =0x33333333 ldr r4, =0x44444444 ldr r5, =0x55555555 //将r1-r5寄存器中的内容存到r0指向的地址的连续的20个字节空间中 stm r0, {r1-r4,r5} //将r0指向的20个字节连续空间中的内容读到r6-r10寄存器中 ldm r0, {r6-r10} @ 注:不管寄存器列表中的寄存器顺序如何永远都是低地址对应小编号寄存器,高地址对应高编号的寄存器 stm r0, {r5,r4,r3,r2,r1} ldm r0, {r10,r9,r8,r7,r6} 3> 栈操作指令 stmfd ldmfd 增栈 压栈时,栈指针向高地址方向移动 减栈 压栈时,栈指针向低地址方向移动 满栈 当前栈指针指向的空间有有效的数据 空栈 当前栈指针指向的空间没有有效的数据 栈的操作方式 4种(满增栈,满减栈,空增栈,空减栈) ARM处理器默认采用的是满减栈 // 满减栈指令:stmfd/ldmfd full descending // 满增栈指令:stmfa/ldmfa full ascending // 空减栈指令:stmed/ldmed empty descending // 空增栈指令:stmea/ldmea empty ascending @ 语法格式: stmfd/ldmfd{cond} SP!, {寄存器列表} !: 更新栈指针 ldr sp, =0x40000800 @ 初始化栈指针 //需要初始化栈指针的原因:默认为0,为满减栈,若不初始化给一个值,会往低地址存,为负数 mov r0, #3 @ r0, r1 赋初始值 mov r1, #4 bl add_func @ 调用加法函数 add r2, r0, r1 @ r2=r0+r1=0x7 b loop add_func: stmfd sp!, {r0-r1, lr} //压栈保存现场 mov r0, #5 @ 修改r0,r1值 mov r1, #6 bl sub_func add r3, r0, r1 @ r3=r0+r1=0xB ldmfd sp!, {r0-r1, pc} //出栈恢复现场 @ mov pc, lr @ 返回 sub_func: stmfd sp!, {r0,r1,lr} @ 保存现场 mov r0, #9 mov r1, #4 sub r4, r0, r1 ldmfd sp!, {r0,r1,lr} @ 恢复现场 mov pc, lr 3.3.4 特殊功能寄存器操作指令 msr mrs 对于cpsr寄存器的读写只能用msr和mrs指令 @ 语法格式: @ msr cpsr, Rn @ 写:cpsr = Rn @ mrs Rn, cpsr @ 读:Rn = cpsr @ 系统上的默认工作在svc模式 @ 从svc模式切换到用户模式 @ 10000 User mode; @ 10011 SVC mode; @ 方法1: @ mov r0, #0xD0 @ msr cpsr, r0 @ 方法2: @ 1. 先将cpsr中的值读到普通寄存器 mrs r0, cpsr @ 2. 修改模式位,保证其他位不变 bic r0, r0, #0x1F orr r0, r0, #0x10 @ 3. 将修改后的值写回到cpsr中 4、异常的处理过程 swi软中断指令 user(用户模式) 向下调用接口 ----------------------(软中断(通过软中断号区分))--------- 向上提供接口 kernel(svc模式) ------------------------------------------------------ hal 5、C和汇编的混合编程 C和汇编混合编程必须遵循ATPCS规范 1. arm-v7 参数的传递使用r0-r3,返回值通过R0返回 如果参数大于4个,使用压栈的方式进行传递。 函数封装时,形参的个数尽量不要超过4个。 2. arm-v8 参数的传递使用x0-x7,返回值通过x0返回, 如果参数大于8个,使用压栈的方式进行传递 5.1 汇编调用C 给r0-r3赋初始值,相当于给C的函数传递实参值 直接使用bl指令进行调用 5.2 C调用汇编 // 函数的声明 extern int add_func(int a, int b); int add_func2(int a, int b, int c); int sum; int main() { // C调用汇编 sum = add_func(3,4); sum = add_func2(4,5,6); sum = add_func(3,4); while(1); return 0; } // 内联汇编 int add_func2(int a, int b, int c) { int sum; asm volatile( "add r0, r0, r1nt" "add r0, r0, r2nt" :"=r"(sum) :"r"(a), "r"(b), "r"(c) :"memory" ); return sum; } .text .global _start _start: @ 切换到用户模式 msr cpsr, #0xD0 @ 初始化User模式下的栈指针 ldr sp, =0x40000800 @ 汇编调用C代码 : 直接调用 b main loop: b loop .end int add_func(int a, int b) { return a+b; } void swap_func(int *a, int *b) { int tmp; tmp = *a; *a = *b; *b = tmp; } int add_func2(int a, int b, int c ,int d, int e) { return a+b+c+d+e; } 5.3 内联汇编(内嵌汇编) asm volatile( "汇编指令" :输出列表 :输入列表 :破坏列表 ); 安装软件
本地开发:(X86 GNU工具集:gcc) PC端编写代码,PC端编译代码, PC端运行代码。 交叉开发: (ARM GNU工具集:arm-none-linux-gnueabi-gcc) PC端编写代码,PC端编译代码, 开发板(Target板)运行代码。 安装交叉编译工具链的过程: 1>. 在ubuntu的家目录下创建toolchain目录 2>. 拷贝交叉编译工具链到toolchain目录下, 并进行解压缩 FS6818(学生资料)工具软件ubuntu版本交叉编译器gcc-4.5.1.tar.bz2 tar -xvf gcc-4.5.1.tar.bz2 3>. 配置ubuntu系统的环境变量 对所有的用户有效: /etc/environment /etc/bash.bashrc /etc/profile 只对当前用户有效 ~/.bashrc 选择一个配置文件进行修改即可。 本次实验: 修改/etc/bash.bashrc,在文件最后边添加以下内容export PATH=$PATH:/home/linux/toolchain/gcc-4.5.1/bin修改为自己的路径 4>. 使环境变量立即生效 source /etc/bash.bashrc 或者重启ubuntu系统 5>. 测试交叉编译工具链是否安装成功 arm-none-linux-gnueabi-gcc -v 64位ubuntu系统兼容库 : sudo apt-get install libncurses5-dev sudo apt-get install lib32z1 # 内存地址的操作位运算符 : & | ^ ~ << >> 口诀: & :与0清0,与1不变 | :或1置1,或0不变 ^ : 异或1取反,异或0不变 1 ^ 1 -> 0 0 ^ 1 -> 1 1 ^ 0 -> 1 0 ^ 0 -> 0 内存 物理地址 地址的功能名 |----------| | | 0xC001A000 reg1 |----------| | | 0xC001A004 reg2 |----------| | | 0xC001A008 reg3 |----------| | | 0xC001A00C reg4 |----------| [31:0] ``c 方法1 : *(unsigned int *)0xC001A000 = *(unsigned int *)0xC001A000 | 0x8; #define reg1 (*(unsigned int *)0xC001A000) reg1 = reg1 | (0x1 << 3); 方法2: // 声明一个结构体 typedef struct{ unsigned int reg1; unsigned int reg2; unsigned int reg3; unsigned int reg4; }reg_t; #define REG (*(reg_t *)0xC001A000) REG.reg1 = REG.reg1 | (0x1 << 3); #define REG ((reg_t *)0xC001A000) REG->reg1 = REG->reg1 | (0x1 << 3); 练习: 31 0 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1> 0xC001A000地址中的,第[3]位置1,保证其他位不变 2> 0xC001A000地址中的,第[10]位清0,保证其他位不变 3> 0xC001A004地址中的,第[7:4]位置1,保证其他位不变 4> 0xC001A004地址中的,第[23:20]位清0,保证其他位不变 5> 0xC001A008地址中的,第[15:10]位设置为0b101010,保证其他位不变 开发板介绍 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 09:58 , Processed in 0.840889 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号