操作系统:ubuntu10.04
测试代码:
start.S 文件:
-
@*************************************************************************
-
@ File:start.S
-
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
-
@*************************************************************************
-
-
.equ MEM_CTL_BASE, 0x48000000 @总线宽度和等待状态控
-
.equ SDRAM_BASE, 0x30000000
-
-
-
.text
-
.global _start
-
_start:
-
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
-
bl memsetup @ 设置存储控制器
-
bl copy_code_to_sdram @ 复制代码到SDRAM中
-
-
ldr pc, =on_sdram @ 跳到SDRAM中继续执行
-
-
on_sdram:
-
ldr sp, =0x34000000 @ 设置堆栈
-
bl main
-
loop:
-
b loop
-
-
@ 关闭看门狗
-
disable_watch_dog:
-
mov r1, #0x53000000 @ 看门狗定时器控制寄存器地址
-
mov r2, #0x0 @ 往WATCHDOG寄存器写0即可
-
str r2, [r1] @ 把r2中的值写入到r1保存的地址中
-
mov pc, lr @ 返回
-
-
@ 设置存储控制器以便使用SDRAM等外设
-
memsetup:
-
mov r1, #MEM_CTL_BASE @ 存储控制器的13个寄存器的开始地址
-
adrl r2, mem_cfg_val @ 这13个值的起始存储地址
-
add r3, r1, #52 @ 13*4 = 52, r3 = r1 + 52
-
-
1:
-
ldr r4, [r2], #4 @ 读取设置值,并让r2加4
-
str r4, [r1], #4 @ 将 r4 中的值写入到 r1做保存的地址中,并让r1加4
-
cmp r1, r3 @ 判断是否设置完所有13个寄存器
-
bne 1b @ 若没有写成,继续
-
mov pc, lr @ 返回
-
-
@ 复制代码到 sdram 中
-
@ 将Steppingstone的4K数据全部复制到SDRAM中去
-
@ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000
-
copy_code_to_sdram:
-
mov r1, #0
-
ldr r2, =SDRAM_BASE
-
mov r3, #4*1024
-
-
1:
-
ldr r4, [r1], #4 @ 从Steppingstone读取4字节的数据r4寄存器中,
-
@ 并让源地址(即 r1 保存的地址)加4
-
str r4, [r2], #4 @ 将r4 保存的4个字节的数据复制到SDRAM中,
-
@ 并让目地地址(即 r2 保存的地址)加4
-
cmp r1, r3 @ 判断是否完成:源地址等于Steppingstone的未地址?
-
bne 1b @ 若没有复制完,继续
-
-
mov pc, lr @ 返回
-
-
-
-
@ 四个字节对齐
-
.align 4
-
mem_cfg_val:
-
@ 存储控制器13个寄存器的设置值
-
.long 0x22011110 @ BWSCON
-
@ 总线宽度和等待控制寄存器
-
@ [31:0] = 0010 0010 0000 0001 0001 0001 0001 0000
-
@ [5:4] DW1 = 0b01 决定Bank 1 的数据总线宽度 01 = 16位
-
@ [6] WS1 = 0b0 决定Bank 1 的WAIT状态 0 = WAIT禁止
-
@ [7] ST1 = 0b0 决定SRAM 是否对Bank 1 使用UB/LB,
-
@ 0 =未使用 UB/LB(引脚对应 nWBE[3:0]);1=使用UB/LB(引脚对应 nBE[3:0] )
-
@ [9:8] DW2 = 0b01 决定Bank 2 的数据总线宽度 01 = 16位
-
@ [13:12]DW3 = 0b01 决定Bank 3 的数据总线宽度 01 = 16位
-
@ [17:16]DW4 = 0b01 决定Bank 4 的数据总线宽度 01 = 16位
-
@ [21:20]DW5 = 0b00 决定Bank 5 的数据总线宽度 00 = 8位
-
@ [25:24]DW6 = 0b10 决定Bank 6 的数据总线宽度 10 = 32位
-
@ [21:20]DW7 = 0b10 决定Bank 7 的数据总线宽度 10 = 32位
-
-
.long 0x00000700 @ BANKCON0
-
@ Bank0 控制寄存器
-
@ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
-
@ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟
-
-
.long 0x00000700 @ BANKCON1
-
@ Bank1 控制寄存器
-
@ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
-
@ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟
-
-
.long 0x00000700 @ BANKCON2
-
@ Bank2 控制寄存器
-
@ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
-
@ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟
-
-
.long 0x00000700 @ BANKCON3
-
@ Bank3 控制寄存器
-
@ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
-
@ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟
-
-
.long 0x00000700 @ BANKCON4
-
@ Bank4 控制寄存器
-
@ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
-
@ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟
-
-
.long 0x00000700 @ BANKCON5
-
@ Bank5 控制寄存器
-
@ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
-
@ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟
-
-
.long 0x00018005 @ BANKCON6
-
@ Bank6 控制寄存器
-
@ [31:0] = 0000 0000 0000 0001 1000 0000 0000 0101
-
@ [16:15]MT = 0b11,决定Bank6 的存储器类型 ,11 = 同步 DRAM
-
@ 存储器类型 = SDRAM [MT= 11] (4 位)
-
@ [1:0] SCAN = 0b01,列地址数 , 01 = 9-bit
-
@ [3:2] Trcd = 0b01,RAS到CAS的延迟, 01 = 3 个时钟
-
-
.long 0x00018005 @ BANKCON7
-
@ Bank7 控制寄存器
-
@ [31:0] = 0000 0000 0000 0001 1000 0000 0000 0101
-
@ [16:15]MT = 0b11,决定Bank6 的存储器类型 ,11 = 同步 DRAM
-
@ 存储器类型 = SDRAM [MT= 11] (4 位)
-
@ [1:0] SCAN = 0b01,列地址数 , 01 = 9-bit
-
@ [3:2] Trcd = 0b01,RAS到CAS的延迟, 01 = 3 个时钟
-
-
.long 0x008C07A3 @ REFRESH
-
@ REFRESH ,SDRAM 刷新控制寄存器
-
@ [31:0] = 0000 0000 1000 1100 0000 0111 1010 0011
-
@ [10:0]Refresh Counter = 0b111 1010 0011 = 1955,SDRAM 刷新计数值,
-
@ refresh count = SDRAM 刷新计数值
-
@ refresh period = SDRAM 刷新周期值
-
@ refresh_period = (2^11 -refresh_count+1)/HCLK
-
@ refresh_count = 2^11+1 - refresh_period*HCLK
-
@ refresh_period = 7.8125 ?s
-
@ HCLK = 在未使用PLL的情况下,SDRAM时钟频率等于晶振频率 12MHz
-
@ refresh_count = 2^11+1 - 7.8125*12 = 1955
-
@ [19:18]Tsrc = 0b11,SDRAM 半行周期时间, 11 = 7 个时钟
-
@ [21:20]Trp = 0b00,SDRAM RAS 预充电时间,00 = 2 个时钟
-
@ SDRAM 行周期时间:Trc=Tsrc+Trp, Trc = 7 + 2 = 9 个时钟
-
@ [22]TREFMD = 0b0,SDRAM 刷新模式 ,0 = CBR/自动刷新 ,
-
@ 在自刷新期间,驱动SDRAM 控制信号为适当电平
-
@ [23]REFEN = 0b1,SDRAM 刷新使能,1 = 使能(自或 CBR/ 自动刷新)
-
-
.long 0x000000B1 @ BANKSIZE
-
@ BANKSIZE 0x48000028 R/W 可变Bank大小寄存器
-
@ [31:0] = 0000 0000 0000 0000 0000 0000 1011 0001
-
@ [2:0]BK76MAP = 0b001,Bank 6/7 存储器映射,001 = 64MB/64MB
-
@ [4]SCLK_EN = 0b1,只在SDRAM 访问周期期间SCLK 使能,以降低功耗。
-
@ 当未访问SDRAM,SCLK 变为低电平.1 = SCLK 只在访问期间有效(推荐)
-
@ [5]SCKE_EN = 0b1,SDRAM 掉电模式使能SCKE 控制 ,1 = 使能 SDRAM 掉电模式
-
@ [7]BURST_EN = 0b1,ARM核突发(Burst)操作使能, 1 = 使能突发操作
-
-
.long 0x00000030 @ MRSRB6
-
@ MRSRB6 0x4800002C R/W 模式寄存器组寄存器Bank6
-
@ [31:0] = 0000 0000 0000 0000 0000 0000 0011 0000
-
@ [6:4]CL= 0b011,CAS等待时间(latency),011 = 3 个时钟.
-
-
.long 0x00000030 @ MRSRB7
-
@ MRSRB7 0x48000030 R/W 模式寄存器组寄存器Bank7
-
@ [31:0] = 0000 0000 0000 0000 0000 0000 0011 0000
-
@ [6:4]CL= 0b011,CAS等待时间(latency),011 = 3 个时钟.
leds.c 文件
-
#define GPFCON ((volatile unsigned long*)0x56000050)
-
#define GPFDAT ((volatile unsigned long*)0x56000054)
-
-
#define LED_NUM 3
-
-
#define LED1_CON GPFCON
-
#define LED1_DAT GPFDAT
-
#define LED1_PIN 4
-
#define LED2_CON GPFCON
-
#define LED2_DAT GPFDAT
-
#define LED2_PIN 5
-
#define LED3_CON GPFCON
-
#define LED3_DAT GPFDAT
-
#define LED3_PIN 6
-
-
struct gpio
-
{
-
volatile unsigned long *gpio_con;
-
volatile unsigned long *gpio_dat;
-
volatile unsigned long *gpio_up;
-
int gpio_pin;
-
};
-
-
-
void init_led(struct gpio * gpios)
-
{
-
int led_index;
-
volatile unsigned long* led_con[LED_NUM] = {LED1_CON,LED2_CON,LED3_CON};
-
volatile unsigned long* led_dat[LED_NUM] = {LED1_DAT,LED2_DAT,LED3_DAT};
-
int led_pin[LED_NUM] = {LED1_PIN,LED2_PIN,LED3_PIN};
-
-
for(led_index = 0; led_index < LED_NUM; led_index++)
-
{
-
gpios[led_index].gpio_con = led_con[led_index];
-
gpios[led_index].gpio_dat = led_dat[led_index];
-
gpios[led_index].gpio_pin = led_pin[led_index];
-
-
*(gpios[led_index].gpio_con) |= (1<<(gpios[led_index].gpio_pin * 2));
-
}
-
}
-
-
void led_on(struct gpio *led)
-
{
-
*(led->gpio_dat) = ~(1<<led->gpio_pin);
-
}
-
-
void led_off(struct gpio *led)
-
{
-
*(led->gpio_dat) |= (1<<led->gpio_pin);
-
}
-
-
-
void delay()
-
{
-
int time_out = 30000;
-
for( ; time_out > 0; time_out--);
-
}
-
-
-
int main(void)
-
{
-
#if 1
-
int index = 0;
-
struct gpio leds[3];
-
init_led(leds);
-
-
while(1)
-
{
-
{
-
led_on(&leds[index]);
-
delay();
-
-
led_off(&leds[index]);
-
delay();
-
}
-
-
++index;
-
if( 3 <= index) index = 0;
-
-
}
-
#endif
-
-
#if 0
-
GPFCON = 0x00001100; // 设置GPF5,6为输出口, 位[11:10]=0b01,[13:12]=0b01
-
GPFDAT = 0x00000000; // GPF5,6输出0,LED2,LED3点亮
-
#endif
-
-
return 0;
-
}
makefile代码:
-
###############################################################################
-
#
-
# A smart Makefile template for GNU/LINUX programming
-
#
-
# Author: SR
-
# Date:
-
#
-
# Usage:
-
# $ make Compile and link (or archive)
-
# $ make clean Clean the objectives and target.
-
###############################################################################
-
-
CROSS_COMPILE = arm-linux-
-
OPTIMIZE := -O2
-
WARNINGS := -Wall -Wno-unused -Wno-format
-
DEFS := -DMYDEF=1 -UMYDEF2
-
EXTRA_CFLAGS :=
-
CFLAGS = $(EXTRA_CFLAGS) $(WARNINGS) $(OPTIMIZE) $(DEFS)
-
-
-
GCC := $(CROSS_COMPILE)gcc
-
LD := $(CROSS_COMPILE)ld
-
OBJCOPY := $(CROSS_COMPILE)objcopy
-
OBJDUMP := $(CROSS_COMPILE)objdump
-
-
OBJ := sdram.bin
-
ELF := sdram_elf
-
DIS := sdram.dis
-
-
-
-
$(OBJ) : start.S leds.c
-
$(GCC) -g -c -o start.o start.S
-
$(GCC) -g -c -o leds.o leds.c
-
$(LD) -Ttext 0x30000000 -g start.o leds.o -o $(ELF)
-
$(OBJCOPY) -O binary -S $(ELF) $(OBJ)
-
$(OBJDUMP) -D -m arm $(ELF) > $(DIS)
-
-
-
-
-
PHONY = clean
-
-
clean:
-
rm -f $(OBJ) $(ELF) $(DIS) *.o
-
-
.PHONY: $(PHONY)
adrl 伪指令
**ldr和 adr/adrl 伪指令的区别
add 指令
-
ADD 相加
-
-
ADD指令的格式为:ADD{条件}{S} 目的寄存器,操作数1,操作数2
-
-
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。
-
操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
-
指令示例:
-
-
ADD R0,R1,R2 ; R0 = R1 + R2
-
ADD R0,R1,#256 ; R0 = R1 + 256
-
ADD R0,R2,R3,LSL#1 ; R0 = R2 + (R3 << 1)
ldr 指令:
-
加载/存储指令
-
ARM微处理器支持加载/存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。
-
常用的加载存储指令如下:
-
LDR
-
LDR指令的格式为:LDR{条件} 目的寄存器,,
-
LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。
-
该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。
-
当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
-
该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。
-
指令示例:
-
LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
-
LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。
-
-
LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。
-
LDR R0,[R1,R2] ! ;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
-
LDR R0,[R1,#8] ! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。
-
LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。
-
LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
-
LDR R0,[R1],R2,LSL#2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
阅读(303) | 评论(0) | 转发(0) |