编写IPL程序

作者: Loyen | 来源:发表于2019-02-03 10:37 被阅读0次

QNX相关历史文章:

这篇文章主要描述Initial program loader的相关内容,并以Freescale IXM6处理器为例讲解

1. Initial program loader

IPL的功能可以类比Uboot,IPL程序的任务是对硬件进行最低限度的配置,以创建一个startup程序运行的环境,至少包括以下内容:

  • 从Reset异常向量开始执行;
  • 配置内存控制器;
  • 配置时钟;
  • 设置堆栈,以便允许IPL库执行OS的验证和设置(下载、扫描、设置、跳转到OS镜像)

IPL的代码可能很简单,也可能非常复杂,这分别对应到Warm-start和Cold-start。在Warm-start中,已经有BIOS或者ROM monitor了,IPL需要做的工作就会少很多,而在Cold-start中,没有BIOS或者ROM monitor,因此需要实现全部的功能。

IPL的初始化部分是用汇编实现的(因为它从ROM执行,没有内存控制器),初始化硬件之后,IPL调用main()函数来初始化C语言环境。

设置好C语言环境后,IPL可以执行不同的任务,这个具体取决于操作系统是从linearly mapped设备启动,还是从bank-switched设备启动:

  • linearly mapped,整个镜像在处理器的线性地址空间中,比如ROM;
  • bank-switched,镜像不能完全由处理器寻址,比如Disk device、Network设备、串口或并口、以及bank-switched的ROM或RAM;

1.1 bank-switched

从bank-switched设备中启动时,需要以下几步:

  • IPL必须调用函数与相关设备通信,比如串口下载时,IPL使用image_download_8250()函数,该函数用于配置和控制8250类串口控制器,完成设置后,该函数会将image拷贝到RAM中;
  • IPL调用image_sacn()来扫描整个image,完成一些校验工作;
  • IPL调用image_setup()来完成一些设置工作;
  • IPL调用image_start(),跳转到startup的起始地址,将控制权交给startup;
    镜像加载时,由于是bank-switched,所以需要将整个镜像都拷贝到RAM中,如下图所示:


从图中可以看出来,IPL处理时可以分为三步:

  • IPL接收控制;
  • IPL将image加载到RAM中;
  • IPL将控制权交给加载的image;

1.2 linearly mapped

linearly mapped设备的启动方式与bank-switched设备是一致的,不同点在于,不需要将整个image都拷贝到RAM中,如下图所示:


2. 自定义IPL程序

编写IPL程序,需要以下几个步骤:

  • 初始化硬件,包括对系统RAM的访问。注意,只需要初始化必须的硬件(比如时钟等),外围硬件不需要初始化;(汇编实现)
  • 将image镜像(使用mkifs生成)加载到RAM中,加载程序使用header信息来拷贝header和startup到RAM中,如果不是在linearly mapped的设备中,则需要将整个镜像拷贝到RAM中;(比如image_download_8250())
  • 定位OS镜像,并做一些校验工作;(调用image_sacn())
  • 拷贝startup程序;(调用image_setup())
  • 跳转到加载镜像起始位置执行;(调用image_start())

3. IPL库

IPL库包含了一系列的接口,用于实现自定义的IPL程序,可用的函数接口如下:


4. Freescale IMX6 IPL

Freescale IMX6 BSP包:BSP_freescale-imx6SoloX-sabre-sdb_br-660_be-660_SVN815609_JBN555.zip

下载Freescale IMX6 BSP zip包并解压,IPL代码位于src/hardware/ipl/boards/mx6sx-sabre-sdb中,其中mx6sx-sabre-sdb.lnk为链接文件,指定了程序的入口以及内存的分段及布局等。
程序的入口:ENTRY(_start),在start.S文件中完成了以下工作:

  • 设置CPU为SVC32模式
  • Invalidate L1 I/D and TLBs
  • Disable MMU和Caches
  • 使能ICache
  • 设置堆栈
  • 跳转到main函数
    在该目录中的main.c完成IPL的主要工作:
