【嵌入式开发】ARM 代码搬移 ( ARM 启动流程 | 代码搬移 起点 终点 | 链接地址 | 汇编代码 )(二)

简介: 【嵌入式开发】ARM 代码搬移 ( ARM 启动流程 | 代码搬移 起点 终点 | 链接地址 | 汇编代码 )(二)

三. 代码搬移 汇编代码




1. 汇编代码编写



( 1 ) 代码搬移 汇编代码


汇编代码 :


copy_to_ram:
  ldr r0, =0x0c000000        @ 设置 代码搬移 起始地址 首地址 , 即 SRAM 垫脚石的 首地址 , 将改地址存放在 r0 寄存器中
  ldr r1, =0x50008000        @ 设置 代码搬移 终点 首地址 , 即 内存的首地址 , 将该地址存放在 r1 寄存器中
  add r3, r0, #1024*4        @ 设置 复制多少指令到 内存中 , 这里复制 4KB 数据 从 SRAM 到 内存 中 ; 
copy_loop:            @ 循环复制代码
  ldr r2, [r0], #4        @ 取出 r0 寄存器的地址 ( 即 SRAM 中的地址 ) 中的数据 放入 r2 寄存器  , 读取完毕后 , r0 中的地址 累加 4
  str r2, [r1], #4        @ 将 r2 中的内容 , 写入到 r1 寄存器对应的地址中 , 写出完毕后 , r1 中的地址 累加 4 
  cmp r0, r3          @ 查看 r0 地址 增量 是否 增加了 4KB , 到了代码搬移的末尾
  bne copy_loop         @ 如果 r0 r3 地址不一致 , 说明还没拷贝完毕 , 继续 跳转回 copy_loop 标号 拷贝
  mov pc, lr




( 2 ) 汇编完整代码


@****************************  
@File:start.S  
@  
@BootLoader 初始化代码 
@****************************  
.text                                   @ 宏 指明代码段  
.global _start                          @ 伪指令声明全局开始符号  
_start:                                 @ 程序入口标志  
        b   reset                       @ reset 复位异常  
        ldr pc, _undefined_instruction  @ 未定义异常, 将 _undefined_instruction 值装载到 pc 指针中  
        ldr pc, _software_interrupt     @ 软中断异常  
        ldr pc, _prefetch_abort         @ 预取指令异常  
        ldr pc, _data_abort             @ 数据读取异常  
        ldr pc, _not_used               @ 占用 0x00000014 地址                            
        ldr pc, _irq                    @ 普通中断异常  
        ldr pc, _fiq                    @ 软中断异常  
_undefined_instruction: .word undefined_instruction @ _undefined_instruction 标号存放了一个值, 该值是 32 位地址 undefined_instruction, undefined_instruction 是一个地址  
_software_interrupt:    .word software_interrupt    @ 软中断异常  
_prefetch_abort:    .word prefetch_abort            @ 预取指令异常 处理  
_data_abort:        .word data_abort                @ 数据读取异常  
_not_used:      .word not_used                      @ 空位处理  
_irq:           .word irq                           @ 普通中断处理  
_fiq:           .word fiq                           @ 快速中断处理  
undefined_instruction:                              @ undefined_instruction 地址存放要执行的内容  
        nop  
software_interrupt:                                 @ software_interrupt 地址存放要执行的内容  
        nop  
prefetch_abort:                                     @ prefetch_abort 地址存放要执行的内容  
        nop  
data_abort:                                         @ data_abort 地址存放要执行的内容  
        nop  
not_used:                                           @ not_used 地址存放要执行的内容  
        nop  
irq:                                                @ irq 地址存放要执行的内容  
        nop  
fiq:                                                @ fiq 地址存放要执行的内容  
        nop  
