Skip to content

天楚锐齿

人工智能 云计算 大数据 物联网 IT 通信 嵌入式

天楚锐齿

  • 下载
  • 物联网
  • 云计算
  • 大数据
  • 人工智能
  • Linux&Android
  • 网络
  • 通信
  • 嵌入式
  • 杂七杂八

mini6410板uboot的lowlevel_init.S

2018-03-13
文件:u-boot/board/samsung/mini6410/lowlevel_init.S
#include <config.h>
#include <version.h>

#include <s3c6410.h>
#include “mini6410_val.h”

_TEXT_BASE:
.word     TEXT_BASE                   @每个lds里面的模块,都可以定义一个TEXT_BASE。

.globl lowlevel_init
lowlevel_init:
mov     r12, lr                                @保存PC值到r12

/* LED on only #8 */
ldr     r0, =ELFIN_GPIO_BASE         @GPIO的基地址=0x7f008000
ldr     r1, =0x55540000
str     r1, [r0, #GPNCON_OFFSET]  @设置GPN15到GPN9(GPN15-GPN13为boot中断?,GPN12为IR红外接口,GPN11/GPN9为外部GPIO口,GPN10为SDIO口使用)为输出管脚;

                                                        @GPN8到GPN0(GPN0-GPN5为mini6410的K1到K6的6个按键,GPN7为DM9000网络芯片的INT中断引脚,GPN6为外部GPIO口,GPN8为USB OTG中断接口)为输入管脚。
ldr     r1, =0x55555555
str     r1, [r0, #GPNPUD_OFFSET]  @全部下拉使能

ldr     r1, =0xf000
str     r1, [r0, #GPNDAT_OFFSET]  @设置GPN15-GPN12为1,GPN11-GPN9为1,GPN8-GPN0为输入管脚,设置无效,外部是什么信号,数据就是什么。

ldr     r0, =ELFIN_GPIO_BASE
ldr     r1, =0x1
str     r1, [r0, #GPECON_OFFSET]  @设置GPE4-GPE1(mini6410保留给GPIO)为输入,GPE0(mini6410为LCD的夜晚背光on或off)为输出。

     ldr     r1, =0x0
str     r1, [r0, #GPEDAT_OFFSET]  @设置GPE0输出0。

ldr     r0, =ELFIN_GPIO_BASE
ldr     r1, =0x2A5AAAAA
str     r1, [r0, #GPPCON_OFFSET]  @设置GPP14(mini6410为GPIO)为输入,GPP13-GPP11(GPP13,GPP12在mini6410为GPIO,GPP11为WiFi_PD),GPP8-GPP0(mini6410为GPIO,GPP7-GPP2为Flash,GPP1和GPP0为mem0暂时未用)为MEM0_XXX,GPP10-GPP9(mini6410下GPP9为GPIO,GPP10为WiFi_IO)为输出。
ldr     r1, =0x0
str     r1, [r0, #GPPDAT_OFFSET]  @设置所有输出为0。

ldr     r1, =0x55555555
str     r1, [r0, #MEM1DRVCON_OFFSET]  @设置存储器端口1(mini6410为RAM)芯片管脚的电平为7毫安或10mA。

/* Disable Watchdog */
ldr     r0, =0x7e000000          @0x7e004000
orr     r0, r0, #0x4000
mov     r1, #0
str     r1, [r0]                     @禁止看门狗定时器、复位功能、中断停止等

@ External interrupt pending clear
ldr     r0, =(ELFIN_GPIO_BASE+EINTPEND_OFFSET)     /*EINTPEND*/
ldr     r1, [r0]
str     r1, [r0]                     @读一次外部中断引脚,读完之后中断信号就都被清除,上面已经禁止了中断,所以读完之后就不会再产生中断了。

ldr     r0, =ELFIN_VIC0_BASE_ADDR      @0x71200000 中断控制器0
ldr     r1, =ELFIN_VIC1_BASE_ADDR      @0x71300000 中断控制器1

@ Disable all interrupts (VIC0 and VIC1)
mvn     r3, #0x0               @0取反,为全1
str     r3, [r0, #oINTMSK]  @中断使能清除寄存器全部设置1,清除所有中断使能
str     r3, [r1, #oINTMSK]

@ Set all interrupts as IRQ
mov     r3, #0x0
str     r3, [r0, #oINTMOD]  @所有中断设置为IRQ中断。
str     r3, [r1, #oINTMOD]

@ Pending Interrupt Clear
mov     r3, #0x0
str     r3, [r0, #oVECTADDR]  @设置矢量地址寄存器(当前中断的矢量地址)为全0。
str     r3, [r1, #oVECTADDR]

/* init system clock */
bl system_clock_init              @初始化系统时钟。

/* for UART */
bl uart_asm_init                   @初始化UART串口。

#if defined(CONFIG_NAND)
/* simple init for NAND */
bl nand_asm_init                 @NAND FLASH初始化。
#endif

#if 0
ldr     r0, =0xff000fff
bic     r1, pc, r0          /* r0 <- current base addr of code */
ldr     r2, _TEXT_BASE          /* r1 <- original base addr in ram */
bic     r2, r2, r0          /* r0 <- current base addr of code */
cmp      r1, r2               /* compare r0, r1                  */
beq     1f               /* r0 == r1 then skip sdram init   */
#endif

bl     mem_ctrl_asm_init      @内存控制初始化(参考cpu_init.S)。

#if 1
ldr     r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) @RESET状态,0x7E00F904
ldr     r1, [r0]
bic     r1, r1, #0xfffffff7
cmp     r1, #0x8
beq     wakeup_reset                     @SLEEP模式唤醒导致的reset。

#endif

1:
ldr     r0, =ELFIN_UART_BASE
ldr     r1, =0x4b4b4b4b
str     r1, [r0, #UTXH_OFFSET]  @UART发送缓冲区设置为’K’。

mov     lr, r12
mov     pc, lr                             @初始化完成,返回。
#if 1
wakeup_reset:

/*Clear wakeup status register*/
ldr     r0, =(ELFIN_CLOCK_POWER_BASE+WAKEUP_STAT_OFFSET)
ldr     r1, [r0]
str     r1, [r0]          @写一次唤醒状态寄存器,可以清除掉这些状态。应该写1,这里为什么只写了一下呢?

/*LED test*/
ldr     r0, =ELFIN_GPIO_BASE
ldr     r1, =0x3000
str     r1, [r0, #GPNDAT_OFFSET] @设置GPN14和GPN13的值为1,跟mini6410实际不一致,mini6410的LED在GPK4,5,6,7。

/*Load return address and jump to kernel*/
ldr     r0, =(ELFIN_CLOCK_POWER_BASE+INF_REG0_OFFSET)                       @0x7E00FA00
ldr     r1, [r0]     /* r1 = physical address of s3c6400_cpu_resume function*/ @s3c6400_cpu_resume函数的物理地址保存在这里。
mov     pc, r1          /*Jump to kernel (sleep-s3c6400.S)*/                            @跳到s3c6400_cpu_resume函数执行。s3c6400_cpu_resume找不到?
nop
nop
#endif
/*
* system_clock_init: Initialize core clock and bus clock.
* void system_clock_init(void)
*/
system_clock_init:
ldr     r0, =ELFIN_CLOCK_POWER_BASE     @0x7e00f000

#ifdef     CONFIG_SYNC_MODE              @同步模式选择,内核和总线不同步时,需用异步模式。
ldr     r1, [r0, #OTHERS_OFFSET]
mov     r2, #0x40
orr     r1, r1, r2
str     r1, [r0, #OTHERS_OFFSET]   @设置SYNCMUX的选择为1,就是DOUTAPLL,就是跟ARM内核用同一个锁相环。

nop     @等待系统稳定。
nop
nop
nop
nop

ldr     r2, =0x80
orr     r1, r1, r2
str     r1, [r0, #OTHERS_OFFSET]  @设置同步模式位7为1,变成同步模式。

check_syncack:
ldr     r1, [r0, #OTHERS_OFFSET]
ldr     r2, =0xf00
and     r1, r1, r2
cmp     r1, #0xf00                        @比较0xf00和(OTHERS的同步确认位11,10,9,8的值和0x0f00相与)的值,不等则循环等待。四位全1表示同步完成。
bne     check_syncack
#else     /* ASYNC Mode */
nop
nop
nop
nop
nop

ldr     r1, [r0, #OTHERS_OFFSET]
bic     r1, r1, #0xC0
orr     r1, r1, #0x40
str     r1, [r0, #OTHERS_OFFSET] @设置为异步模式,SYNCMUX的选择为1,就是DOUTAPLL,下面又设置成0,为什么要这样做呢?

wait_for_async:
ldr     r1, [r0, #OTHERS_OFFSET]
and     r1, r1, #0xf00
cmp     r1, #0x0
bne     wait_for_async                   @同步确认四位为全0,表示异步模式稳定下来。

ldr     r1, [r0, #OTHERS_OFFSET]
bic     r1, r1, #0x40
str     r1, [r0, #OTHERS_OFFSET]  @设置SYNCMUX的选择为0,就是MOUTPLL。
#endif

mov     r1, #0xff00
orr     r1, r1, #0xff
str     r1, [r0, #APLL_LOCK_OFFSET]
str     r1, [r0, #MPLL_LOCK_OFFSET]
str     r1, [r0, #EPLL_LOCK_OFFSET]  @设置时钟输出稳定时间为最大
/* CLKUART(=66.5Mhz) = CLKUART_input(532/2=266Mhz) / (UART_RATIO(3)+1) */
/* CLKUART(=50Mhz) = CLKUART_input(400/2=200Mhz) / (UART_RATIO(3)+1) */
/* Now, When you use UART CLK SRC by EXT_UCLK1, We support 532MHz & 400MHz value */

#if defined(CONFIG_CLKSRC_CLKUART)
ldr        r1, [r0, #CLK_DIV2_OFFSET]
bic     r1, r1, #0x70000
orr     r1, r1, #0x30000
str     r1, [r0, #CLK_DIV2_OFFSET]  @设置UART_RATIO为3,即四分频。
#endif

ldr        r1, [r0, #CLK_DIV0_OFFSET]     /*Set Clock Divider*/
bic     r1, r1, #0x30000
bic     r1, r1, #0xff00
bic     r1, r1, #0xff
ldr     r2, =CLK_DIV_VAL
orr     r1, r1, r2
str     r1, [r0, #CLK_DIV0_OFFSET]   @设置时钟分频,PCLK_RATIO,HCLK2_RATIO,HCLK_RATIO,MPLL_RATIO,APLL_RATIO。

ldr     r1, =APLL_VAL
str     r1, [r0, #APLL_CON_OFFSET]  @设置APLL_MDIV,APLL_PDIV,APLL_SDIV。
ldr     r1, =MPLL_VAL
str     r1, [r0, #MPLL_CON_OFFSET]  @设置MPLL_MDIV,MPLL_PDIV,MPLL_SDIV。

ldr     r1, =0x80200203               /* FOUT of EPLL is 96MHz */
str     r1, [r0, #EPLL_CON0_OFFSET]
ldr     r1, =0x0
str     r1, [r0, #EPLL_CON1_OFFSET]  @设置EPLL_MDIV,EPLL_PDIV,EPLL_SDIV,EPLL_KDIV。

ldr     r1, [r0, #CLK_SRC_OFFSET]     /* APLL, MPLL, EPLL select to Fout */

#if defined(CONFIG_CLKSRC_CLKUART)
ldr     r2, =0x2007
#else
ldr     r2, =0x7
#endif
orr     r1, r1, r2

str     r1, [r0, #CLK_SRC_OFFSET]  @设置APLL,MPLL,EPLL时钟源为FOUT,UART为DOUT(同步模式设置为DOUT,异步模式设置为MOUT)。

/* wait at least 200us to stablize all clock */
mov     r1, #0x10000
1:     subs     r1, r1, #1
bne     1b                               @等待所有时钟稳定。
#if 0
mrc     p15, 0, r0, c1, c0, 0
orr     r0, r0, #0xc0000000     /* clock setting in MMU */
mcr     p15, 0, r0, c1, c0, 0
#endif

#ifdef CONFIG_SYNC_MODE                    /* Synchronization for VIC port */
ldr     r1, [r0, #OTHERS_OFFSET]
orr     r1, r1, #0x20
str     r1, [r0, #OTHERS_OFFSET]    @手册上为保留,这里是为了兼容老的?
#else
ldr     r1, [r0, #OTHERS_OFFSET]
bic     r1, r1, #0x20
str     r1, [r0, #OTHERS_OFFSET]
#endif
mov     pc, lr

/*
* uart_asm_init: Initialize UART in asm mode, 115200bps fixed.
* void uart_asm_init(void)
*/
uart_asm_init:
/* set GPIO to enable UART */
@ GPIO setting for UART
ldr     r0, =ELFIN_GPIO_BASE
ldr     r1, =0x22222222
str        r1, [r0, #GPACON_OFFSET]  @设置GPA0-GPA7口为UART用
ldr     r1, =0x2222
str        r1, [r0, #GPBCON_OFFSET]  @设置GPB0-GPB3为UART用

ldr     r0, =ELFIN_UART_CONSOLE_BASE          @0x7F005000
mov     r1, #0x0
str     r1, [r0, #UFCON_OFFSET]        @正常模式,无校验,1bit停止位,5bit数据位。
str     r1, [r0, #UMCON_OFFSET]       @FIFO为63字节,没有流量控制,没有中断,RTS不使能。

mov     r1, #0x3                     @was 0.
str     r1, [r0, #ULCON_OFFSET]        @设置为8bit数据位

#if defined(CONFIG_CLKSRC_CLKUART)
ldr     r1, =0xe45               /* UARTCLK SRC = 11 => EXT_UCLK1*/
#else
ldr     r1, =0x245               /* UARTCLK SRC = x0 => PCLK */
#endif

str     r1, [r0, #UCON_OFFSET]  @设置接收超时中断不使能,使能接收错误中断,非环回模式,正常传输,中断方式发送,中断方式接收。电平方式的接收、发送中断,时钟为UCLK1或PCLK。

#if defined(CONFIG_UART_50)
ldr     r1, =0x1A
#elif defined(CONFIG_UART_66)
ldr     r1, =0x22
#else
ldr     r1, =0x1A
#endif
str     r1, [r0, #UBRDIV_OFFSET]  @设置波特率整数部分:(66000000/(115200X16))-1=34.81, 34的16进制为0x22。

#if defined(CONFIG_UART_50)
ldr     r1, =0x3
#elif defined(CONFIG_UART_66)
ldr     r1, =0x1FFF
#else
ldr     r1, =0x3
#endif
str     r1, [r0, #UDIVSLOT_OFFSET]  @设置波特率小数部分:(UDIVSLOT中1的个数)/16=0.81,则UDIVSLOT中1的个数=12.92,取整为13个,而0x1fff正好有13个二进制1和3个二进制0。

ldr     r1, =0x4f4f4f4f
str     r1, [r0, #UTXH_OFFSET]          @’O’,发送缓冲寄存器里面填入’O’字符。

mov     pc, lr

/*
* Nand Interface Init for SMDK6400 */
nand_asm_init:
ldr     r0, =ELFIN_NAND_BASE          @0x70200000
ldr     r1, [r0, #NFCONF_OFFSET]
orr     r1, r1, #0x70
orr     r1, r1, #0x7700
str     r1, [r0, #NFCONF_OFFSET]   @设置TACLS(信号清除),TWRPH0(读写阶段0),TWRPH1(读写阶段1)(NAND时序图上有)的持续时间。

ldr     r1, [r0, #NFCONT_OFFSET]
orr     r1, r1, #0x03
str     r1, [r0, #NFCONT_OFFSET]   @为了老芯片兼容,s3c6410x低四位为保留。

mov     pc, lr

#ifdef CONFIG_ENABLE_MMU

/*
* MMU Table for SMDK6400
*/

/* form a first-level section entry */
.macro FL_SECTION_ENTRY base,ap,d,c,b                                                  @定义一个可以生成描述符的宏,按照section方式映射,每个section必须是1M,占20位地址,这里共256M物理内存,映射到整个地址空间4G,所以共有4096(0x1000)个描述符。虚拟地址的高12位(4096)作为描述符位置,低20位作为section里面的地址。从下面映射表看出来,虚拟地址0x00000000-0xa0000000跟对应的物理地址是一致的,虚拟地址0xa0000000-0xc0000000和0xc8000000-0xffffffff没有物理地址对应,虚拟地址0xc0000000-0xc8000000跟物理地址0x50000000-0x58000000相对应,所以TEXT_BASE基地址没有MMU时就是物理地址0x57e00000,有MMU时对应的虚拟地址就是0xc7e00000。
.word (\base << 20) | (\ap << 10) | \
(\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)                        @描述符的最低两位00为无效,01为二级页表方式(由高地址12位的一级页表(TTB的高18位指定的虚拟基地址)位置取出对应二级页表(coarse page table)的基地址,由中间地址8位的二级页表取出对应4KB页表(small page)的基地址,最后由低12为地址的页表取出最终的内存值),10为一级页表方式(如果bit18为0,则为section,bit18为1,则为supersection),11保留。
.endm
.section .mmudata, “a”                                                                              @定义MMU数据段,在lds文件里面用到了,“a”表示这是一个需要鉴权的段
.align 14
// the following alignment creates the mmu table at address 0x4000.        @对齐到0x4000(16KB)的整数倍位置,因为TTB寄存器只保存MMU表的高18位地址(16KB对齐位置),所以必须14位对齐。
.globl mmu_table                                                                                  @在start.S中使能MMU的时候用到了。
mmu_table:
.set __base,0                                                                                       @前0xa00(2560)个描述符定义,ap为3表示读写允许。c,b比特为00表示共享,互斥读写。d为0表示这些描述符都属于domain0(domain用来做权限控制)。
// 1:1 mapping for debugging
.rept 0xA00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr

// access is not allowed.
.rept 0xC00 – 0xA00                                                                             @从0xa00-0xc00共512个描述符,ap为0表示不允许访问。
.word 0x00000000
.endr

// 128MB for SDRAM 0xC0000000 -> 0x50000000
.set __base, 0x500                                                                              @从0xc00-0xc80共128个描述符(因为每个描述符代表1M,就是128MB)定义,cb比特为11表示内存输入输出都为回写模式。
.rept 0xC80 – 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr

// access is not allowed.
.rept 0x1000 – 0xc80                                                                           @从0xc80-0x1000共896个描述符,不允许访问。
.word 0x00000000
.endr

#endif

712次阅读

Post navigation

前一篇:

mini6410板uboot的cpu_init.S

后一篇:

mini6410板uboot的Main.c

发表评论 取消回复

邮箱地址不会被公开。 必填项已用*标注

个人介绍

需要么,有事情这里找联系方式:关于天楚锐齿

=== 美女同欣赏,好酒共品尝 ===

微信扫描二维码赞赏该文章:

扫描二维码分享该文章:

分类目录

  • Linux&Android (79)
  • Uncategorized (1)
  • 下载 (28)
  • 云计算 (37)
  • 人工智能 (8)
  • 大数据 (24)
  • 嵌入式 (34)
  • 杂七杂八 (34)
  • 物联网 (59)
  • 网络 (23)
  • 通信 (21)

文章归档

近期文章

  • 使用Python渲染OpenGL的.obj和.mtl文件
  • 用LVGL图形库绘制二维码
  • Android使用Messenger和SharedMemory实现跨app的海量数据传输
  • CAN信号的c语言解析代码
  • QT qml下DBus的使用例子

近期评论

  • 硕发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • maxshu发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • Ambition发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • Ambition发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • maxshu发表在《Android9下用ethernet 的Tether模式来做路由器功能》

阅读量

  • 使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序 - 16,808次阅读
  • 卸载深信服Ingress、SecurityDesktop客户端 - 12,079次阅读
  • 车机技术之Android Automotive - 6,661次阅读
  • 车机技术之车规级Linux-Automotive Grade Linux(AGL) - 5,866次阅读
  • Linux策略路由及iptables mangle、ip rule、ip route关系及一种Network is unreachable错误 - 5,711次阅读
  • 在Android9下用ndk编译vSomeIP和CommonAPI以及使用例子 - 5,658次阅读
  • linux下的unbound DNS服务器设置详解 - 5,601次阅读
  • linux的tee命令导致ssh客户端下的shell卡住不动 - 4,998次阅读
  • 车机技术之360°全景影像(环视)系统 - 4,897次阅读
  • libwebp(处理webp图像)的安装和使用 - 4,749次阅读

功能

  • 文章RSS
  • 评论RSS

联系方式

地址
深圳市科技园

时间
周一至周五:  9:00~12:00,14:00~18:00
周六和周日:10:00~12:00

标签

android AT命令 centos Hadoop hdfs ip ipv6 kickstart linux mapreduce mini6410 modem OAuth openstack os python socket ssh uboot 内核 协议 安装 嵌入式 性能 报表 授权 操作系统 数据 数据库 月报 模型 汽车 测试 深信服 深度学习 源代码 神经网络 统计 编译 网络 脚本 虚拟机 调制解调器 车机 金融
© 2023 天楚锐齿