Jump to content

Zynq Boot Multiple .elfs


Mihaita

Recommended Posts

Recently I had to make a standalone Zynq project that had multiple .ELF files all residing on an SD card. The board had to somehow know, while being powered off, which .ELF file to boot from. So how to do this?
 
The answer is in the FSBL file. Currently, in Vivado's 2014.2 SDK, the FSBL can handle multiple "partitions" (that's how any Second Stage BootLoader is called, in our case the .ELF files) by executing the first one, when done returning to the FSBL that handoffs control to the second one and so on.
But there is another way with the so called hooks: FsblHookBeforeBitstreamDload, FsblHookAfterBitstreamDload, FsblHookBeforeHandoff. With these handy functions you can halt the FSBL and do whatever (for example read the switches) before the bitstream file has been downloaded, after or right before the SSBL is being booted.
 
Here's a simple usage example: let's you have three .ELF files on the SD card and you want to select which one to boot with the on-board switches.
 
First of all you generate an FSBL project, then open the image_mover.c file from the src folder. Scroll down to line 440 and change the code as bellow:
if (PLPartitionFlag) {
   if (PartitionAttr & ATTRIBUTE_PS_IMAGE_MASK) {
      Status = FsblHookBeforeBitstreamDload();
      if (Status != XST_SUCCESS) {
         fsbl_printf(DEBUG_GENERAL,"FSBL_BEFORE_BSTREAM_HOOK_FAILrn");
         OutputStatus(FSBL_BEFORE_BSTREAM_HOOK_FAIL);
         FsblFallback();
      }
      else {
         HeaderPtr = &PartitionHeader[ExecutionAddress];
         PartitionDataLength = HeaderPtr->DataWordLen;
         PartitionImageLength = HeaderPtr->ImageWordLen;
         PartitionExecAddr = HeaderPtr->ExecAddr;
         PartitionAttr = HeaderPtr->PartitionAttr;
         PartitionLoadAddr = HeaderPtr->LoadAddr;
         PartitionChecksumOffset = HeaderPtr->CheckSumOffset;
         PartitionStartAddr = HeaderPtr->PartitionStart;
         PartitionTotalSize = HeaderPtr->PartitionWordLen;
         ExecAddress = PartitionExecAddr;
      }
   }
}

Open the fsbl_hooks.c file and add the following global variable:

extern u32 ExecutionAddress;

Go to the FsblHookBeforeBitstreamDload function and change it:

u32 FsblHookBeforeBitstreamDload(void) {
   
   u32 Status;
   u32 dwSws;

   Status = XST_SUCCESS;

   // The first partition would usually be the PL bitstream, so we're
   // skipping it.
   do {
      dwSws= Xil_In32(SWS_BASEADDRESS) & 0x03;
   }
   while(dwSws == 0x00);

   ExecutionAddress = dwSws;

   xil_printf("Selected partition %drn", swSws);

   /*
    * User logic to be added here. Errors to be stored in the status variable
    * and returned
    */
   fsbl_printf(DEBUG_INFO,"In FsblHookBeforeBitstreamDload function rn");

   return (Status);
}

ExecutionAddress will hold the value of the first two switches and point to the corresponding partition.

 

And finally here's how the "Create Zynq Boot Image" SDK utility would look like when creating the BOOT.BIN that'll go onto the SD:

post-41-0-67824800-1415346242_thumb.png

 

That's it! Hope it helps someone (or even myself sometime in the future when I forget all this :) ).

 

Link to comment
Share on other sites

  • 2 years later...

HI Mihaita !

Will you please elaborate more in what changes i required if i want to simply run three .elf file sequentially?.. I am confused .

I make Boot.bin  by adding  a) Bootloader    b- bitstream file      c- app1 .elf             d - app2.elf          e- app3.elf  then I created BOOT.bin \

now I  m confused about what changes I need in FSBl?

 

Please help me solving this issue..

thanks in advanced!

 

Amit

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...