reset:                                              @ reset 地址存放要执行的内容  
  bl set_svc                                  @ 跳转到 set_svc 标号处执行
  bl set_serial_port        @ 设置外设基地址端口初始化
  bl disable_watchdog                         @ 跳转到 disable_watchdog 标号执行, 关闭看门狗
  bl disable_interrupt      @ 跳转到 disable_interrupt 标号执行, 关闭中断
  bl disable_mmu        @ 跳转到 disable_mmu 标号执行, 关闭 MMU 
  bl init_clock        @ 跳转到 init_clock 标号, 执行时钟初始化操作
  bl mem_init         @ 跳转到 mem_init 标号 , 执行内存初始化操作 , 该段代码定义在 mem.S 文件中
  bl light_led        @ 打开开发板上的 LED 发光二极管
  bl copy_to_ram        @ 代码搬移 , 从 SRAM 到 内存中
set_svc:
  mrs r0, cpsr                                @ 将 CPSR 寄存器中的值 导出到 R0 寄存器中
  bic r0, r0, #0x1f                           @ 将 R0 寄存器中的值 与 #0x1f 立即数 进行与操作, 并将结果保存到 R0 寄存器中, 实际是将寄存器的 0 ~ 4 位 置 0
  orr r0, r0, #0xd3                           @ 将 R0 寄存器中的值 与 #0xd3 立即数 进行或操作, 并将结果保存到 R0 寄存器中, 实际是设置 0 ~ 4 位 寄存器值 的处理器工作模式代码
  msr cpsr, r0                                @ 将 R0 寄存器中的值 保存到 CPSR 寄存器中
  mov pc, lr          @ 返回到 返回点处 继续执行后面的代码
#define pWTCON 0x7e004000                           @ 定义看门狗控制寄存器 地址 ( 6410开发板 )
disable_watchdog:                                 
  ldr r0, =pWTCON                             @ 先将控制寄存器地址保存到通用寄存器中
  mov r1, #0x0                                @ 准备一个 0 值, 看门狗控制寄存器都设置为0 , 即看门狗也关闭了
  str r1, [r0]                                @ 将 0 值 设置到 看门狗控制寄存器中 
  mov pc, lr          @ 返回到 返回点处 继续执行后面的代码
disable_interrupt:
  mvn r1,#0x0          @ 将 0x0 按位取反, 获取 全 1 的数据, 设置到 R1 寄存器中
  ldr r0,=0x71200014        @ 设置第一个中断屏蔽寄存器, 先将 寄存器 地址装载到 通用寄存器 R0 中 
  str r1,[r0]          @ 再将 全 1 的值设置到 寄存器中, 该寄存器的内存地址已经装载到了 R0 通用寄存器中
  ldr r0,=0x71300014        @ 设置第二个中断屏蔽寄存器, 先将 寄存器 地址装载到 通用寄存器 R0 中 
  str r1,[r0]          @ 再将 全 1 的值设置到 寄存器中, 该寄存器的内存地址已经装载到了 R0 通用寄存器中
  mov pc, lr          @ 返回到 返回点处 继续执行后面的代码
disable_mmu : 
  mcr p15,0,r0,c7,c7,0        @ 设置 I-Cache 和 D-Cache 失效
  mrc p15,0,r0,c1,c0,0        @ 将 c1 寄存器中的值 读取到 R0 通用寄存器中
  bic r0, r0, #0x00000007       @ 使用 bic 位清除指令, 将 R0 寄存器中的 第 0, 1, 2 三位 设置成0, 代表 关闭 MMU 和 D-Cache
  mcr p15,0,r0,c1,c0,0        @ 将 R0 寄存器中的值写回到 C1 寄存器中
  mov pc, lr          @ 返回到 返回点处 继续执行后面的代码
set_serial_port : 
  ldr r0, =0x70000000        @ 将基地址装载到 r0 寄存器中, 该基地址 在 arm 核 手册中定义
  orr r0, r0, #0x13        @ 设置初始化基地址的范围, 将 r0 中的值 与 0x13 立即数 进行或操作, 将结果存放到 r0 中
  mcr p15, 0, r0, c15, c2, 4      @ 将 r0 中的值设置给 c15 协处理器 
  mov pc, lr
