Detailed explanation of u-boot transplantation steps

Publisher:美好的人生Latest update time:2024-07-26 Source: cnblogsKeywords:u-boot Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The following is an example of the steps to port u-boot to the 44B0 development board. Only the hardware-related parts need to be modified during the porting. In terms of code structure:
1) Create the ev44b0ii directory in the board directory, and create ev44b0ii.c, flash.c, memsetup.S, u-boot.lds, etc. You don't need to start from scratch. You can choose a similar directory, copy it directly, and modify the file name and content. When I was porting u-boot, I chose the ep7312 directory. Since u-boot already contains the development board directory based on s3c24b0, you can also copy the corresponding directory as a reference.
2) Create the arm7tdmi directory in the cpu directory, which mainly contains start.S, interrupts.c, cpu.c, and serial.c files. There is no need to create files from scratch. Just copy them from arm720t and then modify the corresponding content.
3) Add ev44b0ii.h in the include/configs directory, and put global macro definitions here.
4) Find the Makefile in the u-boot root directory and modify it to add
ev44b0ii_config: unconfig
@./mkconfig $(@:_config=) arm arm7tdmi ev44b0ii
5) Run make ev44bii_config, if there is no error, you can start the hardware related code transplantation work


3. u-boot architecture
1) Overall structure
u-boot is a hierarchical structure. As can be seen from the above figure, the software personnel doing the transplantation work should provide serial port driver (UART Driver), Ethernet driver (Ethernet Driver), Flash driver (Flash Driver), USB driver (USB Driver). At present, it is not very necessary to download the program through the USB port, so the USB driver has not been transplanted for the time being. Above the driver layer is the u-boot application, and the command provides a human-machine interface through the serial port. We can use some commands to do some common work, such as the memory viewing command md.
The Kermit application is mainly used to support the use of the serial port to download applications through the hyperterminal. TFTP is to download applications through the network, such as the uclinux operating system.
2) Memory distribution
Memory distribution in flash rom The flash size of ev44b0ii is 2M (8bits), and now 0-40000, a total of 256k, is used as the storage space of u-boot. Since there are some environment variables in u-boot, such as IP address, boot file name, etc., they can be configured through setenv in the command line and saved in the space of 40000-50000 (64k in total) through saveenv. If there are saved environment variables, u-boot boot will directly use these environment variables. As can be seen from the code analysis, we will move the flash boot code to DRAM for execution. The following figure shows the location of the u-boot code in DRAM. The boot code u-boot will be moved from 0x0000 0000 to 0x0C700000. Special attention should be paid to the fact that the interrupt vector program address of ev44b0ii uclinux is at 0x0c00 0000, so the program cannot be downloaded to 0x0c00 0000, and is usually downloaded to 0x0c08 0000.

