Full development record (I) Restoring the truth about SD card startup

Source: Internet
Author: User
Full development record (I) Restoring the truth about SD card startup
Classification: Embed Linux2011-07-26 4690 people read comments (2)
Cdisknullbufferintegerbyte
In the previous chapter, we also roughly analyzed the Startup Process of the SD card. In the specific problem locating and solving process, we found that there are still many unclear points, many articles on the Internet are on the cloud. Let's take a step-by-step look at the steps and processes for starting the cloud6410 SD card (My Development Board is configured with ok6410, 256 m + 1G, SD card is 2 GB, MMC)
1. Development Board jumper, started from SD card
[CPP] view plaincopy
《Ok6410development board 2.6 sets the jumper to 11111000 (from left to right for pin8 to pin1)
These settings can be found in the datasheetof 125, and the page of "Redirect" can be opened.
Table 3-1. device operating mode selection at boot-up
From this we can see that the last three digits are 0, indicating that the startup from SD/MMC (ch0)
[CPP] view plaincopy
Modify uboot to allow it to read data from the SD card and lift itself to the memory.
After we have set the CPU jumper, the CPU knows where to get the first finger, and how does the processor perform this operation?
I have found a reference article 《s3c2450_irom_applicationnote_rev003.pdf.
This time I found the official document to explain this point in a more clear way: initi6410_internal_rom_booting.pdf
In this document, we can see that the startup process after CPU power-on is as follows:
[CPP] view plaincopy
① Irom supports initial boot up, initialize system clock, D-TCM, device specific controller and bootin device.
② Irom boot codes can load 4kb of bootloader to stepping stone. The 8kb boot loader is called BL1
③ BL1: BL1 can initialize system clock, UART, and SDRAM for user. After initializing, BL1 will load remaining Boot Loader which is called bl2 on the SDRAM
④ Finally, jump to start address of bl2. that will make good environment to use system.
[CPP] view plaincopy
According to this startup process, we must prepare 8 K Boot Code in BL1,
It is used to initialize the system, always, serial port, and SDRAM, and put the complete bootloader on bl2.

2.7 boot block assignment guide is described in detail

Storage Structure of SD/MMC cards below 2 GB
SD/MMC 1 block = 512 byte
========================================================== ========================================================== ==========
| SD/MMC device |
========================================================== ========================================================== ==========
| Recommendation | mandatory |
| User File System | ========================================== ========================================
| Kernel | bl2 | BL1 (8 K) | signature (512 byte) | reserved (512 byte) |
| 16 block | 1 block | 1 block |
========================================================== ========================================================== ==========

With this general impression, let's take a look. Next we will modify the uboot code.
Ii. Modify uboot code
[CPP] view plaincopy
For the uboot source code of, see the final references.
Modify the absolute path of the makefile cross tool chain (hey, this cross tool chain is of course a self-developed cross tool chain, refer to the previous blog)

Ifeq ($ (ARCH), arm)
Cross_compile = arm-None-Linux-gnueabi-
Endif

Cross_compile =/opt/cross_toolchains/ARM/4.6.1/bin/ARM-None-Linux-gnueabi-
[CPP] view plaincopy
Modify include/configs/smdk6410.h to open the # define config_boot_movinand macro, and disable other startup options.
In uboot code, the irom startup mode is called movinand.
This uboot can already be started from the SD card. How does it work for the purpose of the cloud6410?
[CPP] view plaincopy
We can see the following section in CPU/cloud64xx/start. S:

# Ifdef config_boot_movinand
LDR sp, _ text_phy_base
BL movi_bl2_copy
B after_copy
# Endif
Analyze the movi_bl2_copy Function
[CPP] view plaincopy
Void movi_bl2_copy (void) in CPU/cloud64xx/movi. C is defined as follows:
[CPP] view plaincopy
# If defined (config_initi6400)
Copymovitomem (movi_bl2_pos, movi_bl2_blkcnt, (uint *) bl2_base, config_sys_clk_freq, movi_init_required );
# Else
Writel (readl (hm_control4) | (0x3 <16), hm_control4 );
Copymovitomem (hsmmc_channel, movi_bl2_pos, movi_bl2_blkcnt, (uint *) bl2_base, movi_init_required );
# Endif
Determine the value of movi_bl2_pos
[CPP] view plaincopy
./Include/movi. h: # define movi_bl2_pos (movi_last_blkpos-movi_bl1_blkcnt-movi_bl2_blkcnt-movi_env_blkcnt)

./Include/movi. h: # define movi_last_blkpos (movi_total_blkcnt-(efuse_size/movi_blksize ))

./Include/movi. h: # define movi_bl1_blkcnt (ss_size/movi_blksize)

