文章目录






本博客的参考文章及相关资料下载 :

  • 1.本博客代码及参考手册下载



一. 时钟相关概念解析




1. 相关概念术语



( 1 ) 时钟脉冲信号 ( 概念 : 电压幅度 时间间隔 形成脉冲 | 作用 : 时序逻辑基础 间隔固定 根据脉冲数量可计算出时间 )


时钟脉冲信号 :

【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK


  • 1.概念 :​ 按照 ​一定的电压幅度​ 和 ​一定的时间间隔​ , ​连续发出的 脉冲信号​, 就是 时钟 脉冲信号;
  • 2.重要作用 :​ 时钟脉冲信号 是 ​时序逻辑的 基础​, 脉冲信号的 ​间隔是固定的​, 可以 ​根据脉冲信号的个数 及 间隔 计算出对应的时间​ ;
  • 3.应用场景 :​ 芯片 中的 晶体管 工作状态 都是由 0 1 组成, 即 开和关, 控制这些开关操作都是 ​按照 时钟信号 的 节奏 进行​ 的;
  • 4.说明示例 :​ 现在的主流 CPU i7 8700K 主频是 ​3.7GHz​, 其中 ​1 GHz = 10^3 MHz = 10^6 KHz = 10^9 Hz 即 10亿 Hz​, ​每秒钟有 37亿 次时钟脉冲信号​; 也就是 经常说的 每秒钟 运算 37 亿次; 当前的超级计算机可以到达 每秒 2亿亿次;



( 2 ) 时钟脉冲频率 ( 概念 : 单位时间内产生的脉冲个数 )


时钟脉冲频率 :


  • 1.概念 :​ ​单位时间内 产生 的 时钟脉冲个数​ 就是 时钟脉冲频率;
  • 2.举例 :​ 1秒中 产生 1次, 就是 1Hz, 1秒钟产生 100 次就是 100Hz, 上面举例的 i78700K CPU, 一秒钟产生 37亿次, 就是 3.7GHz 的时钟脉冲频率;



(3) 时钟源 ( 产生来源 : ① 晶振 ② 锁相环 PLL | 晶振 : 晶体震荡电路 | PLL 锁相环 : 晶振 + PLL 合成 | 晶振 与 PLL 对比 优缺点 )


时钟源 :​ 时钟脉冲信号 是由 晶振 或 锁相环 PLL 产生;


  • 1.晶振 :​ 全称 ​晶体振荡器​, 是由 石英晶体 制作的, 石英晶体 ​① 按照一定的方位角 切割​, 并 ​② 在其内部添加电子元件组成振荡电路​;

  • ① 震荡特性 :​ 如果 ​给晶振通电, 就会产生机械震荡​, 其 ​频率由 制作的材质, 切割角度 等决定​;
  • ② 物理特性 :​ 石英非常 ​稳定​, 其控制的 ​震荡频率也很稳定​, 其 ​频率可以根据集合尺寸精确控制​;
  • ③ 晶振优势 :​ 晶振具有 ​A. 结构简单, B. 噪音低, C. 可提供精确定制的频率​, 等优点;
  • ④ 晶振缺陷 :​ ​A. 生产成本高 , B. 交货的周期很长;

  • 2.PLL(锁相环) :​ 锁相环 比 晶振 更复杂, ​PLL 需要一个外部晶振作为输入​, PLL 可以对外部晶振产生的频率进行 ​加倍 或 分频 操作​, 即 提高 或 降低 频率;

  • ① 使用场景 :​ 简单系统一般采用 ​石英晶振​, 复杂的系统采用 ​晶振 + PLL 合成​ 提供时钟源;
  • ② 降低成本 :​ 如果需要特定的时钟频率, 可以使用 PLL + 低频晶振 代替高频的晶振 , 这样成本比较低;
  • ③ 多时钟频率系统 :​ 如果 ​在一个设备上需要多个时钟频率系统​, ​可以使用 PLL + 晶振 合成提供时钟源​, ​PLL 将 晶振频率 进行 加倍 或 分频 即可得到不同频率的时钟源​;
  • ④ 与晶振对比 :​ ​PLL + 晶振 比 纯晶振 成本要低, 并且提供更加灵活多变的时钟频率​ ;






二. 时钟体系简介




时钟体系学习步骤​ : 对不不同的时钟体系, 需要按照下面的学习步骤学习即可;
① 晶振频率 ;② PLL 个数 及 种类 ;③ PLL 产生的时钟类型;④ PLL 产生的时钟作用;




1. 2440 开发板 时钟体系



参考手册 :​ ​S3C2440.pdf​ , ​章节 : 7 CLOCK & POWER MANAGEMENT​ , ​Page 235​;



