嵌入式Linux裸机开发(五)——SDRAM初始化

嵌入式Linux裸机开发(五)——SDRAM初始化

一、SDRAM初始化流程

S5PV210有两个独立的DRAM控制器,一个最大支持512MB,一个最大支持1024MB,但两个控制器必须支持相同类型的内存。

根据三星S5PV210文档可知,DDR2类型内存的初始化流程如下:

1、提供稳压电源给内存控制器和内存芯片,内存控制器必须保持CLE在低电平,此时就会提供稳压电源。注:当CKE引脚为低电平时,XDDR2SEL应该处于高电平

2、根据时钟频率正确配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_inc的值。配置的PhyControl0.ctrl_dll_on值为‘1‘以打开PHY DLL。

3、数据选取脉DQS清除:依照时钟频率和内存的tAC参数正确设置PhyControl1.ctrl_shiftc和PhyControl1.ctrl_offsetcbit位的值。

4、设置PhyControl0.ctrl_start位的值为‘1‘

5、设置ConControl,同时关闭auto refresh自动刷新计数器

6、设置MemControl,同时关闭所有的power down(休眠模式)。

7、设置MemConfig0寄存器。如果有两组内存芯片(比如有8片DDR,这8片DDR是分别挂在Memory Port1和Memory Port2上),再配置MemConfig1寄存器。

8、设置PrechConfig和PwrdnConfig寄存器

9、根据内存的tAC参数设置TimingAref,TimingRow, TimingData和TimingPower寄存器

10、如果需要QoS标准,配置QosControl0—15和QosConfig0-15寄存器

11、等待PhyStatus0.ctrl_locked位变为‘1‘。检查是否PHY DLL是否已锁

12、PHY DLL补偿在内存操作时由PVT(Process, Voltage and Temperature,处理器、电压和温度)变化引起的延迟量。但是,PHY DLL不能因某些可靠的内存操作而切断,除非是工作在低频率下。如果关闭PHY DLL,依照PhyStatus0.ctrl_lock_value[9:2]位的值正确配置PhyControl0.ctrl_force位的值来弥补延迟量(fix delay amount)。清除PhyControl0.ctrl_dll_on位的值来关闭PHY DLL。

13、上电后,确定最小值为200us的稳定时钟是否发出

14、使用DirectCmd寄存器发出一个NOP命令,保证CKE引脚为高电平

15、等最小400ns

16、使用DirectCmd寄存器发出一个PALL命令

17、使用DirectCmd寄存器发出一个EMRS2命令,program操作参数

18、使用DirectCmd寄存器发出一个EMRS3命令,program操作参数

19、使用DirectCmd寄存器发出一个EMRS命令来使能内存DLLs

20、使用DirectCmd寄存器发出一个MRS命令,重启内存DLL

21、使用DirectCmd寄存器发出一个PALL命令

22、使用DirectCmd寄存器发出两个Auto Refresh(自动刷新)命令

23、使用DirectCmd寄存器发出一个MRS命令,program操作参数,不要重启内存DLL

24、等待最小200时钟周期

25、使用DirectCmd寄存器发出一个EMRS命令给程序的运行参数。如果OCD校正(Off-Chip Driver,片外驱动调校)没有使用,改善一个EMRS命令去设置OCD校准的默认值。在此之后,发送一个EMRS指令去退出OCD校准模式,继续program操作参数

26、如果有两组DDR芯片,重复14-25步配置chip1的内存,刚刚配置的是chip0,也就是第一组内存芯片

27、配置ConControlto来打开自动刷新计数器

28、如果需要power down(休眠)模式,配置MemControl寄存器。

二、电路原理图解读

查阅核心板电路原理图,找到DDR相关部分,S5PV210有两个内存端口,分别为DRAM0和DRAM1,对应地址范围如下:

DRAM0:0x20000000——0x3FFFFFFF512MB

DRAM1:0x40000000——0x7FFFFFFF1024MB

Smart210开发板共有四片128MB的内存芯片,每片芯片有14根地址线Xm1ADDR[13:0],8根数据线Xm1DATA[7:0],其余为控制总线。

四片内存芯片并联后逻辑上只是一片内存芯片,大小为512MB,数据线为Xm1DATA[31:0],地址线不变Xm1ADDR[13:0]。根据DRAM原理图的片选引脚nCS、CKE、nWE选择知道,smart210开发板的四片内存芯片挂接到DMC0。