./Include/movi. h: # define movi_bl2_blkcnt (part_zimage_offset-part_uboot_offset)/movi_blksize)-movi_env_blkcnt)

./Include/movi. h: # define movi_env_blkcnt (pai_env_size/movi_blksize)

./Include/movi. h
# Ifdef config_boot_movinand
# Define movi_total_blkcnt * (volatile unsigned int *) (tcm_base-0x4 ))
# Define movi_high_capacity * (volatile unsigned int *) (tcm_base-0x8 ))
# Else
# Define movi_total_blkcnt 7864320 // 7864320 // 3995648 // 1003520/* Static movinand total block count: for writing to movinand when NAND boot */
# Define movi_high_capacity 0
# Endif

./Include/movi. h: # define movi_blksize 512

./Include/movi. h
# If defined (config_initi6400) | defined (config_initi6410) | defined (config_initi6430)
# Define tcm_base 0x0c004000
# Define bl2_base 0x57e00000
# Elif defined (config_s3c2450) | defined (config_s3c2416)
# Define tcm_base 0x40004000
# Define bl2_base 0x33e00000
# Else
# Error tcm_base or bl2_base is not defined
# Endif

./Include/movi. h
# If defined (config_initi6400)
# Define ss_size (4*1024)
# Define efuse_size (2*1024) // 1.5 K efuse, 0.5 K Reserved
# Else
# Define ss_size (8*1024)
# Define efuse_size (1*1024) // 0.5 K efuse, 0.5 K reserved'
# Endif

./Include/movi. h: # define part_zimage_offset 0x40000

./Include/movi. h: # define part_uboot_offset 0x0

./Include/configs/smdk6410.h: # define 1__env_size 0X4000/* total size of environment sector */
Determine the bl2_base Value
[CPP] view plaincopy
./Include/movi. h
# If defined (config_initi6400) | defined (config_initi6410) | defined (config_initi6430)
# Define tcm_base 0x0c004000
# Define bl2_base 0x57e00000
# Elif defined (config_s3c2450) | defined (config_s3c2416)
# Define tcm_base 0x40004000
# Define bl2_base 0x33e00000
# Else
# Error tcm_base or bl2_base is not defined
# Endif
After calculation, we can see that the copymovitomem function is determined here, which is tcm_base-0x4. The value of the register of this address (It also tells us that the value of the uboot should not be greater than 256 K after compilation)
The parameter "maid" is displayed.
0x0c003ffc globalblocksizehide total block count of the MMC Device
The value is 256 K (according to the print result, no specific description is found)
The value of movi_bl2_blkcnt is (0x40000-0)/512-(0X4000/512) = 512-32 (slice)
Most of the information written on the internet is copymovitomem, which transfers KB of data to the memory. From this computation, we can see that this conclusion is wrong.
Only-16 K of data is moved to the memory.
In the definition of movi_bl2_pos, the corresponding processing is performed to ensure the correctness of the location.
Compile uboot to generate u-boot.bin
[CPP] view plaincopy
Make smdk6410_config
Make-J4
3. Install the modified uboot into the SD card.
Can the generated uboot-bin be directly burned into the SD card?
Irom_fusing_tool.exe (open-source, you can find the source code), but this tool burns the nb0 file.
In fact, the structure of the nb0 file is 256 K + 8 K. in Linux, you can use the following script to generate the nb0 file.
[CPP] view plaincopy
#! /Bin/sh
Rm-RF temp x * u-boot_256k.bin u-boot_8k.bin u-boot_mmc.nb0
Cat u-boot.bin> temp
Cat u-boot.bin> temp
Split-B 256 k temp
Music Video xAA u-boot_256k.bin
Split-B 8 K u-boot.bin
Music Video xAA u-boot_8k.bin
Cat u-boot_256k.bin> u-boot_mmc.nb0
Cat u-boot_8k.bin> u-boot_mmc.nb0
I want to directly burn uboot-bin to the SD card. It is too troublesome to use the script. So I plan to write a burning tool myself. The key code is as follows:
It should be noted that I am using vc6, Windows XP, and vc6 to support disk I/O operations itself is not very good. There are many extended definitions and functions cannot be used, many of them are manually added here.
If you use vc2003 or a later version, it will be simpler.
[CPP] view plaincopy
DWORD csc6410bootloaderwriterdlg: blockdataread (char cpart, DWORD dwblockindex, DWORD dwreadcount, byte * pbuffer)
{
Cstring devname;
Devname. Format ("\\\\\\\ % C:", cpart );
Handle hdevice = createfile (devname, generic_read, file_assist_read, null, open_existing, 0, null );
DWORD dwfilepointer = setfilepointer (hdevice, dwblockindex * 512, 0, file_begin );
DWORD dwbytesread = 0;
Bool bread = readfile (hdevice, pbuffer, dwreadcount, & dwbytesread, null );
If (bread = false)
{
DWORD dwerror = getlasterror ();
}
Closehandle (hdevice );
Return dwbytesread;
}
[CPP] view plaincopy
DWORD csc6410bootloaderwriterdlg: blockdatawrite (ulong nphysicaldrivenumber, DWORD dwblockindex, byte * pdata, DWORD dwdatalen)
{
If (maid % 512 )! = 0) dwdatalen = (dwdatalen/512) + 1) * 512;
Cstring devname;
Devname. Format ("\\\\\ physicaldrive % d", nphysicaldrivenumber );
Handle hdevice = createfile (devname, generic_write, file_assist_write, null, open_existing, 0, null );
DWORD dwfilepointer = setfilepointer (hdevice, dwblockindex * 512, 0, file_begin );