4. Start.S Code Structure
1) Define Entry
An executable Image must have an entry point and can only have one unique global entry point, which is usually placed at the 0x0 address of Rom (flash). For example,
.globl _start
_start in start.S:
It is worth noting that you must tell the compiler to know this entry point. This work mainly involves modifying the connector script file (lds).
2) Set the Exception Vector
The exception vector table, also known as the interrupt vector table, must start from address 0 and be stored continuously. The following includes reset, undefined handling (undef), software interrupt (SWI), pre-instruction error (Pabort), data error (Dabort), reserved, and IRQ, FIQ, etc. Note that the value here must be consistent with the vector_base of uclinux. That is to say, if vector_base (include/armnommu/proc-armv/system.h) in uclinux is defined as 0x0c00 0000, then HandleUndef should be at
0x0c00 0004.
b reset //for debug
ldr pc,=HandleUndef
ldr pc,=HandleSWI
ldr pc,=HandlePabort
ldr pc,=HandleDabort
b .
ldr pc,=HandleIRQ
ldr pc,=HandleFIQ
ldr pc,=HandleEINT0 /*mGA H/W interrupt vector table*/
ldr pc,=HandleEINT1
ldr pc,=HandleEINT2
ldr pc,=Han dleEINT3
ldr pc,=HandleEINT4567
ldr pc,=HandleTICK /*mGA*/
b .
b .
ldr pc,=HandleZDMA0 /*mGB*/
ldr pc,=HandleZDMA1
ldr pc,=HandleBDMA0
ldr pc,=HandleBDMA1
ldr pc,=HandleWDT
ldr pc,= HandleTIMER4 ldr pc ,= HandleTIMER5 /* mGC */
b .
b . ldr pc,=HandleTIMER2 ldr pc,=HandleTIMER3 ldr pc,=HandleTIMER4 /*mGC*/ b . =HandleURXD0 /*mGD*/ ldr pc,=HandleURXD1 ldr pc,=HandleIIC ldr pc,=HandleSIO ldr pc,=HandleUTXD0 ldr pc,=HandleUTXD1 /*mGD*/ b . b . ldr pc,=HandleRTC /*mGKA*/ b . b . b . b . b . /*mGKA*/ b . b . ldr pc,=HandleADC /*mGKB*/ b . b . b . b . b . /*mGKB*/ b . b . ldr pc,=EnterPWDN For comparison: See the values ​​of the above tags: .equ HandleReset, 0xc000000 .equ HandleUndef,0xc000004 .equ HandleSWI, 0xc000008 .equ HandlePabort, 0xc00000c .equ HandleDabort, 0xc000010 .equ HandleReserved, 0xc000014 .equ HandleIRQ, 0xc000018 .equ HandleFIQ, 0xc00001c /*the value is different with an address you think it may be. *IntVectorTable */ .equ HandleADC, 0xc000020 .equ HandleRTC, 0xc000024














































