嵌入式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_shiftcPhyControl1.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标准,配置QosControl015和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

嵌入式Linux裸机开发(五)——SDRAM初始化_第1张图片


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

嵌入式Linux裸机开发(五)——SDRAM初始化_第2张图片

    四片内存芯片并联后逻辑上只是一片内存芯片,大小为512MB,数据线为Xm1DATA[31:0],地址线不变Xm1ADDR[13:0]。根据DRAM原理图的片选引脚nCSCKEnWE择知道,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可用,0xD00377800xD0037D80,大小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--led4output

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_p_w_picpath.c -o mk210

./mk210 led.bin smart210.bin


%.o:%.c

$(CC) $(CFLAGS) -c $^ -o $@

%.o:%.S

$(CC) $(CFLAGS) -c $^ -o $@

.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正常闪烁。