Kintex7325平台elf文件快速加载实现

在实际项目中,为了降低硬件成本,一般会选择将程序固化在flash中,并在系统启动时动态搬运程序到DDR中并运行,这就需要引导程序的步骤,xilinx SDK 2018.3 应用模板中有srec bootloader工程,此工程只要配置好flash中应用程序的偏移地址,即可实现程序搬运并正常运行。

在编译完成嵌入式应用软件程序生成elf可执行文件之后,要向程序从flash启动,我们需要将elf可执行文件通过Xilinx 2018.3在的Program Flash小软件将应用程序写入到qspi Flash中。

根据官方的指导文件,需要我们勾选convert ELF to bootloadable SREC format and program, 将将ELF应用程序转换为能够boot的SREC格式文件,
在这里插入图片描述
根据上述设计,引导文件会搬运srec格式文件,将其放置在ddr中并运行,但是在实践中,此搬运过程非常耗时,为了解决这一问题,尝试直接加载elf文件,而不是srec文件。

分析srec bootloader工程中bootloader.c 源文件,发现引导程序循环读取flash中的srec格式数据,然后对数据进行转码,继而拷贝到DDR中,此过程非常消耗资源,费时费力。

static uint8_t load_exec ()
{
    uint8_t ret;
    void (*laddr)();
    int8_t done = 0;
    
    srinfo.sr_data = sr_data_buf;
    
    while (!done) {
        if ((ret = flash_get_srec_line (sr_buf)) != 0) 
            return ret;
 
        if ((ret = decode_srec_line (sr_buf, &srinfo)) != 0)
            return ret;
        
#ifdef VERBOSE
        display_progress (srec_line);
#endif
        switch (srinfo.type) {
            case SREC_TYPE_0:
                break;
            case SREC_TYPE_1:
            case SREC_TYPE_2:
            case SREC_TYPE_3:
                memcpy ((void*)srinfo.addr, (void*)srinfo.sr_data, srinfo.dlen);
                break;
            case SREC_TYPE_5:
                break;
            case SREC_TYPE_7:
            case SREC_TYPE_8:
            case SREC_TYPE_9:
                laddr = (void (*)())srinfo.addr;
                done = 1;
                ret = 0;
                break;
        }
    }
 
#ifdef VERBOSE
    print ("\r\nExecuting program starting at address: ");
    putnum ((uint32_t)laddr);
    print ("\r\n");
#endif
 
    (*laddr)();                 
  
    /* We will be dead at this point */
    return 0;
}

为了缩短系统启动时间,可以精简转码过程。可以直接搬运elf格式文件而不是srec格式文件,即可实现此步骤。
有关elf文件的相关介绍如下:

https://blog.csdn.net/mergerly/article/details/94585901

画布多说,elf搬运源码如下:


typedef struct
{
    unsigned char     ident[EI_NIDENT];        /* Magic number and other info */
    Elf32_Half        type;                    /* Object file type */
    Elf32_Half        machine;                 /* Architecture */
    Elf32_Word        version;                 /* Object file version */
    Elf32_Addr        entry;                   /* Entry point virtual address */
    Elf32_Off         phoff;                   /* Program header table file offset */
    Elf32_Off         shoff;                   /* Section header table file offset */
    Elf32_Word        flags;                   /* Processor-specific flags */
    Elf32_Half        ehsize;                  /* ELF header size in bytes */
    Elf32_Half        phentsize;               /* Program header table entry size */
    Elf32_Half        phnum;                   /* Program header table entry count */
    Elf32_Half        shentsize;               /* Section header table entry size */
    Elf32_Half        shnum;                   /* Section header table entry count */
    Elf32_Half        shstrndx;                /* Section header string table index */
} Elf32_Ehdr;



/* Program segment header.  */
typedef struct
{
    Elf32_Word        type;                 /* Segment type */
    Elf32_Off         offset;                /* Segment file offset  Segment鐎电懓绨查惃鍕敶鐎圭懓婀弬鍥︽閻ㄥ嫬浜哥粔?*/
    Elf32_Addr        vaddr;                /* Segment virtual address Segment閸︺劌鍞寸�涙ü鑵戦惃鍕殠閹冩勾閸�?*/
    Elf32_Addr        paddr;                /* Segment physical address */
    Elf32_Word        filesz;               /* Segment size in file */
    Elf32_Word        memsz;                /* Segment size in memory */
    Elf32_Word        flags;                /* Segment flags */
    Elf32_Word        align;                /* Segment alignment */
} Elf32_Phdr;

#define        PT_NULL           0                /* Program header table entry unused */
#define        PT_LOAD           1                /* Loadable program segment */
#define        PT_DYNAMIC        2                /* Dynamic linking information */
#define        PT_INTERP         3                /* Program interpreter */
#define        PT_NOTE           4                /* Auxiliary information */
#define        PT_SHLIB          5                /* Reserved */
#define        PT_PHDR           6                /* Entry for header table itself */
#define        PT_TLS            7                /* Thread-local storage segment */
#define        PT_NUM            8                /* Number of defined types */

