Experiment 3 - SDRAM

Publisher:自由探索Latest update time:2023-06-13 Source: elecfansKeywords:SDRAM  jz2440  arm-linux-gcc Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

one. Operating environment


  Development board: jz2440


  System: ubuntu12.04


  Compiler: arm-linux-gcc


2. Special registers


     The operation of sdram does not need to be set according to the timing diagram. As long as the relevant 13 registers are set, the storage manager in the arm processor will automatically output the control signal.


 1.long 0x22011110 @BWSCON

 2.long 0x00000700@BANKCON0

 3.long 0x00000700@BANKCON1

 4.long 0x00000700@BANKCON2

 5.long 0x00000700@BANKCON3  

 6.long 0x00000700@BANKCON4

 7.long 0x00000700@BANKCON5

 8 .long 0x00018005@BANKCON6

 9.long 0x00018005@BANKCON7

10 .long 0x008C07A3 @ REFRESH

11.long 0x000000B1@BANKSIZE

12 .long 0x00000030 @MRSRB6

13 .long 0x00000030 @MRSRB7

Let’s look at BWSCON first:

Every four bits control one BKNK

For SDRAM, ST7 is set to 0 and SRAN is set to 1.

WSx is usually set to 0 

DBx is set to 01b. This is generally set according to the actual situation, and also refers to the storage resources on the specific development board.

 

 

For these six registers, they mainly set the timing. The default value is Ouke

MT[16:15] sets SRAM OR SDRAM, set 0B11 here

If it is sdram, then Trcd is set to the recommended value 0b10

SCAN is set to 9-bit

 

For the refresh register, note that the lower 11 bits will be different depending on CLK, that is to say, whether the PLL is used or not, there will be different values.

It can be calculated from this

Refreh_count =2^12+1-12*64/8092=1955

REFRESF=0x008c0000+1955


  Let’s look at the code first: there are three main ones here: head.S, led.c, and Makefile. The LED code is the same as that of the running water lamp, so it can be copied directly.

  In addition, the code refers to the source code of Mr. Wei Dongshan, and it can be verified that there is no problem after programming.


three. Paste the code directly

Let’s look at the Makefile first:

1 sdram.bin:head.S led.c

2 arm-linux-gcc -Wall -O2 -c -g -o head.o head.S

3 arm-linux-gcc -Wall -O2 -c -g -o led.o led.c

4 arm-linux-ld -Ttext 0x30000000 head.o led.o -o sdram_elf

5 arm-linux-objcopy -O binary -S sdram_elf sdram.bin

6 arm-linux-objdump -D -m arm sdram_elf>sdram.dis

8 clean:

9 rm -f sdram.bin sdram_elf*.o sdram.dis


Look at head.h again


 1.equ MEM_BASE,0x48000000

 2.equ SDRAM_BASE,0x30000000

 3 

 4.text

 5.global_start

 6_start:

 7 

 8 bl close_watchdog @Close watchdog

 9 bl mem_set @Set storage register group

10 bl steppingstone_sdram @copy code to sdram

11 

12 ldr pc,=on_sdram

13 on_sdram:

14 ldr sp,=0x34000000

15blmain

16 halt_loop:

17 b halt_loop

18 

19 

20 

21 close_watchdog:

22 mov r1,#0x53000000

23 mov r2,#0x0

24 str r2,[r1]

25 

26 mov pc,lr @return

27 

28 steppingstone_sdram: @start address 0x00000000, target address 0x30000000

29 mov r1,#0

30 ldr r2,=SDRAM_BASE

31 mov r3,#1024*4

32 

33 

34 copy_loop:

35 ldr r4,[r1],#4

36 str r4,[r2],#4

37 

38 cmp r1,r3

39 bne copy_loop

40 mov pc,lr @return

41 

42 mem_set:

43 mov r1,#MEM_BASE

44 

45 adrl r2,JCQ

46 add r3,r1,#52 @4*13

47 

48 set_loop:

49 ldr r4,[r2],#4

50 str r4,[r1],#4

51 cmp r1,r3

52 bne set_loop

53 

54 mov pc,lr

55 

56 

57.align 4

58JCQ:

59 .long 0x22011110 @BWSCON

60 .long 0x00000700 @bankcon0

61 .long 0x00000700 @bankcon1

62 .long 0x00000700 @bankcon2

63 .long 0x00000700 @bankcon3

64 .long 0x00000700 @bankcon4

65 .long 0x00000700 @bankcon5

66 .long 0x00018005 @bankcon6

67 .long 0x00018005 @bankcon7

68 .long 0x008c07a3 @refresh

69 .long 0x000000b1 @banksize

70 .long 0x00000030 @mrsrb6

71 .long 0x00000030 @mrsrb7


