现在开始就进入板级相关的初始化了,跳转到board/samsung/goni/lowlevel_init.S文件,注意这里lowlevel_init搜索出来在arch/arm/cpu/armv7/lowlevel_init.S文件里面也有,而且这个文件还被编译了,但仔细看一下就会发现,这个文件里面的lowlevel_init被声明成了弱属性,所以真正调用的是board/samsung/goni/lowlevel_init.S文件。

ENTRY(cpu_init_crit)/** Jump to board specific initialization...* The Mask ROM will have already initialized* basic memory. Go here to bump up clock rate and handle* wake up conditions.*/b lowlevel_init       @ go setup pll,mux,memory
ENDPROC(cpu_init_crit)

其实在lowlevel_init里面也不需要干多少事,但DDR是必须要初始化好的,我们都知道s5pv210的整个IRAM也就96K,而u-boot的大小远远超过了96K,所以比较好的办法就是在BL1阶段就初始化好DDR,并且将u-boot搬运到DDR运行。

下面看下lowlevel_init得源码(里面有几个宏,如:S5PC100_GPIO_BASE,在两个文件内都有定义,分别是arch\arm\mach-s5pc1xx\include\mach\cpu.h和arch\arm\include\asm\arch\cpu.h,但根据头文件包含#include <asm/arch/cpu.h>可以知道应该是前面那个文件有效,也可以通过ls -l命令查看目录arch/arm/include/asm/可以看到这个符号链接arch -> ../../mach-s5pc1xx/include/mach):

board/samsung/goni/lowlevel_init.S

.globl lowlevel_init
lowlevel_init:/*这里将lr得值保存到r11中,以便之后返回,因为后面也有跳转得过程,防止lr跳转后丢失*/mov   r11, lr/* r5 has always zero */mov  r5, #0ldr   r7, =S5PC100_GPIO_BASEldr  r8, =S5PC100_GPIO_BASE/* Read CPU ID */ldr r2, =S5PC110_PRO_IDldr r0, [r2]mov r1, #0x00010000and  r0, r0, r1/*根据手册可以得出,这里是不等的*/cmp r0, r5beq   100f/*这里将r8重新赋值成了C110的GPIO基地址*/ldr  r8, =S5PC110_GPIO_BASE
100:/* Turn on KEY_LED_ON [GPJ4(1)] XMSMWEN *//*比较结果不相等,这里比较后,Z位的值是一直保持的*/cmp r7, r8/*不相等,不执行*/beq skip_check_didle            @ Support C110 only/*读取复位状态*/ldr   r0, =S5PC110_RST_STATldr   r1, [r0]and r1, r1, #0x000D0000cmp  r1, #(0x1 << 19)          @ DEEPIDLE_WAKEUP/*如果是从DEEPIDLE模式唤醒的就直接跳到didle_wakeup过程*/beq   didle_wakeupcmp r7, r8skip_check_didle:/*下面这一堆代码就是点亮了一颗led灯,我们改成自己板子上对应的灯GPJ0_3*/addeq   r0, r8, #0x280              @ S5PC100_GPIO_J4addne r0, r8, #0x240              @ S5PC110_GPIO_J0ldr   r1, [r0, #0x0]              @ GPIO_CON_OFFSETbic   r1, r1, #(0xf << 12)          @ 3 * 4-bitorr r1, r1, #(0x1 << 12)str   r1, [r0, #0x0]              @ GPIO_CON_OFFSETldr   r1, [r0, #0x4]              @ GPIO_DAT_OFFSETbic   r1, r1, #(1 << 3)str  r1, [r0, #0x4]              @ GPIO_DAT_OFFSET/*执行到这里,上面点的那颗led灯,如果亮了的话那就说明前面暂时没什么问题了*//* Don't setup at s5pc100 */beq   100f/*下面这堆都是写的默认值,不知道具体的作用*//*省略*//** Diable ABB block to reduce sleep current at low temperature* Note that it's hidden register setup don't modify it*//*这里操作的是隐藏寄存器,不要动*/ldr r0, =0xE010C300ldr r1, =0x00800000str r1, [r0]100:/* IO retension release *//*这一堆好像与低功耗有关*/ldreq  r0, =S5PC100_OTHERS            @ 0xE0108200ldrne  r0, =S5PC110_OTHERS            @ 0xE010E000ldr    r1, [r0]ldreq   r2, =(1 << 31)               @ IO_RET_RELldrne  r2, =((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28))orr    r1, r1, r2/* Do not release retention here for S5PC110 */streq  r1, [r0]/* Disable Watchdog */ldreq r0, =S5PC100_WATCHDOG_BASE     @ 0xEA200000ldrne  r0, =S5PC110_WATCHDOG_BASE     @ 0xE2700000str    r5, [r0]/* setting SRAM */ldreq r0, =S5PC100_SROMC_BASEldrne   r0, =S5PC110_SROMC_BASEldr r1, =0x9str    r1, [r0]/* S5PC100 has 3 groups of interrupt sources *//*s5pv210有四组中断源,这里只失能了三组,再添加一组*/ldreq  r0, =S5PC100_VIC0_BASE         @ 0xE4000000ldrne  r0, =S5PC110_VIC0_BASE         @ 0xF2000000add    r1, r0, #0x00100000add  r2, r0, #0x00200000/*r4还没被用过,使用r4*/add   r4, r0, #0x00300000/* Disable all interrupts (VIC0, VIC1 and VIC2, VIC3) */mvn  r3, #0x0str r3, [r0, #0x14]             @ INTENCLEARstr    r3, [r1, #0x14]             @ INTENCLEARstr    r3, [r2, #0x14]             @ INTENCLEAR/*增加VIC3*/str  r3, [r4, #0x14]             @ INTENCLEAR/* Set all interrupts as IRQ */str r5, [r0, #0xc]              @ INTSELECTstr r5, [r1, #0xc]              @ INTSELECTstr r5, [r2, #0xc]              @ INTSELECT/*增加VIC3*/str   r5, [r4, #0xc]              @ INTSELECT/* Pending Interrupt Clear */str    r5, [r0, #0xf00]            @ INTADDRESSstr    r5, [r1, #0xf00]            @ INTADDRESSstr    r5, [r2, #0xf00]            @ INTADDRESS/*增加VIC3*/str  r5, [r4, #0xf00]            @ INTADDRESS/* for UART *//*由于IROM代码已经初始化了串口2,而在u-boot里面我也使用的串口2作为调试串口,所以可以选择不初始化,但是后面重新配置了时钟,IROM中的配置在新的时钟下工作不正常,没有输出,主要应该就是波特率相关寄存器的设置没法用了,所以再重新配置一下(参考后面的修改)*/bl    uart_asm_init/* 看手册是与安全相关的,不考虑 */bl  internal_ram_initcmp    r7, r8/* Clear wakeup status register */ldreq   r0, =S5PC100_WAKEUP_STATldrne  r0, =S5PC110_WAKEUP_STAT/*这里是不是感觉什么都没做,但实际上手册说的是写1清除该位,默认状态为0,那猜测有效状态应该是1,将读出来的值1又写回去就清除了该位*/ldr   r1, [r0]str r1, [r0]/* IO retension release *//*是不是很熟悉,前面也有一段一模一样的代码,不知道意欲何为*//*省略*//*向下找标号1*/b   1f/*如果前面检测出是DEEPIDLE模式唤醒的,那么直接就到这儿了*/
didle_wakeup:/* Wait when APLL is locked */ldr  r0, =0xE0100100            @ S5PC110_APLL_CON
lockloop:/*等待APLL时钟稳定*/ldr  r1, [r0]and r1, r1, #(1 << 29)cmp r1, #(1 << 29)bne lockloop/*S5PC110_INFORM0是一个用户自定义寄存器*/ldr   r0, =S5PC110_INFORM0ldr    r1, [r0]/*这里将r1的值放到pc指针里面了,猜测是某个地方进入DEEPIDLE的时候,将lr的值保存到了S5PC110_INFORM0里面,这里直接读出来后返回之前执行的地方*/mov  pc, r1nopnopnopnopnop1:/*到了这里就直接返回了*/mov    lr, r11mov  pc, lr

从源码可以看出,目前lowlevel_init主要做的事:

  • 检测唤醒条件
  • 点了一颗灯显示当前运行到哪儿了
  • Initialize Async Register

  • IO retension release相关的

  • 关看门狗
  • 设置SRAM
  • 关中断(这里中断和之前arm内核部分的中断不一样,这些中断是三星公司设计的)
  • 初始化了四个串口的引脚
  • 初始化内部RAM
  • 清除唤醒状态
  • IO retension release相关的

目前CPU好像是运行在400MHz下的,在本文件lowlevel_init.S的末尾有一个时钟初始化的过程,但是没有被调用,将其添加上:

   /*添加到这句后面*/
bl  internal_ram_init/*初始化时钟*/bl system_clock_init

由于重新配置了时钟,而串口2的初始化使用的PCLK时钟没有使用串口专有的时钟,所以也跟着发生了变化,串口2在IROM中的配置已经不能用了,不能输出信息,重新配置一下:

/** uart_asm_init: Initialize UART's pins*/
uart_asm_init:/* set GPIO to enable UART0-UART4 */mov   r0, r8ldr   r1, =0x22222222str r1, [r0, #0x0]          @ S5PC100_GPIO_A0_OFFSETldr    r1, =0x00002222str r1, [r0, #0x20]         @ S5PC100_GPIO_A1_OFFSET/* Check S5PC100 */cmp r7, r8bne   110f/* UART_SEL GPK0[5] at S5PC100 *//*省略*/b    200f
110:/** Note that the following address* 0xE020'0360 is reserved address at S5PC100*//* UART_SEL MP0_5[7] at S5PC110 *//*下面这堆代码是在设置MP05_7这个脚,但在我的开发板上悬空的,可以删除,也可以不管*//*省略*//*配置串口2*/ldr r0, =S5PC110_UART_BASE/*ULCON 8n1*/ldr r1, =0x3str r1, [r0, #0x800]/*UCON*/ldr r1, =0x5str r1, [r0, #0x804]/*UFCON*/ldr r1, =0x217str r1, [r0, #0x808]/*UMCON*/ldr r1, =0x0str r1, [r0, #0x80C]/*UBRDIV*/ldr r1, =34str r1, [r0, #0x828]/*UDIVSLOT*/ldr r1, =0xDFDDstr r1, [r0, #0x82C]
200:mov pc, lr

接着是初始化DDR,我这个开发板的配置是4片128M,每两片并联组成32bit的数据线访问,总容量512M,从手册上面可以得知此芯片有两个DDR控制器,总共能扩展的DDR内存最大1.5G:

图1 内存映射图

硬件上前256M在DRAM0区域,后256M在DRAM1区域,为了让两片地址连续起来,前256M的起始地址设置为0x30000000,后256M的起始地址设为0x40000000,这样刚好地址连续,DDR的初始化程序参考三星提供的,下面只对配置部分参数进行说明,关于时间参数不进行讲解,配置流程参见手册DRAM CONTROLLER篇(完整初始化代码见本文末尾):

/*chip相当于rank,就好像电脑的内存插槽是有正反两面的,我们只有一面,也就是一个rank*/
#define DMC0_MEMCONTROL     0x00202400  // MemControl   BL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off/*30代表起始地址是0x30000000,F0有点像大小的意思代表0xfffffff,1有点像扫描方式,3列的位数是10,2行的位数是14,3bank数是8*/
#define DMC0_MEMCONFIG_0    0x30F01323  // MemConfig0   256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
/*前面说了我们只用了一面,另一面没用*/
#define DMC0_MEMCONFIG_1    0x30F00312  // MemConfig1       默认值#define DMC0_TIMINGA_REF 0x00000618  // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
#define DMC0_TIMING_ROW     0x28233287  // TimingRow    for @200MHz
#define DMC0_TIMING_DATA    0x23240304  // TimingData   CL=3
#define DMC0_TIMING_PWR     0x09C80232  // TimingPower#define   DMC1_MEMCONTROL     0x00202400  // MemControl   BL=4, 1chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off/*除了起始地址,其它描述和DMC0都一样*/
#define DMC1_MEMCONFIG_0    0x40F01323  // MemConfig0   256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
/*这个也是只用了一面*/
#define DMC1_MEMCONFIG_1    0x60E00312  // MemConfig1       默认值#define DMC1_TIMINGA_REF 0x00000618  // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4
#define DMC1_TIMING_ROW     0x28233289  // TimingRow    for @200MHz
#define DMC1_TIMING_DATA    0x23240304  // TimingData   CL=3
#define DMC1_TIMING_PWR     0x08280232  // TimingPower

将DDR初始化程序,ddr_init.S文件放到board/samsung/goni/目录,然后修改该目录下的Makefile,添加ddr_init.S的编译:

obj-y    := goni.o onenand.o
obj-y   += lowlevel_init.o
/*增加ddr_init*/
obj-y   += ddr_init.o

然后在时钟初始化的后面添加上DDR的初始化:

/*...*/
bl  internal_ram_init/*初始化时钟*/bl system_clock_init/*初始化DDR*/bl sdram_asm_init

DDR怎么验证有没有初始化成功呢,可以添加一段测试程序,先向DDR的某个地址(注意这个地址一定要四字节对齐,因为前面开启了对齐检查,否则访问非对齐地址时会出错,而且这个错误的唯一现象就是你看不到任何输出,这时你可能会怀疑你的DDR初始化没有成功,导致写DDR时出错,但实际上是因为访问了非对齐地址)写入几个值,然后再读出来,我这里写了OK两个字符,通过串口打印查看就可以了:

/*写入字符'O'*/ldr r0, =0x40000000ldr r1, =0x4fstr r1, [r0]/*写入字符'K'*/ldr r0, =0x40000004ldr r1, =0x4bstr r1, [r0]/*读出然后通过串口输出*/ldr r0, =0xE2900820ldr r1, =0x40000000ldr r2, [r1]str r2, [r0]/*读出然后通过串口输出*/ldr r0, =0xE2900820ldr r1, =0x40000004ldr r2, [r1]str r2, [r0]

由于硬件设计的原因,开发板上电后还需要进行电源置锁,不然的话开机按钮如果松手的话就掉电了,这里将电源置锁加上:

/*这个只是简单的拉了一个IO的电平,不作介绍,添加函数体的实现到lowlevel_init.S文件的末尾,然后在时钟初始化的前面调用*/
board_power_hold:ldr r0, =0xE010E81Cldr r1, [r0]ldr r2, =((0x1 << 0) | (0x1 << 8) | (0x1 << 9))orr r1, r1, r2str r1, [r0]mov pc, lr

在时钟初始化前调用:

/*...*/
bl  internal_ram_init/*电源置锁*/bl board_power_hold/*初始化时钟*/bl system_clock_init/*初始化DDR*/bl sdram_asm_init

到了这里,DDR已经初始化好了,下一步就是将u-boot拷贝到DDR去执行了,我们u-boot是烧写到sd卡的,三星在IROM代码中已经提供了将SD卡的内容拷贝到内存的函数实现,我们只需要调用就可以了,这里参考手册(S5PV210_iROM_ApplicationNote_Preliminary_20091126.pdf):

图2

图3

上面图2表示这个地址存储了当前的启动通道地址,图3就是拷贝函数,三星提供了好几个这样的拷贝函数,用于从不同启动介质中拷贝内容到内存中,这里只截取了SD/MMC和eMMC的拷贝函数,从上面的图可以看出CopySDMMCtoMem这个函数的函数体就放在0xD0037F98这个地址,所以我们只需要通过函数指针的方式,访问这个地址的内容就相当于调用这个函数了,在board/samsung/goni/目录添加一个copy_image_to_mem.c文件,写入以下代码:

#include <configs/s5p_goni.h>/*
参数1:通道号
参数2:从SD卡的哪个扇区开始拷贝
参数3:拷贝多少个扇区
参数4:拷贝到内存的哪里
参数5:不知道具体用途
*/
typedef bool (*CopySDMMCtoMemTypeDef)(int, unsigned int, unsigned short, unsigned int*, bool);void CopySDMMCtoMem(void)
{CopySDMMCtoMemTypeDef pFuncCopySDMMCtoMem;pFuncCopySDMMCtoMem = (CopySDMMCtoMemTypeDef)(*((volatile unsigned int *)0xD0037F98));unsigned int ch = *((volatile unsigned int*)(0xd0037488));if(ch == 0xeb000000){/*通道0,iNand*/}else if(ch == 0xeb200000){/*通道2,SD卡*/pFuncCopySDMMCtoMem(2, 45, 1000,(unsigned int*)CONFIG_SYS_TEXT_BASE, 0); }
}

有个需要注意的地方就是拷贝到内存的地址,这是个C函数,函数的调用需要使用栈,前面start.S里面设置过一次栈,这里的内存地址最好不要和当时设置的栈空间冲突(注意栈的生长方向是向下的);然后就是SD卡的起始扇区,这个是和你烧写u-boot的起始扇区一样的,因为我是烧写到45扇区开始的位置(这个位置不是固定的,只要没有覆盖掉BL1就行了),所以这里设置45,拷贝大小(这里设置的参数值是扇区数,乘以扇区大小512才是真正的大小,我这里拷贝1000*512=500K)只要大于等于u-boot的大小就行了,然后内存地址我设置的是链接地址(经过后面的验证这里必须设置为链接地址,因为重定位的时候代码拷贝的起始地址就是这儿)。

顺便贴下我的烧写脚本:

#! /bin/bashUBOOT=2020.04#mkv210_image是制作BL1的,因为BL1前16个字节需要填写头信息
./mkv210_image ~/Desktop/s5pv210/u-boot-${UBOOT}/u-boot.bin u-boot-sd.bin
sudo dd iflag=dsync oflag=dsync if=u-boot-sd.bin of=/dev/sdb seek=1
sudo dd iflag=dsync oflag=dsync if=~/Desktop/s5pv210/u-boot-${UBOOT}/u-boot.bin of=/dev/sdb seek=45

在board/samsung/goni/Makefile中添加,让其编译进u-boot,就可以调用这个函数进行拷贝了:

obj-y    := goni.o onenand.o
obj-y   += lowlevel_init.o
obj-y   += ddr_init.o
/*添加编译*/
obj-y   += copy_image_to_mem.o
/*...*/
bl  internal_ram_init/*电源置锁*/bl board_power_hold/*初始化时钟*/bl system_clock_init/*初始化DDR*/bl sdram_asm_init/*拷贝u-boot到DDR*/bl CopySDMMCtoMem

其实还有很重要的一步,我前面没有提到,就是我们调用的这个函数是不是都在BL1里面,也就是是不是在u-boot的前16K,我们可以通过查看System.map文件,这个文件是u-boot编译后生成的,位于u-boot根目录:

图4

起始地址可以看到是0x34800000,前16K的内容就截止与0x34804000这个地址,所以我们只需要看我们调用的内容有没有在这个地址内就行了,或者可以反汇编u-boot文件也可以知道,相对来说反汇编u-boot文件要详细点。

好的,u-boot已经拷贝到DDR里面了,所以紧接着我们进入DDR的u-boot中去执行,修改arch/arm/cpu/armv7/start.S文件:

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
#ifdef CONFIG_CPU_V7Abl cpu_init_cp15
#endif
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLYbl    cpu_init_crit
#endif
#endif/*注释掉*/@ bl  _main/*修改这里,跳转到DDR中去执行,因为IRAM里面只有u-boot的前16k代码*/ldr pc, =_main

这部分内容结束,就进入board_init_f了(也就是大家说的u-boot的第一阶段),所以编译看一下效果:

图5

可以看到已经出来很多信息了,说明我们成功跳转到DDR去执行了,不过卡在了OneNAND初始化的后面。

完整DDR初始化代码:

#include <config.h>#define ELFIN_GPIO_BASE   S5PC110_GPIO_BASE#define MP1_0DRV_SR_OFFSET       0x3CC
#define MP1_1DRV_SR_OFFSET      0x3EC
#define MP1_2DRV_SR_OFFSET      0x40C
#define MP1_3DRV_SR_OFFSET      0x42C
#define MP1_4DRV_SR_OFFSET      0x44C
#define MP1_5DRV_SR_OFFSET      0x46C
#define MP1_6DRV_SR_OFFSET      0x48C
#define MP1_7DRV_SR_OFFSET      0x4AC
#define MP1_8DRV_SR_OFFSET      0x4CC#define MP2_0DRV_SR_OFFSET         0x4EC
#define MP2_1DRV_SR_OFFSET      0x50C
#define MP2_2DRV_SR_OFFSET      0x52C
#define MP2_3DRV_SR_OFFSET      0x54C
#define MP2_4DRV_SR_OFFSET      0x56C
#define MP2_5DRV_SR_OFFSET      0x58C
#define MP2_6DRV_SR_OFFSET      0x5AC
#define MP2_7DRV_SR_OFFSET      0x5CC
#define MP2_8DRV_SR_OFFSET      0x5EC/** SDRAM Controller*/
#define APB_DMC_0_BASE          0xF0000000
#define APB_DMC_1_BASE          0xF1400000
#define ASYNC_MSYS_DMC0_BASE    0xF1E00000#define DMC_CONCONTROL            0x00
#define DMC_MEMCONTROL          0x04
#define DMC_MEMCONFIG0          0x08
#define DMC_MEMCONFIG1          0x0C
#define DMC_DIRECTCMD           0x10
#define DMC_PRECHCONFIG         0x14
#define DMC_PHYCONTROL0         0x18
#define DMC_PHYCONTROL1         0x1C
#define DMC_RESERVED            0x20
#define DMC_PWRDNCONFIG         0x28
#define DMC_TIMINGAREF          0x30
#define DMC_TIMINGROW           0x34
#define DMC_TIMINGDATA          0x38
#define DMC_TIMINGPOWER         0x3C
#define DMC_PHYSTATUS           0x40
#define DMC_CHIP0STATUS         0x48
#define DMC_CHIP1STATUS         0x4C
#define DMC_AREFSTATUS          0x50
#define DMC_MRSTATUS            0x54
#define DMC_PHYTEST0            0x58
#define DMC_PHYTEST1            0x5C
#define DMC_QOSCONTROL0         0x60
#define DMC_QOSCONFIG0          0x64
#define DMC_QOSCONTROL1         0x68
#define DMC_QOSCONFIG1          0x6C
#define DMC_QOSCONTROL2         0x70
#define DMC_QOSCONFIG2          0x74
#define DMC_QOSCONTROL3         0x78
#define DMC_QOSCONFIG3          0x7C
#define DMC_QOSCONTROL4         0x80
#define DMC_QOSCONFIG4          0x84
#define DMC_QOSCONTROL5         0x88
#define DMC_QOSCONFIG5          0x8C
#define DMC_QOSCONTROL6         0x90
#define DMC_QOSCONFIG6          0x94
#define DMC_QOSCONTROL7         0x98
#define DMC_QOSCONFIG7          0x9C
#define DMC_QOSCONTROL8         0xA0
#define DMC_QOSCONFIG8          0xA4
#define DMC_QOSCONTROL9         0xA8
#define DMC_QOSCONFIG9          0xAC
#define DMC_QOSCONTROL10        0xB0
#define DMC_QOSCONFIG10         0xB4
#define DMC_QOSCONTROL11        0xB8
#define DMC_QOSCONFIG11         0xBC
#define DMC_QOSCONTROL12        0xC0
#define DMC_QOSCONFIG12         0xC4
#define DMC_QOSCONTROL13        0xC8
#define DMC_QOSCONFIG13         0xCC
#define DMC_QOSCONTROL14        0xD0
#define DMC_QOSCONFIG14         0xD4
#define DMC_QOSCONTROL15        0xD8
#define DMC_QOSCONFIG15         0xDC#define DMC0_MEMCONTROL     0x00202400  // MemControl   BL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off#define DMC0_MEMCONFIG_0  0x30F01323  // MemConfig0   256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC0_MEMCONFIG_1    0x30F00312  // MemConfig1       默认值#define DMC0_TIMINGA_REF 0x00000618  // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
#define DMC0_TIMING_ROW     0x28233287  // TimingRow    for @200MHz
#define DMC0_TIMING_DATA    0x23240304  // TimingData   CL=3
#define DMC0_TIMING_PWR     0x09C80232  // TimingPower#define   DMC1_MEMCONTROL     0x00202400  // MemControl   BL=4, 1chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off#define DMC1_MEMCONFIG_0  0x40F01323  // MemConfig0   256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC1_MEMCONFIG_1    0x60E00312  // MemConfig1       默认值#define DMC1_TIMINGA_REF 0x00000618  // TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4
#define DMC1_TIMING_ROW     0x28233289  // TimingRow    for @200MHz
#define DMC1_TIMING_DATA    0x23240304  // TimingData   CL=3
#define DMC1_TIMING_PWR     0x08280232  // TimingPower.globl sdram_asm_init
sdram_asm_init: ldr r0, =0xf1e00000ldr r1, =0x0str    r1, [r0, #0x0]/* DMC0 Drive Strength (Setting 2X) */ldr r0, =ELFIN_GPIO_BASEldr    r1, =0x0000AAAAstr r1, [r0, #MP1_0DRV_SR_OFFSET]       // 寄存器中对应0b10,就是2Xldr    r1, =0x0000AAAAstr r1, [r0, #MP1_1DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP1_2DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP1_3DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP1_4DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP1_5DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP1_6DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP1_7DRV_SR_OFFSET]ldr    r1, =0x00002AAAstr r1, [r0, #MP1_8DRV_SR_OFFSET]/* DMC1 Drive Strength (Setting 2X) */ldr  r0, =ELFIN_GPIO_BASEldr    r1, =0x0000AAAAstr r1, [r0, #MP2_0DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP2_1DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP2_2DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP2_3DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP2_4DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP2_5DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP2_6DRV_SR_OFFSET]ldr    r1, =0x0000AAAAstr r1, [r0, #MP2_7DRV_SR_OFFSET]ldr    r1, =0x00002AAAstr r1, [r0, #MP2_8DRV_SR_OFFSET]/* DMC0 initialization at single Type*/ldr r0, =APB_DMC_0_BASEldr r1, =0x00101000                @PhyControl0 DLL parameter setting, manual 0x00101000str   r1, [r0, #DMC_PHYCONTROL0]ldr   r1, =0x00000086                @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Casestr   r1, [r0, #DMC_PHYCONTROL1]ldr   r1, =0x00101002                @PhyControl0 DLL onstr r1, [r0, #DMC_PHYCONTROL0]ldr   r1, =0x00101003                @PhyControl0 DLL startstr  r1, [r0, #DMC_PHYCONTROL0]find_lock_val:ldr r1, [r0, #DMC_PHYSTATUS]        @Load Phystatus register valueand  r2, r1, #0x7cmp r2, #0x7                @Loop until DLL is lockedbne   find_lock_valand    r1, #0x3fc0 mov r2, r1, LSL #18orr  r2, r2, #0x100000orr    r2 ,r2, #0x1000 orr r1, r2, #0x3                @Force Value lockingstr    r1, [r0, #DMC_PHYCONTROL0]#if 0 /* Memory margin test 10.01.05 */orr    r1, r2, #0x1                @DLL offstr    r1, [r0, #DMC_PHYCONTROL0]
#endif/* setting DDR2 */ldr r1, =0x0FFF2010                @ConControl auto refresh offstr    r1, [r0, #DMC_CONCONTROL]ldr    r1, =DMC0_MEMCONTROL           @MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]ldr    r1, =DMC0_MEMCONFIG_0          @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedstr    r1, [r0, #DMC_MEMCONFIG0]ldr    r1, =DMC0_MEMCONFIG_1          @MemConfig1str r1, [r0, #DMC_MEMCONFIG1]ldr    r1, =0xFF000000                @PrechConfigstr    r1, [r0, #DMC_PRECHCONFIG]ldr   r1, =DMC0_TIMINGA_REF          @TimingAref    7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)str r1, [r0, #DMC_TIMINGAREF]ldr    r1, =DMC0_TIMING_ROW           @TimingRow for @200MHzstr r1, [r0, #DMC_TIMINGROW]ldr r1, =DMC0_TIMING_DATA          @TimingData    CL=3str    r1, [r0, #DMC_TIMINGDATA]ldr    r1, =DMC0_TIMING_PWR           @TimingPowerstr    r1, [r0, #DMC_TIMINGPOWER]ldr   r1, =0x07000000                @DirectCmd chip0 Deselectstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000                @DirectCmd chip0 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00020000                @DirectCmd chip0 EMRS2str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00030000                @DirectCmd chip0 EMRS3str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400                @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000542                @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000                @DirectCmd chip0 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000                @DirectCmd chip0 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000                @DirectCmd chip0 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000442                @DirectCmd chip0 MRS (MEM DLL unreset)str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010780                @DirectCmd chip0 EMRS1 (OCD default)str    r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400                @DirectCmd chip0 EMRS1 (OCD exit)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x07100000                @DirectCmd chip1 Deselectstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000                @DirectCmd chip1 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00120000                @DirectCmd chip1 EMRS2str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00130000                @DirectCmd chip1 EMRS3str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400                @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100542                @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000                @DirectCmd chip1 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000                @DirectCmd chip1 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000                @DirectCmd chip1 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100442                @DirectCmd chip1 MRS (MEM DLL unreset)str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110780                @DirectCmd chip1 EMRS1 (OCD default)str    r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400                @DirectCmd chip1 EMRS1 (OCD exit)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x0FF02030                @ConControl    auto refresh onstr  r1, [r0, #DMC_CONCONTROL]ldr    r1, =0xFFFF00FF                @PwrdnConfigstr    r1, [r0, #DMC_PWRDNCONFIG]ldr   r1, =0x00202400                @MemControl    BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr  r1, [r0, #DMC_MEMCONTROL]// 上面是DRAM0初始化步骤
/*******************************************************************************************/
// 下面是DRAM1初始化步骤,两者没有联系,是并列的。/* DMC1 initialization */ldr r0, =APB_DMC_1_BASEldr r1, =0x00101000                @Phycontrol0 DLL parameter settingstr  r1, [r0, #DMC_PHYCONTROL0]ldr   r1, =0x00000086                @Phycontrol1 DLL parameter settingstr  r1, [r0, #DMC_PHYCONTROL1]ldr   r1, =0x00101002                @PhyControl0 DLL onstr r1, [r0, #DMC_PHYCONTROL0]ldr   r1, =0x00101003                @PhyControl0 DLL startstr  r1, [r0, #DMC_PHYCONTROL0]find_lock_val1:ldr    r1, [r0, #DMC_PHYSTATUS]        @Load Phystatus register valueand  r2, r1, #0x7cmp r2, #0x7                @Loop until DLL is lockedbne   find_lock_val1and   r1, #0x3fc0 mov r2, r1, LSL #18orr  r2, r2, #0x100000orr    r2, r2, #0x1000orr  r1, r2, #0x3                @Force Value lockingstr    r1, [r0, #DMC_PHYCONTROL0]#if 0 /* Memory margin test 10.01.05 */orr    r1, r2, #0x1                @DLL offstr    r1, [r0, #DMC_PHYCONTROL0]
#endif/* settinf fot DDR2 */ldr r0, =APB_DMC_1_BASEldr r1, =0x0FFF2010                @auto refresh offstr   r1, [r0, #DMC_CONCONTROL]ldr    r1, =DMC1_MEMCONTROL           @MemControl    BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr  r1, [r0, #DMC_MEMCONTROL]ldr    r1, =DMC1_MEMCONFIG_0          @MemConfig0    512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedstr r1, [r0, #DMC_MEMCONFIG0]ldr    r1, =DMC1_MEMCONFIG_1          @MemConfig1str r1, [r0, #DMC_MEMCONFIG1]ldr    r1, =0xFF000000str r1, [r0, #DMC_PRECHCONFIG]ldr   r1, =DMC1_TIMINGA_REF          @TimingAref    7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4str   r1, [r0, #DMC_TIMINGAREF]ldr    r1, =DMC1_TIMING_ROW           @TimingRow for @200MHzstr r1, [r0, #DMC_TIMINGROW]ldr r1, =DMC1_TIMING_DATA          @TimingData    CL=3str    r1, [r0, #DMC_TIMINGDATA]ldr    r1, =DMC1_TIMING_PWR           @TimingPowerstr    r1, [r0, #DMC_TIMINGPOWER]ldr   r1, =0x07000000                @DirectCmd chip0 Deselectstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000                @DirectCmd chip0 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00020000                @DirectCmd chip0 EMRS2str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00030000                @DirectCmd chip0 EMRS3str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400                @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000542                @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000                @DirectCmd chip0 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000                @DirectCmd chip0 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000                @DirectCmd chip0 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000442                @DirectCmd chip0 MRS (MEM DLL unreset)str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010780                @DirectCmd chip0 EMRS1 (OCD default)str    r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400                @DirectCmd chip0 EMRS1 (OCD exit)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x07100000                @DirectCmd chip1 Deselectstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000                @DirectCmd chip1 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00120000                @DirectCmd chip1 EMRS2str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00130000                @DirectCmd chip1 EMRS3str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110440                @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100542                @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000                @DirectCmd chip1 PALLstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000                @DirectCmd chip1 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000                @DirectCmd chip1 REFAstr   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100442                @DirectCmd chip1 MRS (MEM DLL unreset)str  r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110780                @DirectCmd chip1 EMRS1 (OCD default)str    r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400                @DirectCmd chip1 EMRS1 (OCD exit)str   r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x0FF02030                @ConControl    auto refresh onstr  r1, [r0, #DMC_CONCONTROL]ldr    r1, =0xFFFF00FF                @PwrdnConfig   str r1, [r0, #DMC_PWRDNCONFIG]ldr   r1, =DMC1_MEMCONTROL           @MemControl    BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr  r1, [r0, #DMC_MEMCONTROL]// 函数返回mov pc, lr

欢迎扫码关注我的微信公众号

漫长当下

u-boot2020.04移植(3、lowlevel_init.S)相关推荐

  1. 6004.ubuntu18.04移植qgroundcontrol地面站

    ubuntu18.04移植qgroundcontrol地面站 参考博客: 下载qgroundControl源码 第1种方式: git clone --recursive https://github. ...

  2. uboot研读笔记 | 04 - 移植uboot 2012.04到JZ2440(支持Nor Flash读写)

    项目开源地址:https://github.com/Mculover666/uboot-jz2440 0. 教程完整目录 00 - 嵌入式Linux系统中Bootloader的作用和基本运行原理 01 ...

  3. IMX6ULL-UBoot 20.04移植记录

    开发环境简介 开发板 正点原子MINI 操作系统 Linux-Mint 20.2 交叉编译链 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf U ...

  4. IMX6ULL u-boot 2020.04 移植LAN8720A(网卡)

    1.修改设备树arch/arm/dts/imx6ul-14x14-evk.dtsi 修改后 &fec1 {pinctrl-names = "default";pinctrl ...

  5. uboot研读笔记 | 05 - 移植uboot 2012.04到JZ2440(支持Nand Flash读写)

    项目开源地址:https://github.com/Mculover666/uboot-jz2440 0. 教程完整目录 00 - 嵌入式Linux系统中Bootloader的作用和基本运行原理 01 ...

  6. RT73 wifi无线网卡驱动移植过程 和wpa支持

    转 移植环境: 主机操作系统:Ubantu 8.10 目标系统:linux-2.6.22.6 交叉编译器:arm-softfloat-linux-gnu-gcc-3.4.5 一.RT73驱动编译 1. ...

  7. 移植u-boot v2018

    本篇文章阐述移植 u-boot v2018.01 至 S5PV210 开发板上的主要流程和细节.市场上的S5PV210开发板,均是基于三星smdkv210公版平台山寨出来的.我使用的GEC210开发板 ...

  8. OK6410A移植mw150us无线网卡驱动

    一 ubuntu 12.04移植mw150us驱动 参考: 1)https://blog.csdn.net/wangdapao12138/article/details/82559422 2)http ...

  9. STM32移植uC/OSIII

    坚持就是胜利 一.UCOS简介 01 简介 02 uC/OS-III的任务 03 其他介绍 二.操作过程 01 题目要求 02 配置CubeMX 03 下载代码 04 移植代码 05 效果展示 三.实 ...

  10. Linux系统的madplay、mplayer音视频播放器的制作

    Linux系统音视频播放器的制作 madplay和mplayer的安装环境 一.Linux系统录音播放源码的下载和移植 1.需要下载alsa-lib-1.2.6.tar.bz2(声音驱动的内核组件库) ...

最新文章

  1. OA的核心模块在那里?
  2. mysql event使用,用MySQL的Event设置定时任务执行sql语句 | 老疯子
  3. php redis support,ThinkPHP5报错php not support: redis以及Redis的使用
  4. 一次由于网卡流量跑满引起的服务器丢包总结(sar命令排查)
  5. EditPlus配置Python环境
  6. linux下qt加载boost,信号槽的实现实例—— Qt 和 Boost
  7. Ogre 1.7 SDKTRAY 初探
  8. 针对Micro Framework 3.0模拟器进行改造方法(浅谈)
  9. 如何从完好的数据文件恢复oracle数据库
  10. Atiitt 经济学体系树与知识点概念大总结attilax
  11. 6678学习笔记开篇
  12. 箫演奏技巧符号大全图解
  13. SpringBoot实现抽奖大转盘
  14. 【评测】Attana Cell 200蛋白互作分析仪,实现细胞原位生物大分子互作检测
  15. 如何用Python解析JSON数据
  16. 计算机编程语言排行榜—TIOBE世界编程语言排行榜(2021年11月份最新版)
  17. 【mysql报错】Data truncation: Data too long for column ‘XXX‘ at row 1
  18. Android百度地图之位置定位和附近查找代码简单实现 (上)
  19. linux之进程观察命令:ps和top
  20. 判断一个字符串是否为全字母句

热门文章

  1. linux中文件权限为drwxr,linux drwxr-xr-x 什么意思 ?
  2. 【GDB】__stack_chk_fail 栈溢出问题定位
  3. 一图看懂互联网各职位都是干啥的
  4. 李开复:我要找什么样的人一起创业?
  5. HDU5956 The Elder(树上斜率DP)
  6. [Windows系统]visio安装时提示和即点即用版本不能并行怎么办
  7. 基于python学生档案管理系统的设计与实现.rar(毕业论文+程序源码+答辩PPT)
  8. 外滩画报:揭秘全球电子垃圾坟墓
  9. 人工神经网络的算法原理,人工神经网络算法优点
  10. 转载:王垠 的《完全用Linux工作》