3882|16

60

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

请教大侠:2440启动代码中函数ReadImageFromNand读起来有点费劲,能帮忙分析下吗? [复制链接]

具体函数如下:
TOC toc; // made global because it's too big for our tiny stack

DWORD ReadImageFromNand(DWORD dwEntry, DWORD dwSig)
{
    DWORD dwSectorsNeeded;
    DWORD dwSector, dwLength;         // Start Sector & Length
    DWORD dwRAM, i;
        //这里是如何从Nand读到DRAM的?
    if ( !FMD_ReadSector(TOC_SECTOR,        //起始page地址:TOC_SECTOR = BLOCK_TO_SECTOR(TOC_BLOCK)=32*1
                        (LPBYTE)&toc,        //要复制到的地址,一般为DRAM,不能等于0
                        NULL, 1) )
    {
        Uart_SendString("ERR_DISK_OP_FAIL1\n");
        return ERR_DISK_OP_FAIL1;
    }
        //VALID_TOC(&toc)是用来干什么的?
    if ( !VALID_TOC(&toc) ) {
        Uart_SendString("ERR_INVALID_TOC: ");
        Uart_SendDWORD(toc.dwSignature, TRUE);
        return ERR_INVALID_TOC;
    }
        //这下面的基本上都读不懂
    if ( !(toc.id[dwEntry].dwImageType & IMAGE_TYPE_RAMIMAGE) ) {
        Uart_SendString("ERR_INVALID_FILE_TYPE: ");
        Uart_SendDWORD(toc.id[dwEntry].dwImageType, TRUE);
        return ERR_INVALID_FILE_TYPE;
    }
    dwSectorsNeeded = toc.id[dwEntry].dwTtlSectors;                // xipkernel size = 0x9B4
        // Record The Total Sectors
        totalSec=toc.id[dwEntry].dwTtlSectors+toc.chainInfo.dwLength;
        Uart_SendString("Total Sectors:");
        Uart_SendDWORD(totalSec,TRUE);
        //////////////////////////////
       
        Uart_SendString("Sector addr on NAND: ");
        Uart_SendDWORD(toc.id[dwEntry].sgList[0].dwSector, TRUE);
    Uart_SendString("TotalSector: ");
    Uart_SendDWORD(dwSectorsNeeded, TRUE);

    dwRAM    = VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwLoadAddress);

    JumpAddr = toc.id[dwEntry].dwJumpAddress ? VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwJumpAddress) :
                                               VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwLoadAddress);
                                               
    // Load the disk image directly into RAM
    // .BUGBUG: recover from read failures
        Uart_SendString("Reading Kernel Image from NAND\r\n");
    i = 0;
        while (dwSectorsNeeded && i < MAX_SG_SECTORS)
        {
        dwSector = toc.id[dwEntry].sgList.dwSector;
        dwLength = toc.id[dwEntry].sgList.dwLength;

                Uart_SendString("    dwSector: ");
                Uart_SendDWORD(dwSector, TRUE);
                Uart_SendString("    dwLength: ");
                Uart_SendDWORD(dwLength, TRUE);
                Uart_SendString("    dwRAM: ");
                Uart_SendDWORD(dwRAM, TRUE);

        // read each sg segment
        while (dwLength)
        {        //这里还有一个读NAND的函数?
            if ( !FMD_ReadSector(dwSector,
                                (LPBYTE)dwRAM,
                                NULL, 1) )
            {
                Uart_SendString("ERR_DISK_OP_FAIL2: ");
                Uart_SendDWORD(dwSector, TRUE);
                            dwSector++;
                                continue;
            }
            
                    dwSector++;
                    dwLength--;
            dwRAM += SECTOR_SIZE;
            drawProcessBar(totalSec,currSec);        //显示启动进度条
        }
        dwSectorsNeeded -= toc.id[dwEntry].sgList.dwLength;
        i++;
    }
    //  We only do this if the dwRAM is not zero (The default tocblock1
    //  set the dwRAM to be 0)
    if (toc.chainInfo.dwLoadAddress == 0)
    {
        return ERR_SUCCESS;
    }
    // Load the Chain.bin stored from NAND to the SDRAM
        dwRAM = VIRTUAL_TO_PHYSICAL(toc.chainInfo.dwLoadAddress);                // 0x303c0000
        dwSectorsNeeded = toc.chainInfo.dwLength;                                                // 0x20
        dwSector = toc.chainInfo.dwFlashAddress;                                                // 0x103c0
    while(dwSectorsNeeded)
    {   //这里还有一个?
        if (!FMD_ReadSector(dwSector,
                            (LPBYTE) dwRAM,
                            NULL, 1) )
        {
            Uart_SendString("Failed reading Chain.bin:");
            Uart_SendDWORD(dwSector, TRUE);
                        dwSector++;
                        continue;
        }
        dwSector++;
        dwSectorsNeeded--;
        dwRAM += SECTOR_SIZE;
        drawProcessBar(totalSec,currSec);
    }
        return ERR_SUCCESS;
}