#define CLK_DIV0 0x7E00F020       @ 定义 CLK_DIV0 寄存器地址, 时钟的分频参数都是通过该寄存器进行设置的 
#define OTHERS 0x7E00F900       @ 定义 OTHERS 寄存器地址, 用于设置 CPU 异步工作模式
#define CLK_VAL ( (0x0 << 0) | (0x1 << 9) | (0x1 << 8) | (0x3 << 12) ) @ 设置 CLK_DIV0 寄存器的值, 即 各个时钟分频器的参数
#define MPLL_CON 0x7E00F010       @ 定义 MPLL_CON 寄存器地址常量
#define APLL_CON 0x7E00F00C       @ 定义 APLL_CON 寄存器地址常量
#define PLL_VAL ( (0x1 << 31) | (266 << 16) | (3 << 8) | (1 << 0) ) @ 设置 PLL 控制寄存器的值
#define CLK_SRC 0x7E00F01C        @ 定义 CLK_SRC 时钟源控制寄存器的地址常量
init_clock : 
  ldr r0, =CLK_DIV0        @ 将 CLK_DIV0 的地址装载到 r0 通用寄存器中
  ldr r1, =CLK_VAL          @ 将 要设置给 CLK_DIV0 寄存器的值 CLK_VAL 立即数 装载到 r1 通用寄存器中; 
  str r1, [r0]          @ 将 r1 寄存器中的内容 存储到 r0 存储的地址 指向的内存中
  ldr r0, =OTHERS         @ 将 OTHERS 寄存器地址存到 r0 通用寄存器中
  ldr r1, [r0]          @ 将 r0 寄存器存储的地址指向的寄存器中的值读取到 r1 通用寄存器中
  bic r1, r1, #0xc0        @ 将 r1 寄存器中的值的 第 6 位 和 第 7 位 设置成 0
  str r1, [r0]          @ 将 r1 寄存器中的值 写出到 r0 寄存器存储的地址指向的内存位置 即 OTHERS 寄存器
  ldr r0, =APLL_CON        @ 将 APLL_CON 寄存器地址存到 r0 通用寄存器中
  ldr r1, =PLL_VAL        @ 将 要设置给 APLL_CON 寄存器的值 PLL_VAL 立即数 装载到 r1 通用寄存器中;
  str r1, [r0]          @ 将 r1 寄存器中的内容 存储到 r0 存储的地址 指向的内存中, 即 将 PLL_VAL 的值 设置到 APLL_CON 寄存器中
  ldr r0, =MPLL_CON        @ 将 MPLL_CON 寄存器地址存到 r0 通用寄存器中
  ldr r1, =PLL_VAL                                @ 将 要设置给 MPLL_CON 寄存器的值 PLL_VAL 立即数 装载到 r1 通用寄存器中;
  str r1, [r0]                                    @ 将 r1 寄存器中的内容 存储到 r0 存储的地址 指向的内存中, 即 将 PLL_VAL 的值 设置到 MPLL_CON 寄存器中
  ldr r0, =CLK_SRC        @ 将 CLK_SRC 寄存器地址设置到 r0 通用寄存器中
  mov r1, #0x3          @ 将 0x3 立即数设置给 r1 寄存器
  str r1, [r0]          @ 将 r1 中存储的立即数设置给 r0 寄存器存储的地址指向的内存中, 即 CLK_SRC 寄存器中
  mov pc, lr
copy_to_ram:
  ldr r0, =0x0c000000        @ 设置 代码搬移 起始地址 首地址 , 即 SRAM 垫脚石的 首地址 , 将改地址存放在 r0 寄存器中
  ldr r1, =0x50008000        @ 设置 代码搬移 终点 首地址 , 即 内存的首地址 , 将该地址存放在 r1 寄存器中
  add r3, r0, #1024*4        @ 设置 复制多少指令到 内存中 , 这里复制 4KB 数据 从 SRAM 到 内存 中 ; 