三、SDRAM初始化

sdram_init.S源代码:

#include "s5pv210.h"

// MemControlBL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off

#define DMC0_MEMCONTROL0x00202400

// MemConfig0256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed

#define DMC0_MEMCONFIG_00x20F00313

// MemConfig1

#define DMC0_MEMCONFIG_10x00F00313

// TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) 200MHZ=0x618

#define DMC0_TIMINGA_REF        0x00000618

// TimingRow    for @200MHz

#define DMC0_TIMING_ROW         0x2B34438A

// TimingData   CL=3

#define DMC0_TIMING_DATA        0x24240000

// TimingPower

#define DMC0_TIMING_PWR         0x0BDC0343

.global sdram_init

sdram_init:

//IO端口驱动强度设置

// 1. 设置DMC0 Drive Strength (Setting 2X)

ldrr0, =ELFIN_GPIO_BASE

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_0DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_1DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_2DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_3DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_4DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_5DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_6DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_7DRV_SR_OFFSET]

ldrr1, =0x00002AAA

strr1, [r0, #MP1_8DRV_SR_OFFSET]

// 2. 初始化PHY DLL

ldrr0, =APB_DMC_0_BASE

//step 3: PhyControl0 DLL parameter setting, manual 0x00101000

ldrr1, =0x00101000

strr1, [r0, #DMC_PHYCONTROL0]

//PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case

ldrr1, =0x00000086

strr1, [r0, #DMC_PHYCONTROL1]

//step 2: PhyControl0 DLL on

ldrr1, =0x00101002

strr1, [r0, #DMC_PHYCONTROL0]

//step 4: PhyControl0 DLL start

ldrr1, =0x00101003

strr1, [r0, #DMC_PHYCONTROL0]

find_lock_val:

//Loop until DLL is locked

ldrr1, [r0, #DMC_PHYSTATUS]

andr2, r1, #0x7

cmpr2, #0x7

bnefind_lock_val

//Force Value locking

andr1, #0x3fc0

movr2, r1, LSL #18

orrr2, r2, #0x100000

orrr2 ,r2, #0x1000

orrr1, r2, #0x3

strr1, [r0, #DMC_PHYCONTROL0]

// 3. 初始化DMC0

//step 5: ConControl auto refresh off

ldrr1, =0x0FFF2010

strr1, [r0, #DMC_CONCONTROL]

//step 6: MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off

ldrr1, =DMC0_MEMCONTROL

strr1, [r0, #DMC_MEMCONTROL]

//step 7: MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed

ldrr1, =DMC0_MEMCONFIG_0

strr1, [r0, #DMC_MEMCONFIG0]

//MemConfig1

ldrr1, =DMC0_MEMCONFIG_1

strr1, [r0, #DMC_MEMCONFIG1]

//step 8:PrechConfig

ldrr1, =0xFF000000

strr1, [r0, #DMC_PRECHCONFIG]

//step 9:TimingAref7.8us//133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)

ldrr1, =DMC0_TIMINGA_REF

strr1, [r0, #DMC_TIMINGAREF]

//TimingRowfor //200MHz

ldrr1, =DMC0_TIMING_ROW

strr1, [r0, #DMC_TIMINGROW]

//TimingDataCL=4

ldrr1, =DMC0_TIMING_DATA

strr1, [r0, #DMC_TIMINGDATA]

//TimingPower

ldrr1, =DMC0_TIMING_PWR

strr1, [r0, #DMC_TIMINGPOWER]

// 4. 初始化DDR2 DRAM

//DirectCmdchip0 Deselect

ldrr1, =0x07000000//NOP

strr1, [r0, #DMC_DIRECTCMD]

//step 16:DirectCmdchip0 PALL

ldrr1, =0x01000000//

strr1, [r0, #DMC_DIRECTCMD]

//step 17:DirectCmdchip0 EMRS2

ldrr1, =0x00020000

strr1, [r0, #DMC_DIRECTCMD]

//step 18:DirectCmdchip0 EMRS3

ldrr1, =0x00030000

strr1, [r0, #DMC_DIRECTCMD]

//step 19:DirectCmdchip0 EMRS1 (MEM DLL on, DQS# disable)

ldrr1, =0x00010400

strr1, [r0, #DMC_DIRECTCMD]

//step 20:DirectCmdchip0 MRS (MEM DLL reset) CL=4, BL=4

ldrr1, =0x00000542

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 PALL

ldrr1, =0x01000000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 REFA

ldrr1, =0x05000000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 REFA

ldrr1, =0x05000000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 MRS (MEM DLL unreset)

ldrr1, =0x00000442

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 EMRS1 (OCD default)

ldrr1, =0x00010780

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 EMRS1 (OCD exit)

ldrr1, =0x00010400

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 Deselect

ldrr1, =0x07100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 PALL

ldrr1, =0x01100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS2

ldrr1, =0x00120000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS3

ldrr1, =0x00130000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS1 (MEM DLL on, DQS# disable)

ldrr1, =0x00110400

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 MRS (MEM DLL reset) CL=4, BL=4

ldrr1, =0x00100542

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 PALL

ldrr1, =0x01100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 REFA

ldrr1, =0x05100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 REFA

ldrr1, =0x05100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 MRS (MEM DLL unreset)

ldrr1, =0x00100442

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS1 (OCD default)

ldrr1, =0x00110780

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS1 (OCD exit)

ldrr1, =0x00110400

strr1, [r0, #DMC_DIRECTCMD]

//ConControlauto refresh on

ldrr1, =0x0FF02030

strr1, [r0, #DMC_CONCONTROL]

//PwrdnConfig

ldrr1, =0xFFFF00FF

strr1, [r0, #DMC_PWRDNCONFIG]

//MemControlBL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off

ldrr1, =0x00202400

strr1, [r0, #DMC_MEMCONTROL]

movpc, lr

四、重定位至SDRAM实践

程序源码文件包含:

start.S:程序主函数

sdram_init.S:初始化SDRAM的函数

led_blink.c:led闪烁函数

Makefile和link.lds

start.S:

//#define WDTCON0xE2700000

#define SVC_SP0xD0037D80

.global _start

_start:

//C语言运行时栈设置SVC模式下的栈 CPU复位后为SVC模式,DRAM尚未初始化,

//只有SRAM可用,0xD0037780,0xD0037D80,大小1.5K

ldr sp,=SVC_SP

//初始化SDRAM

bl sdram_init

//重定位

adr r0,_start//加载_start当前运行地址

ldr r1,=_start//加载_start的链接地址

ldr r2,=bss_start//加载bss段的起始地址

cmp r0,r1//比较运行地址和链接地址是否相等

beq clean_bss//相等则表明不需要重定位

//拷贝text段和data段

copy_loop:

ldr r3,[r0],#4

str r3,[r1],#4

cmp r1,r2

bne copy_loop

//清除bss段满足C语言运行时要求,编译器会负责清除bss段,

//编译器清除了运行时地址的bss段,链接地址的bss段未清除

clean_bss:

ldr r0,=bss_start

ldr r1,=bss_end

cmp r0,r1

beq run_on_dram//相等则bss为空

mov r2,#0

clear_loop:

str r2,[r0],#4//现将r2放入r0的值对应的内存地址中,然后r0=r0+4

cmp r0,r1

bne clear_loop

run_on_dram:

ldr pc,=led_blink

.end

sdram_init.S源码:

#include "s5pv210.h"

// MemControlBL=4, 1Chip, DDR2 Type, dynamic self refresh, force precharge, dynamic power down off

#define DMC0_MEMCONTROL0x00202400

// MemConfig0256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed

#define DMC0_MEMCONFIG_00x20F00313

// MemConfig1

#define DMC0_MEMCONFIG_10x00F00313

// TimingAref   7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)

#define DMC0_TIMINGA_REF        0x00000618

// TimingRow    for @200MHz

#define DMC0_TIMING_ROW         0x2B34438A

// TimingData   CL=3

#define DMC0_TIMING_DATA        0x24240000

// TimingPower

#define DMC0_TIMING_PWR         0x0BDC0343

.globl sdram_init

sdram_init:

// 1. 设置DMC0 Drive Strength (Setting 2X)

ldrr0, =ELFIN_GPIO_BASE

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_0DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_1DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_2DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_3DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_4DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_5DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_6DRV_SR_OFFSET]

ldrr1, =0x0000AAAA

strr1, [r0, #MP1_7DRV_SR_OFFSET]

ldrr1, =0x00002AAA

strr1, [r0, #MP1_8DRV_SR_OFFSET]

// 2. 初始化PHY DLL

ldrr0, =APB_DMC_0_BASE

//step 3: PhyControl0 DLL parameter setting, manual 0x00101000

ldrr1, =0x00101000

strr1, [r0, #DMC_PHYCONTROL0]

//PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case

ldrr1, =0x00000086

strr1, [r0, #DMC_PHYCONTROL1]

//step 2: PhyControl0 DLL on

ldrr1, =0x00101002

strr1, [r0, #DMC_PHYCONTROL0]

//step 4: PhyControl0 DLL start

ldrr1, =0x00101003

strr1, [r0, #DMC_PHYCONTROL0]

find_lock_val:

//Loop until DLL is locked

ldrr1, [r0, #DMC_PHYSTATUS]

andr2, r1, #0x7

cmpr2, #0x7

bnefind_lock_val

//Force Value locking

andr1, #0x3fc0

movr2, r1, LSL #18

orrr2, r2, #0x100000

orrr2 ,r2, #0x1000

orrr1, r2, #0x3

strr1, [r0, #DMC_PHYCONTROL0]

// 3. 初始化DMC0

//step 5: ConControl auto refresh off

ldrr1, =0x0FFF2010

strr1, [r0, #DMC_CONCONTROL]

//step 6: MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off

ldrr1, =DMC0_MEMCONTROL

strr1, [r0, #DMC_MEMCONTROL]

//step 7: MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed

ldrr1, =DMC0_MEMCONFIG_0

strr1, [r0, #DMC_MEMCONFIG0]

//MemConfig1

ldrr1, =DMC0_MEMCONFIG_1

strr1, [r0, #DMC_MEMCONFIG1]

//step 8:PrechConfig

ldrr1, =0xFF000000

strr1, [r0, #DMC_PRECHCONFIG]

//step 9:TimingAref7.8us//133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)

ldrr1, =DMC0_TIMINGA_REF

strr1, [r0, #DMC_TIMINGAREF]

//TimingRowfor //200MHz

ldrr1, =DMC0_TIMING_ROW

strr1, [r0, #DMC_TIMINGROW]

//TimingDataCL=4

ldrr1, =DMC0_TIMING_DATA

strr1, [r0, #DMC_TIMINGDATA]

//TimingPower

ldrr1, =DMC0_TIMING_PWR

strr1, [r0, #DMC_TIMINGPOWER]

// 4. 初始化DDR2 DRAM

//DirectCmdchip0 Deselect

ldrr1, =0x07000000

strr1, [r0, #DMC_DIRECTCMD]

//step 16:DirectCmdchip0 PALL

ldrr1, =0x01000000

strr1, [r0, #DMC_DIRECTCMD]

//step 17:DirectCmdchip0 EMRS2

ldrr1, =0x00020000

strr1, [r0, #DMC_DIRECTCMD]

//step 18:DirectCmdchip0 EMRS3

ldrr1, =0x00030000

strr1, [r0, #DMC_DIRECTCMD]

//step 19:DirectCmdchip0 EMRS1 (MEM DLL on, DQS# disable)

ldrr1, =0x00010400

strr1, [r0, #DMC_DIRECTCMD]

//step 20:DirectCmdchip0 MRS (MEM DLL reset) CL=4, BL=4

ldrr1, =0x00000542

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 PALL

ldrr1, =0x01000000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 REFA

ldrr1, =0x05000000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 REFA

ldrr1, =0x05000000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 MRS (MEM DLL unreset)

ldrr1, =0x00000442

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 EMRS1 (OCD default)

ldrr1, =0x00010780

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip0 EMRS1 (OCD exit)

ldrr1, =0x00010400

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 Deselect

ldrr1, =0x07100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 PALL

ldrr1, =0x01100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS2

ldrr1, =0x00120000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS3

ldrr1, =0x00130000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS1 (MEM DLL on, DQS# disable)

ldrr1, =0x00110400

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 MRS (MEM DLL reset) CL=4, BL=4

ldrr1, =0x00100542

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 PALL

ldrr1, =0x01100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 REFA

ldrr1, =0x05100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 REFA

ldrr1, =0x05100000

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 MRS (MEM DLL unreset)

ldrr1, =0x00100442

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS1 (OCD default)

ldrr1, =0x00110780

strr1, [r0, #DMC_DIRECTCMD]

//DirectCmdchip1 EMRS1 (OCD exit)

ldrr1, =0x00110400

strr1, [r0, #DMC_DIRECTCMD]

//ConControlauto refresh on

ldrr1, =0x0FF02030

strr1, [r0, #DMC_CONCONTROL]

//PwrdnConfig

ldrr1, =0xFFFF00FF

strr1, [r0, #DMC_PWRDNCONFIG]

//MemControlBL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off

ldrr1, =0x00202400

strr1, [r0, #DMC_MEMCONTROL]

movpc, lr

led_blink.c源码:

#define rGPJ2CON (*((volatile unsigned int *)0xE0200280))

#define rGPJ2DAT (*((volatile unsigned int *)0xE0200284))

void led_blink(void);

void delay(void);

void led_blink(void)

{

rGPJ2CON = 0x00001111;//设置led1--led4为output

rGPJ2DAT = (0<<0 | 0<<1 | 0<<2 | 0<<3);//点亮led1--led4

delay();//延时

rGPJ2DAT = (1<<0 | 1<<1 | 1<<2 | 1<<3);//熄灭led1--led4

delay();

rGPJ2DAT = (0<<0 | 1<<1 | 1<<2 | 1<<3);//点亮led1

delay();

rGPJ2DAT = (1<<0 | 0<<1 | 1<<2 | 1<<3);//点亮led2

delay();

rGPJ2DAT = (1<<0 | 1<<1 | 0<<2 | 1<<3);//点亮led3

delay();

rGPJ2DAT = (1<<0 | 1<<1 | 1<<2 | 0<<3);//点亮led4

delay();

}

void delay(void)

{

volatile unsigned int i = 0x1FFFFF;

while(i--);

}

Makefile:

OBJS += start.o led_blink.o sdram_init.o

CFLAGS += -Wall -O2

LDFLAGS += -Tlink.lds

CROSS_COMPILER := arm-linux-

CC := $(CROSS_COMPILER)gcc

led.bin: $(OBJS)

$(CROSS_COMPILER)ld -Tlink.lds -o led.elf $^

$(CROSS_COMPILER)objcopy -O binary led.elf led.bin

$(CROSS_COMPILER)objdump -D led.elf > led_elf.dis

gcc mkv210_image.c -o mk210

./mk210 led.bin smart210.bin

%.o:%.c

$(CC) $(CFLAGS) -c $^ -o [email protected]

%.o:%.S

$(CC) $(CFLAGS) -c $^ -o [email protected]

.PHONY = clean

clean:

rm -rf *.o *.elf *.bin *.dis mk210

.PHONY = install

install:

DATE = $(shell date --rfc-3339=date)

.PHONY = dist

dist:

tar -cvf $(BIN)-$(DATE).tar.gz $(BIN)

link.lds:

SECTIONS

{

. = 0x20000000;

.text :

{

start.o

* (.text)

}

.data :

{

* (.data)

}

bss_start = .;

.bss :

{

* (.bss)

}

bss_end = .;

}

烧录后运行结果,led正常闪烁。

时间: 2024-12-04 16:52:52

嵌入式Linux裸机开发(五)——SDRAM初始化的相关文章

嵌入式Linux裸机开发(十五)——LCD

嵌入式Linux裸机开发(十五)--LCD 一.LCD简介 LCD(Liquid Crystal Display)是液晶显示器简称.LCD的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置TFT(薄膜晶体管),上基板玻璃上设置彩色滤光片,通过TFT上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的. 1.LCD类型 按照背光源的不同,LCD可以分为CCFL和LED两种. A.CCFL 指用CCFL(冷阴极荧光灯管)作为背光光源的液晶显示器(L

嵌入式Linux裸机开发(十)——SD卡启动

嵌入式Linux裸机开发(十)--SD卡启动 存储设备分类: 磁存储设备:软盘.硬盘.光盘.CD.磁带 Flash:NandFlash.NorFlash 缺点:时序复杂,无坏块处理机制,接口不统一 NandFlash:MLC(可靠性差,容量大).SLC(可靠性高.容量小) 扩展卡式Flash:SD卡.MMC卡.MicroSD(TF卡) 内部为NnadFlash存储颗粒,外部封装了接口,接口标准统一.通用. 缺点:频繁使用导致卡槽接触不可靠 iNand.MoviNand.eSSD: 内部为Nand

嵌入式Linux裸机开发(四)——重定位relocate

嵌入式Linux裸机开发(四)--重定位relocate 一.位置有关编码 汇编源文件被编译成二进制可执行程序时编码方式可能与内存地址有关,也可能与内存地址无关.与内存地址有关的为位置有关编码,与内存地址无关的为位置无关编码. 程序在设计时需要规划一个程序运行时的地址(链接地址),编译连接器在链接时必须指定这个链接地址,得到的二进制程序的程序理论规划的运行时地址和编译连接器指定的链接地址才相同,程序才能正常运行.位置无关编码程序则无需设计程序时规划运行时地址,编译链接器链接时同样无需指定链接地址

嵌入式Linux裸机开发(七)——UART串口通信

嵌入式Linux裸机开发(七)--UART串口通信 一.UART串口通信简介 通用异步收发器简称UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER, 它用来传输串行数据.发送数据时, CPU 将并行数据写入UART,UAR按照一定的格式在一根电线上串 行发出:接收数据时, UART检测另一根电线的信号,将串行收集在缓冲区中, CPU 即可读取 UART 获得这些数据. 在 S5PV210中, UART提供了 4 对独立的异步串口I/O端口,

嵌入式Linux裸机开发(九)——S5PV210定时器

嵌入式Linux裸机开发(九)--S5PV210定时器 S5PV210内部一共有四类定时器. 一.PWM定时器 1.PWM定时简介 S5PV210内部共有5个32bit的PWM定时器.PWM定时器可以生成内部中断.PWM定时器0.1.2.3具有PWM功能,可以驱动外部I/O信号.PWM定时器4是一个无外部引脚的内部定时器.PWM 定时器使用 PCLK_PSYS 作为时钟源. 每个定时器有一个由定时器时钟驱动的32位递减计数器.递减计数器的初始值是由TCNTBn自动装载而获得的.如果递减计数器减到

嵌入式Linux裸机开发(八)——S5PV210中断处理流程

嵌入式Linux裸机开发(八)--S5PV210中断处理流程 中断是一个过程,是CPU在执行当前程序的过程中因硬件或软件的原因插入了另一段程序运行的过程.因硬件原因引起的中断过程的出现是不可预测的,即随机的,而软中断是事先安排的.引起中断的信号源称之为中断源.根据中断源的来源将中断分为外部中断和内部中断.中断源来自SoC内部(内部外设)的中断称为内部中断.中断源来自SoC外部,通过中断对应的GPIO引脚产生的中断称为外部中断.中断有四种状态: Inactive(不激活):没有被激活或挂起的中断 

嵌入式Linux裸机开发(十四)——ADC

嵌入式Linux裸机开发(十四)--ADC 一.AD转换简介 AD转换就是模数转换,就是把模拟信号转换成数字信号.A/D转换器是用来通过一定的电路将模拟量转变为数字量.模拟量可以是电压.电流等电信号,也可以是压力.温度.湿度.位移.声音等非电信号.在A/D转换前,输入到A/D转换器的输入信号必须经各种传感器把各种物理量转换成电压信号.A/D转换后,输出的数字信号可以有8位.10位.12位.14位和16位等. 二.ADC控制器 ADC控制器时钟: 时钟源为PCLK_PSYS,经过一次分频后得到AD

嵌入式Linux裸机开发(十一)——Nandflash

嵌入式Linux裸机开发(十一)--Nandflash 一.Nand Flash简介 NandFlash是Flash的一种,具有容量较大,改写速度快等优点,适用于大量数据的存储.NandFlash没有专门的地址线,发送指令.地址和数据都通过8/16位宽的总线(I/O接口)到内部的寄存器. NandFlash分为SLC和MLC两类.SLC全称为Single-Level Cell,单层单元闪存,MLC全称为Multi-Level Cell,多层单元闪存.SLC每一个单元储存一位数据,而MLC通过使用

嵌入式Linux裸机开发(十三)——I2C通信

嵌入式Linux裸机开发(十三)--I2C通信 一.IIC协议 1.IIC总线简介 I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备.I2C总线是一种串行数据总线,只有二根信号线,一根是双向的数据线SDA,另一根是时钟线SCL.在 I2C总线上传送的一个数据字节由八位组成.总线对每次传送的字节数没有限制,但每个字节后必须跟一位应答位. IIC总线是一种串行总线,用于连接微控制器及其外围设备,具有以下特点: