Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17673
  • 博文数量: 5
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 16
  • 用 户 组: 普通用户
  • 注册时间: 2015-02-06 22:26
文章分类

全部博文(5)

文章存档

2015年(5)

我的朋友
最近访客

分类: 嵌入式

2015-02-06 22:53:27

原文地址:**arm 存储控制器 作者:andyhzw

操作系统:ubuntu10.04


测试代码:
    start.S 文件:

点击(此处)折叠或打开

  1. @*************************************************************************
  2. @ File:start.S
  3. @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
  4. @*************************************************************************

  5. .equ    MEM_CTL_BASE,    0x48000000        @总线宽度和等待状态控
  6. .equ    SDRAM_BASE,        0x30000000


  7. .text
  8. .global    _start
  9. _start:
  10.     bl    disable_watch_dog                @ 关闭WATCHDOG,否则CPU会不断重启
  11.     bl    memsetup                        @ 设置存储控制器
  12.     bl    copy_code_to_sdram                @ 复制代码到SDRAM中

  13.     ldr    pc,        =on_sdram                @ 跳到SDRAM中继续执行

  14. on_sdram:
  15.     ldr    sp,        =0x34000000                @ 设置堆栈
  16.     bl    main
  17. loop:
  18.     b    loop    

  19. @ 关闭看门狗
  20. disable_watch_dog:
  21.     mov    r1,        #0x53000000                @ 看门狗定时器控制寄存器地址    
  22.     mov    r2,        #0x0                     @ 往WATCHDOG寄存器写0即可
  23.     str    r2,        [r1]                    @ 把r2中的值写入到r1保存的地址中
  24.     mov    pc,        lr                        @ 返回

  25. @ 设置存储控制器以便使用SDRAM等外设
  26. memsetup:
  27.     mov    r1,        #MEM_CTL_BASE            @ 存储控制器的13个寄存器的开始地址
  28.     adrl    r2,    mem_cfg_val                @ 这13个值的起始存储地址
  29.     add    r3,        r1,    #52                    @ 13*4 = 52, r3 = r1 + 52

  30. 1:
  31.     ldr    r4,        [r2],    #4                @ 读取设置值,并让r2加4
  32.     str    r4,        [r1],    #4                @ 将 r4 中的值写入到 r1做保存的地址中,并让r1加4    
  33.     cmp    r1,        r3                        @ 判断是否设置完所有13个寄存器
  34.     bne    1b                                @ 若没有写成,继续
  35.     mov    pc,        lr                        @ 返回

  36. @ 复制代码到 sdram 中    
  37. @ 将Steppingstone的4K数据全部复制到SDRAM中去
  38. @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000
  39. copy_code_to_sdram:
  40.     mov    r1,        #0
  41.     ldr    r2,        =SDRAM_BASE
  42.     mov    r3,        #4*1024

  43. 1:
  44.     ldr    r4,        [r1],    #4                @ 从Steppingstone读取4字节的数据r4寄存器中,
  45.                                         @ 并让源地址(即 r1 保存的地址)加4
  46.     str    r4,        [r2],    #4                @ 将r4 保存的4个字节的数据复制到SDRAM中,
  47.                                         @    并让目地地址(即 r2 保存的地址)加4
  48.     cmp    r1,        r3                        @ 判断是否完成:源地址等于Steppingstone的未地址?
  49.     bne    1b                                @ 若没有复制完,继续

  50.     mov    pc,        lr                        @ 返回    



  51. @ 四个字节对齐
  52. .align 4
  53. mem_cfg_val:
  54.     @ 存储控制器13个寄存器的设置值
  55.     .long 0x22011110 @ BWSCON    
  56.         @ 总线宽度和等待控制寄存器
  57.         @ [31:0] = 0010 0010 0000 0001 0001 0001 0001 0000
  58.         @ [5:4] DW1 = 0b01 决定Bank 1 的数据总线宽度 01 = 16位
  59.         @ [6]     WS1 = 0b0 决定Bank 1 的WAIT状态 0 = WAIT禁止
  60.         @ [7]     ST1 = 0b0    决定SRAM 是否对Bank 1 使用UB/LB,
  61.                 @ 0 =未使用 UB/LB(引脚对应 nWBE[3:0]);1=使用UB/LB(引脚对应 nBE[3:0]
  62.         @ [9:8] DW2 = 0b01 决定Bank 2 的数据总线宽度 01 = 16位
  63.         @ [13:12]DW3 = 0b01 决定Bank 3 的数据总线宽度 01 = 16位
  64.         @ [17:16]DW4 = 0b01 决定Bank 4 的数据总线宽度 01 = 16位
  65.         @ [21:20]DW5 = 0b00 决定Bank 5 的数据总线宽度 00 = 8位
  66.         @ [25:24]DW6 = 0b10 决定Bank 6 的数据总线宽度 10 = 32位
  67.         @ [21:20]DW7 = 0b10 决定Bank 7 的数据总线宽度 10 = 32位

  68.     .long 0x00000700 @ BANKCON0
  69.         @ Bank0 控制寄存器
  70.         @ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
  71.         @ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟

  72.     .long 0x00000700 @ BANKCON1
  73.         @ Bank1 控制寄存器
  74.         @ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
  75.         @ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟

  76.     .long 0x00000700 @ BANKCON2
  77.         @ Bank2 控制寄存器
  78.         @ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
  79.         @ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟

  80.     .long 0x00000700 @ BANKCON3
  81.         @ Bank3 控制寄存器
  82.         @ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
  83.         @ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟
  84.  
  85.     .long 0x00000700 @ BANKCON4
  86.         @ Bank4 控制寄存器
  87.         @ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
  88.         @ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟

  89.     .long 0x00000700 @ BANKCON5
  90.         @ Bank5 控制寄存器
  91.         @ [31:0] = 0000 0000 0000 0000 0000 0111 0000 0000
  92.         @ [10:8]Tacc = 0b111,访问周期 ,111 = 14个时钟

  93.     .long 0x00018005 @ BANKCON6
  94.         @ Bank6 控制寄存器
  95.         @ [31:0] = 0000 0000 0000 0001 1000 0000 0000 0101
  96.         @ [16:15]MT = 0b11,决定Bank6 的存储器类型 ,11 = 同步 DRAM
  97.         @ 存储器类型 = SDRAM [MT= 11] (4 位)
  98.         @ [1:0] SCAN = 0b01,列地址数          ,     01 = 9-bit
  99.         @ [3:2] Trcd = 0b01,RAS到CAS的延迟,    01 = 3 个时钟

  100.     .long 0x00018005 @ BANKCON7
  101.         @ Bank7 控制寄存器
  102.         @ [31:0] = 0000 0000 0000 0001 1000 0000 0000 0101
  103.         @ [16:15]MT = 0b11,决定Bank6 的存储器类型 ,11 = 同步 DRAM
  104.         @ 存储器类型 = SDRAM [MT= 11] (4 位)
  105.         @ [1:0] SCAN = 0b01,列地址数          ,     01 = 9-bit
  106.         @ [3:2] Trcd = 0b01,RAS到CAS的延迟,    01 = 3 个时钟

  107.     .long 0x008C07A3 @ REFRESH
  108.         @ REFRESH ,SDRAM 刷新控制寄存器
  109.         @ [31:0] = 0000 0000 1000 1100 0000 0111 1010 0011
  110.         @ [10:0]Refresh Counter = 0b111 1010 0011 = 1955,SDRAM 刷新计数值,
  111.         @        refresh count    = SDRAM 刷新计数值
  112.         @        refresh period    = SDRAM 刷新周期值
  113.         @        refresh_period     = (2^11 -refresh_count+1)/HCLK
  114.         @         refresh_count    = 2^11+1 - refresh_period*HCLK
  115.         @        refresh_period    = 7.8125 ?s
  116.         @         HCLK            = 在未使用PLL的情况下,SDRAM时钟频率等于晶振频率 12MHz
  117.         @        refresh_count    = 2^11+1 - 7.8125*12 = 1955
  118.         @ [19:18]Tsrc = 0b11,SDRAM 半行周期时间,    11     = 7 个时钟
  119.         @ [21:20]Trp = 0b00,SDRAM RAS 预充电时间,00     = 2 个时钟
  120.         @         SDRAM 行周期时间:Trc=Tsrc+Trp,    Trc = 7 + 2 = 9 个时钟
  121.         @ [22]TREFMD = 0b0,SDRAM 刷新模式 ,0 = CBR/自动刷新 ,
  122.         @        在自刷新期间,驱动SDRAM 控制信号为适当电平
  123.         @ [23]REFEN     = 0b1,SDRAM 刷新使能,1 = 使能(自或 CBR/ 自动刷新)

  124.     .long 0x000000B1 @ BANKSIZE
  125.         @ BANKSIZE 0x48000028 R/W 可变Bank大小寄存器
  126.         @ [31:0] = 0000 0000 0000 0000 0000 0000 1011 0001
  127.         @ [2:0]BK76MAP     = 0b001,Bank 6/7 存储器映射,001 = 64MB/64MB
  128.         @ [4]SCLK_EN    = 0b1,只在SDRAM 访问周期期间SCLK 使能,以降低功耗。
  129.         @        当未访问SDRAM,SCLK 变为低电平.1 = SCLK 只在访问期间有效(推荐)
  130.         @ [5]SCKE_EN    = 0b1,SDRAM 掉电模式使能SCKE 控制 ,1 = 使能 SDRAM 掉电模式
  131.         @ [7]BURST_EN    = 0b1,ARM核突发(Burst)操作使能,    1 = 使能突发操作         

  132.     .long 0x00000030 @ MRSRB6
  133.         @ MRSRB6 0x4800002C R/W 模式寄存器组寄存器Bank6
  134.         @ [31:0] = 0000 0000 0000 0000 0000 0000 0011 0000
  135.         @ [6:4]CL= 0b011,CAS等待时间(latency),011 = 3 个时钟.

  136.     .long 0x00000030 @ MRSRB7
  137.         @ MRSRB7 0x48000030 R/W 模式寄存器组寄存器Bank7
  138.         @ [31:0] = 0000 0000 0000 0000 0000 0000 0011 0000
  139.         @ [6:4]CL= 0b011,CAS等待时间(latency),011 = 3 个时钟.
 leds.c 文件

点击(此处)折叠或打开

  1. #define    GPFCON    ((volatile unsigned long*)0x56000050)
  2. #define    GPFDAT    ((volatile unsigned long*)0x56000054)

  3. #define    LED_NUM        3

  4. #define    LED1_CON    GPFCON
  5. #define    LED1_DAT    GPFDAT
  6. #define    LED1_PIN    4
  7. #define    LED2_CON    GPFCON
  8. #define    LED2_DAT    GPFDAT
  9. #define    LED2_PIN    5
  10. #define    LED3_CON    GPFCON
  11. #define    LED3_DAT    GPFDAT
  12. #define    LED3_PIN    6

  13. struct     gpio
  14. {
  15.     volatile unsigned long    *gpio_con;
  16.     volatile unsigned long    *gpio_dat;
  17.     volatile unsigned long    *gpio_up;
  18.     int                        gpio_pin;
  19. };


  20. void    init_led(struct gpio * gpios)
  21. {
  22.     int        led_index;
  23.     volatile unsigned long* led_con[LED_NUM] = {LED1_CON,LED2_CON,LED3_CON};
  24.     volatile unsigned long* led_dat[LED_NUM] = {LED1_DAT,LED2_DAT,LED3_DAT};
  25.     int                     led_pin[LED_NUM] = {LED1_PIN,LED2_PIN,LED3_PIN};

  26.     for(led_index = 0; led_index < LED_NUM; led_index++)
  27.     {
  28.         gpios[led_index].gpio_con    = led_con[led_index];
  29.         gpios[led_index].gpio_dat    = led_dat[led_index];
  30.         gpios[led_index].gpio_pin    = led_pin[led_index];

  31.         *(gpios[led_index].gpio_con)     |= (1<<(gpios[led_index].gpio_pin * 2));
  32.     }
  33. }

  34. void    led_on(struct gpio *led)
  35. {
  36.     *(led->gpio_dat)    = ~(1<<led->gpio_pin);
  37. }

  38. void    led_off(struct gpio *led)
  39. {
  40.     *(led->gpio_dat)    |= (1<<led->gpio_pin);
  41. }


  42. void    delay()
  43. {
  44.     int    time_out = 30000;
  45.     for( ; time_out > 0; time_out--);
  46. }


  47. int main(void)
  48. {
  49. #if 1
  50.     int        index = 0;
  51.     struct gpio    leds[3];
  52.     init_led(leds);

  53.     while(1)
  54.     {
  55.         {
  56.             led_on(&leds[index]);
  57.             delay();

  58.             led_off(&leds[index]);
  59.             delay();
  60.         }
  61.     
  62.         ++index;
  63.         if( 3 <= index)    index = 0;

  64.     }
  65. #endif

  66. #if 0
  67.     GPFCON    = 0x00001100;    // 设置GPF5,6为输出口,[11:10]=0b01,[13:12]=0b01
  68.     GPFDAT    = 0x00000000;    // GPF5,6输出0,LED2,LED3点亮
  69. #endif

  70.     return 0;
  71. }



makefile代码:

点击(此处)折叠或打开

  1. ###############################################################################
  2. #
  3. # A smart Makefile template for GNU/LINUX programming
  4. #
  5. # Author: SR
  6. # Date:
  7. #
  8. # Usage:
  9. # $ make Compile and link (or archive)
  10. # $ make clean Clean the objectives and target.
  11. ###############################################################################

  12. CROSS_COMPILE = arm-linux-
  13. OPTIMIZE := -O2
  14. WARNINGS := -Wall -Wno-unused -Wno-format
  15. DEFS := -DMYDEF=1 -UMYDEF2
  16. EXTRA_CFLAGS :=
  17. CFLAGS = $(EXTRA_CFLAGS) $(WARNINGS) $(OPTIMIZE) $(DEFS)


  18. GCC := $(CROSS_COMPILE)gcc
  19. LD        := $(CROSS_COMPILE)ld
  20. OBJCOPY    := $(CROSS_COMPILE)objcopy
  21. OBJDUMP    := $(CROSS_COMPILE)objdump

  22. OBJ        := sdram.bin
  23. ELF        := sdram_elf
  24. DIS        := sdram.dis



  25. $(OBJ) : start.S leds.c
  26.     $(GCC) -g -c -o start.o    start.S
  27.     $(GCC) -g -c -o leds.o leds.c
  28.     $(LD) -Ttext 0x30000000 -g start.o leds.o -o $(ELF)
  29.     $(OBJCOPY) -O binary -S $(ELF) $(OBJ)
  30.     $(OBJDUMP) -D -m arm $(ELF) > $(DIS)




  31. PHONY = clean

  32. clean:
  33.     rm -f $(OBJ) $(ELF) $(DIS) *.o

  34. .PHONY: $(PHONY)



adrl 伪指令
    **ldr和 adr/adrl 伪指令的区别 

add 指令

点击(此处)折叠或打开

  1. ADD 相加
  2. ADD指令的格式为:ADD{条件}{S} 目的寄存器,操作数1,操作数2
  3. ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。
  4. 操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
  5. 指令示例:
  6. ADD R0,R1,R2 ; R0 = R1 + R2
  7. ADD R0,R1,#256 ; R0 = R1 + 256
  8. ADD R0,R2,R3,LSL#1 ; R0 = R2 + (R3 << 1)

ldr 指令:

点击(此处)折叠或打开

  1. 加载/存储指令
  2. ARM微处理器支持加载/存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。
  3. 常用的加载存储指令如下:
  4. LDR
  5. LDR指令的格式为:LDR{条件} 目的寄存器,,
  6. LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。
  7. 该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。
  8. 当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
  9. 该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。
  10. 指令示例:
  11. LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
  12. LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。
  13. LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。
  14. LDR R0,[R1,R2] ! ;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
  15. LDR R0,[R1,#8] ! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。
  16. LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。
  17. LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
  18. LDR R0,[R1],R2,LSL#2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。


阅读(744) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~