u-boot 移植 --->3、S5PV210启动序列
通过三星官方的资料S5PV210_iROM_ApplicationNote_Preliminary_20091126.pdf,了解到S5PVS10这款芯片的复位过程启动序列。芯片在出厂时就在内部固化了一段程序internal ROM简称iROM,这段代码在芯片复位一后会自动运行,他主要负责初始化系统的时钟等具体如下:
1. Disable the Watch-Dog Timer \\关闭看门狗 2. Initialize the instruction cache \\关闭指定cache 3. Initialize the stack region (see “memory map” on chap 2.5) \\设置不同模式的栈指针 4. Initialize the heap region. (see “memory map” on chap 2.5) \\设置堆 5. Initialize the Block Device Copy Function. (see “Device Copy Function” on chap 2.7) \\初始化块设备拷贝的函数这些函数对用户开放 6. Initialize the PLL and Set system clock. (see “clock configuration” on chap 2.11) \\系统时钟配置 7. Copy the BL1 to the internal SRAM region (see “Device Copy Function” on chap 2.7) \\自动拷贝启动介质指定的地方指定长度的代码到IRAM中 8. Verify the checksum of BL1. If checksum fails, iROM will try the second boot up. (SD/MMC channel 2)\\校验拷贝的代码,格式和拷贝过程校验,失败的话会尝试其他的启动方式 9. Check if it is secure-boot mode or not. If the security key value is written in S5PV210, It’s secure-boot mode. \\检查是否是安全启动,进而进行更严格的验证。 If it is secure-boot mode, verify the integrity of BL1. 10. Jump to the start address of BL1 \\跳转到指定的地址0xD002_0010开始执行。此时就开始把执行权交给用户了。
三星原厂的资料中有一个流程图可更加详细形象的展示内嵌的IROM程序的操作详细。不用安全模式则只需要将可执行程序的头上按照其手册添加指定的hearer info 就可以了,这里借鉴网上的代码,参也可以考手册字节写,比较简单源码如下:
/* 在BL0阶段,Irom内固化的代码读取nandflash或SD卡前16K的内容,
* 并比对前16字节中的校验和是否正确,正确则继续,错误则停止。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE (16*1024)
#define IMG_SIZE (16*1024)
#define SPL_HEADER_SIZE 16
#define SPL_HEADER "S5PC110 HEADER "
int main (int argc, char *argv[])
{
FILE *fp;
char *Buf, *a;
int BufLen;
int nbytes, fileLen;
unsigned int checksum, count;
int i;
// 1. 3个参数
if (argc != 3)
{
printf("Usage: mkbl1 <source file> <destination file>\n");
return -1;
}
// 2. 分配16K的buffer
BufLen = BUFSIZE;
Buf = (char *)malloc(BufLen);
if (!Buf)
{
printf("Alloc buffer failed!\n");
return -1;
}
memset(Buf, 0x00, BufLen);
// 3. 读源bin到buffer
// 3.1 打开源bin
fp = fopen(argv[1], "rb");
if( fp == NULL)
{
printf("source file open error\n");
free(Buf);
return -1;
}
// 3.2 获取源bin长度
fseek(fp, 0L, SEEK_END);
fileLen = ftell(fp);
fseek(fp, 0L, SEEK_SET);
// 3.3 源bin长度不得超过16K-16byte
count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))
? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);
// 3.4 buffer[0~15]存放"S5PC110 HEADER "
memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);
// 3.5 读源bin到buffer[16]
nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);
if ( nbytes != count )
{
printf("source file read error\n");
free(Buf);
fclose(fp);
return -1;
}
fclose(fp);
// 4. 计算校验和
// 4.1 从第16byte开始统计buffer中共有几个1
a = Buf + SPL_HEADER_SIZE;
for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
checksum += (0x000000FF) & *a++;
// 4.2 将校验和保存在buffer[8~15]
a = Buf + 8;
*( (unsigned int *)a ) = checksum;
// 5. 拷贝buffer中的内容到目的bin
// 5.1 打开目的bin
fp = fopen(argv[2], "wb");
if (fp == NULL)
{
printf("destination file open error\n");
free(Buf);
return -1;
}
// 5.2 将16k的buffer拷贝到目的bin中
a = Buf;
nbytes = fwrite( a, 1, BufLen, fp);
if ( nbytes != BufLen )
{
printf("destination file write error\n");
free(Buf);
fclose(fp);
return -1;
}
free(Buf);
fclose(fp);
return 0;
}
编译生成可执行文件 这里为imagemeker最后可以使用 ./imagemeker u-boot.bin outputfilename 提取U-boot的前16K代码生成BL1代码,进而烧写到SD卡中选择好SD启动后就可以运行了,BL1这一段代码的任务就是初始化DRAM然后将后续剩余的u-boot或其他代码拷贝到DRAM中去,因为内部IRAM 的空间太小。
第一启动方案是按外部OM脚的配置情况来决定启动方式的如果启动方式失败了(非安全模式,安全模式启动失败芯片将停止任何动作),则会执行第二启动方案其中包括UART和USB启动。第二启动方案会再次尝试OM选择的启动介质,如果还是失败则会执行默认的第二个启动介质引导启动这个过程成功后同上面的启动方式相同会执行BL1,否则将尝试UART启动,成功后也将执行BL1,否则尝试USB启动,行为同上面的UART启动,这里将额BL1指用户代码的前16K-16字节+16字节的header info。