(embedded development) write bootloader The first stage _ embedded development

Source: Internet
Author: User
Tags set time volatile


The simplest bootloader steps to write:
1. Initialization hardware: Close watchdog, set clock, set SDRAM, initialize NAND FLASH
2. If the bootloader is larger, reposition it to SDRAM
3. Read the kernel from NAND flash to SDRAM
4. Set "parameters to pass to kernel"
5. Jump Execution Kernel


Improved:
1. Increase CPU frequency, 200MHZ ==> 400MHZ
2. Start Icache

Relocation is divided into nor startup and NAND start
int Isbootfromnorflash (void)
{
volatile int *p = (volatile int *) 0;
int Val;


val = *p;
*p = 0x12345678;
if (*p = = 0x12345678)
{
/* Write successfully, is NAND start * *
NAND start, 0 address corresponding memory, memory can be written
*p = val;//revert to original value
return 0;
}
Else
{
/* Nor cannot be written as memory.
return 1;
}
}



Tacls, TWRPH0, TWRPH1 settings

Nand_read Read page data read to page register NAND structure






The ultimate goal of bootloader is to start the kernel, and a series of initialization before starting the kernel:
shutting down the watchdog, changing the system clock, initializing the storage controller, relocating the code (copying more code into memory), and so on, and
then the kernel from the NAND Flash reads in SDRAM, passes the startup parameters for the kernel, and jumps to the appropriate address boot kernel.
<pre name= "code" class= "OBJC" style= "widows:1"; > #define S3c2440_mpll_200mhz (0x5c<<12) | ( 0X01<<4) | (0x02))
#define Mem_ctl_base 0x48000000
<pre name= "code" class= "OBJC" style= "widows:1"; >.text//Specifies that the subsequent compiled content is placed in the code snippet "executable";
. Global _start//tells the compiler to follow a globally visible name "may be a variable or a function name";
_start:/*_start is the starting address of a function and the starting address of a compiled, linked program.                       Because the program is loaded through the loader, you
must find a function that _start the name, so the _start must be defined globally so that it exists in the compiled Global compliance table.
For other programs "such as loaders" to find. */
1. Close the watchdog
write 0 assembly code to the Wtcon register Wtcon
:
ldr r0, =0x53000000
mov r1, #0
str R1, [r0]
C code: ( Before calling C code, you must set up the stack, that is, the SP pointer, the instruction MOV sp, #4096)
#define WTCON (* (volatile unsigned long *) 0x53000000)
void Disable_watch_ Dog (void)
{
Wtcon = 0;//close watchdog very simple, write 0 to this register
}
2. Set system clock
assembly code:
#define S3c2440_ Mpll_400mhz ((0x5c<<12) | ( 0X01<<4) | (0x01))

Ldr r0, =0x4c000014
/mov r1, #0x03//Fclk:hclk:pclk=1:2:4, hdivn=1,pdivn=1
mov r1, #0x05;//fclk:hclk:pclk= 1:4:8
str R1, [R0]
//Fixed mode/* If HDIVN non-0,CPU bus mode should be changed from "fast mode" to "Asynchronous buses mode"/MRC P15, 0, R1, C1, C0, 0//read out control registers */O RR R1, R1, #0xc0000000/* Set to "Asynchronous Bus Mode"/MCR P15, 0, R1, C1, C0, 0/* Write control Register/* Mpllcon = S3c2440_mpll_ 200MHZ */Ldr r0, =0x4c000004 ldr R1, =s3c2440_mpll_400mhz str R1, [R0] C code: void Clock_init (void) {//Locktime = 0X00FF Ffff Use the default value to Clkdivn = 0x03;
Fclk:hclk:pclk=1:2:4, Hdivn=1,pdivn=1//dive assembly writing, grammatical requirements. 
* * If the HDIVN 0,cpu bus mode should be changed from "fast mode" to "Asynchronous"/__asm__ ("MRC P15, 0, R1, C1, C0, 0\n"//read out control registers/* "Orr R1, R1, #0xc0000000 \ n"/* is set to "Asynchronous Bus Mode" * * MCR P15, 0, R1, C1, C0, 0\n "/* Write Control registers * *); 
/*******************************************************************  *                 Clock initialization function  * for Mpllcon registers, [19:12] is mdiv,[9:4] pdiv[1:0] for sdiv  * The calculation formula is as follows:  * S3c2410:mpl L (FCLK) = (M*fin)/(P*2^s)  * s3c2440:mpll (FCLK) = (2*m*fin)/(P*2^s)  *: m=mdiv+8;    p=PDIV+2; S=sdiv  * set CLKDIVN, so that the frequency ratio is: Fclk:hclk:pclk=1:2:4  * because the development board input clock is 12MHz, and set MDiv pdiv the Sdiv are  * s3c2410 respectively: mdiv=0x5c      pdiv=0x04    sdiv=0x00  * s3c2440:mdiv=0x12   pdiv=0x01   &NBSP;SD iv=0x02  *: Fclk=200mhz      hclk=100mhz   Pclk=50mhz ************************************* /Mpllcon = S3c2440_mpll_200mhz; /* Now, Fclk=200mhz,hclk=100mhz,pclk=50mhz/}//3. Initialize the SDRAM assembly code: LDR R0, =mem_ctl_base ADR R1, sdram_config/* sdram_config Current address */
Add R3, R0, # (13*4) 1:ldr R2, [R1], #4//Saves the contents of the R1 address to R2, r1=r1+4 str R2, [r0], #4//Saves the value in the R2 to the address specified by R0, while R0=r0+4 CMP R0, R
3//Comparison of R0 and R1 values BNE 1b//BNE indicates that if the label of a different jump is 1, then a b indicates that the jump to the previous 1 label, if the jump to the back to the B can be changed to F Sdram_config:. Long 0x22011110//bwscon . Long 0x00000700//bankcon0. Long 0x00000700//bankcon1. Long 0x00000700//bankcon2. Long 0x00000700  0000700//bankcon4 Long 0x00000700//bankcon5. Long 0x00018005//bankcon6. Long 0x00018005// REFRESH. Long 0x000000b1//banksize. Long 0x00000030//mrsrb6. Long 0x00000030//mrsrb7 C code: void Memsetup (void) {Volat

Ile unsigned long *p = (volatile unsigned long *) mem_ctl_base; /* This function is so assigned, rather than in the previous experiment (such as the MMU experiment) to write the configuration value * in the array, because to generate "position-independent code", so that this function can be copied to the * SDRAM can be run in the steppingstone * * * The value of the storage Controller 13 registers */p[0] = 0x22011110; Bwscon p[1] = 0x00000700; BANKCON0 p[2] = 0x00000700; BANKCON1 p[3] = 0x00000700; BANKCON2 p[4] = 0x00000700; BANKCON3 p[5] = 0x00000700; BANKCON4 P[6] = 0x00000700; BANKCON5 p[7] = 0x00018005; BANKCON6 p[8] = 0x00018005;
BANKCON7/* REFRESH, * hclk=12mhz:0x008c07a3, * hclk=100mhz:0x008c04f4 * * p[9] = 0X008C04F4; P[10] = 0x000000b1; Banksize p[11] = 0x00000030; MRSRB6 p[12] = 0x00000030; MRSRB7}/* * After initialization of SDRAM, the stack must be reset and the SP pointer memory is pointed to the highest because the stack is heavily addressed to the lower address, * that is, using the command Ldr SP, =0x34000000 (assigning 0x34000000 to SP pointers, LDR is a pseudo instruction, when the 0x34000000 number is very large can not be converted to an immediate number, will be done through a few assembly instructions to do it) * * * 4.  Initialize NAND controller BL Nand_init//Assembler call C function/* Initialize NAND flash/void Nand_init (void) {//These three values combined with s3c2440 manual and NAND Flash manual set time series #define TACLS 0 #define TWRPH0 1 #define TWRPH1 0/* Set time series * * nfconf = (tacls<<12) | (twrph0<<8) |
(TWRPH1&LT;&LT;4); /* Enable NAND Flash Controller, initialize ECC, prohibit film selection/Nfcont = (1<<4) | (1<<1) |
(1<<0); }//5. When the C function is called in the relocation Code//assembly, R1 pass the first parameter of the function, R2 pass the second parameter of the function, R3 the third parameter of the transfer function mov r0, #0//copied from the 0 address LDR R1, =_start//from the first line of assembly code//. Text//. Global _start//_START:LDR R2, =__bss_start//__bss_start from link script Sub R2, R2, R1 bl Copy_code_to_sdram void Copy_code_ To_SDRAM (unsigned char *src, unsigned char *dest, unsigned int len) {int i = 0; /* If it is nor start/if (Isbootfromnorflash ()) {while (I < len) {Dest[i] = src[i]; i++;}} else {//nand_init (); nand_read
((unsigned int) src, dest, Len); 
} void Nand_select (void) {Nfcont &= ~ (1<<1); 
} void Nand_deselect (void) {Nfcont |= (1<<1);
} void Nand_cmd (unsigned char cmd) {volatile int i;
NFCMMD = cmd;
for (i = 0; i < i++);

} void nand_addr (unsigned int addr) {unsigned int col = addr% 2048; unsigned int page = addr/2048; volatile int i;
nfaddr = col & 0xFF;
for (i = 0; i < i++);
Nfaddr = (col >> 8) & 0xFF;

for (i = 0; i < i++);
nfaddr = page & 0xFF;
for (i = 0; i < i++);
nfaddr = (page >> 8) & 0xFF;
for (i = 0; i < i++);
nfaddr = (page >>) & 0xFF; 
for (i = 0; i < i++); } void Nand_wait_ready (void) {while (!) (
Nfstat & 1));

} unsigned char nand_data (void) {return nfdata;} void nAnd_read (unsigned int addr, unsigned char *buf, unsigned int len) {int col = addr% 2048; int i = 0; /* 1.

SELECT */Nand_select ();

while (I < len) {/* 2. Pronounce read command 00h/nand_cmd (0x00); /* 3.

Issue address (5 steps issued)/nand_addr (addr); /* 4.

Issue read Command 30h/nand_cmd (0x30); /* 5.

Judgement State * * Nand_wait_ready (); /* 6. Read data * for (; (Col < 2048) && (i < len);

col++) {Buf[i] = Nand_data (); i++; addr++;}
col = 0; }/* 7.
Uncheck */Nand_deselect ();  The link script is: SECTIONS {. = 0x33f80000;//Start link address. Text: {* (. Text)}//code snippet. = ALIGN (4);//four byte alignment. Rodata: {* (. rodata*)} Read-only data segments.

= ALIGN (4); . Data: {* (. Data)}//segment.

= ALIGN (4); __bss_start =.; BSS segment start address. BSS ALIGN (4): {* (. BSS) * (COMMON)} __bss_end =.;
 BSS segment End Address}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.