(1) 2440 开发板时钟体系介绍 ( 12MHz 晶振 | 2 PLL : ① MPLL ② UPLL | MPLL -> ① FCLK [ ARM 核 ] ② HCLK [ AHB 总线 ] ③ PCLK [ APB 总线 ] | UPLL -> UCLK [ USB 总线 ] )


2440 开发板时钟体系介绍 :


  • 1.晶振频率 :​ 12MHz;
  • 2.PLL (锁相环) :​ 有 2 个 PLL, 分别是 MPLL 和 UPLL;
  • 3.产生时钟个数 :​ ① ​MPLL​ 锁相环 产生出 ​FCLK , HCLK, PCLK​ 三个时钟; ② ​UPLL​ 锁相环 产生出 ​UCLK​ 时钟;
  • 4.各个时钟作用 :

  • ① FCLK 时钟作用 :​ 处理器 中使用, ARM 核使用的时钟是 FCLK, 该时钟是 MPLL 产生的;
  • ② HCLK 时钟作用 :​ AHB 总线中使用, 如 LCD, DMA 控制, 该时钟是 MPLL 产生的;
  • ③ PCLK 时钟作用 :​ APB 总线中使用, 如 Uart 串口, GPIO, 该时钟是 MPLL 产生的;
  • ④ UCLK 时钟作用 :​ USB 总线中使用, 该时钟是 UPLL 产生的;

  • 5.2440 时钟体系图示 :​ 该图在 S3C2440.pdf 文档中的 7 CLOCK & POWER MANAGEMENT 章节, 237 页 ;

【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK_02



(2) 6410 开发板时钟体系介绍 ( 12MHz 晶振频率 | 3 PLL : ① APLL ② MPLL ③ EPLL | APLL -> ACLK [ ARM 核 ] | MPLL -> ① HCLK [ AHB 总线 ] ② PCLK [ APB 总线 ] | EPLL -> SCLK [ USB 总线 ] )



参考手册 :​ ​S3C6410X.pdf​ , ​章节 : 3.3.4.1 Clock selection between PLLs and input reference clock​ , ​Page 124​;


6410 开发板时钟体系介绍 :


  • 1.晶振频率 :​ 12MHz;
  • 2.PLL (锁相环) :​ 有 3 个 PLL, 分别是 APLL , MPLL 和 EPLL;
  • 3.产生时钟个数 :​ ① ​APLL​ 锁相环 产生出 ​ACLK​ 一个时钟; ② ​MPLL​ 锁相环 产生出 ​HCLK, PCLK​ 时钟; ③ ​EPLL​ 产生 ​SCLK​ 时钟;
  • 4.各个时钟作用 :

  • ① ACLK 时钟作用 :​ 处理器中使用, ​ARM核中使用 ACLK 时钟​, 该时钟是 APLL 锁相环产生;
  • ② HCLK 时钟作用 :​ ​AHB 总线中使用​, 如 LCD, DMA ; 该时钟是 MPLL 产生的;
  • ③ PCLK 时钟作用 :​ ​APB 总线中使用​, 如 Uart 串口, GPIO 中使用, 该时钟是 MPLL 产生的;
  • ④ SCLK 时钟作用 :​ ​USB 总线中使用​, 该时钟是 EPLL 锁相环产生的;

  • 5.6410时钟体系图示 : 该图在 S3C6410X.pdf 文档中的 3.3.4.1 Clock selection between PLLs and input reference clock 章节, 124 页 ;

【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PLL_03


(3) S5PV210 开发板时钟体系介绍 ( 24MHz 晶振频率 | 4 PLL ① APLL ② MPLL ③ EPLL ④ VPLL )



参考手册 :​ ​S5PV210_UM_REV1.1.pdf​ , ​章节 : 3.4 CLOCK GENERATION​ , ​Page 361​;


S5PV210 开发板时钟体系介绍 :


  • 1.晶振频率 :​ 24MHz;
  • 2.PLL (锁相环) :​ 有 4 个 PLL, 分别是 ​APLL​ , ​MPLL​ , ​EPLL​ 和 ​VPLL​;
  • 3.S5PV210 的 时钟体系分类​ : 分为 以下 三类 ;


    • ① 主系统时钟体系 :​ MSYS , 由 ​APLL​ 锁相环产生, 产生的时钟有 ​ARMCLK, HCLK_MSYS, PCLK_MSYS​ , 应用在 ARM 核 中;
    • ② 显示相关时钟体系 :​ DSYS , 由 ​MPLL​ 锁相环产生, 产生的时钟有 ​HCLK_DSYS, PCLK_DSYS​, 主要应用在显示相关的部件中 ;
    • ③ 外围设备时钟体系 :​ PSYS , 由 ​EPLL​ 锁相环产生, 产生的时钟有 ​HCLK_PSYS, CLK_DPM​, 主要用于外设, 如 Uart 串口 等;
    • ④ VPLL 锁相环产生的时钟 :​ ​VPLL​ 产生的时钟 主要用于​视频处理​;


  • 4.S5PV210时钟体系图示 :​ 该图在 S5PV210_UM_REV1.1.pdf 文档中的3.4 CLOCK GENERATION, 361 页 ;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_04





