《朱老师物联网大讲堂》学习笔记
学习地址:www.zhulaoshi.org
这次的代码,可以在上次重定位的代码基础上进行添加,或者icache设置代码基础上增加,
这里我是选择的是重定位的代码。
新增代码的位置,选择的是关看门狗后。
blclock_init
初始化时钟单独通过一个函数来实现,
通过这句代码跳转到对应函数。
为了能更好的解释代码,我选择了在解释代码的同时,在旁边附上对应数据手册的图片。
那么开始吧!
#define ELFIN_CLOCK_POWER_BASE0xE0100000
在这里定了一个基地址,通过使用 基地址 + 偏移地址 的方法来定位到我们要访问的寄存器位,
这个用法在重定位也用过,
对于那些寄存器功能相关,地址相连的寄存器,很适合使用这种方法。
见数据手册P367,有没有看到第一个32位寄存器的地址就是我上面那句话的值,
这里只是为了说明,所以就没把后面那好几大页贴出来。
后面就是偏移量的宏定义,
#define APLL_LOCK_OFFSET0x00
#define MPLL_LOCK_OFFSET0x08
#define APLL_CON0_OFFSET0x100
#define APLL_CON1_OFFSET0x104
#define MPLL_CON_OFFSET0x108
#define CLK_SRC0_OFFSET0x200
#define CLK_SRC1_OFFSET0x204
#define CLK_SRC2_OFFSET0x208
#define CLK_SRC3_OFFSET0x20c
#define CLK_SRC4_OFFSET0x210
#define CLK_SRC5_OFFSET0x214
#define CLK_SRC6_OFFSET0x218
#define CLK_SRC_MASK0_OFFSET0x280
#define CLK_SRC_MASK1_OFFSET0x284
#define CLK_DIV0_OFFSET0x300
#define CLK_DIV1_OFFSET0x304
#define CLK_DIV2_OFFSET0x308
#define CLK_DIV3_OFFSET0x30c
#define CLK_DIV4_OFFSET0x310
#define CLK_DIV5_OFFSET0x314
#define CLK_DIV6_OFFSET0x318
#define CLK_DIV7_OFFSET0x31c
#define CLK_DIV0_MASK0x7fffffff
#define APLL_MDIV 0x7d// 125
#define APLL_PDIV 0x3
#define APLL_SDIV 0x1
#define MPLL_MDIV0x29b// 667
#define MPLL_PDIV0xc
#define MPLL_SDIV0x1
#define set_pll(mdiv, pdiv, sdiv)(1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
#define APLL_VALset_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
#define MPLL_VALset_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)
.global clock_init
clock_init:
ldrr0, =ELFIN_CLOCK_POWER_BASE
ldr r1, =0x0
strr1, [r0, #CLK_SRC0_OFFSET]
这里暂时不是用PLL进行倍频,
看CLK_SRC0的第0位。
ldr r1,=0x0000FFFF
strr1,[r0, #APLL_LOCK_OFFSET]
str r1, [r0, #MPLL_LOCK_OFFSET]
这几句,设置锁定时间为FFFF,不过默认的是FFF,详细见下图数据手册,
ldr r1, [r0, #CLK_DIV0_OFFSET]
ldrr2, =CLK_DIV0_MASK
bicr1, r1, r2
ldrr2, =0x14131440
orrr1, r1, r2
strr1, [r0, #CLK_DIV0_OFFSET]
这里是在设置分频,试着把0x14131440换算成二进制就是
00010100 00010011 00010100 01000000
在结合数据手册可以得到如下关系
PCLK_PSYS = HCLK_PSYS / (PCLK_PSYS_RATIO + 1) 这里对应为(1+1)
HCLK_PSYS = MOUT_PSYS / (HCLK_PSYS_RATIO + 1)这里对应为(1+4)
PCLK_DSYS = HCLK_DSYS / (PCLK_DSYS_RATIO + 1) 这里对应为(1+1)
HCLK_DSYS = MOUT_DSYS / (HCLK_DSYS_RATIO + 1) 这里对应为(1+3)
PCLK_MSYS = HCLK_MSYS / (PCLK_MSYS_RATIO + 1) 这里对应为(1+1)
HCLK_MSYS = ARMCLK / (HCLK_MSYS_RATIO + 1)这里对应为(1+4)
SCLKA2M = SCLKAPLL / (A2M_RATIO + 1)这里对应为(1+4)
ARMCLK = MOUT_MSYS / (APLL_RATIO + 1)这里对应为(1+0)
对应的数据手册为
这里的设置弄bic,orr什么的,让人有些不是很明白,
不过在下一节用C语言实现中,解释了下,可能是由于以前版本Reserved位的原因留下的,
不过这些不是很关键,所以没事。
ldr r1, =APLL_VAL
strr1, [r0, #APLL_CON0_OFFSET]
ldrr1, =MPLL_VAL
strr1, [r0, #MPLL_CON_OFFSET]
这里就是设置PLL倍频参数了,不过APLL_VAL是什么鬼啊?
嘿嘿~是个宏定义。
#define APLL_MDIV 0x7d // 125#define APLL_PDIV 0x3
#define APLL_SDIV 0x1
#define MPLL_MDIV 0x29b // 667
#define MPLL_PDIV 0xc
#define MPLL_SDIV 0x1
#define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
#define APLL_VAL set_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
#define MPLL_VALset_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)
这里有个不同于前面设置的地方,就是这些参数,比如参数M,P,S的设置,
不是单纯的依靠数据手册中的公式就可以了,那个只是纯数学的角度来看的,
实际上,这里还涉及到元器件自身适合的工作条件。
所以具体设置多少,不是你你软件工程师能够决定的,你需要去看看相关推荐值,见下图。
这里只列出了两个,在数据手册p357.
解释一下,如果你想要到达1GHz,也就是FOUT = 1000.00MHz,
相应的P,M,S推荐值为3,123,1,
FIN在我们这个开发板是固定的24MHz。
ldr r1, [r0, #CLK_SRC0_OFFSET]
ldrr2, =0x10001111
orrr1, r1, r2
strr1, [r0, #CLK_SRC0_OFFSET]
mov pc, lr
有一个地方,orr,也是有些想不明白,感觉多次一举,
不过根据下面一节C语言实现,可以这样理解,
这是个32位的寄存器,
怕赋值的时候,有些为0的位没设置到,
不过这里设置的值其实已经对这些位的设置涉及到了,
所以可以不用管了,
不过这次思考的过程还是挺有意义。
MSYS domain comprises(包含) Cortex A8 processor,
Figure 3-3shows block diagram of the clock generation logic. An externalcrystal clock is connected to the
oscillation(震荡) amplifier(放大器).
The clock generator block also includes a built-in logic to stabilize the clock frequency after each system reset, since
clock takes time before stabilizing.
时钟发生器块还包括一个内置的逻辑,以稳定每个系统复位后的时钟频率,因为时钟稳定之前需要时间。