copy_loop:            @ 循环复制代码
  ldr r2, [r0], #4        @ 取出 r0 寄存器的地址 ( 即 SRAM 中的地址 ) 中的数据 放入 r2 寄存器  , 读取完毕后 , r0 中的地址 累加 4
  str r2, [r1], #4        @ 将 r2 中的内容 , 写入到 r1 寄存器对应的地址中 , 写出完毕后 , r1 中的地址 累加 4 
  cmp r0, r3          @ 查看 r0 地址 增量 是否 增加了 4KB , 到了代码搬移的末尾
  bne copy_loop         @ 如果 r0 r3 地址不一致 , 说明还没拷贝完毕 , 继续 跳转回 copy_loop 标号 拷贝
  mov pc, lr
#define GPBCON 0x7F008820
#define GPBDAT 0x7F008824
light_led : 
  ldr r0, =GPBCON            @ 将 0x7F008820 GPM 控制寄存器的地址 0x7F008820 装载到 r0 寄存器中
  ldr r1, =0x1111          @ 设置 GPM 控制寄存器的行为 为 Output 输出, 即每个对应引脚的设置为 0b0001 值
  str r1, [r0]          @ 将 r1 中的值 存储到 r0 指向的 GPBCON 0x7F008820 地址的内存中
  ldr r0, =GPBDAT         @ 将 GPBDAT 0x7F008824 地址值 装载到 r0 寄存器中
  ldr r1, =0b110101        @ 计算 GPM 数据寄存器中的值, 设置 0 为 低电平, 设置 1 为高电平, 这里设置 0 ~ 3 位为低电平, 其它为高电平
  str r1, [r0]          @ 将 r1 中的值 存储到 r0 指向的 GPBDAT 0x7F008824 地址的内存中
  mov pc, lr









( 3 ) mem.S ( 内存初始化 )