三. S3C6410 初始化时钟




1. S3C 6410 时钟初始化流程简介



(1) CPU 频率变化过程 ( ① 上电后 12MHz | ② 配置 PLL | ③ 处于 Lock Time 频率 0Hz | ④ 正常 PLL 频率 )



CPU 上电后 从 低频率 到 高频率的变化过程 :


  • 1.上电后的工作频率 :​ ​上电后 ARM 核的工作频率就是晶振频率, 即 12MHz, 这个速度非常慢​;
  • 2.配置锁相环 :​ ​配置锁相环​, ​使 频率 增加​;
  • 3.Lock Time 时间 :​ 配置 PLL 锁相环后, 会​出现一段不工作的时间​, 此时 ​CPU 频率为 0Hz​, 这段时间叫 ​Lock Time​;
  • 4.正常频率 :​ 在 Lock Time 之后, 就会进入正式的 ​锁相环 工作频率​, ​此时的频率是 晶振频率 经过 锁相环 处理后的 高频率​;
  • 5.图示 :​ 下图是处理器上电后各种参数的变化, 横轴是时间轴, 没有纵轴, 各个参数在上电后的每个时间段的表现;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_05


整个时钟初始化流程是需要软件帮助进行的, 因此这些步骤需要开发者进行开发, 这也是该博客的主要内容;




(2) 时钟初始化的四个步骤 ( ① 配置 Lock Time | ② 设置分频系数 | ③ 设置 APLL MPLL 频率 | ④ 设置 CPU 工作模式 -> 异步工作模式 )


时钟初始化流程 :


  • 1.配置 Lock Time :​ ​配置 PLL 锁相环后会有一段 CPU 频率为 0 的时间​, 这段时间处理器不工作, 这段时间就是 Lock Time;
  • 2.设置分频系数 :​ 通过 ​为 不同的时钟设置不同的分频系数​, ​根据这个分频系数, 来确定每个时钟的频率​;
  • 3.设置 APLL MPLL 频率 :​ ​设置一个时钟的频率, 可以根据分频系数计算出其它所有时钟的频率了​;
  • 4.设置 CPU 工作模式 :如果 FCLK 与 HCLK 的频率不同​, 那么 ​CPU 需要设置为 异步工作模式​, FCLK 是 ARM 核的时钟, HCLK 是 总线时钟, 如果两个时钟不一致, 需要将 CPU 设置为 异步工作模式;
  • ① 常用设置 :​ 一般情况下 设置 分频系数的时候, 不会给 FCLK 与 HCLK 设置相同的分频系数, 因此, 该步骤大部分情况下都要执行;




2. S3C 6410 时钟初始化 汇编代码编写



参考手册 :​ ​ ARM芯片 手册 S3C6410X.pdf ( 基于 6410 开发板 ARM 11 )


  • 1.手册对应章节 :​ ​3 SYSTEM CONTROLLER​;
  • 2.S3C6410X.pdf手册下载地址 :


(1) 配置 Lock Time


配置 Lock Time :


  • 1.文档位置 :​ ​S3C6410X.pdf​ 手册, ​Page 141​, ​3.4.2.1 PLL Control Registers​ 章节;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_06
  • 2.默认设置不变 ( 推荐 ) :​ 一般情况下, 使用开发板的默认设置即可, 如果有特殊定制需求才修改该 PLL_LOCK 寄存器的值;



(2) 设置分频系数