In fact, there are no changes, just changing some names. But if you type it by yourself, of course there will be some details that you will make mistakes and you will not pay attention to them.


The above startup file is written in assembly, and the c language version is posted below.


 head.S:


 1. extern main

 2.text

 3.global_start

 4_start:

 5 b reset

 6 

 7 reset:

 8 ldr sp,=4096 @

 9 

10 bl close_watchdog @Close watchdog

11 bl mem_set @Set storage register group

12 bl steppingstone_sdram @copy code to sdram

13 

14 

15     

16 ldr pc,=on_sdram

17 on_sdram:

18 ldr sp,=0x34000000

19 ldr pc,=0x30000000

20 halt_loop:

21 b halt_loop


init.c:


 1 /************************************************ *************************

 2 > File Name: init.c

 3 > Author: hulig

 4>Mail:  

 5 > Created Time: Saturday, November 08, 2014 15:52:55

 6 >function:init disable watchdog ,init mem .goto main and on

 7>result:ok

 8 ************************************************* *************************/

 9 

10 #define WTCON (*(volatile unsigned long *)0x53000000)

11 #define MEM_BASE (*(volatile unsigned long *)0x48000000)

12 

13 void close_watchdog()

14 {

15 WTCON =0; //Just write 0 to the watchdog register

16}

17 

18 void mem_set() //Write the corresponding values ​​into the 13 registers related to sdram settings and it will be ok.

19 {

20 unsigned long const mem_jcq[]={

21 0x22011110,

22 0x00000700,

23 0x00000700,

24 0x00000700,

25 0x00000700,

26 0x00000700,

27 0x00000700,

28 0x00018005,

29 0x00018005,

30 0x008c07a3,

31 0x000000b1,

32 0x00000030,

33 0x00000030,

34};

35 

36 int i=0;

37 volatile unsigned long *p=(volatile unsigned long *)MEM_BASE;

38 for(;i<13;i++)

39 p[i]=mem_jcq[i];

40}

41 

42 void steppingstone_sdram(void)

43 {

44 unsigned int *pSrc=(unsigned int *)0; // Copy the steppingstone 0 address to the sdram starting address

45 unsigned int *pDes =(unsigned int *)0x30000000;//sdram starting address

46 

47 while(pSrc<(unsigned int*)4096)

48 {

49 *pDes=*pSrc;

50pDes++;

51 pSrc++;

52 }    

53 

54 

55 }


The above C code cannot achieve the expected results. The main problem is the initialization of SDRAM, that is, when assigning values ​​to 13 registers:


 1 a".

 2 #define BWSCON (*(volatile unsigned long * )0x48000000)

 3 #define BANKCON0 (*(volatile unsigned long * )0x48000004)

 4 #define BANKCON1 (*(volatile unsigned long * )0x48000008)

 5 #define BANKCON2 (*(volatile unsigned long * )0x4800000c)

 6 #define BANKCON3 (*(volatile unsigned long * )0x48000010)

 7 #define BANKCON4 (*(volatile unsigned long * )0x48000014)

 8 #define BANKCON5 (*(volatile unsigned long * )0x48000018)

 9 #define BANKCON6 (*(volatile unsigned long * )0x4800001c)

10 #define BANKCON7 (*(volatile unsigned long * )0x48000020)

11 #define REFRESH (*(volatile unsigned long * )0x48000024)

12 #define BANKSIZE (*(volatile unsigned long * )0x48000028)

13 #define MRSRB6 (*(volatile unsigned long * )0x4800002c)

14 #define MRSRB7 (*(volatile unsigned long * )0x48000030)

15 

16 

17 void mem_set() 

18 {

19 BWSCON= 0x22011110;

20 BANKCON0=0x00000700;

21 BANKCON1=0x00000700;

22 BANKCON2=0x00000700;

23 BANKCON3=0x00000700;

24 BANKCON4=0x00000700;

25 BANKCON5=0x00000700;

26 BANKCON6=0x00018005;

27 BANKCON7=0x00018005;

28 REFRESH=0x008c07a3;

29 BANKSIZE=0x000000b1;

30 MRSRB6 =0x00000030;

31 MRSRB7= 0x00000030;

32}

33 

34 

35 "Two".

36 void mem_set() //Write the corresponding values ​​into the 13 registers related to sdram settings and it will be ok.

37 {

38 int i=0;

39 unsigned long *p=(unsigned long *)MEM_BASE;

40 unsigned long const mem_jcq[]={

41 0x22011110,

42 0x00000700,

43 0x00000700,

44 0x00000700,

45 0x00000700,

46 0x00000700,

47 0x00000700,

48 0x00018005,

49 0x00018005,

50 0x008c07a3,

51 0x000000b1,

52 0x00000030,

53 0x00000030,

54};

55 

56 for(;i<13;i++)

57 p[i]=mem_jcq[i];

58 }