@****************************  
@File:mem.S  
@  
@内存 初始化代码 
@****************************  
.text                               @ 宏 指明代码段  
.global mem_init                    @ 伪指令  mem.S 可以理解成一个函数 , 该函数由 start.S 进行调用 , 它必须是一个全局的
mem_init:       @ 定义内存初始化的标号 , 在 start.S 中进行调用
          @ 设置 MEM_SYS_CFG 寄存器中的 [ 7 ] 位 , 设置 XmlDATA [31 : 16] pin 脚作用
          @ 这些 pin 脚 用于作为 内存输出的 数据线 的
          @ 如果 该位 为 0 , 那么 就作为 [ 31 : 16 ] 位的数据线引脚 , 这里设置为 0 即可
    ldr r0, =0x7e00f120    
    mov r1, #0x0
    str r1, [r0]
          @ 步骤一 : DRAM 控制器进入配置状态
  ldr r0, =0x7e001004    @ 将 DRAM CONTROLLER COMMAND REGISTER 寄存器地址装在到 r0 中
    mov r1, #0x4      @ 设置 DRAM 控制命令寄存器 ( DRAM CONTROLLER COMMAND REGISTER  ) 值 0x4 进入配置 ( Config ) 状态
    str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中
          @ 步骤二 : 设置一系列寄存器
    ldr r0, =0x7e001010     @刷新寄存器地址
    ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) )      @设置刷新时间
    str r1, [r0]
    ldr r0, =0x7e001014     @CAS latency寄存器
    mov r1, #(3 << 1)
    str r1, [r0]
    ldr r0, =0x7e001018     @t_DQSS寄存器
    mov r1, #0x1
    str r1, [r0]
    ldr r0, =0x7e00101c     @T_MRD寄存器
    mov r1, #0x2
    str r1, [r0]
    ldr r0, =0x7e001020      @t_RAS寄存器
    ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e001024      @t_RC寄存器
    ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e001028      @t_RCD寄存器
    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e00102c      @t_RFC寄存器
    ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e001030      @t_RP寄存器
    ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e001034      @t_rrd寄存器
    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e001038      @t_wr寄存器
    ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
 @  ldr r2, [r0]
    str r1, [r0]
    ldr r0, =0x7e00103c      @t_wtr寄存器
    mov r1, #0x07
    str r1, [r0]
    ldr r0, =0x7e001040      @t_xp寄存器
    mov r1, #0x02
    str r1, [r0]
    ldr r0, =0x7e001044      @t_xsr寄存器
    ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e001048      @t_esr寄存器
    ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
    str r1, [r0]
    ldr r0, =0x7e00100c      @内存控制配置寄存器
    ldr r1, =0x00010012      @配置控制器
    str r1, [r0]
    ldr r0, =0x7e00104c      @32位DRAM配置控制寄存器
    ldr r1, =0x0b45
    str r1, [r0]
    ldr r0, =0x7e001200      @片选寄存器
    ldr r1, =0x150f8
    str r1, [r0]
    ldr r0, =0x7e001304      @用户配置寄存器
    mov r1, #0x0
    str r1, [r0]        
          @ 步骤三 : 可以不执行 , 等待 电压 和 时钟稳定下来 , 但是电压和时钟本来就是稳定的
          @ 步骤四 : 内存初始化
          @ 步骤四 : 内存初始化 1. 写入 NOP 命令 : 
          @ 执行过程 : 向 Direct Command Register 的 Memory Command [19:18] 域中写入 0b11
          @ 整体值为 0b 11 00 0000 0000 0000 0000 , 转为 16 进制为 0xC0000
  ldr r0, =0x7e001008    @ 装载 DIRECT COMMAND REGISTER 寄存器 地址到 r0 寄存器中
  ldr r1, =0xc0000    @ 装载 要写入的值 到 r1 寄存器中
  str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中
          @ 步骤四 : 内存初始化 2. 写入 Precharge All 命令 : 
          @ 执行过程 : 向 Direct Command Register 的 Memory Command [19:18] 域中写入 0b00
          @ 整体值为 0b 00 00 0000 0000 0000 0000 , 转为 16 进制为 0x0
  ldr r0, =0x7e001008    @ 装载 DIRECT COMMAND REGISTER 寄存器 地址到 r0 寄存器中
  ldr r1, =0x0      @ 装载 要写入的值 到 r1 寄存器中
  str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中
          @ 步骤四 : 内存初始化 3 , 4 . 写入 Autorefresh 命令 : 该步骤执行两次
          @ 执行过程 : 向 Direct Command Register 的 Memory Command [19:18] 域中写入 0b01
          @ 整体值为 0b 01 00 0000 0000 0000 0000 , 转为 16 进制为 0x40000
  ldr r0, =0x7e001008    @ 装载 DIRECT COMMAND REGISTER 寄存器 地址到 r0 寄存器中
  ldr r1, =0x40000    @ 装载 要写入的值 到 r1 寄存器中
  str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中  
  ldr r0, =0x7e001008    @ 装载 DIRECT COMMAND REGISTER 寄存器 地址到 r0 寄存器中
  ldr r1, =0x40000    @ 装载 要写入的值 到 r1 寄存器中
  str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中  
          @ 步骤四 : 内存初始化 5. 写入 MRS 命令 : ( EMRS )
          @ 执行过程 : 向 Direct Command Register 的 Memory Command [19:18] 域中写入 0b10
          @ 同时还需要设置 Bank Address , 该步骤设置的是 EMRS 的 Bank Address
          @ 整体值 转为 16 进制为 0xa0000
  ldr r0, =0x7e001008    @ 装载 DIRECT COMMAND REGISTER 寄存器 地址到 r0 寄存器中
  ldr r1, =0xa0000    @ 装载 要写入的值 到 r1 寄存器中
  str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中  
          @ 步骤四 : 内存初始化 6. 写入 MRS 命令 : ( MRS )
          @ 执行过程 : 向 Direct Command Register 的 Memory Command [19:18] 域中写入 0b10, 
          @ 同时还需要设置 Bank Address , 该步骤设置的是 MRS 的 Bank Address
          @ 整体值 转为 16 进制为 0x80032
  ldr r0, =0x7e001008    @ 装载 DIRECT COMMAND REGISTER 寄存器 地址到 r0 寄存器中
  ldr r1, =0x80032    @ 装载 要写入的值 到 r1 寄存器中
  str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中  
          @ 步骤五 : DRAM 控制器进入 Ready 状态
  ldr r0, =0x7e001004    @ 将 DRAM CONTROLLER COMMAND REGISTER 寄存器地址装在到 r0 中
    mov r1, #0x0      @ 设置 DRAM 控制命令寄存器 ( DRAM CONTROLLER COMMAND REGISTER  ) 值 0x0 进入配置 ( Ready ) 状态
    str r1, [r0]      @ 将 r1 装载到 r0 所指向的内存地址对应的空间中
          @ 步骤六 : 检查 DRAM 控制器 是否 进入 Ready 状态