设置分频系数 :


  • 1.相关文档位置 :​ ​S3C6410X.pdf​ 手册, ​Page 125​, ​3.3.4.2 ARM and AXI/AHB/APB bus clock generation​ 章节;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_MPLL_07
  • 2.APLL 锁相环 :​ 12 MHz 的晶振频率, 经过 APLL 锁相环 产生 ​输出时钟​, 该输出时钟 经过 ​DIV​ARM​ 分频, 产生 ​ARMCLK​, 这是 ARM 核使用的时钟;
  • 3.MPLL 锁相环 :​ 12MHz 晶振频率时钟, 经过 MPLL 锁相环 产生的 时钟, 该时钟 经过 ​DIV​HCLKX2​ 分频后, 产生 ​HCLKx2 时钟​, 同时 ​DIV​HCLKX2​ 分频后的时钟 又 经过不同的 分频 产生 ​HCLK, PCLK, CLKJPEG, CLKSECUR​ 时钟;


    • ① HCLK 时钟 :​ HCLKx2 时钟 经过 ​DIV​HCLK​ 分频后, 产生 ​HCLK​ 时钟;
    • ② PCLK 时钟 :​ HCLKx2 时钟 经过 ​DIV​PCLK​ 分频后, 产生 ​PCLK​ 时钟;
    • ③ CLKJPEG 时钟 :​ HCLKx2 时钟 经过 ​DIV​CLKJPEG​ 分频后, 产生 ​CLKJPEG​ 时钟;
    • ④ CLKSECUR 时钟 :​ HCLKx2 时钟 经过 ​DIV​CLKSECUR​ 分频后, 产生 ​CLKSECUR​ 时钟;


  • 4.分频参数参考 :​ 不同的时钟分频器的分频参数列表 , 来源 ​S3C6410X.pdf​ 手册, ​Page 126​, ​3.3.4.2 ARM and AXI/AHB/APB bus clock generation​ 章节;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_08
  • 5.时钟分频公式 :​ 文档位置 ​S3C6410X.pdf​ 手册, ​Page 126​, ​3.4.2.3 Clock divider control register​ 章节;


    • ① DIV​ARM​ 分频公式 :​ ​ARMCLK = DOUTAPLL / (ARM_RATIO + 1)​ , DOUTAPLL 是 APLL 锁相环输出的时钟, ARM_RATIO 是设置的分频系数;
    • ② DIV​HCLKX2​ 分频公式 :​ ​HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1)​, HCLKX2IN 是 MPLL 锁相环的输出时钟频率, HCLKX2_RATIO 是设置的分频系数;
    • ③ DIV​HCLK​ 分频公式 :​ ​HCLK = HCLKX2 / (HCLK_RATIO + 1)​, HCLKX2 是 DIV​HCLKX2​ 分频后的时钟频率, HCLK_RATIO 是设置的分频系数;
    • ④ DIV​PCLK​ 分频公式 :​ ​PCLK = HCLKX2 / (PCLK_RATIO + 1)​, HCLKX2 是 DIV​HCLKX2​ 分频后的时钟频率, PCLK_RATIO 是设置的分频系数;


  • 6.PLL 锁相环输出频率 :


    • ① APLL 锁相环输出频率 :​ 533 MHz ;
    • ② MPLL 锁相环输出频率 :​ 533 MHz ;


  • 7.具体参考参数设置 :​ 从 6410 开发板中的 u-boot 源码中查找相关的时钟 分频系数 ;


    • ① DIV​ARM​ 分频参数 :​ 0 , APLL 输出频率为 533MHz, 根据公式计算 ARMCLK 时钟频率为 533MHz;
    • ② DIV​HCLKX2​ 分频参数 :​ 1 , MPLL 输出频率 533MHz, 根据公式计算 HCLKX2 时钟为 266 MHz;
    • ③ DIV​PCLK​ 分频参数 :​ 3 , HCLKX2 时钟为 266 MHz, PCLK 频率为 66MHz;
    • ④ DIV​HCLK​ 分频参数 :​ 1 , HCLKX2 时钟为 266 MHz, HCLK 频率为 133MHz;




设置分频系数代码编写 :


  • 1.定义分频控制寄存器( Clock divider control register ) 地址 :​ 之前说的 分频参数 都是通过 CLK_DIV0 寄存器设置的, 将 CLK_DIV0 的地址定义成常量, ​​#define CLK_DIV0 0x7E00F020​​;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PLL_09
  • 2.定义分频参数的值 :​ 参考 CLK_DIV0 值的表格 设置 CLK_DIV0 寄存器的实际值;


    • ① 定义 ARM_RATIO 分频参数 :​ 这个参数设置成 0, CLK_DIV0 寄存器的 [3:0] 位 设置该参数, 该参数单独为 ​0x0 << 0​;
    • ② 定义 HCLKX2_RATIO 分频参数 :​ 这个参数设置成 1, CLK_DIV0 寄存器的 [11:9] 位 设置该参数, 值为 ​0x1 << 9​;
    • ③ 定义 HCLK_RATIO 分频参数 :​ 这个参数设置成 1, CLK_DIV0 寄存器的 [8] 位 设置该参数, 值为 ​0x1 << 8​;
    • ④ 定义 PCLK_RATIO 分频参数 :​ 这个参数设置成 3, CLK_DIV0 寄存器的 [15:12] 位 设置该参数, 值为 ​0x3 << 12​;
    • ⑤ 设置的值 :​ 将上面四个值汇总起来为 ​(0x0 << 0) | (0x1 << 9) | (0x1 << 8) | (0x3 << 12)​ ;
    • ⑥ 代码 :​ ​​#define CLK_VAL ( (0x0 << 0) | (0x1 << 9) | (0x1 << 8) | (0x3 << 12) )​​ ;
      【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_10


  • 3.装载 CLK_DIV0 地址到通用寄存器中 :​ ​​ldr r0, =CLK_DIV0​​;
  • 4.装载 CLK_DIV0 的寄存器值到通用寄存器中 :​ ​​ldr r1, =CLK_VAL​​;
  • 5.设置 CLK_DIV0 寄存器的值 :​ ​​str r1, [r0]​​, 将 r1 寄存器中的内容 存储到 r0 存储的地址 指向的内存中 ;
  • 6.截止到当前的汇编代码展示 :