int main(void)
{
    unsigned int image = QNX_LOAD_ADDR;
 
    init_aips();
 
    init_clocks();
 
    init_pinmux();
 
    init_sermx6(MXC_CONSOLE_BASE, 115200, 80000000, 2);
 
    ser_putstr("\nWelcome to QNX Neutrino Initial Program Loader for:\n");
    ser_putstr("  Freescale i.MX6 SoloX Sabre SDB (ARM Cortex-A9/M4)\n");
 
    while (1) {
    ser_putstr("Command:\n");
    ser_putstr("Press 'D' for UART IFS download, using the 'sendnto' utility.\n");
    ser_putstr("Press 'M' for SDMMC IFS download.\n");
    ser_putstr("Press 'J' for JTAG IFS boot of image loaded to 0x"); ser_puthex(QNX_LOAD_ADDR); ser_putstr(".\n");
    switch (ser_getchar()) {
        case 'D': case 'd':
        ser_putstr("send image now...\n");
        if (image_download_ser(QNX_LOAD_ADDR)) {
            ser_putstr(str_download_failed);
            continue;
        } else {
            ser_putstr(str_download_ok);
        }
        break;
 
        case 'M': case 'm':
        if (sdmmc_load_file(QNX_LOAD_ADDR, QNX_IFS_FILENAME) != 0) {
            ser_putstr(str_download_failed);
            continue;
        }
        ser_putstr(str_download_ok);
        break;
 
        case 'J': case 'j':
        break;
 
        default:
        break;
    }
 
    /* No safe boot media, must be scanned */
    image = image_scan_2(image, image + MAX_SCAN, 1);
    if (image != 0xffffffff) {
        ser_putstr(str_found_image);
        ser_puthex(image);
        ser_putstr("\n");
        image_setup_2(image);
 
        ser_putstr(str_jump_to_image);
        ser_puthex(startup_hdr.startup_vaddr);
        ser_putstr("\n\n");
 
        image_start_2(image);
 
        /* Never reaches here */
        return 0;
    }
    ser_putstr(str_image_scan_fail);
    } /* Forever */
 
    /* Never reaches here */
    return 0;
}

进入main分别完成了以下工作:

  • init_aips(),该函数用于设置AHB到IP Bridge的属性,跟Trust Zone相关;
  • init_clocks(),该函数用于设置系统的时钟;
  • init_pinmux(),该函数用于设置管脚的复用,主要是设置Uart和SD相关,其中Uart用于调试,而SD用于加载image;
  • init_sermx6(),该函数用于初始化串口信息;
  • image_download_ser()/sdmmc_load_file(),这两个函数用于完成Image的加载;
  • image_scan_2(),该函数用于扫描image,对Image进行一些校验检查;
  • image_start_2(),该函数跳转到Image的入口去执行,也就是跳转到startup程序中去运行;
    从以上的流程可以看出IPL整体的功能并不复杂,完成最少硬件(需要用到的,比如时钟、串口、SD)的初始化,然后对Image加载和校验,最终跳转过去执行即可。

当然,我对这个IPL可运行性是持怀疑态度的,因为很重要的DDR Controler的相关初始化并没有看到。

相关文章

  • 编写IPL程序

    QNX相关历史文章:QNX简介QNX Neutrino微内核QNX IPC机制QNX进程管理器QNX资源管理器QN...

  • 《JNI开发——Java与C之间的桥梁 二》

    用java 语言编写的程序能否调用C语言编写的程序类库呢? 同样 C(程序)能否调用 java语言编写的api呢?...

  • udp知识求教

    想利用socket 编写程序 ,虚拟机编写一个程序接收数据,windows编写一个程序发送数据。类似与聊天软件,不...

  • Java的开发流程

    Java的程序开发,包括三个步骤:编写程序,编译程序,运行程序 编写程序——java源代码,.java文件 编译程...

  • java学习之7/22(编程HelloWorld程序)

    编程helloworld程序 1. java程序编写过程 a. 编写源文件> [HelloWorld.java]...

  • 8. 在Spring 5中使用JUnit单元测试

    1.在pom.xml中添加依赖 2.编写待测试程序Max 3.配置bean 4.编写测试程序 5.编写测试程序后自...

  • C#语言入门详解002-003

    002 C#都能编写哪些程序 编写console,wpf,windows form的hello world程序 1...

  • day8-作业

    编写⼀个函数,求1+2+3+...+N程序: 结果: 编写⼀个函数,求多个数中的最⼤值程序: 结果: 编写⼀个函数...

  • 常用术语

    IPL 指令级并行 Instruction-level parallelismSMT 同时多线程 Simultan...

  • solidity的helloWord

    为了初次编写solidity程序的方便,无需考虑本地环境的影响。我们使用remix编写hello world程序。...

网友评论

    本文标题:编写IPL程序

    本文链接:https://www.haomeiwen.com/subject/lgrysqtx.html