DWORD dwbyteswrite = 0;
Bool bwrite = writefile (hdevice, pdata, dwdatalen, & dwbyteswrite, null );
If (bwrite = false)
{
DWORD dwerror = getlasterror ();
}

Closehandle (hdevice );
Return dwbyteswrite;
}
Do you see the difference? Pay attention to it!
The building form of devname in the write function is different from that in the READ function. This problem has been debugged for a long time. If the building form of the READ function is used in the write function, the writefile is abnormal.
Specifically: when the last several fan blocks are operated, bwrite is equal to true, while dwbyteswrite is 0 (why? Still failing to go further)
In addition, if the length of the data to be written is not an integer multiple of 512, it must be processed. Otherwise, getlasterror is 87 and the parameter is incorrect.
Because the smallest sector of all Flash files is 512 bytes, the minimum operating unit is 512 bytes.
(The file system has helped us solve these problems. We are operating bare disks now, so we cannot consider this problem according to the idea of a file system)
The following are the functions used by the write function to construct devname.
[CPP] view plaincopy
Ulong csc6410bootloaderwriterdlg: getphysicaldrivenumber (char cpart)
{
Typedef struct _ disk_extent {
Ulong disknumber;
Large_integer startingoffset;
Large_integer extentlength;
} Disk_extent, * pdisk_extent;


Typedef struct _ volume_disk_extents {
Ulong numberofdiskextents;
Disk_extent extents [anysize_array];
} Volume_disk_extents, * pvolume_disk_extents;

# Define volumedisksize (sizeof (volume_disk_extents ))

# Define ioctl_volume_get_volume_disk_extents 5636096

Cstring devname;
Devname. Format ("\\\\\\\ % C:", cpart );
Handle hdevice = createfile (devname, generic_read, file_cmd_read | file_cmd_write, null, open_existing, 0, null );

Volume_disk_extents volumedata;
DWORD dwout = 0;
Deviceiocontrol (hdevice, ioctl_volume_get_volume_disk_extents, null, 0, & volumedata, volumedisksize, & dwout, null );
Closehandle (hdevice );

Return volumedata. extents [0]. disknumber;
}
The following code is used to obtain the drive letters of all inserted U disks (removable disks, pay attention to the following judgment ).
[CPP] view plaincopy
Void csc6410bootloaderwriterdlg: onbuttongetdriverinfo ()
{
// Todo: add your control notification handler code here
// Obtain all drive letters
M_cblist.resetcontent ();
DWORD dwstrlen = getlogicaldrivestrings (0, null );
Char * pstring = new char [dwstrlen + 1];
Memset (pstring, 0, dwstrlen + 1 );
Getlogicaldrivestrings (dwstrlen + 1, pstring );

Char * pnow = pstring;
While (true)
{
If (pnow> = (pstring + dwStrLen-1) break;
DWORD dwret = getdrivetype (pnow );
If (dwret = drive_removable)
{
M_cblist.insertstring (0, pnow );
}
Pnow + = strlen (pnow );
Pnow ++;
}

Delete [] pstring;

M_cblist.setcursel (0 );
M_cblist.setfocus ();

Writelog ("U disk check completed ");
}
Finally, write the code. Here we will ask the SD card to be converted into FAT32 first, so that we can read the MBR part of the fta32 File Allocation Table.
[CPP] view plaincopy
Void csc6410bootloaderwriterdlg: onbuttonop ()
{
// Todo: add your control notification handler code here

Int ncursel = m_cblist.getcursel ();
If (ncursel =-1)
{
MessageBox ("disk information detection ");
Return;
}

Cstring strbootfilepath;
M_ebootfilepath.getwindowtext (strbootfilepath );
If (strbootfilepath = "")
{
MessageBox ("select the boot file to be burned first ");
Return;
}

// Get the drive letter
Cstring strtext;
M_cblist.getlbtext (m_cblist.getcursel (), strtext );
Char cpart = strtext [0];

// Obtain physicaldrivenumber
Ulong nphysicaldrivenumber = getphysicaldrivenumber (cpart );

// Read the 0-sector MBR
Byte szmbr [512];
Memset (szmbr, 0, sizeof (szmbr ));
DWORD dwreturn = blockdataread (cpart, 0, sizeof (szmbr), szmbr );
If (dwreturn! = Sizeof (szmbr ))
{
MessageBox ("read MBR error.", "error", mb_ OK | mb_iconerror );
Return;
}
{
Cstring strlog;
Strlog. Format ("MBR read succeeded ");
Writelog (strlog );
}

// Determine whether it is FAT32
// Fat16 is 0x36 0x37 0x38 0x39 0x3a 0x3b
Char szfs [6];
Szfs [0] = szmbr [0x52];
Szfs [1] = szmbr [0x53];
Szfs [2] = szmbr [0x54];
Szfs [3] = szmbr [0x55];
Szfs [4] = szmbr [0x56];
Szfs [5] = '\ 0 ';

If (strcmp (szfs, "FAT32 ")! = 0)
{
MessageBox ("format the SD card as a FAT32 File System", "error", mb_ OK | mb_iconinformation );
Return;
}

// Obtain the total number of disk sectors
// 1ch-1fh 4 Number of hidden sectors in the Partition
// 20 h-23 H 4 actual number of sectors used by the disk (excluding hidden sectors)

DWORD count_block_hidden = 0;
Memcpy (& count_block_hidden, & szmbr [0x1c], sizeof (count_block_hidden ));

DWORD count_block = 0;
Memcpy (& count_block, & szmbr [0x20], sizeof (count_block ));

DWORD count_block_total = count_block_hidden + count_block;

// Another method to obtain the total number of sectors
// # Define ioctl_disk_get_drive_geometry_ex 458912
// Struct _ disk_geometry_ex
// {Disk_geometry geometry;
// Large_integer disksize;
// Uchar data [1];
//} Diskex;
// Deviceiocontrol (hdevice, ioctl_disk_get_drive_geometry_ex, null, 0, (lpvoid) & diskex, sizeof (diskex), (lpdword) & bytesreturned, null );

// Read the u-boot.bin File
// Up to 256 K
# Define movi_total_blkcnt 0x40000
Byte buffer_utoot [movi_total_blkcnt];
Memset (buffer_utoot, 0, sizeof (buffer_utoot ));

Cfile CF;
Cf. Open (strbootfilepath, cfile: moderead );

DWORD uboot_size = min (movi_total_blkcnt, Cf. getlength ());

Cf. Read (buffer_utoot, uboot_size );
Cf. Close ();

// Write the boot program uboot-bin to the corresponding location
DWORD bl2_begin = count_block_total-1-1-16-512;
DWORD bl1_begin = count_block_total-1-1-16;

Dwreturn = blockdatawrite (nphysicaldrivenumber, blphybegin, buffer_utoot, 8192 );
If (dwreturn! = 8192)
{
MessageBox ("8 K Bytes failed to write Boot ");
Return;
}
{
Cstring strlog;
Strlog. Format ("8 K bytes written to boot succeeded ");
Writelog (strlog );
}
Dwreturn = blockdatawrite (nphysicaldrivenumber, bl2_begin, buffer_utoot, uboot_size );

If (dwreturn <uboot_size)
{
MessageBox ("failed to write Boot ");
Return;
}
{
Cstring strlog;
Strlog. Format ("boot file write completed, total disk sectors: % d", count_block_total );
Writelog (strlog );
}
}
Here, we can completely analyze the problem and create a startup SD card for the program. It is attached with some reference materials and there is no way to paste the attachment here. Leave a message for me.
In the following content, we will go to uboot to modify uboot. Please pay attention to the next section "how to calculate the memory size and adjust the memory size in uboot".
Iv. References
Download uboot1.1.6 (movinand supported)

Http://www.rayfile.com/zh-cn/files/7ac4e133-0e58-11de-bd70-0014221b798a/

Enable uboot to support the SD startup

Http://blog.csdn.net/zwj0403/article/details/6420245

《S36410_internal_rom_booting.pdf
《S36410_rev12.pdf
《Smdk6410_users_manual_rev1.0.pdf
《K4x42563pc.pdf
《Ok6410development board 2.6user Manual
《Ok6410development board hardware manual 2.1.pdf

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.