#define CLK_DIV0 0x7E00F020             @ 定义 CLK_DIV0 寄存器地址, 时钟的分频参数都是通过该寄存器进行设置的 
#define CLK_VAL ( (0x0 << 0) | (0x1 << 9) | (0x1 << 8) | (0x3 << 12) ) @ 设置 CLK_DIV0 寄存器的值, 即 各个时钟分频器的参数
init_clock :
ldr r0, =CLK_DIV0 @ 将 CLK_DIV0 的地址装载到 r0 通用寄存器中
ldr r1, =CLK_VAL @ 将 要设置给 CLK_DIV0 寄存器的值 CLK_VAL 立即数 装载到 r1 通用寄存器中;
str r1, [r0] @ 将 r1 寄存器中的内容 存储到 r0 存储的地址 指向的内存中
mov pc, lr


(3) 设置 CPU 异步工作模式


设置 CPU 异步工作模式 :


  • 1.相关文档位置 :​ ​S3C6410X.pdf​ 手册, ​Page 169​, ​3.4.2.14 Others control register​ 章节;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_11
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_12
  • 2.Others control register 寄存器 [7] :​ 第 7 位 [7], 设置为 ​0 时工作在 异步模式​下, 设置为 ​1 时 工作在 同步模式​ 下;
  • 3.Others control register 寄存器 [6]​ : 第 6 位 用于选择 锁相环输出源, 设置为 0 选择 MPLL 锁相环 输出时钟, 设置为 1 选择 APLL 锁相环输出时钟, 注意 只有在 CPU 同步模式下才设置为1;


汇编代码编写 :


  • 1.定义 OTHERS 寄存器地址 :​ ​​#define OTHERS 0x7E00F900​​;
  • 2.将 OTHERS 寄存器地址存储到 r0 寄存器中 :​ ​​ldr r0, =OTHERS​​;
  • 3.读取 OTHERS 寄存器的值 :​ ​​ldr r1, [r0]​​, 即 将 r0 寄存器存储的地址指向的内存中的值 装载到 r1 通用寄存器中;
  • 4.设置寄存器值 :​ 将 r1 寄存器中存储的 OTHERS 寄存器的 6 和 7 位 清零, 设置 CPU 异步工作模式, 同时设置 MPLL 锁相环时钟输出, ​​bic r1, r1, #0xc0​​;
  • 5.设置 OTHERS 寄存器值 :​ ​​str r1, [r0]​​, 将 r1 通用寄存器中的值 存储到 r0 寄存器中保存的地址指向的内存中, 即 OTHERS 寄存器;
  • 6.截止到当前的汇编代码展示 :

#define CLK_DIV0 0x7E00F020             @ 定义 CLK_DIV0 寄存器地址, 时钟的分频参数都是通过该寄存器进行设置的 
#define OTHERS 0x7E00F900 @ 定义 OTHERS 寄存器地址, 用于设置 CPU 异步工作模式
#define CLK_VAL ( (0x0 << 0) | (0x1 << 9) | (0x1 << 8) | (0x3 << 12) ) @ 设置 CLK_DIV0 寄存器的值, 即 各个时钟分频器的参数
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 寄存器

mov pc, lr


(4) 设置 APLL 和 MPLL 时钟频率


设置 APLL 和 MPLL 时钟频率 :


  • **1.相关文档位置 : **​S3C6410X.pdf​ 手册, ​Page 141​, ​3.4.2.1 PLL Control Registers​ 章节;
  • 2.APLL 和 MPLL 控制寄存器 :​ 下面两张表格 分别说明了 两个 PLL 控制寄存器对应的地址, 以及寄存器每一位设置的值;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_13
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_14
  • 3.PLL 输出频率公式 :​ FOUT = MDIV X FIN / (PDIV X 2^SDIV), 该公式在 S3C6410X.pdf 文档 142 页, 由公式可以得到 PLL 输出频率由 MDIV , PDIV, SDIV 三个参数决定, 文档中给出了一个固定的表格示例, 这里我们选择 第 5 行的参数进行设置;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK_15