最新回复

请问谁能帮提供一份2440的UMON的源代码程序吗? 即在ADS工程里面能够通过EBOOT列出一些菜单继而进行相关操作, 如通过USB下载NK,格式化FLASH等的源代码? 我邮箱:phosphor88@yahoo.cn 谁能提供给我一份,感激不尽!  详情 回复 发表于 2009-5-20 22:11
点赞 关注

回复
举报

84

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
这段之前没细看过,得翻一下老bsp了。

你可以问问gooogleman,他对2440的研究很不错的。
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
TOC toc。我也对这个不了解,toc是干什么用的,好像还必须用到,我升级eboot.bin的时候,没有弄好它,就失败了,但是不清楚怎么弄呢?
 
 
 

回复

86

帖子

0

TA的资源

一粒金砂(中级)

4
 
VALID_TOC从字面上都可以明白,它就是判断TOC是否有效。这段代码其实不复杂,只要搞明白TOC,应该没什么困难的。第一次读的就是TOC的内容。
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(中级)

5
 
TOC 其实是 table of content的缩写。

其实就是用来组织nk.bin的。记得是个结构体,(去年看的了,但愿不要记错)

因为NK.bin 是微软自己搞的一套数据格式。不是裸体二进制,不能直接在内存运行。

TOC 正好对NK.bin的结构进行一些简单的描述。

楼主看代码 把所有相关代码放在一个路径,用sourceinsight看,什么都明白了。

这方面 网上很多人写了博客的,多看看吧。
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

6
 
这是用来给bootloader提取image中的pe文件用的。
pe文件是可以重定位的,有了这个ptoc,bootloader就可以知道nk.exe在哪,找到nk.exe的entry point并fixup,然后nk.exe会接着利用toc的chain去依次寻找kernel.dll等文件,获取entry point并fixup。
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

7
 
引用 5 楼 codewarrior 的回复:
这是用来给bootloader提取image中的pe文件用的。
pe文件是可以重定位的,有了这个ptoc,bootloader就可以知道nk.exe在哪,找到nk.exe的entry point并fixup,然后nk.exe会接着利用toc的chain去依次寻找kernel.dll等文件,获取entry point并fixup。


所言极是。但是和PE文件又有点不同,不过都是换汤不换药的。
 
 
 

回复

81

帖子

0

TA的资源

一粒金砂(初级)

8
 
引用 6 楼 gooogleman 的回复:
引用 5 楼 codewarrior 的回复:
这是用来给bootloader提取image中的pe文件用的。
pe文件是可以重定位的,有了这个ptoc,bootloader就可以知道nk.exe在哪,找到nk.exe的entry point并fixup,然后nk.exe会接着利用toc的chain去依次寻找kernel.dll等文件,获取entry point并fixup。


所言极是。但是和PE文件又有点不同,不过都是换汤不换药的。

nk.exe就是一个不折不扣的pe文件,只不过被打包进了一个“不知道天南地北”的大包裹NK.bin里面去了。bootloader面对这样一个大包裹,如果没有指点,是没办法去取到nk.exe并为其fixup的。pTOC的用处简言之,就四个字:顺藤摸瓜。
 
 
 

回复

89

帖子

0

TA的资源

一粒金砂(初级)

9
 
mark。
TOC一般都会在烧录程序前需要检查一下的。呵呵。
S&C社的东东烧录eboot的时候就要擦写一次 Erase and Reset TOC。然后再来烧录eboot。
codewarrior大牛已经讲的很明确了。一个chain的功能。链子将所有需要的东西链起来。呵呵。
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(中级)

10
 
VALID_TOC从字面上都可以明白,它就是判断TOC是否有效。这段代码其实不复杂,只要搞明白TOC,应该没什么困难的。第一次读的就是TOC的内容。

仔细查了TOC的相关资料,发现它是用来描述ce内核镜像文件image的xipkernel段核心结构体。
typedef struct _TOC {
//和CSW中的认证域类似,只用来验证接下去内容的合法
DWORD       dwSignature;
//包含image的索引(我的是1)、启动delay时间、ip地址、MAC地址和掩码等
BOOT_CFG       BootCfg;
//用来描述3个之多的ce内核image数组,我用的是id[1]
IMAGE_DESCRIPTOR   id[MAX_TOC_DESCRIPTORS];
CHAININFO     chainInfo;
} TOC, *PTOC;                   // 512 字节
但是这里仍然有点模糊,不是那么清晰。
TOC 其实是 table of content的缩写。

