@ Check if this is a wake-up from sleep
Procedure to Wake-up from Power_OFF mode
(电源从POWER-OFF MODE中wake-up需做的事,在这里主要讨论如何设置SDRAM那部分,第2,3,4、5)
1. The internal reset signal will be asserted if one of the wake-up sources is issued. This reset duration is
determined by the internal 16-bit counter logic and the reset assertion time is calculated as tRST = (65535 /
XTAL_frequency).
2. Check GSTATUS2[2] in order to know whether or not the power-up is caused by the wake-up from
Power_OFF mode.
3. Release the SDRAM signal protection by setting MISCCR[19:17]=000b.
4. Configure the SDRAM memory controller.
5. Wait until the SDRAM self-refresh is released. Mostly SDRAM needs the refresh cycle of all SDRAM row.
6. The information in GSTATUS3,4 can be used for user’s own purpose because the value in GSTATUS3,4 has
been preserved during Power_OFF mode.
7. – For EINT[3:0], check the SRCPND register.
– For EINT[15:4], check the EINTPEND instead of SRCPND (SRCPND will not be set although some bits of
EINTPEND are set.).
– For alarm wake-up, check the RTC time because the RTC bit of SRCPND isn’t set at the alarm wake-up.
– If there was the nBATT_FLT assertion during POWER_OFF mode, the corresponding bit of SRCPND has
been set.
ldr r1, PMST_ADDR
ldr r0, [r1]
tst r0, #(PMST_SMR)
bne WakeupStart
2. Check GSTATUS2[1] in order to know whether or not the power-up is caused by the wake-up from
Power_OFF mode.
翻译出来就很明白这段代码在做什么。
【GENERAL STATUS REGISTER (GSTATUSn)
通用状态寄存器】
GSTATUS2 0x560000B4 —— Reset status
OFFRST [1] Power_OFF reset. The reset after the wakeup from Power_OFF mode.
The setting is cleared by writing "1" to this bit.
如果GSTATUS2[1]=1则表示SDRAM处于wake-up状态,不等则跳转到WakeupStart
head.S定义如下:
PMST_ADDR:
.long 0x560000B4
"vivi/include/S3c2410.h"中定义如下
#define PMST_WDR (1
#endif
#ifdef CONFIG_S3C2410_SMDK
@ All LED on
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_F
ldr r2,=0x55aa
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
mov r2, #0x00
str r2, [r1, #oGPIO_DAT]
配置GPIO口点亮所有开发板上面的LED,具体输出IO口根据具体的开发板配置
#endif
#if 0@这段代码没执行,代码所做的事是使处理器工作在管理模式,指令arm执行
@ SVC
mrs r0, cpsr
bic r0, r0, #0xdf
orr r1, r0, #0xd3
msr cpsr_all, r1
#endif
@ set GPIO for UART(这段代码可选)
mov r1, #GPIO_CTL_BASE
GPIO_CTL_BASE=0x56000000
add r1, r1, #oGPIO_H
oGPIO_H=0x70
这样r1=0x56000070
GPHCON 0x56000070 R/W Configure the pins of port H
ldr r2, gpio_con_uart
gpio_con_uart=vGPHCON=0x0016faaa
str r2, [r1, #oGPIO_CON]
oGPIO_CON=0x0 ,将r2的值载入到0x56000070
ldr r2, gpio_up_uart
gpio_up_uart=vGPHUP=0x000007ff
str r2, [r1, #oGPIO_UP]
oGPIO_UP=0x8,将0x7ff的值载入0x56000078
作用是使上拉电阻不起作用
bl InitUART
#ifdef CONFIG_DEBUG_LL
@ Print current Program Counter
ldr r1, SerBase
mov r0, #'\r'
bl PrintChar
mov r0, #'\n'
bl PrintChar
mov r0, #'@'
bl PrintChar
mov r0, pc
bl PrintHexWord
#endif
#ifdef CONFIG_BOOTUP_MEMTEST
@ simple memory test to find some DRAM flaults.
bl memtest
#endif
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
#ifdef CONFIG_DEBUG_LL
ldr r1, SerBase
ldr r0, STR_STACK
bl PrintWord
ldr r0, DW_STACK_START
bl PrintHexWord
#endif
@ get read to call C functions
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
mov a2, #0 @ set argv to NULL
bl main @ call main
mov pc, #FLASH_BASE @ otherwise, reboot
@
@ End VIVI head
@
/*
* subroutines
*/
@
@ Wake-up codes
@
#ifdef CONFIG_PM
WakeupStart:
@ Clear sleep reset bit
ldr r0, PMST_ADDR
mov r1, #PMST_SMR
str r1, [r0]
这段代码详见上面 Check if this is a wake-up from sleep
@ Release the SDRAM signal protections
ldr r0, PMCTL1_ADDR
ldr r1, [r0]
bic r1, r1, #(SCLKE | SCLK1 | SCLK0)
str r1, [r0]
3. Release the SDRAM signal protection by setting MISCCR[19:17]=000b.在下面
“Set the SDRAM singal protections”
有详细说明
@ Go...
ldr r0, PMSR0_ADDR @ read a return address
ldr r1, [r0]
mov pc, r1
“head.S”有如下定义
PMSR0_ADDR:
.long 0x560000B8
GSTATUS3 0x560000B8 Infrom register 0x0
INFORM [31:0] Inform register. This register is cleared by nRESET or watchdog timer.
Otherwise, preserve data value.
GSTATUS3寄存器中保存了return address?没看到????
当程序转移时,转移指令执行的最终结果就是要改变PC的值,此PC值就是转去的地址,以此实现转移
nop
nop
1: b 1b @ infinite loop
设置这个死循环的作用是,假如上面的指令没实现跳转,程序将在这永远执行,不会顺序执行到下面。
SleepRamProc:
@ SDRAM is in the self-refresh mode */
ldr r0, REFR_ADDR
在head.S后面有这样的定义
REFR_ADDR:
.long 0x48000024
REFRESH CONTROL REGISTER(SDRAM刷新控制寄存器)
SDRAM refresh control register
9. Let SDRAM enter the self-refresh mode by setting the REFRESH[22]=1b.
由上面这句话可知,只需设置REFRESH[22]=1b
[ vivi/include/S3c2410.h]
#define SELF_REFRESH (1
ldr r1, [r0]
orr r1, r1, #SELF_REFRESH
使用orr语句赋值的原因是说只改变REFRESH的[22]这一位
str r1, [r0]
10. Wait until SDRAM self-refresh is effective.
11. Set MISCCR[19:17]=111b to make SDRAM signals(SCLK0,SCLK1 and SCKE) protected during Power_OFF
mode
12. Set the Power_OFF mode bit in the CLKCON register.
@ wait until SDRAM into self-refresh
mov r1, #16
1: subs r1, r1, #1
bne 1b
10. Wait until SDRAM self-refresh is effective.
设置延时程序使SDRAM的自我刷新有效。
解释下bne 1b
意思是上面减法r1的值不为0则跳转,跳转到程序向前标号最近为1的地方执行,若指令为bne 1f则为程序向后寻找跳转
@ Set the SDRAM singal protections
11. Set MISCCR[19:17]=111b to make SDRAM signals(SCLK0,SCLK1 and SCKE) protected during Power_OFF
mode
找出MISCCR寄存器(混杂控制寄存器):
MISCCR 0x56000080 Miscellaneous control register
Set MISCCR[19:17]=111b
nEN_SCKE [19] 0: SCKE = Normal 1:SCKE = L level
Used to protect SDRAM during the Power_OFF moe.
nEN_SCLK1 [18] 0: SCLK1= SCLK 1:SCLK1= L level
Used to protect SDRAM during the Power_OFF moe.
nEN_SCLK0 [17] 0: SCLK0= SCLK 1:SCLK0= L level
Used to protect SDRAM during the Power_OFF moe.
下面语句中
head.S中有定义如下:
PMCTL1_ADDR:
.long 0x56000080
[ vivi/include/S3c2410.h]中有如下定义:
#define SCLKE (1
ldr r0, PMCTL1_ADDR
ldr r1, [r0]
orr r1, r1, #(SCLKE | SCLK1 | SCLK0)
str r1, [r0]
/* Sleep... Now */
12. Set the Power_OFF mode bit in the CLKCON register.
CLOCK CONTROL REGISTER (CLKCON)
CLKCON 0x4C00000C Clock generator control register
POWER-OFF [3]
Control Power Off mode of S3C2410.
0 = Disable, 1 = Transition to Power_OFF mode
0
head.S中有定义如下:
PMCTL0_ADDR:
.long 0x4c00000c
[ vivi/include/S3c2410.h]中有如下定义:
#define SLEEP_ON (1
ldr r0, PMCTL0_ADDR
ldr r1, [r0]
orr r1, r1, #SLEEP_ON
str r1, [r0]
1: b 1b
上面这句代码,执行起来是一个无限循环,放在这的意思,实在迷惑。
做个大胆猜测,S3C2410进入POWER-OFF MODE,就在这跳转,直到
WAKE-UP的到来?
#ifdef CONFIG_TEST
hmi:
ldr r0, PMCTL0_ADDR
PMCTL0_ADDR=0x4C00000C
CLKCON 0x4C00000C R/W Clock generator control register 0x7FFF0
使用默认值
代码的具体功能?然道是测试所有设备工作状态
ldr r1, =0x7fff0
str r1, [r0]
@ All LED on
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_F
ldr r2,=0x55aa
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
mov r2, #0xe0
str r2, [r1, #oGPIO_DAT]
1: b 1b
#endif
#endif
ENTRY(memsetup)
@ initialise the static memory
SDRAM初始化
@ set memory control registers
mov r1, #MEM_CTL_BASE
"vivi/include/S3c2410.h"
#define MEM_CTL_BASE 0x48000000
adrl r2, mem_cfg_val
add r3, r1, #52
1: ldr r4, [r2], #4
str r4, [r1], #4
cmp r1, r3
bne 1b
在SDRAM设置过程中,通过一个比较循环完成13个寄存器的配置,其写入的值如下:
"head.S"有如下定义:
@ Memory configuration values
.align 4
mem_cfg_val:
.long vBWSCON
.long vBANKCON0
.long vBANKCON1
.long vBANKCON2
.long vBANKCON3
.long vBANKCON4
.long vBANKCON5
.long vBANKCON6
.long vBANKCON7
.long vREFRESH
.long vBANKSIZE
.long vMRSRB6
.long vMRSRB7
"vivi/include/Smdk2410.h"
/* initial values for DRAM */
#define vBWSCON 0x22111110
#define vBANKCON0 0x00000700
#define vBANKCON1 0x00000700
#define vBANKCON2 0x00000700
#define vBANKCON3 0x00000700
#define vBANKCON4 0x00000700
#define vBANKCON5 0x00000700
#define vBANKCON6 0x00018005
#define vBANKCON7 0x00018005
#define vREFRESH 0x008e0459
#define vBANKSIZE 0xb2
#define vMRSRB6 0x30
#define vMRSRB7 0x30
先看S3C2410的第五部分有如下一段话:
The S3C2410X has the following features:
— Little/Big endian (selectable by a software)
— Address space: 128Mbytes per bank (total 1GB/8 banks)
— Programmable access size (8/16/32-bit) for all banks except bank0 (16/32-bit)
— Total 8 memory banks
Six memory banks for ROM, SRAM, etc.
Remaining two memory banks for ROM, SRAM, SDRAM, etc .
— Seven fixed memory bank start address
— One flexible memory bank start address and programmable bank size
从这段文字我们可以知道,S3C2410支持1GB的内存寻址,一共8个BANK,8*128MB=1GB,而且只有在bank6和bank7上才能接SRAM。
从开发板datasheet可知:
在板上用了两块HY57V561620BT-H SDRAM构成动态存储器
查看HY57V561620BT-H的datesheet可知
HY57V561620BT-H 4Banks x 4Mbits x16=256Mbite=32MB
两片为64MB够成32bit位宽可以查看其寻址范围为:
[0x30000000-0x33ffffff]
由于Bank 6 and 7 must have the same memory size
bank7的内存空间为
[0x34000000-0x37ffffff]
下面介绍具体的寄存器配置:
在配置的13个寄存器中:有些是默认值,只是为了写程序方便才配置如此多
BWSCON 0x48000000 Bus width & wait status control register
32位,8个bank,除了bank0只使用了【2:1】其他四位配置一个bank。
主要配置每个bank的位宽,以bank6为例,其为32位所以选择10
DW6 [25:24] Determine data bus width for bank 6.
00 = 8-bit 01 = 16-bit, 10 = 32-bit 11 = reserved
顾配置其值为0x22111110
BANK CONTROL REGISTER (BANKCONN: nGCS0-nGCS5)
for bank0-5 control,使用默认值就可
BANKCON0 0x48000004 R/W Bank 0 control register 0x0700
BANKCON1 0x48000008 R/W Bank 1 control register 0x0700
BANKCON2 0x4800000C R/W Bank 2 control register 0x0700
BANKCON3 0x48000010 R/W Bank 3 control register 0x0700
BANKCON4 0x48000014 R/W Bank 4 control register 0x0700
BANKCON5 0x48000018 R/W Bank 5 control register 0x0700
BANK CONTROL REGISTER (BANKCONn: nGCS6-nGCS7)
BANKCON6 0x4800001C R/W Bank 6 control register
BANKCON7 0x48000020 R/W Bank 7 control register
[16:15] Determine the memory type for bank6 and bank7
00 = ROM or SRAM 01 = Reserved (Do not use)
10 = Reserved (Do not use) 11 = Sync. DRAM
很显然这里选择11
[14:4]采用默认值:
Trcd [3:2] RAS to CAS delay
00 = 2 clocks 01 = 3 clocks 10 = 4 clocks
查看datesheet Trcd的-H指标为至少20ns,而HCLK的时钟周期为10ns,所以选01
SCAN [1:0] Column address number
00 = 8-bit 01 = 9-bit 10= 10-bit
Column Address : CA0 ~ CA8, 选01
所以写入该寄存器的值为0x18005
REFRESH 0x48000024 R/W SDRAM refresh control register
具体参考S3C2410的第五章REFRESH的datesheet
·REFEN[23]:开启自动模式,设为1
·TREFMD[22]:设为Auto refresh模式,设为0
·Trp[21:20]:看看RAS precharge Time,查看SDRAM手册,发现-H系列此参数至少为20ns,所以至少应该为2个clock。可以设为00
·Tsrc:也就是RAS Cycle Time,至少65ms,所以至少得6.5clock,按照可选值,应该设置为11
·Refresh[10:0]:
公式refresh period = (2^11 - refresh_count +1)/Hclk,由此推导出refresh_count=2^11+1-refresh period*Hclk。带入数值,计算得出2^11+1-7.8125u*100M=1268=0x04f4与0459有点误差但无大碍
·其余的保留值,均设置为0
所以写入该寄存器的值为0x8e04f4
mov pc, lr
lr=R14,pc=R15,在执行带链接的分支指令时,lr得到PC的拷贝,当程序返回了,把lr返回给PC
#ifdef CONFIG_S3C2410_NAND_BOOT
@
@ copy_myself: copy vivi to ram
@
copy_myself:
mov r10, lr
把程序计数器的值保存在r10中
@ reset NAND
因为前4KB自动引导到 S3C2410X 的内在SRAM buffer (“Steppingstone”)后 ,NAND FLASH 被自动禁用
提供S3C2410 NAND Flash的中文datesheet

文件:
S3C2410中文手册第六章.pdf
大小:
257KB
下载:
下载
mov r1, #NAND_CTL_BASE
"vivi/include/S3c2410.h"
/* NAND Flash Controller */
#define NAND_CTL_BASE 0x4E000000
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
ldr r2, =0xf830 @ initial value
str r2, [r1, #oNFCONF]
将0xf830 装载到0x4E000000
NFCONF 0x4E000000 R/W NAND Flash configuration
Enable/Disable [15] 1=Enable NAND Flash Controller
Initialize ECC [12] 1 : Initialize ECC
NAND Flash Memory chip enable [11] NAND Flash Memory nFCE control
0 : NAND flash nFCE = L (active)
1 : NAND flash nFCE = H (inactive)
(After auto-boot, nFCE will be inactive.)
由TACLS=0, TWRPH0=1, TWRPH1=0
可设置位【10:8】=000,【6:4】=011,【2:0】=000
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800
使NFCONF【11】=0 0:NAND flash nFCE = L 使能芯片
这里有个问题,为什么不在上面直接写0,而是在配置好了才使能芯片???
str r2, [r1, #oNFCONF]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
将0xff 装载到0x4E000004
mov r3, #0 @ wait
1: add r3, r3, #0x1
cmp r3, #0xa
blt 1b
延时小程序,给NAND Flash准备时间,准备好
2: ldr r2, [r1, #oNFSTAT] @ wait ready
NFSTAT 0x4E000010 R NAND Flash operation status
只读寄存器,这段代买测试NAND Flash 运行状态,若其值为0x00则说明NAND Flash准备好了
tst r2, #0x1
beq 2b
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy vivi to RAM
ldr r0, =VIVI_RAM_BASE
mov r1, #0x0
mov r2, #0x20000
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
#ifdef CONFIG_DEBUG_LL
bad_nand_read:
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
1: b 1b @ infinite loop
#endif
ok_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
@ verify
mov r0, #0
ldr r1, =0x33f00000
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq done_nand_read
bne go_next
notmatch:
#ifdef CONFIG_DEBUG_LL
sub r0, r0, #4
ldr r1, SerBase
bl PrintHexWord
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
#endif
1: b 1b
done_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
mov pc, r10
@ clear memory
@ r0: start address
@ r1: length
mem_clear:
mov r2, #0
mov r3, r2
mov r4, r2
mov r5, r2
mov r6, r2
mov r7, r2
mov r8, r2
mov r9, r2
clear_loop:
stmia {r2-r9}
subs r1, r1, #(8 * 4)
bne clear_loop
mov pc, lr
#endif @ CONFIG_S3C2410_NAND_BOOT
#ifdef CONFIG_BOOTUP_MEMTEST
@
@ Simple memory test function
@
