lowlevel_init 相关代码分析

文件路径board/freescale/mx6q_sabresd/low_init.S

 

.globl lowlevel_init     

lowlevel_init:

    inv_dcache

    init_l2cc

    init_aips

    init_clock

    mov pc, lr

1.寄存器相关说明

r0-r3   用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 r0-r3 用于任何用途。被调用函数在返回之前不必恢复 r0-r3。如果调用函数需要再次使用 r0-r3 的内容,则它必须保留这些内容。

r4-r11 被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。

r12     是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。

13      是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。

r14     是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复

r15     是程序计数器 PC。它不能用于任何其它用途。     

注意:在中断程序中,所有的寄存器都必须保护,编译器会自动保护R4~R11

 

    

2.代码段 

2.1 inv_dcache   

/* invalidate the D-CACHE */ /* CP15寄存器是系统控制协处理器,用于连接在内存中的页表描述符,此外还用于决定对MMU的操作。设置CP15寄存器的目的是失效Icache(指令cache)和Dcache(数据cache),然后禁止MMUcache */

.macro inv_dcache

    mov     r0,#0              /* r0=0x0 */

    mcr     p15,2,r0,c0,c0,0  /* cache size selection register, select dcache */

         /* CP15 中寄存器 C0 对应两个标识符寄存器,由访问 CP15 中的寄存器指令中的 <opcode2> 指定要访问哪个具体物理寄存器 */

                                /* 该指令将 ARM 处理器寄存器 R0 中的数据传送到协处理器 P15 的寄存器 c0 c0  */

                                /* MCR 指令将ARM 处理器的寄存器中的数据传送到协处理器的寄存器中。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 */

                                /* p15为指令操作的协处理器名。 标准名为:Pn (n的范围:0~15) */

                                /* 2 为协处理器的特定操作码  */

                                /* r0 为目标寄存器 */

                                /* c0 存放第1个操作数的协处理器寄存器   ID Code (1) */

                                /* c0 存放第2个操作数的协处理器寄存器   Catch type(1) */

                                /* 0 可选的协处理器特定操作码    */

    mrc     p15,1,r0,c0,c0,0  /* cache size ID register */ /* 清除cache ID */

                                /* 读取CP15的主标识寄存器的指令,该指令将主标识符寄存器的内容读取到ARM寄存器R0 */

                                /* MRC 协处理器寄存器到ARM 处理器寄存器的数据传送指令 */

    mov     r0,r0,ASR #13       /* asr----逻辑右移并且符号位不参与运算   r0中的值右移13位,前面补1 */

    ldr     r3,=0xfff           /* ldr常用于加载芯片外围功能部件的寄存器地址(32 位立即数),以实现各种控制操作加载32位立即数   装载32位立即数 */

    and     r0,r0,r3            /*获取r0的低12*/

    cmp     r0,#0x7f            /* r0 7f 比较,设置相关标志位 */

    moveq   r6,#0x1000          /* 如果 r0 7f 相等, r6 = 0x1000 */

    beq     size_done           /* 如果相等就跳转,不相等就不跳转,这里的eq就是条件 */

    cmp     r0,#0xff            /* r0 ff 比较, */

    moveq   r6,#0x2000          /* 如果 r0 ff 相等, r6 = 0x2000 */

    movne   r6,#0x4000         /* 如果 r0 ff 不相等, r6 = 0x4000 */

 

size_done:

    mov     r2,#0

    mov     r3,#0x40000000

    mov     r4,#0x80000000

    mov     r5,#0xc0000000

 

d_inv_loop:

    mcr     p15,0,r2,c7,c6,2  /* invalidate dcache by set / way */

        /* C6 MMU中的作用:内存失效地址  PU中:保护区域控制 */

                                /* C7 MMU:高速缓存和写缓存控制 */

    mcr     p15,0,r3,c7,c6,2  /* invalidate dcache by set / way */

    mcr     p15,0,r4,c7,c6,2  /* invalidate dcache by set / way */

    mcr     p15,0,r5,c7,c6,2  /* invalidate dcache by set / way */

    add     r2,r2,#0x20         /* r2 = r2 + 0x20 */

    add     r3,r3,#0x20

    add     r4,r4,#0x20

    add     r5,r5,#0x20

 

    cmp     r2,r6

    bne     d_inv_loop        /* r6r2不相等,则跳转到d_inv_loop继续 */

.endm

 

补充:协处理器部分说明

MCR{cond}     coprocopcode1Rd(源寄存器),CRn(目标寄存器),CRm(目标寄存 器),opcode2

