嵌入式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_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正常闪烁。