Start with the code (first write a code like a normal microcontroller):
/********led.c****************************/
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
/*The number behind is the address of the pin register. (volatile unsignedlong *) This is a forced conversion, which is to force the number behind to be converted into a volatile unsigned long pointer type. The first "*" represents the data stored at this address*/
static voidpin_init(void)
{
/*First look at the pin that the LED is connected to in the schematic diagram, and then find the register address of the pin in the datasheet*/
GPFCON&=~(3<<8); //GPF4 corresponding control bit cleared to 0
GPFCON&=~(3<<10); //GPF5 corresponding control bit cleared to 0
GPFCON&=~(3<<12); //GPF6 corresponding control bit cleared to 0
GPFCON |=1<<8; //GPF4 corresponding control bit is set to output
GPFCON |=1<<10;
GPFCON |=1<<12;
GPFDAT&=~(1<<4); //GPF4 sets output 0
GPFDAT&=~(1<<5); //GPF5 sets output 0
GPFDAT&=~(1<<6); //GPF6 sets output 0
}
static void delay(volatile unsigned int a)
{
int k;
k=30000;
while(--k>0)
for(;a>0;a--);
}
int main ()
{
int temp=1; //Using the inverted flag
pin_init();
while(1)
{
if (temp>0)
{
GPFDAT |=1<<4;
delay(6000);
GPFDAT |=1<<5;
delay(6000);
GPFDAT |=1<<6;
delay(6000);
temp=-1;
}
else
{
GPFDAT &=~(1<<4);
delay(6000);
GPFDAT &=~(1<<5);
delay(6000);
GPFDAT &=~(1<<6);
delay(6000);
temp=1;
}
}
return 0;
}
The c code is relatively simple, and the next step is to use the startup file.
The startup file contains some initialization information. The related initialization work includes:
(1) Create an exception vector table, set up the stack, and initialize the hardware
Hardware-related initialization tasks include:
① Turn off the watchdog
②Initialize the clock
③ Initialize SDRAM
(2) Set the return address of the main function
(3) Call the main function
(4) Complete some cleanup work
A brief description:
First of all, the exception vector table is not necessary. Its function is to establish a relationship between the user program and the startup code, and between the startup codes. This is accomplished by a series of jump instructions. When an exception occurs in the system, the processor will force the PC pointer to point to the corresponding exception handling function in the exception vector table by hardware. In order for the development board to enter the reset exception handling function after power-on (this function completes the initialization work of the following steps), the exception vector table should be written at the very beginning of the startup code.
Then setting up the stack is necessary
It is necessary to turn off the watchdog, otherwise the chip will be in a continuous restart process.
Initializing the clock means setting the clock frequency. The default system clock is 12M, which can be set according to your actual situation.
If you want to use SDRAM, you need to initialize SDRAM.
Since this program is relatively simple, the compiled code is definitely less than 4k, so the writing of the startup file can be divided into two experiments:
⑴ The program runs directly in SRAM (Steppingstone) without copying the contents of nand flash to SDRAM.
; ...
.text
.global _start
_start:
ldr r0, =0x53000000 ; WATCHDOG register address
mov r1,#0x0
str r1,[r0] ; Assign WATCHDOG to 0, turn off the watchdog
ldr sp, =4096 ; Set up the stack, sram is 4k
bl main ; Call the main function in the C program
loop:
b loop
The above does not initialize sdran, and uses the default clock of 12M. At this time, the running address in the makefile should be set to -Ttext 0
⑵Button control LED
Here you just need to modify the led.c file.
For the development board I use, the three buttons of the development board are connected to the GPF0 GPF2 GPG3 pins of 2440 respectively, so the led.c file is modified as follows:
/************************************************************
Button control LED
The schematic diagram shows that the three buttons are connected to GPF0 GPF2 GPG3 of 2440 respectively.
The three LEDs correspond to GPF4, GPF5 and GPF6 respectively.
*****************************************************/
#defineGPFCON (*(volatile unsigned long*)0x56000050)
#defineGPFDAT (*(volatile unsigned long*)0x56000054)
#defineGPGCON (*(volatile unsigned long*)0x56000060)
#defineGPGDAT (*(volatile unsigned long*)0x56000064)
static voidpin_init(void)
{
/*led*/
GPFCON&=~(3<<8);
GPFCON&=~(3<<10); //GPF5 corresponding control bit cleared to 0
GPFCON&=~(3<<12); //GPF6 corresponding control bit cleared to 0
GPFCON |=1<<8; //GPF4 corresponding control bit is set to output
GPFCON |=1<<10;
GPFCON |=1<<12;
GPFDAT&=~(1<<4); //GPF4 sets output 0
GPFDAT&=~(1<<5); //GPF5 sets output 0
GPFDAT&=~(1<<6); //GPF6 sets output 0
/*key*/
GPFCON&=~(3<<0);
GPFCON&=~(3<<(2*2)); //GPF2 corresponding control bit cleared to 0
GPGCON&=~(3<<(2*3)); //GPG3 corresponding control bit cleared to 0
/* While clearing, also set the pin corresponding to the button to input*/
}
int main ()
{
unsigned long key_state; //Record the state of the key
pin_init();
while(1)
{
/*When a button is pressed, the LED turns on, and when the button is released, the LED turns off*/
key_state=GPFDAT;
if(key_state&(1<<0))
GPFDAT|=(1<<4); //GPF4 sets output 1
else
GPFDAT&=~(1<<4); //GPF4 sets output 0
if(key_state&(1<<2))
GPFDAT|=(1<<5); //GPF5 sets output 1
else
GPFDAT&=~(1<<5); //GPF5 sets output 0
key_state=GPGDAT;
if(key_state&(1<<3))
GPFDAT|=(1<<6); //GPF6 sets output 1
else
GPFDAT&=~(1<<6); //GPF6 sets output 0
}
return 0;
}
After modification, re-make and download to the development board, there is a phenomenon that when a button is pressed, the LED lights up, and when the button is released, the LED goes out.
⑶ To run the program in SDRAM, the contents of SRAM need to be copied to SDRAM.
A complete startup code is given below. For the explanation of the code, please refer to "Writing Mini Startup Code (Third Edition)". Most of the code is written with reference to the startup code of the ads1.2 library file. The one downloaded here is from Baiwen.com.
For specific code files, see the bare metal code section in the appendix. The required files are: startup.S init.c nand .c s3c24xx.h
At this time, when compiling, you need to set the running address to: -Ttext is 0x30000000
In this way, the startup process of the code is to download the program to the nand flash, and then the hardware automatically copies the first 4k code of nand (mainly initialization code) to SRAM, and then the code starts to execute at address 0 of SRAM, and then the code in SRAM is copied to SDRAM through the code, and then the program control jumps to SDRAM for execution.
;****************************************************************************
; File: init.S
; Function: Set up SDRAM, copy the program to SDRAM, and then jump to SDRAM to continue execution
;****************************************************************************
.equ MEM_CTL_BASE, 0x48000000
.equ SDRAM_BASE, 0x30000000
.text
.global _start
_start:
bl disable_watch_dog ; Disable WATCHDOG, otherwise the CPU will keep restarting
bl memsetup ; Set up the memory controller
bl copy_steppingstone_to_sdram ; copy code to SDRAM
ldr pc, =on_sdram ; Jump to SDRAM and continue execution
on_sdram:
ldr sp, =0x34000000 ; Set up the stack
bl main
halt_loop:
b halt_loop
disable_watch_dog:
; Write 0 to the WATCHDOG register
mov r1, #0x53000000
mov r2, #0x0
str r2, [r1]
mov pc, lr ; return
copy_steppingstone_to_sdram:
; Copy all 4K data of Steppingstone to SDRAM
; The starting address of Steppingstone is 0x00000000, and the starting address of SDRAM is 0x30000000
mov r1, #0
ldr r2, =SDRAM_BASE
mov r3, #4*1024
1:
ldr r4, [r1],#4 ; Read 4 bytes of data from Steppingstone and add 4 to the source address
str r4, [r2], #4 ; Copy this 4-byte data to SDRAM and add 4 to the destination address
cmp r1, r3 ; Check whether it is completed: Is the source address equal to the unsigned address of Steppingstone?
bne 1b ; If not finished copying, continue
mov pc, lr ; return
memsetup:
; Set up the memory controller to use peripherals such as SDRAM
mov r1, #MEM_CTL_BASE ; Start address of 13 registers of storage controller
adrl r2, mem_cfg_val ; The starting storage address of these 13 values
add r3, r1, #52 ; 13*4 = 54
1:
ldr r4, [r2], #4 ; Read the setting value and add 4 to r2
str r4, [r1], #4 ; Write this value to the register and add 4 to r1
cmp r1, r3 ; Check whether all 13 registers have been set
bne 1b ; If not written, continue
mov pc, lr ; return
.align 4
mem_cfg_val:
; Storage controller 13 register settings
.long 0x22011110 ; BWSCON
.long 0x00000700 ; BANKCON0
.long 0x00000700 ; BANKCON1
.long 0x00000700 ; BANKCON2
.long 0x00000700 ; BANKCON3
Previous article:6. 2440 bare metal development LCD operation
Next article:3. Setting the clock and timer of the bare metal system of s3c2440
- Popular Resources
- Popular amplifiers
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
- Play with EK-TM4C1294XL——by 54chenjq
- Lattice, Altera, Xilinx three-in-one image to ROM, MIF software
- How to design the CC2530 antenna? What is the size or package of the dual-ended antenna?
- Qorvo's Best-in-Class Low-Noise Amplifier for Wideband Defense Receivers
- The Vgs of NMOS is greater than Vgsth and Vds is a negative value. What is the voltage of Vds?
- Mobile phone fast charging detector, the hardware is completed, and the software is coming soon!
- How to unlock HUAWEI phone
- I have a question about CAN baud rate setting
- Renesas H8S/2398 (HD64F2398FV20) programming program
- Clock configuration and routine analysis of msp430f5529