MCR 指令用于将ARM处理器寄存器中的数据传送到协处理器寄存器中。

CP15 的寄存器 C0

CP15 中寄存器 C0 对应两个标识符寄存器,由访问 CP15 中的寄存器指令中的 <opcode2> 指定要访问哪个具体物理寄存器, <opcode2> 与两个标识符寄存器的对应关系如下所示:

opcode2 编码

对应的标识符号寄存器

0b000

主标识符寄存器

0b001

cache类型标识符寄存器

保留

2.2 init_l2cc

.macro init_l2cc

    ldr     r1, =0xa02000       /* LDR   r0,=label 

                                如果label是立即数,就把数值赋给r0, 如果lable是标识符,就把label地址的值赋给r0 */

                                /* r1= 0xa02000 */

    ldr     r0, =0x0

    str     r0, [r1, #0x100]    /* R0中的值放到以R1中的值为地址 在偏移 0x100 的存储单元去 */

.endm /* init_l2cc */

 

补充:LDR,STR指令 

LDR,STR 的第一操作数是目标寄存器,第二操作数是内存地址, LDR 内存 --> 寄存器; STR 寄存器 --> 内存 

内存的表示方式有:立即数,寄存器,或寄存器加偏移,立即数:内存的物理位置,前面加个#,如0x56000050 

寄存器,加个[],如[r1],偏移的话[r1,r2],或者[r1,#4],[r1,LSL #4]等,都差不多,就是把寄存器里的数当成地址。

STR       R0,[R1] 是一个典型的存储指令,将R0中的值放到以R1中的值为地址的存储单元去。

 

2.3 init_aips

.macro init_aips

    /*

     * Set all MPROTx to be non-bufferable, trusted for R/W,

     * not forced to user-mode.

     */

    ldr r0, =AIPS1_ON_BASE_ADDR     /* r0 = 0x0207 c000 */

    ldr r1, =0x77777777             /* r1 = 0x77777777 */

    str r1, [r0, #0x0]              /* R1中的值放到以R0中的值为地址 在偏移 0x0 的存储单元去(0x0207 c000) */ /* AIPS-1 配置 */

    str r1, [r0, #0x4]              /* R1中的值放到(0x0207 c004这个地址)存储单元去 */

    ldr r1, =0x0                    /* 0x0这个地址写到r1 */

    str r1, [r0, #0x40]             /* R1中的值放到(0x0207 c040)存储单元去 *//*  */

    str r1, [r0, #0x44]             /* R1中的值放到(0x0207 c044)存储单元去 */

    str r1, [r0, #0x48]             /* R1中的值放到(0x0207 c048)存储单元去 */

    str r1, [r0, #0x4C]             /* R1中的值放到(0x0207 c04c)存储单元去 */

    str r1, [r0, #0x50]             /* R1中的值放到(0x0207 c050)存储单元去 */

 

    ldr r0, =AIPS2_ON_BASE_ADDR     /* r0 = 0x02100000 */

    ldr r1, =0x77777777

    str r1, [r0, #0x0]

    str r1, [r0, #0x4]

    ldr r1, =0x0

    str r1, [r0, #0x40]

    str r1, [r0, #0x44]

    str r1, [r0, #0x48]

    str r1, [r0, #0x4C]

    str r1, [r0, #0x50]

.endm /* init_aips */

 

补充:AIPSTZ Memory Map/Register Definition(AIPSTZx_OPACR)

 

3 BW Buffer Writes - 这个位决定是否允许对这个外设的写访问被缓冲。

2 SP Supervisor Protect - 这一点决定了外围设备是否需要主管特权来访问。

1 WP Write Protect - 这个位决定了外设是否允许写访问。

0 TP Trusted Protect - 这一点决定了外围设备是否允许来自anuntrusted master的访问。

 

对于AIPSTZ来说,缓冲写是不可用的。这个位应该设为'0'

Address: Base address + 40h offset

OPAC0

非平台外围访问控制0

xxx0 TP — 允许来自不可信的主机的访问。

xxx1 TP — 不允许从不受信任的主人那里访问。如果一个存取是由一个不可信的主人尝试的,那么访问就会被一个错误响应终止,并且在IPS总线上没有启动外围访问。

xx0x WP — 这个外设允许写访问

xx1x WP — 这个外设是受保护的。如果尝试了写访问,则通过错误响应终止访问,并且在IPS总线上不启动外围访问。

x0xx SP — 这个外设不需要管理员权限级别的访问权限。.

x1xx SP — 这个外设需要管理员权限级别的访问权限。主权限级别必须通过hprot 1访问属性指示主管,并且必须设置主控权的MPROTx MPL控制位。如果没有,则使用错误响应终止访问,并且在IPS总线上不启动外围访问。

0xxx BW — 对这个外围设备的写访问不能被AIPSTZ所利用。

1xxx BW — 对这个外设的写访问权限被AIPSTZ进行缓冲。

 

 

 

2.4 init_clock

.macro init_clock

 

/* PLL1, PLL2, and PLL3 are enabled by ROM */

#ifdef CONFIG_PLL3

    /* enable PLL3 for UART */

    ldr r0, ANATOP_BASE_ADDR_W      /* 0x020c 8000 */

 

    /* power up PLL */

    ldr r1, [r0, #ANATOP_USB1]      /* ANATOP_USB1 = 0x10 r0+ANATOP_USB1 地址的数据计读出,保存到r1(r0的值不变) */

    orr r1, r1, #0x1000             /* r1 = r1 | 0x1000 */ /* r1的第13位置1 */

    str r1, [r0, #ANATOP_USB1]      /* r1的值写入 r0+ANATOP_USB1 地址 */

 

    /* enable PLL */

    ldr r1, [r0, #ANATOP_USB1]

    orr r1, r1, #0x2000             /* r1的第14位置1 */

    str r1, [r0, #ANATOP_USB1]

 

    /* wait PLL lock */

100:

    ldr r1, [r0, #ANATOP_USB1]

    mov r1, r1, lsr #31             /* r1左移31 */

    cmp r1, #0x1

    bne 100b

 

    /* clear bypass bit */

    ldr r1, [r0, #ANATOP_USB1]

    and r1, r1, #0xfffeffff         /* r1的第17位置0 */

    str r1, [r0, #ANATOP_USB1]

#endif

 

    /* Restore the default values in the Gate registers */

    ldr r0, CCM_BASE_ADDR_W         /* 0x020c 4000 */

    ldr r1, =0xC0003F

    str r1, [r0, #CLKCTL_CCGR0]     /* CLKCTL_CCGR0 = 0x68 */  /* 0x020c 4068 这个地址中写值0xc0003f */ /* 时钟门控 CG01211 */

    ldr r1, =0x30FC00               /* r1 = 0x30FC00 */

    str r1, [r0, #CLKCTL_CCGR1]     /* CLKCTL_CCGR1 = 0x6c */   /* CG56710 */

    ldr r1, =0xFFFC000

    str r1, [r0, #CLKCTL_CCGR2]     /* CLKCTL_CCGR2 = 0x70 */   /* CG7891013 */

    ldr r1, =0x3FF00000

    str r1, [r0, #CLKCTL_CCGR3]     /* CLKCTL_CCGR3 = 0x74 */   /* CG1011121314 */

    ldr r1, =0xFFF300

    str r1, [r0, #CLKCTL_CCGR4]     /* CLKCTL_CCGR4 = 0x78 */   /* CG46~11 *//* pl301_mx6qfast1_s133pl301_mx6qper1_bchpl301_mx6qper2_mainclk_enablepwm1~4 */

    ldr r1, =0xF0000C3

    str r1, [r0, #CLKCTL_CCGR5]     /* CLKCTL_CCGR5 = 0x7c */   /* CG031213 *//* rom/sdma/uart/uart_serial */

    ldr r1, =0x3FC

    str r1, [r0, #CLKCTL_CCGR6]     /* CLKCTL_CCGR6 = 0x80 */   /* CG1~4 *//* 使能 usdhc1~4 */

.endm

补充:

CCM Clock Gating Register 0 (CCM_CCGR0)

地址:0x020c 4068

这些比特位都被用来独立地打开或者关闭时钟,下表详细说明了每个模块可能的时钟活动条件。

 

在将其位设置为“0”之前,模块应该停止;该模块的时钟将立即停止。

上面的表格显示了不同CGRs的寄存器映射。时钟连接表应该用于匹配实际的进入相应模块的“CCM输出时钟。

下图显示了CCM时钟门控寄存器0ccmccgr0)。时钟门控寄存器为每个时钟的功率减少定义了时钟门控(CGi)位)。有7CGR寄存器。所需要的寄存器的数量是根据系统中外围设备的数量来决定的。

Address: 20C_4000h base + 68h offset = 20C_4068h

 

 

CCGR0 ~ CCGR6 原理都是一样的。

 

 

 

 

猜你喜欢

转载自blog.csdn.net/qq_38022972/article/details/81511339