其实就是用来组织nk.bin的。记得是个结构体,(去年看的了,但愿不要记错)

因为NK.bin 是微软自己搞的一套数据格式。不是裸体二进制,不能直接在内存运行。

TOC 正好对NK.bin的结构进行一些简单的描述。

这里不一定非 得NK.bin才用到TOC吧!nk.bin只不过是对nk.nb0打包,加了些校验而已,如果要加载nk.nb0同样需要用到TOC,个人理解!


TOC toc; // made global because it's too big for our tiny stack


/***************************************************************************

dwEntry=1:TOC结构体中使用ID[1]描述CE内核image.

***************************************************************************/
DWORD ReadImageFromNand(DWORD dwEntry, DWORD dwSig)
{
    DWORD dwSectorsNeeded;                                //定义ce内核镜像文件image的xipkernel需要的扇区大小
    DWORD dwSector, dwLength;                 //定义起始扇区及长度
    DWORD dwRAM, i;                                                //定义DRAM的物理地址
        //这里是读取block1的第一个page,检查是否有坏块。
         //这个函数到底想做什么?将block1的page0的数据全读到&toc地址吗?
    if ( !FMD_ReadSector(TOC_SECTOR,        //起始page地址:TOC_SECTOR = BLOCK_TO_SECTOR(TOC_BLOCK)=32*1
                        (LPBYTE)&toc,        //扇区数据buffer,从NandFlash中读出的每一个扇区的数据都存放在这个buffer中。
                        NULL,                        //NULL表示不读取扇区信息?
                        1) )                        //一次只读取一个扇区,即一个page = 512byte
    {
        Uart_SendString("ERR_DISK_OP_FAIL1\n");
        return ERR_DISK_OP_FAIL1;
    }
        //VALID_TOC(&toc)是用来干什么的?
        //这个函数是不是与上面的FMD_ReadSector函数有着一定的联系???
    if ( !VALID_TOC(&toc) ) {
        Uart_SendString("ERR_INVALID_TOC: ");
        Uart_SendDWORD(toc.dwSignature, TRUE);
        return ERR_INVALID_TOC;
    }
        //
    if ( !(toc.id[dwEntry].dwImageType & IMAGE_TYPE_RAMIMAGE) )
    {
        Uart_SendString("ERR_INVALID_FILE_TYPE: ");
        Uart_SendDWORD(toc.id[dwEntry].dwImageType, TRUE);
        return ERR_INVALID_FILE_TYPE;
    }
    dwSectorsNeeded = toc.id[dwEntry].dwTtlSectors;                // xipkernel size = 0x9B4
        // Record The Total Sectors
        totalSec=toc.id[dwEntry].dwTtlSectors+toc.chainInfo.dwLength;
        Uart_SendString("Total Sectors:");
        Uart_SendDWORD(totalSec,TRUE);       
        Uart_SendString("Sector addr on NAND: ");
        Uart_SendDWORD(toc.id[dwEntry].sgList[0].dwSector, TRUE);
    Uart_SendString("TotalSector: ");
    Uart_SendDWORD(dwSectorsNeeded, TRUE);

    dwRAM    = VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwLoadAddress);

    JumpAddr = toc.id[dwEntry].dwJumpAddress ? VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwJumpAddress) :
                                               VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwLoadAddress);
                                               
    // Load the disk image directly into RAM
    // .BUGBUG: recover from read failures
        Uart_SendString("Reading Kernel Image from NAND\r\n");
    i = 0;
        while (dwSectorsNeeded && i < MAX_SG_SECTORS)
        {
        dwSector = toc.id[dwEntry].sgList.dwSector;        //计算xipkernel需要的扇区数量
        dwLength = toc.id[dwEntry].sgList.dwLength;        //计算xipkernel需要的长度

                Uart_SendString("    dwSector: ");
                Uart_SendDWORD(dwSector, TRUE);
                Uart_SendString("    dwLength: ");
                Uart_SendDWORD(dwLength, TRUE);
                Uart_SendString("    dwRAM: ");
                Uart_SendDWORD(dwRAM, TRUE);

        // read each sg segment
        while (dwLength)
        {        //校验NK存放扇区是否有坏块,如果有则自动读取下一个扇区
                  //这里又出现了一个FMD_ReadSector,是对存储NK的扇区进行校验吗?
            if ( !FMD_ReadSector(dwSector,
                                (LPBYTE)dwRAM,
                                NULL, 1) )
            {
                Uart_SendString("ERR_DISK_OP_FAIL2: ");
                Uart_SendDWORD(dwSector, TRUE);
                            dwSector++;
                                continue;
            }
            
                    dwSector++;
                    dwLength--;
            dwRAM += SECTOR_SIZE;
            drawProcessBar(totalSec,currSec);        //显示启动进度条
        }
        dwSectorsNeeded -= toc.id[dwEntry].sgList.dwLength;
        i++;
    }
    //  We only do this if the dwRAM is not zero (The default tocblock1
    //  set the dwRAM to be 0)
    if (toc.chainInfo.dwLoadAddress == 0)
    {
        return ERR_SUCCESS;
    }
    // Load the Chain.bin stored from NAND to the SDRAM
        dwRAM = VIRTUAL_TO_PHYSICAL(toc.chainInfo.dwLoadAddress);                // 0x303c0000
        dwSectorsNeeded = toc.chainInfo.dwLength;                                                // 0x20
        dwSector = toc.chainInfo.dwFlashAddress;                                                // 0x103c0
    while(dwSectorsNeeded)
    {
        //为什么这里又出来了一个FMD_ReadSector???
        if (!FMD_ReadSector(dwSector,
                            (LPBYTE) dwRAM,
                            NULL, 1) )
        {
            Uart_SendString("Failed reading Chain.bin:");
            Uart_SendDWORD(dwSector, TRUE);
                        dwSector++;
                        continue;
        }
        dwSector++;
        dwSectorsNeeded--;
        dwRAM += SECTOR_SIZE;
        drawProcessBar(totalSec,currSec);
    }
        return ERR_SUCCESS;
}