汇编代码编写 :


  • 1.定义 APLL_CON 寄存器地址常量 :​ ​​#define APLL_CON 0x7E00F00C​​ ;
  • 2.定义 MPLL_CON 寄存器地址常量 :​ ​​#define MPLL_CON 0x7E00F010​​ ;
  • 3.分析 PLL 控制寄存器要设置的位 :​ 我们要设置 533MHz 的 PLL 输出频率, APLL 和 MPLL 都输出 533MHz 的频率;


    • ① 533MHz 输出确定的参数 :​ MDIV 设置成 266, PDIV 设置 3, SDIV 设置 1;
      【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK_16
    • ② 寄存器值设置 :​ ​​#define PLL_VAL ( (0x1 << 31) | (266 << 16) | (3 << 8) | (1 << 0) )​​ ;


      • a. 启用 PLL :​ [31] 设置成 1 , 设置值为 1 << 31;
      • b. 设置 MDIV :​ [25:16] 位设置成 266, 设置值为 266 << 16;
      • c. 设置 PDIV :​ [13:8] 位 设置成 3, 值为 3 << 8 ;
      • d.设置 SDIV :​ [2:0] 位 设置成 1, 值为 1 << 0;
      • e. 最终值为 :​ ​​(0x1 << 31) | (266 << 16) | (3 << 8) | (1 << 0)​​ ;
        【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_14




  • 4.设置 APLL_CON 寄存器的值 :​ 首先将 APLL_CON 寄存器地址存储到 r0 寄存器中, 然后将 要设置的值 存储到 r1 寄存器中, 之后 使用 str 指令将 r1 寄存器的值 存储到 r0 寄存器中存储的地址指向的内存中, 即 ​将 PLL_VAL 值设置给 APLL_CON 寄存器​;

ldr r0, =APLL_CON 
ldr r1, =PLL_VAL
str r1, [r0]
  • 5.设置 MPLL_CON 寄存器的值 :​ 首先将 MPLL_CON 寄存器地址存储到 r0 寄存器中, 然后将 要设置的值 存储到 r1 寄存器中, 之后 使用 str 指令将 r1 寄存器的值 存储到 r0 寄存器中存储的地址指向的内存中, 即 ​将 PLL_VAL 值设置给 MPLL_CON 寄存器​;
ldr r0, =MPLL_CON 
ldr r1, =PLL_VAL
str r1, [r0]
  • 6.截止到当前的代码 :​ 目前已完成 ​① 分频参数设置,② CPU 异步模式设置, ③APLL 和 MPLL 时钟频率设置工作​;
#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 控制寄存器的值
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 寄存器中

mov pc, lr


(5) 设置 时钟源


时钟源设置 :

  • 1.相关文档位置 : ​S3C6410X.pdf​ 手册, ​Page 145​, ​3.4.2.2 Clock source control register​ 章节;

【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_18

  • 2.CLK_SRC 寄存器 :​ 控制时钟源;


    • ① 控制 APLL 时钟源 :​ [0] 位 控制 APLL 时钟源, 如果设置为 0 , 使用晶振作为时钟源, 如果设置为 1, 使用 APLL 输出的时钟作为时钟源;
    • ② 控制 MPLL 时钟源 :​ [1] 位 控制 MPLL 时钟源, 如果设置为 0 , 使用晶振作为时钟源, 如果设置为 1, 使用 MPLL 输出的时钟作为时钟源;
    • ③ 控制 EPLL 时钟源 :​ [2] 位 控制 EPLL 时钟源, 如果设置为 0 , 使用晶振作为时钟源, 如果设置为 1, 使用 EPLL 输出的时钟作为时钟源;
      【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK_19



汇编代码编写 :


  • 1.定义 CLK_SRC 寄存器地址常量 :​ ​​#define CLK_SRC 0x7E00F01C​​ ;
  • 2.设置 CLK_SRC 寄存器的值 :​ ​将 [1:0] 两位设置成 1;​ 首先将 CLK_SRC 寄存器地址存储到 r0 寄存器中, 然后将 要设置的值 0x3 立即数 存储到 r1 寄存器中, 之后 使用 str 指令将 r1 寄存器的值 存储到 r0 寄存器中存储的地址指向的内存中, 即 ​将 0x3 值设置给 CLK_SRC 寄存器​;

ldr r0, =CLK_SRC  
mov r1, #0x3
str r1, [r0]


(6) 代码示例


代码示例 :​ 截止到当前的代码示例 ​① 设置 MVC 模式 ② 外设基地址初始化, ③ 关闭看门狗, ④ 关闭中断, ⑤ 关闭 MMU, ⑥ 初始化时钟, ⑦ 打开 LED 发光二极管​;

@****************************  
@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
init_clock @ 跳转到 init_clock 标号, 执行时钟初始化操作
bl light_led @ 打开开发板上的 LED 发光二极管

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