.equ HandleUTXD1, 0xc000028
.equ HandleUTXD0, 0xc00002c
.equ HandleSIO, 0xc000030
.equ HandleIIC, 0xc000034
.equ HandleURXD1, 0xc000038 .equ
HandleURXD0, 0xc00003c .equ
HandleTIMER 5, 0xc000040
.equ HandleTIMER4, 0xc000044
.equ HandleTIMER3, 0xc000048
.equ HandleTIMER2, 0xc00004c
.equ HandleTIMER1, 0xc000050
.equ HandleTIMER0, 0xc000054
.equ HandleUERR01, 0xc000058
.equ HandleWDT, 0xc00005c
.equ HandleBDMA1, 0xc000060
.equ HandleBDMA0, 0xc000064
.equ HandleZDMA1, 0xc000068 .equ
HandleZDMA0, 0xc00006c
.equ HandleTICK, 0xc 000070
.equ HandleEINT4567, 0xc000074
.equ HandleEINT3, 0xc000078
.equ HandleEINT2, 0xc00007c
.equ HandleEINT1, 0xc000080
.equ HandleEINT0, 0xc000084
3) Initialize CPU Related pll, clock, interrupt control registers
These are to turn off the watch dog timer, turn off interrupts, set LockTime, PLL (phase lock loop), and clock.
These values ​​(except LOCKTIME) can be found in the Samsung 44b0 manual.
ldr r0,WTCON //watch dog disable
ldr r1,=0x0
str r1,[r0]
ldr r0,INTMSK
ldr r1,MASKALL //all interrupt disable
str r1,[r0]
/************ *******************************************
* Set clock control registers *
* *************************************************** **/
ldr r0,LOCKTIME
ldr r1,=800 // count = t_lock * Fin (t_lock=200us, Fin=4MHz) = 800
str r1,[r0]
ldr r0,PLLCON /*temporary setting of PLL*/
ldr r1 ,PLLCON_DAT /*Fin=10MHz,Fout=40MHz or 60MHz*/
str r1,[r0]
ldr r0,CLKCON
ldr r1,=0x7ff8 //All unit block CLK enable
str r1,[r0]
4) Initialize memory controller
The memory controller is mainly configured by setting 13 registers starting from 1c80000, including bus width,
8 memory banks, bank size, sclk, and two bank modes.
/* ************************************************** **
* Set memory control registers *
****************************************** ***********/
memsetup:
adr r0,SMRDATA
ldmia r0,{r1-r13}
ldr r0,=0x01c80000 //BWSCON Address
stmia r0,{r1-r13}
5) Put the program in rom Copy to RAM
First, use PC to get the starting address of bootloader in flash, and then calculate
the size of the program code by the difference of labels. The compiler will generate the correct distribution value of these labels when linking. After getting
the correct information, copy the code to RAM through registers (r3 to r10) as the intermediate medium for copying.
relocate:
/*
* relocate armboot to RAM
*/
adr r0, _start /* r0 <- current position of code */
ldr r2, _armboot_start
ldr r3, _armboot_end
sub r2, r3, r2 /* r2 <- size of armboot */
ldr r1, _TEXT_BASE /* r1 <- destination address */
add r2, r0, r2 /* r2 <- source end address */
/*
* r0 = source address
* r1 = target address
* r2 = source end address
*/
copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble copy_loop
6) Initialize stack
Enter various modes and set the stack of corresponding mode.
InitStacks:
/*Don't use DRAM,such as stmfd,ldmfd...
SVCstack is initialized before*/
mrs r0,cpsr
bic r0,r0,#0X1F
orr r1,r0,#0xDB /*UNDEFMODE|NOINT*/
msr cpsr,r1 /*UndefMode*/
ldr sp,UndefStack
orr r1,r0,#0XD7 /*ABORTMO DE|NOINT*/
msr cpsr,r1 /*AbortMode*/ ldr
sp,AbortStack
orr r1,r0,#0XD2 /*IRQMODE|NOINT*/
msr cpsr,r1 /*IRQMode*/
ldr sp,IRQStack
orr r1,r0,#0XD1 /*FIQMODE|NOINT*/
msr cpsr,r1 /*FIQMode*/
ldr sp,FIQStack
bic r0,r0,#0XDF /*MODEMASK|NOINT*/
orr r1,r0,#0X13
msr cpsr,r1 /*SVCMode*/
ldr sp,SVCStack
7) Transfer to RAM for execution
Use the instruction ldr,pc, the C function address in RAM to transfer to RAM for execution.
5. System initialization part
1. Serial port part
The setting of the serial port mainly includes the initialization of the serial port part. It is worth noting that the Baudrate of the serial port is closely related to the clock MCLK, which is calculated by: rUBRDIV0=( (int)(MCLK/16./(gd ->baudrate) + 0.5) -1 ). This can be found in the manual. Other functions include sending and receiving. There is no interrupt at this time, and the loop wait is used to determine whether the action is completed.
For example, the receiving function:
while(!(rUTRSTAT0 & 0x1)); //Receive data read
return RdURXH0();
2. Clock part
The delay function udelay is implemented.
Since get_timer here does not use interrupts, it uses global variables to accumulate.
3. Flash part
As part of the memory, there is definitely no problem in reading flash. The key is the writing part of flash.
Flash must be erased first and then written.
unsigned long flash_init (void)
{
int i;
u16 manId,devId;
//first we init it as unknown, even if you forget assign it below, it's not a problem
for (i=0; i < CFG_MAX_FLASH_BANKS; ++i){
flash_info[i].flash_id = FLASH_UNKNOWN;
flash_info[i].sector_count=CFG_MAX_FLASH_SECT;
}
/* check manId,devId*/
_RESET();
_WR(0x555,0xaa); _WR(0x2aa,0x55); _WR(0x555,0x90); manId=_RD(0x0); _WR(0x555,0xaa); _WR(0x2aa,
0x55 ); _WR(0x555,0x90); devId=_RD(0x1); _RESET(); printf("flashn");








printf("Manufacture ID=%4x(0x0004), Device ID(0x22c4)=%4xn",manId,devId);
if(manId!=0x0004 && devId!=0x22c4){
printf("flash check faliluren");
return 0;
}else{
for (i=0; i < CFG_MAX_FLASH_BANKS; ++i){
flash_info[i].flash_id=FLASH_AM160T;/*In fact it is fujitu,I only don't want to
modify common files*/
}
}
/* Setup offsets */
flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
/* zhangyy comment
#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
//onitor protection ON by default
flash_protect(FLAG_PROTECT_SET,
CFG_MONITOR_BASE,
CFG_MONITOR_BASE+monitor_flash_len-1,
&flash_info[0]);
#endif
*/
flash_info[0].size = PHYS_FLASH_SIZE;
return (PHYS_FLASH_SIZE);
}
flash_init completes the initialization part. The main purpose here is to check the flash Is the model correct?
int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
int flag, prot, sect, l_sect;
//ulong start, now, last;
u32 targetAddr;
u32 targetSize;
/*zyy note:It is required and can't be omitted*/
rNCACHBE0=( (0x2000000>>12)<<16 )|(0>>12); //flash area(Bank0) must be non-cachable
area.
rSYSCFG=rSYSCFG & (~0x8); //write buffer has to be off for proper timing.
if ((s_first < 0) || (s_first > s_last)) {
if ( info->flash_id == FLASH_UNKNOWN) {
printf ("- missingn");
} else {
printf ("- no sectors to erasen");
}
return 1;
}
if ((info->flash_id == FLASH_UNKNOWN) ||
(info->flash_id > FLASH_AMD_COMP)) {
printf ("Can't erase unknown flash type - abortedn");
return 1;
}
prot = 0;
for (sect=s_first; sect<=s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot) {
printf ("- Warning: %d protected sectors will not be erased!n",
prot);
} else {
printf ("n");
}
l_sect = -1;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++) {
if (info->protect[sect] == ​​0) {/* not protected */
targetAddr=0x10000*sect;
if(targetAddr<0x1F0000)
targetSize=0x10000 ; else if(targetAddr<0x1F8000) targetSize=0x8000; else if(targetAddr<0x1FC000
) targetSize=0x2000; else targetSize=0x4000; F29LV160_EraseSector(targetAddr); l_sect = sect; if(! BlankCheck (targetAddr, targetSize)) printf("BlankCheck Errorn"); } } /* re-enable interrupts if necessary */ if (flag) enable_interrupts(); /* wait at least 80us - let's wait 1 ms */ udelay (1000 ); /* *We wait for the last triggered sector */ if (l_sect < 0) goto DONE; DONE: printf (" donen"); return 0; } int BlankCheck(int targetAddr,int targetSize) { int i,j; for(i=0;i{ j=*((u16 *)(i+targetAddr)); if( j!=0xffff) { printf(" E:%x=%xn",(i+targetAddr),j); return 0; } } return 1; } flash_erase erases flash, BlankCheck checks whether the content is erased successfully. /*----- -------------------------------------------------- ---------------- *Write a word to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */ static int write_word (flash_info_t *info, ulong dest, ulong data) { volatile u16 *tempPt; /*zhangyy note:because of compatiblity of function,I use low & hi*/ u16 low = data & 0xffff; u16 high = (data >> 16) & 0xffff; low=swap_16(low); high=swap_16(high); tempPt=(volatile u16 *)dest; _WR(0x555,0xaa); _WR(0x2aa,0x55); _WR(0x555,0xa0); * tempPt=high; _WAIT(); _WR(0x555,0xaa); _WR(0x2aa,0x55); _WR(0x555,0xa0); *(tempPt+1)=low; _WAIT(); return 0; } write_word to flash Write unsigned long data in it. Since the flash can only write 16 bits at a time, it is written in two times.


































































[1] [2] [3] [4]
Keywords:u-boot Reference address:Detailed explanation of u-boot transplantation steps

Previous article:Analysis of uboot.lds of uboot
Next article:uboot_freescale_imx51_start.s_Detailed explanation

Recommended ReadingLatest update time:2024-11-15 18:34

[Linux bottom layer] U-boot ksz8081 network driver debugging
Micrel is an excellent PHY chip. For more information about the chip, please refer to: ksz8081 datasheet interpretation System version: Ubuntu18.04-64 Compiler version: gcc version 7.4.0 (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1) uboot version: 2018.07-linux4sam_6.0 Board model: at91sama5d3x-xplained MCU mode
[Microcontroller]
Migrate the mtdparts partition of u-boot-1.1.6
Unlike higher versions of u-boot, the mtdparts command does not have a separate file like cmd_mtdparts to implement. However, if you search for uboot, you can see the following code in cmd_jffs2.c:  1 U_BOOT_CMD(  2     mtdparts,    6,    0,    do_jffs2_mtdparts,  3     "mtdparts- define flash/nand partitionsn",  
[Microcontroller]
U-Boot transplanted on FL2440 (4) - supports network card DM9000 and programming yaffs file system
1 Support network card chip DM9000 Under driver, there are network card drivers DM9000x.c and DM9000x.h DM9000 is connected to BANK4, bit width 16 Set the network card base address in include/configs/TX2440.h: At line 56, change the definition of CS8900 to: #define CONFIG_DRIVER_DM9000 1 #define CONFIG_DM9000_BASE 0
[Microcontroller]
U-boot porting on mini2440-S3C2440 (2)
1. This article mainly explains the transplantation of U-boot on mini2440-S3C2440. The version used is U-boot-2009.11_tekkaman-master, download address: https://download.csdn.net/download/jinanhezhuang/20823342?spm=1001.2014.3001.5501 1. Download the official u-boot: Download address: 2. Use xftp software to upload
[Microcontroller]
U-boot porting on mini2440-S3C2440 (2)
u-boot-2014.10 transplantation (3) Identify NOR Flash
The main thing is to add the nor flash model we use to jedec_table File : drivers/mtd/jedec_flash.c jz2440: MX29LV160DB 2M id= 0x2249, MX29LV160B macro needs to be added by yourself #define MX29LV160B      0x2249 mini2440  :SST29LV1601 (AM29LV160DB)   35sectors   id = 0x2249 // for jz2440                 {      
[Microcontroller]
A brief discussion on how to pass parameters from U-boot to Kernel under ARM
We may all know that U-boot will pass many parameters to the Linux Kernel, such as serial port baud rate, RAM Size, videofb, MAC Address, etc., and the Linux kernel will also read and process these parameters. The parameters are passed between the two through struct tag. U-boot saves the things to be passed to the k
[Microcontroller]
U-Boot transplanted on FL2440 (2)----Support NOR Flash
1 Select NOR flash model     The nor flash chip on my development board is Intel's JS28F320 (4MB) (1device=32blocks, 1block=128MB The fl2440 defaults to nandflash startup. To start norflash, just unplug the jumper cap J5.    1. Delete all the flash configuration parts in the development board’s configuration file fl24
[Microcontroller]
u-boot-2009.08 transplantation on mini2440 (I) --- Establishing mini2440 engineering environment (1)
Migration environment 1. Host environment: CentOS 5.5 under VMare, 1G memory. 2. Integrated development environment: Eclipse IDE 3. Compilation environment: arm-linux-gcc v4.4.3, arm-none-eabi-gcc v4.5.1. 4. Development board: mini2440, 2M nor flash, 128M nand flash. 5. u-boot version: u-boot-2009.08 6. References: ht
[Microcontroller]
u-boot-2009.08 transplantation on mini2440 (I) --- Establishing mini2440 engineering environment (1)
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号