check_ready:
    ldr r0, =0x7e001000    @ 将 DRAM CONTROLLER STATUS REGISTER 地址 装载到 r0 寄存器中
    ldr r1, [r0]      @ 将 r0 寄存器存储的地址对应的内存中的内容装载到 r1 寄存器中 , 这个 DRAM CONTROLLER STATUS REGISTER 寄存器的值就获取到了
    mov r2, #0x3      @ 将 立即数 3 设置给 r2 寄存器中, 用于 与操作 , 获取最后的 两位 二进制数值
    and r1, r1, r2      @ 将 r1 ( 第二个 ) 与 r2 进行 与 操作 , 将结果放入 r1 ( 第一个 ) 寄存器中
    cmp r1, #0x1      @ 将 与 结果 与 0x1 进行比较 , 如果相等 继续执行 , 如果不相等, 跳转到 check_ready 继续执行判定操作
    bne check_ready     @ 如果不相等, 跳转到 check_ready 继续执行判定操作
    nop
    mov pc, lr

 









( 4 ) u-boot.lds ( 链接器脚本 )


OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS {
  . = 0x50008000;
  . = ALIGN(4);
  .text :
  {
  start.o (.text)
  *(.text)
  }
  . = ALIGN(4);
  .data : 
  {
  *(.data)
  }
  . = ALIGN(4);
  bss_start = .;
  .bss : 
  {
  *(.bss) 
  }
  bss_end = .;
}


( 5 ) Makefile ( 编译脚本 )


all: start.o mem.o
  arm-linux-ld -Tu-boot.lds -o u-boot.elf $^  
  arm-linux-objcopy -O binary u-boot.elf u-boot.bin 
%.o : %.S
  arm-linux-gcc -g -c $^
%.o : %.c
  arm-linux-gcc -g -c $^
.PHONY: clean 
clean:
  rm *.o *.elf *.bin







2. 编译输出可执行文件

编译过程 :


1.文件准备 : 将 汇编代码 ( start.S ) 链接器脚本 ( gboot.lds ) makefile 文件 拷贝到编译目录 ;

2.执行编译命令 : make ;

3.编译结果 : 可以看到 生成了 编译目标文件 start.o, 链接文件 u-boot.elf, 可执行的二进制文件 u-boot.bin ;


image.png


3. 烧写代码到开发板并执行


( 1 ) OK6410 开发板启动切换方式

OK6410 开发板启动切换方式 : 通过控制 开发板右侧的 8个开关来设置启动来源;


1.sd 卡启动 : (1~8) 位置 : 0, 0, 0, 1, 1, 1, 1, 1;

2.nand flash 启动 : (1~8) 位置 : x, x, x, 1, 1, 0, 0, 1;

3.nor flash 启动 : (1~8) 位置 : x, x, x, 1, 0, 1, 0, x;


( 2 ) 制作 SD 卡启盘 并 准备程序

制作 SD 卡启动盘 :

image.png

1.找到开发板的烧写工具 : OK6410-A 开发板的烧写工具 在开发光盘 A 的 OK6410-A-1G用户光盘(A)-20160812\Linux-3.0.1\Linux烧写工具 目录下, 开发板光盘资料下载地址 ;


