project : vivi for QQ2440 develope board.
instruction : vivi(boot loader for arm) how to run before load system image.
(1) makefile of vivi.
(2) Head.S
(2.1) steppingstone (4k) (Nand flash can not execute directly but Nor flash and RAM).
(2.2) memory layout.
-- __________________________0x3400_0000 ( total: 64 M )
-- | ++++++ ViVi (1M) +++++++|
-- |_____________________|____0x33F0_0000 ( ViViRAM_BASE)
-- | ++++++ Heap (1M)++++++ |
-- |_____________________|____0x33E0_0000 ( Heap_BASE )
-- | ++++ MMU Table (16K)+++|
-- |_____________________|____0x33DF_C000 ( MMU_Table_BASE )
-- | ++ Priviate Data(16K x 3) ++|
-- |_____________________|__0x33DF_0000 ( ViVi_Priv_RAM_BASE )
-- | ++++++ Stack (32K) +++++|
-- |_____________________|____0x33DE_8000 ( STACK_BASE )
-- | ++++++ ++++++ ++++++ +|
-- |++++++ 61.90625 (M) ++++|
-- |++++++ ++++++ ++++++ + |
-- |____________________|____0x3000_0000 ( RAM_BASE )
(2.3) how the program jump to RAM from the startup code.
(2.3.1) The first step: (following text refer from S3C2440 datasheet)
( A ) S3C2440A boot code can be executed on an external NAND flash memory. In order to support NAND flash boot
loader, the S3C2440A is equipped with an internal SRAM buffer called ‘Steppingstone’. When booting, the first 4
KBytes of the NAND flash memory will be loaded into Steppingstone and the boot code loaded into Steppingstone
will be executed.
( B ) Auto boot: The boot code is transferred into 4-kbytes Steppingstone during reset. After the transfer, the boot
code will be executed on the Steppingstone.
(2.3.2) The second step:
( A ) Because of program can not execute from the media of Nandflash but Norflash, so must have to copy the vivi-self to
RAM when runing in steppingstone. The below figure was the first phase of vivi bootloadr(before go to main function).
-- __________________________
-- | ++++++++Reset target++++++++ |
-- |_________________________|
-- ----------------\|/
-- __________________________
-- | ++++++Disable watch dog +++++|
-- |_________________________|
-- ----------------\|/
-- __________________________
-- | +++++Disable all interupt ++++++|
-- |_________________________|
------------------ \|/
-- __________________________
-- |+++++Initialize system clock++++ |
-- |_________________________|
-- ----------------\|/
-- __________________________
-- |++++++ Memory setup++++++++ |
-- |_________________________|
------------------ \|/
-- __________________________
-- | +++++ All led on (indicate)+++++ |
-- |_________________________|
------------------ \|/
-- __________________________
-- | ++++++++Init UART++++++++ |
-- |_________________________|
------------------ \|/
-- _________________________
-- |+++++ Copy Vivi to RAM +++++ |
-- |________________________|
------------------ \|/
-- _________________________
-- | +++++Go to main func+++++++ |
-- |________________________|
--
( B ) Because the code be flash down into the Nandflash, and the PC must be reset 0x00000000 to starup.
-- ( 1 ) Linker option:
-- link script file for arm-linux-ld
-- "LINKFLAGS = -Tarch/vivi.lds" -Bstatic from the $(TOPDIR)/Makefile
-- The comtent of vivi.lds as following:
-- SECTIONS {
-- . = 0x33f00000;
-- .text : { *(.text) }
-- .data ALIGN(4) : { *(.data) }
-- .bss ALIGN(4) : { *(.bss) *(COMMON) }
-- }
--
-- The 0x33f00000 is the start address create by arm-linux-ld.
-- You can use tool arm-linux-objdump to dump the elf file with option "-D"
-- the below fragement as the example:
--
-- $ /cygdrive/c/Cygnus/arm-tools/bin/arm-uclibc-objdump.exe -D d:/vivi-elf
-- d:/vivi-elf: file format elf32-littlearm
-- Disassembly of section .text:
-- 33f00000 <>:
-- 33f00000: ea00000b b 33f00034 <>
-- 33f00004 <>:
-- 33f00004: ea000099 b 33f00270 <>
-- 33f00008 <>:
-- 33f00008: ea000099 b 33f00274 <>
-- and so on ...
--
-- ( 2 ) Reset target:
-- Because the Code be localed from address 0x00000000, so at the beginning the all
-- branch instruction (as like B, BL ) will jump to the relative address.
-- For exmaple:
$ /cygdrive/c/Cygnus/arm-tools/bin/arm-uclibc-objdump.exe -D d:/vivi-elf
Disassembly of section .text:
33f00000 <>:
33f00000: ea00000b b 33f00034 <>
B to instruction_address+8+4*offset
-------------------------------------------------------------------------------------------------------------
| 31 30 29 28 | 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
-------------------------------------------------------------------------------------------------------------
| ++cond++ | ++1 0 1 0++ | ++++++++ signed 24-bit branch offset +++++++++++++|
-------------------------------------------------------------------------------------------------------------
ea00000b:
-------------------------------------------------------------------------------------------------------------
| ++ 1110++ |++ 1010 ++ | +++0000_0000_0000_0000_0000_1011 (0x34) ++++|
-------------------------------------------------------------------------------------------------------------
According to formula "instruction_address+8+4*offset", so the current PC be load in relative address:
(instruction_address: PC=0x00000000) + 8 + 4 * (offset: 1011=11) = 0x34
-- ( 3 ) Copy Vivi to RAM:
-- We are now not describe the Copy code here, we will intruduce the PC register how to jumping
-- at RAM area from current SARM (steppingstone.)
-- Following fragment is the disassembling code by the "arm-linux-objdump -D" command:
==================================================================================================
@ fragment code of head.S
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
@ get read to call C functions
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
mov a2, #0 @ set argv to NULL
bl main @ call main
mov pc, #FLASH_BASE @ otherwise, reboot
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
.align 4
SerBase:
#if defined(CONFIG_SERIAL_UART0)
.long UART0_CTL_BASE
#elif defined(CONFIG_SERIAL_UART1)
.long UART1_CTL_BASE
#elif defined(CONFIG_SERIAL_UART2)
.long UART2_CTL_BASE
#error not defined base address of serial
#endif
the end of file "head.S"
==================================================================================================
33f000d8: e59f1230 ldr r1, [pc, #560] ; 33f00310 <>
33f000dc: e281f000 add pc, r1, #0 ; 0x0
33f000e0: e1a00000 nop (mov r0,r0)
33f000e4: e1a00000 nop (mov r0,r0)
33f000e8: eafffffe b 33f000e8 <>
33f000ec <>:
33f000ec: e59fd200 ldr sp, [pc, #512] ; 33f002f4 <>
33f000f0: e3a0b000 mov fp, #0 ; 0x0
33f000f4: e3a01000 mov r1, #0 ; 0x0
33f000f8: eb000405 bl 33f01114 <>
33f000fc: e3a0f000 mov pc, #0 ; 0x0
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33f00300 <>:
33f00300: 50000000 andpl r0, r0, r0
33f00304: 000007ff streqd r0, [r0], -pc
33f00308: 0007f021 andeq pc, r7, r1, lsr #32
33f0030c: 000055aa andeq r5, r0, sl, lsr #11
33f00310: 33f000ec mvnccs r0, #236 ; 0xec
33f00314: 00007770 andeq r7, r0, r0, ror r7
33f00318: 33f00000 mvnccs r0, #0 ; 0x0
33f0031c: 00000245 andeq r0, r0, r5, asr #4
==================================================================================================
-- First step: suppose now execute instruction "ldr r1, [pc, #560]" and so we had known the PC now be load with 0x000000e0 since
-- ARM process support line pipe, and now we can work out the r1 = mem[0x000000e0 + #560(dec)] = mem[0x00000310], now we can look at
-- the content of offset 0x00000310 from mem is 33f000ec, therefore r1 = 0x33f000ec, then the next instruction "add pc, r1, #0"
-- is make the PC go to RAM ( PC=0x33f000ec ).
--
-- Second step: why the value of offset 33f00310 from mem is the value of PC jumping, we first look at the C code: the lable "on_the_ram"
-- is create by arm-linux-as assembler and generate the code like this: "on_the_ram: .word 33f000ec" and lay it at address: 0x33f00310.
-- so can see the line "33f00310: 33f000ec mvnccs r0, #236 ; 0xec" is the dissembling code of "on_the_ram: .word 33f000ec",
-- and be place at the end of ROM code. this is genrated by assembler automatically.
--
-- Third step: You can enable the switch "CONFIG_DEBUG_LL" for debugging via serial port.
--
-- Done!
--
(3) others for vivi
instruction : vivi(boot loader for arm) how to run before load system image.
(1) makefile of vivi.
(2) Head.S
(2.1) steppingstone (4k) (Nand flash can not execute directly but Nor flash and RAM).
(2.2) memory layout.
-- __________________________0x3400_0000 ( total: 64 M )
-- | ++++++ ViVi (1M) +++++++|
-- |_____________________|____0x33F0_0000 ( ViViRAM_BASE)
-- | ++++++ Heap (1M)++++++ |
-- |_____________________|____0x33E0_0000 ( Heap_BASE )
-- | ++++ MMU Table (16K)+++|
-- |_____________________|____0x33DF_C000 ( MMU_Table_BASE )
-- | ++ Priviate Data(16K x 3) ++|
-- |_____________________|__0x33DF_0000 ( ViVi_Priv_RAM_BASE )
-- | ++++++ Stack (32K) +++++|
-- |_____________________|____0x33DE_8000 ( STACK_BASE )
-- | ++++++ ++++++ ++++++ +|
-- |++++++ 61.90625 (M) ++++|
-- |++++++ ++++++ ++++++ + |
-- |____________________|____0x3000_0000 ( RAM_BASE )
(2.3) how the program jump to RAM from the startup code.
(2.3.1) The first step: (following text refer from S3C2440 datasheet)
( A ) S3C2440A boot code can be executed on an external NAND flash memory. In order to support NAND flash boot
loader, the S3C2440A is equipped with an internal SRAM buffer called ‘Steppingstone’. When booting, the first 4
KBytes of the NAND flash memory will be loaded into Steppingstone and the boot code loaded into Steppingstone
will be executed.
( B ) Auto boot: The boot code is transferred into 4-kbytes Steppingstone during reset. After the transfer, the boot
code will be executed on the Steppingstone.
(2.3.2) The second step:
( A ) Because of program can not execute from the media of Nandflash but Norflash, so must have to copy the vivi-self to
RAM when runing in steppingstone. The below figure was the first phase of vivi bootloadr(before go to main function).
-- __________________________
-- | ++++++++Reset target++++++++ |
-- |_________________________|
-- ----------------\|/
-- __________________________
-- | ++++++Disable watch dog +++++|
-- |_________________________|
-- ----------------\|/
-- __________________________
-- | +++++Disable all interupt ++++++|
-- |_________________________|
------------------ \|/
-- __________________________
-- |+++++Initialize system clock++++ |
-- |_________________________|
-- ----------------\|/
-- __________________________
-- |++++++ Memory setup++++++++ |
-- |_________________________|
------------------ \|/
-- __________________________
-- | +++++ All led on (indicate)+++++ |
-- |_________________________|
------------------ \|/
-- __________________________
-- | ++++++++Init UART++++++++ |
-- |_________________________|
------------------ \|/
-- _________________________
-- |+++++ Copy Vivi to RAM +++++ |
-- |________________________|
------------------ \|/
-- _________________________
-- | +++++Go to main func+++++++ |
-- |________________________|
--
( B ) Because the code be flash down into the Nandflash, and the PC must be reset 0x00000000 to starup.
-- ( 1 ) Linker option:
-- link script file for arm-linux-ld
-- "LINKFLAGS = -Tarch/vivi.lds" -Bstatic from the $(TOPDIR)/Makefile
-- The comtent of vivi.lds as following:
-- SECTIONS {
-- . = 0x33f00000;
-- .text : { *(.text) }
-- .data ALIGN(4) : { *(.data) }
-- .bss ALIGN(4) : { *(.bss) *(COMMON) }
-- }
--
-- The 0x33f00000 is the start address create by arm-linux-ld.
-- You can use tool arm-linux-objdump to dump the elf file with option "-D"
-- the below fragement as the example:
--
-- $ /cygdrive/c/Cygnus/arm-tools/bin/arm-uclibc-objdump.exe -D d:/vivi-elf
-- d:/vivi-elf: file format elf32-littlearm
-- Disassembly of section .text:
-- 33f00000 <>:
-- 33f00000: ea00000b b 33f00034 <>
-- 33f00004 <>:
-- 33f00004: ea000099 b 33f00270 <>
-- 33f00008 <>:
-- 33f00008: ea000099 b 33f00274 <>
-- and so on ...
--
-- ( 2 ) Reset target:
-- Because the Code be localed from address 0x00000000, so at the beginning the all
-- branch instruction (as like B, BL ) will jump to the relative address.
-- For exmaple:
$ /cygdrive/c/Cygnus/arm-tools/bin/arm-uclibc-objdump.exe -D d:/vivi-elf
Disassembly of section .text:
33f00000 <>:
33f00000: ea00000b b 33f00034 <>
B to instruction_address+8+4*offset
-------------------------------------------------------------------------------------------------------------
| 31 30 29 28 | 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
-------------------------------------------------------------------------------------------------------------
| ++cond++ | ++1 0 1 0++ | ++++++++ signed 24-bit branch offset +++++++++++++|
-------------------------------------------------------------------------------------------------------------
ea00000b:
-------------------------------------------------------------------------------------------------------------
| ++ 1110++ |++ 1010 ++ | +++0000_0000_0000_0000_0000_1011 (0x34) ++++|
-------------------------------------------------------------------------------------------------------------
According to formula "instruction_address+8+4*offset", so the current PC be load in relative address:
(instruction_address: PC=0x00000000) + 8 + 4 * (offset: 1011=11) = 0x34
-- ( 3 ) Copy Vivi to RAM:
-- We are now not describe the Copy code here, we will intruduce the PC register how to jumping
-- at RAM area from current SARM (steppingstone.)
-- Following fragment is the disassembling code by the "arm-linux-objdump -D" command:
==================================================================================================
@ fragment code of head.S
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
@ get read to call C functions
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
mov a2, #0 @ set argv to NULL
bl main @ call main
mov pc, #FLASH_BASE @ otherwise, reboot
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
.align 4
SerBase:
#if defined(CONFIG_SERIAL_UART0)
.long UART0_CTL_BASE
#elif defined(CONFIG_SERIAL_UART1)
.long UART1_CTL_BASE
#elif defined(CONFIG_SERIAL_UART2)
.long UART2_CTL_BASE
#error not defined base address of serial
#endif
the end of file "head.S"
==================================================================================================
33f000d8: e59f1230 ldr r1, [pc, #560] ; 33f00310 <>
33f000dc: e281f000 add pc, r1, #0 ; 0x0
33f000e0: e1a00000 nop (mov r0,r0)
33f000e4: e1a00000 nop (mov r0,r0)
33f000e8: eafffffe b 33f000e8 <>
33f000ec <>:
33f000ec: e59fd200 ldr sp, [pc, #512] ; 33f002f4 <>
33f000f0: e3a0b000 mov fp, #0 ; 0x0
33f000f4: e3a01000 mov r1, #0 ; 0x0
33f000f8: eb000405 bl 33f01114 <>
33f000fc: e3a0f000 mov pc, #0 ; 0x0
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33f00300 <>:
33f00300: 50000000 andpl r0, r0, r0
33f00304: 000007ff streqd r0, [r0], -pc
33f00308: 0007f021 andeq pc, r7, r1, lsr #32
33f0030c: 000055aa andeq r5, r0, sl, lsr #11
33f00310: 33f000ec mvnccs r0, #236 ; 0xec
33f00314: 00007770 andeq r7, r0, r0, ror r7
33f00318: 33f00000 mvnccs r0, #0 ; 0x0
33f0031c: 00000245 andeq r0, r0, r5, asr #4
==================================================================================================
-- First step: suppose now execute instruction "ldr r1, [pc, #560]" and so we had known the PC now be load with 0x000000e0 since
-- ARM process support line pipe, and now we can work out the r1 = mem[0x000000e0 + #560(dec)] = mem[0x00000310], now we can look at
-- the content of offset 0x00000310 from mem is 33f000ec, therefore r1 = 0x33f000ec, then the next instruction "add pc, r1, #0"
-- is make the PC go to RAM ( PC=0x33f000ec ).
--
-- Second step: why the value of offset 33f00310 from mem is the value of PC jumping, we first look at the C code: the lable "on_the_ram"
-- is create by arm-linux-as assembler and generate the code like this: "on_the_ram: .word 33f000ec" and lay it at address: 0x33f00310.
-- so can see the line "33f00310: 33f000ec mvnccs r0, #236 ; 0xec" is the dissembling code of "on_the_ram: .word 33f000ec",
-- and be place at the end of ROM code. this is genrated by assembler automatically.
--
-- Third step: You can enable the switch "CONFIG_DEBUG_LL" for debugging via serial port.
--
-- Done!
--
(3) others for vivi
没有评论:
发表评论