#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, =0b110000 @ 计算 GPM 数据寄存器中的值, 设置 0 为 低电平, 设置 1 为高电平, 这里设置 0 ~ 3 位为低电平, 其它为高电平
str r1, [r0] @ 将 r1 中的值 存储到 r0 指向的 GPBDAT 0x7F008824 地址的内存中
mov pc, lr



3. 链接器脚本


u-boot.lds 链接器脚本 代码解析 :


  • 1.指明输出格式 ( 处理器架构 ) :​ 使用 ​​OUTPUT_ARCH(架构名称)​​​ 指明***输出格式, 即处理器的架构***, 这里是 arm 架构的, ​​OUTPUT_ARCH(arm)​​ ;
  • 2.指明输出程序的入口 :​ 设置编译输出的程序入口位置, 语法为 ​​ENTRY(入口位置)​​​, 在上面的 Start.S 中设置的程序入口是 ​​_start​​​, 代码为 ​​ENTRY(_start)​​ ;
  • 3.设置代码段 :​ 使用 ​​.text :​​ 设置代码段;
  • 4.设置数据段 :​ 使用 ​​.data :​​ 设置数据段;
  • 5.设置 BSS 段 :​ 使用 ​​.bss :​​ 设置 BSS 段;

  • ( 1 ) 记录 BSS 段的起始地址 :​ ​​bss_start = .;​​ ;
  • ( 2 ) 记录 BSS 段的结束地址 :​ ​​bss_end = .;​​ ;

  • 6.对齐 :​ 每个段都需要设置内存的对齐格式, 使用 ​​. = ALIGN(4);​​ 设置四字节对齐即可;
  • 7.代码示例 :

OUTPUT_ARCH(arm)        /*指明处理器结构*/  
ENTRY(_start) /*指明程序入口 在 _start 标号处*/
SECTIONS {
. = 0x50008000; /*整个程序链接的起始位置, 根据开发板确定, 不同开发板地址不一致*/

. = ALIGN(4); /*对齐处理, 每段开始之前进行 4 字节对齐*/
.text : /*代码段*/
{
start.o (.text) /*start.S 转化来的代码段*/
*(.text) /*其它代码段*/
}

. = ALIGN(4); /*对齐处理, 每段开始之前进行 4 字节对齐*/
.data : /*数据段*/
{
*(.data)
}

. = ALIGN(4); /*对齐处理, 每段开始之前进行 4 字节对齐*/
bss_start = .; /*记录 bss 段起始位置*/
.bss : /*bss 段*/
{
*(.bss)
}
bss_end = .; /*记录 bss 段结束位置*/
}



4. Makefile 编译脚本


makefile 文件编写 :


  • 1.通用规则 ( 汇编文件编译规则 ) :​ ​汇编文件 编译 成同名的 .o 文件​, 文件名称相同, 后缀不同, ​​%.o : %.S​​​, 产生过程是 ​​arm-linux-gcc -g -c $^​​​ , 其中 ​​^​​ 标识是所有的依赖文件, 在该规则下 start.S 会被变异成 start.o ;
  • 2.通用规则 ( C 文件编译规则 ) :​ C 代码编译成同名的 .o 文件, ​​%.o : %.c​​​ , 产生过程是 ​​arm-linux-gcc -g -c $^​​ ;
  • 3.设置最终目标 :​ 使用 ​​all:​​ 设置最终编译目标;

  • ( 1 ) 依赖文件 :​ ​产生最终目标需要依赖 start.o 文件​, 使用 ​​all: start.o​​ 表示最终目标需要依赖该文件;
  • ( 2 ) 链接过程 :​ ​​arm-linux-ld -Tu-boot.lds -o u-boot.elf $^​​, 需要使用链接器脚本进行连接, ​①链接工具是 arm-linux-ld 工具​, ​②使用 ​​-Tu-boot.lds​​ 设置链接器脚本 是刚写的 u-boot.lds 链接器脚本​, ​③输出文件是 u-boot.elf 这是个中间文件​, ​④ 依赖文件是 ​​$^​​ 代表所有的依赖​;
  • ( 3 ) 转换成可执行二进制文件 :​ ​​arm-linux-objcopy -O binary u-boot.elf u-boot.bin​​​, 使用 ​​-O binary​​​ 设置输出二进制文件, 依赖文件是 ​​u-boot.elf​​​, 输出的可执行二进制文件 即 结果是 ​​u-boot.bin​​ ;

  • 4.makefile 文件内容 :

all: start.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



5. 编译输出可执行文件


编译过程 :


  • 1.文件准备 : 将 汇编代码 ( start.S ) 链接器脚本 ( gboot.lds ) makefile 文件 拷贝到编译目录​ ;
  • 2.执行编译命令 :​ ​​make​​ ;
  • 3.编译结果 :​ 可以看到 生成了 编译目标文件 start.o, 链接文件 u-boot.elf, 可执行的二进制文件 u-boot.bin ;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_20




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