59 

60 "Three".

61 

62 #define MEM_CTL_BASE 0x48000000

63 #define MEM_CTL_END 0x48000034

64 unsigned long const mem_cfg_val[]={ // Declare array to store memory controller setting data

65 

66 0x22000000, //BWSCON

67 0x00000700, //BANKCON0

68 0x00000700, //BANKCON1

69 0x00000700, //BANKCON2

70 0x00000700, //BANKCON3 

71 0x00000700, //BANKCON4

72 0x00000700, //BANKCON5

73 0x00018005, //BANKCON6

74 0x00018005, //BANKCON7

75 0x008e07a3, //REFRESH (HCLK = 12MHz, the value is 0x008e07a3 //HCLK = 100MHz 0x008e04f5)

76 0x000000b1, //BANKSIZE

77 0x00000030, //MRSRB6

78 0x00000030, //MRSRB7

79};


There are three ways to write above, only the first one is feasible. why?


Comparing 1, 2, 3 and consulting the data, we can see that the root cause is position-independent code


Note that before copying the code to sdram, the link address is 0x30000000, which is the starting address of sdram. If you want to execute it correctly at this time, you must use a jump instruction.


Both methods 2 and 3 are stored in the form of arrays, so naturally they are not position-independent, so they won't work.


So, how to write position-independent code?


Let’s summarize it in two basic points:


one. In assembly, use the B/BL instruction


two. In C, avoid using static to limit the range; try to assign values ​​to consecutive register groups separately.


Attachment, another feasible method:


 1 void memsetup(void)

 2 {

 3 volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

 4 

 5 /* The reason why this function assigns the value in this way is not to assign the configuration value like the previous experiment (such as the mmu experiment)

 6 * Written in an array, the reason is to generate "position-independent code" so that this function can be copied to

 7* SDRAM has worked in steppingstone before

 8 */

 9 /* Store the values ​​of 13 registers of the controller*/

10 p[0] = 0x22011110; //BWSCON

11 p[1] = 0x00000700; //BANKCON0

12 p[2] = 0x00000700; //BANKCON1

13 p[3] = 0x00000700; //BANKCON2

14 p[4] = 0x00000700; //BANKCON3  

15 p[5] = 0x00000700; //BANKCON4

16 p[6] = 0x00000700; //BANKCON5

17 p[7] = 0x00018005; //BANKCON6

18 p[8] = 0x00018005; //BANKCON7

19 p[9] = 0x008C07A3; //REFRESH

20 p[10] = 0x000000B1; //BANKSIZE

21 p[11] = 0x00000030; //MRSRB6

22 p[12] = 0x00000030; //MRSRB7

twenty three }


Keywords:SDRAM  jz2440  arm-linux-gcc Reference address:Experiment 3 - SDRAM

Previous article:Experiment 4--Use of nand flash
Next article:Experiment 2 - Flowing Water Lamp

Recommended ReadingLatest update time:2024-11-16 12:00

Describe the concepts of DRAM, SDRAM, and DDR SDRAM
 DRAM (Dynamic Random Access Memory) is particularly attractive to designers because it provides a wide range of performance and is used in the design of memory systems for various computers and embedded systems. This article summarizes the concept of DRAM and introduces SDRAM, DDR SDRAM, DDR2 SDRAM, DDR3 SDRAM, DDR4
[Microcontroller]
Describe the concepts of DRAM, SDRAM, and DDR SDRAM
[Embedded] arm-linux-gcc/ld/objcopy/objdump parameter overview
arm-linux-gcc   -o only activates preprocessing, compilation, and assembly, that is, it only makes the program into an obj file     -Wall specifies to generate all warning messages     -O2 The compiler provides a compilation optimization option for the program. Using this option during compilation can improve the exec
[Microcontroller]
Chapter 8. Timing and Principle of Eight SDRAM Transplantation in Tiny4412 U-BOOT
DDR originated from SDRAM. Strictly speaking, it should be called DDR SDRAM. DDR SDRAM is the abbreviation of Double Data Rate SDRAM, which means double data rate synchronous dynamic random access memory. Therefore, to a large extent, the two are the same. Understand SDRAM, and then understand DDR. The improvement on
[Microcontroller]
Chapter 8. Timing and Principle of Eight SDRAM Transplantation in Tiny4412 U-BOOT
JZ2440 bare board SDRAM startup analysis
Startup file head.S source code: @****************************************************** ************************ @File:head.S @ Function: Set up SDRAM, copy the program to SDRAM, and then jump to SDRAM to continue execution @****************************************************** ************************        .equ M
[Microcontroller]
JZ2440 bare board SDRAM startup analysis
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号