mini2440test: How to relocate program code from NAND to SRAM?

HuyNguyen
Hi all,

I am investigating the source code of 2440init.s file to understand how to
boot from NAND flash.
Basically, I understand the whole code of the file but the problem is that
I don't understand how s3c2440 executes the boot process and runs the main
function.
As I know that the MCU will copy program code from NAND flash to its 4K
internal SRAM for execution. From that execution, program code from NAND
flash will be copied to an external SRAM. The problem is:
  - In uVision project, it sets the ROM base addr to 0x30000000 which is
the start addr of SRAM space
  => All labels will have addresses above 0x30000000 (belong to SRAM space)
  - But at the begining, there is no code exists in SRAM space yet until
the boot code copy program code to it.
  => How MCU executes the boot code in 2440init.s file ????

Ex: At power-on event, MCU copies code of 2440init.s file from NAND flash
to the internal SRAM and executes it. The instruction "b ResetHandler"
which is transleted to "b 0x3000011C" instructs the MCU to jump to addr
0x3000011C and exececute code from there. But the MCU has not copied
program from NAND flash to SRAM yet => no code at addr 0x3000011C => how
the MCU continues its execution ???
I tried to search for such question but no result yet.

Can anyone help me to understand the execution flow of the MCU for booting
NAND flash?

Thanks
Huy

Juergen Beisert
Are you sure it jumps to 0x3000011C? I guess it branches to "current
address + 0x11C" instead. Just an idea.

HuyNguyen
Hi,

I also think about that.
But the instruction "b ResetHandler" uses absolute address, not relative
address (from ARM instruction set manual)
And I am still confused about how it jumps to SRAM to starts user
application:
  In case of booting from NAND, it copies program code from NAND to SRAM
starting from 0x3000000. Then it initializes BSS region and executes "bl
Main" instruction to jump to main function.
 => How the instruction "bl  Main" jumps to Main function located in SRAM??
Or it just jumps to Main function stored in NAND flash????

Currently, I am stuck in there and need help from everybody.

Reggie
Where is the 2440init.s file from?  it's just one part of the puzzle from
what I can see from various sources, it appears that this file is just one
part in a bigger project where there is C and/or more assembler that
actually handles setting up the registers and memory allocation and jump
address correctly.

If you look at the datasheet at Table 5-1. Bank 6/7 Addresses, 0x30000000
is the correct place for the ram to start in the virtual address space,
0x3000_0000 is actually 0x0 in your ram.

if it's friendlyarm demo code then it's using memcfg.inc and the
2440addr.inc files to pull in the correct addresses :)  The memcfg.inc file
gives it the 0x3000_0000 start address for ram, the 2440addr.inc file gives
it the register addresses, again you can check these against the datasheet,
0x4800_0000 for instance will find you the bwscon register in the datasheet
:)

you can study those files here:
https://github.com/ceeback/FriendlyARM_DemoCode

HuyNguyen
Hi,

Thanks for your response.

1/ In my project, there are two assembler files. 2440init.s is one of them,
the other is used as library to access co-processor of ARM7
And I see the code of 2440init.s does booting process.

2/ I do not concern about register addresses defined n 2440addr.inc, but
how the MCU execute the booting code.
 Lets me summarize my understanding and my problem:
  - At power-on event, if it boots from NAND, the MCU will copy program
code from NAND to its 4K stepping stone SRAM for execution => it copies
2440init.s to its internal SRAM
  - The first instruction in 2440init.s is "b  ResetHandler" which
instructs the MCU to jump to location of "ResetHandler" and execute code
from there
 However, "ResetHandler" refers to SRAM space (it is 0x3000xxxx). So I am
confused because SRAM has no program code at the beginning !!!!

I know there is something wrong in my understanding because I can compile
and run the project successfully. But I want to correct my knowledge.

I put my project to Dropbox, I am appreciate if you take a look and help me
to understand it.

https://www.dropbox.com/s/097zn0169wt6q6p/33753140keil_2440_000.zip

Thanks,
Huy

Juergen Beisert
> But the instruction "b ResetHandler" uses absolute address,
> not relative address (from ARM instruction set manual)

You are wrong.

This instruction *branches*, it does not *jump*! The final assembler
instruction is always relative to its current address

From our bootloader barebox

33e00000: ea00007a  b 33e001f0 <barebox_arm_reset_vector>
[...]
33e001f0 <barebox_arm_reset_vector>:

0x7a << 2 + 8 = 0x1f0 -> 0x33e00000 + 0x1f0 = 33e001f0

From the ARMARM:
---------------------------------------------------------------------
<target_address>
Specifies the address to branch to. The branch target address is calculated
by:
  1. Sign-extending the 24-bit signed (two&#8217;s complement) immediate to
     32 bits.
  2. Shifting the result left two bits.
  3. Adding this to the contents of the PC, which contains the address of
    the branch instruction plus 8.

The instruction can therefore specify a branch of approximately ±32MB.
---------------------------------------------------------------------

You "bl 0x3000011C" jumps to 0x3000011C when it runs from 0x30000000, but
jumps to 0x0000011C if it runs from the stepping stone SRAM in NAND boot
case.

HuyNguyen
Hi Juergen Beisert,

I got it.
Thank you very much for your information.
One more thing I want to ask is how the boot code instructs the MCU to
branch to main function in SRAM after it copies all program code from NAND
flash to SRAM.
I see that it just uses instruction "bl Main" at the end of the routine
=>I think it branch to Main function in internal SRAM not the external SRAM

Here is the code:
ResetHandler
        ...........   ; initialize hardware 
        ...........   ; copy program code from NAND to external SRAM
InitRam
        ...........   ; initialize bss region in external SRAM
  
        bl Main       ; => branch to main function in internal SRAM ????

How the instruction gets the MCU branch to the main function in the
external SRAM ??

I am appriciate your support. It get me much headache a lot ^_^;

Thanks
Huy

Juergen Beisert
As the internal SRAM will be used for any kind of data transfer from and to
the NAND, the first thing your routine has to do after initializing the
external SDRAM is to copy itself out of the way. The regular way is to copy
itself to the destination address (linked address) in the external SDRAM
and then jump to this address to continue bootstrapping.
Then it loads the remaining part from NAND into the external SDRAM.
And since your routine already runs from external SDRAM also the branch's
target address will be the final address in the external SDRAM.

HuyNguyen
Attachment: 2440init.txt (20.87 KB)
Hi Juergen Beisert

Thank you for your response.
I understand your idea.
However, I do not see the execution flow of the program as your suggestion
(copy from internal SRAM to external SRAM, jump to external SRAM and copy
the remaining part of NAND to external SRAM)

I attach 2440init file here. Could you have a look and help me to point
out:
  - Where it copies from internal SRAM to external SRAM
  - Where it jumps to external SRAM
  - Where it loads the remaining part of NAND to external SRAM

I am sorry for asking you many question. I am new in bootloader project and
want to get comprehensive knowledge for it.

Thanks,
Huy

Juergen Beisert
Arrghh, what a ugly code. Sorry, no idea and no time to dig into this code.
BTW: please stop using "external SRAM". There is no. The external memory is
of type "SDRAM". Only the SoC internal memory is of type "SRAM".

HuyNguyen
Hi Juergen Beisert,

It is OK.
I will try to search and investigate more about it.
Anyway, thank you for your support.

BRs,
Huy