对这段程序仍然不是很懂,很高人继续指点指点!感激不尽!
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

11
 
这里不一定非 得NK.bin才用到TOC吧!nk.bin只不过是对nk.nb0打包,加了些校验而已,如果要加载nk.nb0同样需要用到TOC,个人理解!

_我就是没有使用TOC的。

我用的是NK.nb0文件,


使用NK.nb0很简单,什么TOC等等格式问题都不用考虑。



 
 
 

回复

46

帖子

0

TA的资源

一粒金砂(初级)

12
 
其他的呢?一并帮分析一下,讲解一下
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

13
 
FMD_ReadSector——读一个扇区而已。但是里面已经包含了ECC校验的功能。

。还有我的博客有FMD驱动分析。你去看看吧。
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

14
 
如果是RAM版的nk,eboot直接将所有的文件一股脑全扔到sdram里,这时是不需要TOC的,只要知道起始地址和长度即可。
但现在用的更多的是binfs格式的xip kernel,这种“需要时再加载”的方法,就需要知道各个文件在flash里的具体分布了。
不过在系统里用的又不一样,没细看。看过的dx解释一番。
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

15
 
借贵帖问个问题!DWORD ReadImageFromNand(DWORD dwEntry, DWORD dwSig)
{
    DWORD dwSectorsNeeded; //定义ce内核镜像文件image的xipkernel需要的扇区大小
    DWORD dwSector, dwLength;        //定义起始扇区及长度
    DWORD dwRAM, i; //定义DRAM的物理地址
//这里是读取block1的第一个page,检查是否有坏块。
        //这个函数到底想做什么?将block1的page0的数据全读到&toc地址吗?
    if ( !FMD_ReadSector(TOC_SECTOR, //起始page地址:TOC_SECTOR = BLOCK_TO_SECTOR(TOC_BLOCK)=32*1
                        (LPBYTE)&toc, //扇区数据buffer,从NandFlash中读出的每一个扇区的数据都存放在这个buffer中。
                        NULL, //NULL表示不读取扇区信息?
                        1) ) //一次只读取一个扇区,即一个page = 512byte
    {
       Uart_SendString("ERR_DISK_OP_FAIL1\n");
        return ERR_DISK_OP_FAIL1;

    }
我在mini2440上 用自带的Nboot 自己做的Eboot,NK,下载运行串口出现
** Downloading UNKNOWN image type ***
........................
dwImageStart : 0x8c200000
dwImageLength: 0x1887850
LaunchAddr   : 0x8c201000

rom_offset=0x0.
Run eboot, JumpAddr = 0x30038000
..
  ?
WinCE NAND Boot v1.00
Oct 27 2008 16:11:22
**********
dwEntry is 0x00000001
ERR_DISK_OP_FAIL1

Boot ERROR:0x00000001
这是为什么啊!可能什么地方不对,帮忙分析下!今天上网搜这个问题发现了这个帖子!
继续关注中!
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

16
 
FMD_ReadSector。。那就是这个FMD的这个函数除了问题呗。。返回了FALSE.是你的nand驱动的问题吧
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

17
 
请问谁能帮提供一份2440的UMON的源代码程序吗?

即在ADS工程里面能够通过EBOOT列出一些菜单继而进行相关操作,

如通过USB下载NK,格式化FLASH等的源代码?

我邮箱:phosphor88@yahoo.cn

谁能提供给我一份,感激不尽!
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表