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
7
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 }
Previous article:Experiment 4--Use of nand flash
Next article:Experiment 2 - Flowing Water Lamp
Recommended ReadingLatest update time:2024-11-16 12:00
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- EEWORLD University Hall----Engineering Application of Random Signal Analysis
- Power adapter
- Design of ultra-wideband high- and low-frequency nested antenna based on asymmetric radiating elements
- Negative feedback amplifier circuit design
- Disassembling the display module of Audi Q3 and A4L
- The netizens who commented and downloaded the content this time are so excellent, and some good information has surfaced~all of them are top-notch information!
- Design a tester for measuring resistance and inductance using a DC digital multimeter (5-digit, maximum input voltage 10V).
- On the last day of 2019, make a New Year’s wish for 2020!
- Gallium Nitride Transistors Open New Frontiers in High-Speed Motor Drives
- How to use Labview to perform secondary development on Ginkgo 2