2.设置 SD_Writer.exe 属性 ( win10系统需要进行的设置 ) : 右键点击属性, 在兼容性一栏, 设置 以 Windows 7 兼容模式运行, 并设置 以管理员身份运行此程序 ; 注意 一定要 使用管理员身份 运行 , 否则报错 , 报错信息 Select Volume Error , 无法格式化SD卡 , 无法烧写 程序 ;

image.png

3.先格式化 SD 卡 : 注意这里要使用 SD_Writer 中的 format 功能进行格式化 , 按照下面的步骤, 一步一步点击确定执行 ;


image.png


4.选择要烧写的文件 : 这里选择 OK6410-A-1G用户光盘(A)-20160812\Linux-3.0.1\Linux烧写工具\mmc_ram256.bin 文件;

5.烧写文件到 SD 卡中 : 直接点击 Program 按钮, 就将启动程序烧写到了 SD 卡中;

image.png

6.准备 LED 灯程序 : 将编译出的 gboot.bin 文件名修改成 u-boot.bin, 必须修改成该文件名, 否则无法烧写上去;

7.将程序拷贝到 SD 卡中 : 将程序直接拷贝到 SD 卡中即可;

参考资料 : OK6410烧写裸板程序方法

这是之前写过的博客, 仅作为参考;


目录
相关文章
|
3月前
|
网络协议 C++
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
|
4月前
|
存储 算法 程序员
神秘代码世界惊现高效秘籍!究竟是什么让汇编语言编程如此强大?快来一探究竟!
【8月更文挑战第31天】《代码之美:探索高效汇编语言编程的最佳实践》介绍了汇编语言在系统内核、嵌入式系统及高性能应用中的不可替代作用。书中强调了深入理解处理器架构、提升代码可读性、优化算法与数据结构及有效利用寄存器等最佳实践的重要性。通过具体示例,如在 x86 架构下实现高效的加法函数,展示了如何运用这些技巧编写出既高效又可靠的汇编代码,充分展现了汇编语言的独特魅力及其在现代软件开发中的价值。
46 0
|
3月前
|
Windows
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
|
4月前
|
NoSQL 前端开发 程序员
【震撼揭秘!】程序员绝不会告诉你的秘密:掌握汇编语言调试,轻松从软件故障中全身而退——透视代码底层,成为Bug猎人!
【8月更文挑战第31天】《调试的艺术:如何利用汇编语言追踪和解决软件问题》探讨了使用汇编语言进行高效调试的方法。无论是初学者还是资深开发者,面对棘手的 bug 时,高级语言的信息往往不足。文章通过具体示例展示如何通过汇编代码定位问题,如 C 语言中数组求和函数的崩溃问题。借助 `gcc -S` 生成的汇编代码和 GDB 调试器,可以深入理解程序行为,从而更准确地解决问题。掌握这一技能,将使你在复杂问题面前更加从容。
44 2
|
4月前
|
C语言
51单片机汇编语言流水灯代码
51单片机汇编语言流水灯代码
|
3月前
ARM地址对齐访问笔记
ARM地址对齐访问笔记
|
4月前
|
C# 开发者 图形学
Xamarin 竟在游戏开发领域大胆探索,跨平台优势与强大功能结合,开启游戏开发新潮流!
【8月更文挑战第31天】《Xamarin在游戏开发领域的探索》介绍了Xamarin作为跨平台开发框架,在移动游戏开发中的应用。它利用C#语言的优势,提供高效的开发体验,并结合各平台图形库实现高质量画面。本文还展示了Xamarin如何简化游戏逻辑处理、支持多线程编程及与Unity等工具集成,提升游戏质量和开发效率。此外,Xamarin还支持热更新和多平台发布,进一步优化游戏维护流程。
44 0
|
7月前
|
存储 Unix 编译器
汇编语言----X86汇编指令
汇编语言----X86汇编指令
256 2
|
2月前
|
存储 移动开发 C语言
【ARM汇编速成】零基础入门汇编语言之指令集(三)
【ARM汇编速成】零基础入门汇编语言之指令集(三)