Elf32_Ehdr elf;
Elf32_Phdr phdr;

static uint8_t load_exec ()
{
    int i = 0;
    int ret = 0;
    int addr = 0;
    char elfStartOffset = 0;
    u8 readBuffer[256] = {0};
    void (*laddr)();

    print(" start readData from flash!!!\n");
    memset(readBuffer, 0x00, sizeof(readBuffer));
    ret = ReadData(&Isf, 0xf00000, readBuffer, 64);
    if(ret != XST_SUCCESS)
    {
        print("readData from flash failed\n");
        return -1;
    }

    for(i = 0; i < 64; i++)
    {
        if((readBuffer[i] == 0x7f) && (readBuffer[i + 1] == 'E') && (readBuffer[i + 2] == 'L') && (readBuffer[i + 3] == 'F') )
        {
            elfStartOffset = i;
            //printf(" elfStartOffset = %d\n", elfStartOffset);
            break;
        }
    }
    memcpy((void *)elf.ident, (void *)&readBuffer[elfStartOffset], sizeof(Elf32_Ehdr));


    //	printf("\n-------------------\n");
    //	printf("elf.type = %d\r\n", elf.type);
    //	printf("elf.machine = %d\r\n", elf.machine);
    //	printf("elf.version = %d\r\n", elf.version);
    //	printf("elf.entry = %d\r\n", elf.entry);
    //	printf("elf.phoff = %d\r\n", elf.phoff);
    //	printf("elf.shoff = %d\r\n", elf.shoff);
    //	printf("elf.flags = %d\r\n", elf.flags);
    //	printf("elf.ehsize = %d\r\n", elf.ehsize);
    //	printf("elf.phentsize = %d\r\n", elf.phentsize);
    //	printf("elf.phnum = %d\r\n", elf.phnum);
    //	printf("elf.shentsize = %d\r\n", elf.shentsize);
    //	printf("elf.shnum = %d\r\n", elf.shnum);
    //	printf("elf.shstrndx = %d\r\n", elf.shstrndx);
    //	printf("\n-------------------\n");


    /* move to ddr */
    for(i = 0; i < elf.phnum; i++)
    {
        memset(readBuffer, 0x00, sizeof(readBuffer));
        ret = ReadData(&Isf, 0xF00000 + elf.phoff + i * sizeof(Elf32_Phdr), readBuffer, sizeof(Elf32_Phdr) + SPI_VALID_DATA_OFFSET);
        if(ret == XST_SUCCESS)
        {
            memcpy((void *)&phdr, (void *)&readBuffer[elfStartOffset], sizeof(Elf32_Phdr));
            //			printf("phdr.type = %d\n", phdr.type);
            //			printf("phdr.offset = %d\n", phdr.offset);
            //			printf("phdr.vaddr = %08x\n", phdr.vaddr);
            //			printf("phdr.paddr = %08x\n", phdr.paddr);
            //			printf("phdr.filesz = %d\n", phdr.filesz);
            //			printf("phdr.memsz = %d\n", phdr.memsz);
            //			printf("phdr.flags = %d\n", phdr.flags);
            //			printf("phdr.align = %d\n", phdr.align);
            //			printf("-------------------\n");

            if(phdr.type == PT_LOAD)
            {
                for(addr = 0; addr < phdr.filesz; addr += EFFECTIVE_READ_BUFFER_SIZE)
                {
                    feedWdg();
                    if((addr + EFFECTIVE_READ_BUFFER_SIZE) > phdr.filesz)
                    {
                        memset(readBuffer, 0x00, sizeof(readBuffer));
                        ret = ReadData(&Isf, 0xF00000 + phdr.offset + addr, readBuffer, phdr.filesz - addr + SPI_VALID_DATA_OFFSET);
                    }
                    else
                    {
                        memset(readBuffer, 0x00, sizeof(readBuffer));
                        ret = ReadData(&Isf, 0xF00000 + phdr.offset + addr, readBuffer, EFFECTIVE_READ_BUFFER_SIZE + SPI_VALID_DATA_OFFSET);
                    }

                    if(ret == XST_SUCCESS)
                    {
                        if((addr + EFFECTIVE_READ_BUFFER_SIZE) > phdr.filesz)
                        {
                            memcpy((void * )(phdr.paddr + addr), (void *)&readBuffer[elfStartOffset], phdr.filesz - addr);
                        }
                        else
                        {
                            memcpy(phdr.paddr + addr, (void *)&readBuffer[elfStartOffset], EFFECTIVE_READ_BUFFER_SIZE);
                        }
                    }
                    else
                    {
                        print("Failed to read ELF program segment");
                        return -1;
                    }
                }
            }

            if(phdr.memsz > phdr.filesz)
            {
                memset((void *)(phdr.paddr + phdr.filesz), 0, phdr.memsz - phdr.filesz);
            }
        }
        else
        {
            print("Failed to read ELF program header");
            return -1;
        }
    }

    laddr = (void (*)())elf.entry;
    (*laddr)();

    return 0;
}

经过上述修改,再次启动系统,程序能能够迅速加载并运行。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我若成精

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值