( 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 卡启动盘 :


  • 1.找到开发板的烧写工具 :​ OK6410-A 开发板的烧写工具 在开发光盘 A 的 ​OK6410-A-1G用户光盘(A)-20160812\Linux-3.0.1\Linux烧写工具​ 目录下, ​​开发板光盘资料下载地址​​ ;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_21
  • 2.设置 SD_Writer.exe 属性 ( win10系统需要进行的设置 ) :​ 右键点击属性, 在兼容性一栏, 设置 以 Windows 7 兼容模式运行, 并设置 以管理员身份运行此程序 ;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PLL_22
  • 3.先格式化 SD 卡 :​ 注意这里要使用 SD_Writer 中的 format 功能进行格式化 , 按照下面的步骤, 一步一步点击确定执行 ;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_23
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PLL_24
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK_25
  • 4.选择要烧写的文件 :​ 这里选择 ​OK6410-A-1G用户光盘(A)-20160812\Linux-3.0.1\Linux烧写工具\mmc_ram256.bin​ 文件;
  • 5.烧写文件到 SD 卡中 :​ 直接点击 Program 按钮, 就将启动程序烧写到了 SD 卡中;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_26
  • 6.准备 LED 灯程序 :​ ​将编译出的 gboot.bin 文件名修改成 u-boot.bin​, 必须修改成该文件名, 否则无法烧写上去;
  • 7.将程序拷贝到 SD 卡中 :​ 将程序直接拷贝到 SD 卡中即可;


参考资料 :​ ​​OK6410烧写裸板程序方法​​ 这是之前写过的博客, 仅作为参考;




( 3 ) SecureCRT 连接开发板并烧写程序


SecureCRT 连接开发板并烧写程序 步骤 :


  • 1.硬件连接操作 :​ 使用 USB 转 串口工具 将电脑 与 开发板链接, USB 插在电脑端, 串口端插在 开发板上, 插上电源适配器, 但是不要打开电源开关;
  • 2.开发板设置 :​ 将开发板右侧的开关设置成 SD 卡启动, 即 (1~8) 位置 : 0, 0, 0, 1, 1, 1, 1, 1; 该步骤很重要;
  • 2.查询串口端口号 :​ 在设备管理器中查看串口端口号, 这里可以看到是 COM9;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PLL_27
  • 3.SecureCRT 连接串口 :​ 打开 SecureCRT 软件, 点击快速连接, 然后在弹出的对话框中按照下面进行配置, ① 首先要选择 Serial 协议, ② 然后选择端口, 这个端口从设备管理器中查看, ③ 波特率选择 115200, ④ 取消 RTS/CTS 选项;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_MPLL_28
  • 4.打开开发板 ( 很重要 ) :​ 选中 SecureCRT 软件, 然后按住空格键不放, 这个操作很重要, 打开开发板开关, ​① 先按住空格键, ②再打开开关​;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK_29
  • 5.首先格式化 Nand Flash :​ 选择 [1] 选项, 格式化 Nand Flash;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_PCLK_30
  • 6.选择从 SD 卡中烧写 :​ 选择 [2] Burn image from SD card 选项, 从 SD 卡中向开发板烧写程序;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_MPLL_31
  • 7.选择烧写 u-boot :​ 选择 [2] Flash u-boot, 烧写 u-boot, 会从 SD 卡中查找 u-boot.bin 文件, 然后烧写到 nand flash 中, 如果 SD 卡中 没有 u-boot.bin 会报错;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_ARMCLK_32
  • 8.设置从 Nand Flash 启动 :​ 设置开发板上的启动开关, (1~8) 位置 : x, x, x, 1, 1, 0, 0, 1; 此时 四个 LED 全亮;
  • 9.效果展示 :​ 设置的 GPBDAT 寄存器值为 0b110000, 四个 LED 灯都亮起来;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_33
  • 10.修改 LED 灯显示参数后显示结果 :​ 设置 GPBDAT 寄存器中值为 0b110101 是 第一个 和 第三个 LED 亮起来;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_34




7. 将程序烧写到开发板上运行 ( 仅做参考 )


烧写程序并运行 :


  • 1.参考步骤 :​ ​烧写代码到开发板并执行
  • 2.本次运行结果 :​ 设置的 GPBDAT 寄存器值为 0b110000, 四个 LED 灯都亮起来;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_33
  • 3.修改 LED 灯显示参数后显示结果 :​ 设置 GPBDAT 寄存器中值为 0b110101 是 第一个 和 第三个 LED 亮起来;
    【嵌入式开发】时钟初始化 ( 时钟相关概念 | 嵌入式时钟体系 | Lock Time | 分频参数设置 | CPU 异步模式设置 | APLL MPLL 时钟频率设置 )_APLL_34