现在,我们要关心的是s5pv210的存储设备代码拷贝函数的函数原型以及函数指针的存放位置。
主要参考文档:《S5PV210-iROM-ApplicationNote-Preliminary-20091126》
先一段文档里面的说明:
_The S5PV210 internally has a ROM code of block copy function for boot-u device. Therefore,
developer may not needs to implements device copy functions. These internal functions can copy any
data from memory devices to SDRAM. User can use these function after ending up the internal ROM
boot process completely._
简单翻译为如下: s5pv210的IROM中集成了一些启动存储设备的块拷贝函数。因此,开发者不需要实现对应的存储设备的拷贝函数了。这些拷贝函数可以实现从存储设备到memory的拷贝。当IROM启动完成之后,开发者也可以直接使用这些拷贝函数了。
这和我们第一节中,说明的是一致的。
0xD0037F90
NF8_ReadPage_Adv
is advanced NF8_ReadPage function.
0xD0037F94
NF16_ReadPage_Adv
is advanced NF16_ReadPage function.
0xD0037F98
CopySDMMCtoMem
can copy any data from SD/MMC device to SDRAM.
0xD0037F9C
CopyMMC4_3toMem
can copy any data from eMMC device to SDRAM.
0xD0037FA0
CopyOND_ReadMultiPages
can copy any data from OneNand device to SDRAM.
0xD0037FA4
CopyOND_ReadMultiPages_Adv
can copy any data from OneNand device to SDRAM.
0xD0037FA8
Copy_eSSDtoMem
can copy any data from eSSD device to SDRAM.
0xD0037FAC
Copy_eSSDtoMem_Adv
can copy any data from eSSD device to SDRAM.
0xD0037FB0
NF8_ReadPage_Adv128p
is advanced NF8_ReadPage function.
更详细的功能介绍建议参考文档《S5PV210-iROM-ApplicationNote-Preliminary-20091126》。
这些地址是递归的,位于0xD003_7F90-0xD003_7FB0
通过文档《[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)》,我们知道了0xD002_0000-0xD003_7FFF是属于IRAM的区域,所以说’函数指针存放地址’是放在IRAM上的,按照我猜,应该是在启动过程中,BL0把这些IROM上这些固化的函数的地址写到IRAM对应的位置上,例如0xD0037F90,对应位置就可以当作一个函数指针来使用。
2、函数原型说明
文档中的函数原型和使用过程中的函数原型有所差异。个人感觉可能是文档有问题,但是这里还是以文档为准。使用介绍中,再以实际的使用为准。
因为tiny210只支持SD boot和nand flash的方式,下面我就以SD和nand flash作为存储设备的拷贝函数做介绍。
(1)CopySDMMCtoMem
从SD/MMC拷贝(加载)块到内存中的函数。
函数结构如下(也就是一个简单的使用范例)
/**
* This Function copy MMC(MoviNAND/iNand) Card Data to memory.
* Always use EPLL source clock.
* This function works at 20Mhz.
* @param u32 StartBlkAddress : Source card(MoviNAND/iNand MMC)) Address.(It must block address.)
* @param u16 blockSize : Number of blocks to copy.
* @param u32* memoryPtr : Buffer to copy from.
* @param bool with_init : determined card initialization.
* @return bool(u8) - Success or failure.
*/#define CopySDMMCtoMem(z,a,b,c,e) (((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))(*((unsigned int *)0xD0037F98)))(z,a,b,c,e))
可以简单推测出函数原型为bool CopySDMMCtoMem(int, unsigned int, unsigned short, unsigned int*, bool)。
argv0=起始块号
argv1=块数量
argv2=要拷贝到内存的什么位置上,也就是目标地址指针。
argv3=是否需要检测初始化
argv4=返回参数,用于决定是成功还是失败。
注意:以上是文档的说明,
但是在实际使用中,实际的函数原型如下:
boot copy_sd_to_ddr(u32 channel, u32 start_block, u16 block_size, u32 *trg, u32 init);
可见,文档是有问题的。后续会说明。
(2)NF8_ReadPage_Adv
从nand flash拷贝(加载)页到内存中的函数。
8bit ECC校验的函数结构如下(也就是一个简单的使用范例)
/**
* This Function copies a block of page to destination memory.( 8-Bit ECC only )
* @param uint32 block : Source block address number to copy.
* @param uint32 page : Source page address number to copy.
* @param uint8 *buffer : Target Buffer pointer.
* @return int32 - Success or failure.
*/#define NF8_ReadPage_Adv (a,b,c) (((int(*)(uint32, uint32, uint8*))(*((uint32 *) 0xD0037F90)))(a,b,c))
其参数意义参考注释,这里不加以说明了。
假设有一个函数原型是int function(int a, int b),其函数指针被存放在了0x10的位置上。
那么我们调用该函数的方法如下:
(1)首先需要获取到函数指针
因为函数指针存放在了0x10的位置上,所以先对0x10进行强制类型转换成一个指针(unsigned int *)0x10,
然后*((unsigned int *)0x10)就可以获取到函数指针变量。
暂时表示如下
f_ptr=(*((unsigned int *)0x10))
(2)根据函数原型可以得到对应的函数指针类型是int (*)(int, int),所以需要对(1)的函数指针进行强制类型转换
(int (*)(int, int))f_ptr,
暂时表示如下
ok_f_ptr=((int (*)(int, int))f_ptr)
(3)调用该函数的方法为ok_f_ptr(a, b)
等价于*ok_f_ptr(a, b),一般都是使用ok_f_ptr(a, b)
综上,展开则为((int (*)(int, int))(*((unsigned int *)0x10)))(a,b)