在上一篇文章中,实现应用程序操作FLASH及更新Nboot。这篇讨论应用程序更新NK,这个比更新Nboot要复杂一些。由于MINI2440不使用EBOOT,系统从SD卡系统后,Flash是没有分区的,理论上NK.nb0不一定需要BINFS,但如果不使用BINFS,系统是启动不了的,这让我百思不得其解。。。
分区可使用BP_OpenPartition(),这个只能在驱动中使用,因此在FMD_OEMIoControl()加多一个Case, BP_OpenPartition()需要指定超始地址,长度,分区类型等。MINI2440第2块写TOC,第3块到第19块是BootLogo,第20块开始才是BINFS。SuperVivi烧入NK时可看到分区的一些信息,如下:
Enter your selection: w
Clear the free memory
Please send the Image through USB.
Download Address=0x80200000 Length=0x1a338e0
........................Done.
Low Level Format: Start = 0x1300(19 块), Num = 0x7ed00(2029 块)
.............................................................................................................................................................................................................Done.
Create Partition: Start = 0x1400(20 块), Num = 0xd200(210 块).
................................................Done.
Create Partition: Start = 0xe600(230 块), Num = 0x6fd00(1789 块).
...Done.
Start Windows CE...;
从上面得知,分了两个区,第一个区为BINFS ,第二区为FAT 。
在调用BP_OpenPartition() 之前需调用BP_LowLevelFormat(),因为BP_OpenPartition 会检测MBR 。
1
case
0xFF44
:
2
BP_Init(…);
3
BP_LowLevelFormat(…);
4
BP_OpenPartition(…);
5
BP_OpenPartition(…);
6
break
;
7
BINFS 从第20 开始的,但友善烧NK 却从第39 块开始,想不明白?
第2 块写TOC ,可查看NBOOT 相关代码
代码
1
TOC
*
pToc
=
NULL;
2
pToc
=
(TOC
*
)malloc(
512
);
//
512字节
3
volatile
unsigned
int
dwSector, dwLength;
//
Start Sector & Length
4
void
(
*
run)(
void
)
=
(
void
(
*
)(
void
))(DOWNLOAD_ADDRESS);
5
int
dwEntry
=
1
;
6
pToc
->
id[dwEntry].dwTtlSectors
=
dwSectorsNeeded;
//
这个根据NK.NB0大小,计算出需要多少块
7
pToc
->
id[dwEntry].dwImageType
=
0x2
;
8
dwRAM
=
0x30200000
;
9
pToc
->
id[dwEntry].dwLoadAddress
=
0x80200000
;
10
dwSector
=
39
*
256
;
//
NK从第块开始写
11
dwLength
=
dwSectorsNeeded;
12
pToc
->
id[dwEntry].sgList[
0
].dwSector
=
dwSector;
13
pToc
->
id[dwEntry].sgList[
0
].dwLength
=
dwLength;
14
pToc
->
dwSignature
=
TOC_SIGNATURE;
15
pToc
->
id[dwEntry].dwJumpAddress
=
0x8
将TOC 写在第2 块,接下来就把NK.nb0 从第39 块开始写,NK文件太大,不能一次性将其读入内存,可参考如何实现从SD卡更新NK ? 提到的分段读写NK 。
在写NK 时,若遇到坏块,需跳过,检测是否为坏块可调用驱动中的IsBlockBad()
关键代码:
代码
1
DWORD ReadSize
=
30
*
1024
;
//
每次读取30K文件
2
DWORD startSectorAdd
=
39
*
256
;
//
起始页
3
LONG lFileToMove
=
0
;
4
for
(
int
j
=
0
; j
<
FileSize
/
ReadSize; j
++
)
5
{
6
DWORD actlen
=
0
;
7
PCHAR pBuff
=
NULL;
8
pBuff
=
(
char
*
)malloc(ReadSize);
9
memset(pBuff,
0xFF
,ReadSize);
10
SetFilePointer(hFile, lFileToMove, NULL, FILE_BEGIN);
//
移动文件指针
11
iRet
=
ReadFile(hFile, pBuff, ReadSize,
&
actlen, NULL);
12
if
(iRet
==
FALSE)
13
{
14
RETAILMSG(
1
,(TEXT(
"
Read NB0 File Failed.
"
)));
15
return
;
16
}
17
//
将数据写入FLash中,每页写512字节
18
int
i
=
0
;
19
while
(i
<
ReadSize
/
512
)
20
{
21
if
(startSectorAdd
%
PAGES_PER_BLOCK
==
0
)
22
{
23
if
(IsBadBlock(hFirm,startSectorAdd
/
PAGES_PER_BLOCK))
24
{
25
RETAILMSG(
1
,(TEXT(
"
***** Bad Block %d.\n\r
"
),startSectorAdd
/
PAGES_PER_BLOCK));
26
startSectorAdd
+=
PAGES_PER_BLOCK;
27
continue
;
28
}
29
}
30
31
iRet
=
WriteSector(hFirm,startSectorAdd,
&
pBuff[i
*
512
]);
32
if
(iRet
==
FALSE)
33
{
34
RETAILMSG(
1
,(TEXT(
""
Write NB0 File Failed.
"
)));
35
return
;
36
}
37
startSectorAdd
++
;
38
i
++
;
39
}
40
if
(pBuff)
41
{
42
free(pBuff);
43
pBuff
=
NULL;
44
}
45
lFileToMove
+=
ReadSize;
//
文件指纹后移
46
if
(ReadSize
>
actlen)
47
{
48
RETAILMSG(
1
,(TEXT(
"
Break!
"
)));
49
break
;
50
}
51
}
----------------------------------------------------------
尊重他人劳动成果,转载请标明出处http://www.cnblogs.com/feishanm