Jump to content

    

Bootloader for Microblaze

Здравствуйте! Уважаемые товарищи подскажите пожалуйста, какие варианты решения для следующей задачки:

необходимо последовательно запустить два elf файла на microblaze, который загружается из FLASH памяти.

Сейчас создаю свой bootloader в виде bit файла с проинициализированной BRAM (16 КБайт), который записываю во FLASH (адресом выше записываю основной elf файл для работы процессора ). При подаче питания в ПЛИС подгружается  bit файл и запускается elf из BRAM памяти, который вычитывает основной elf в DDR и сбрасывает Microblaze для выполнения кода уже из DDR. Тут все просто.

Теперь возникла необходимость перед запуском основного elf файла записать массив  user data во FLASH (выше bit, elf). Проинициализировать BRAM bootloader'ом и массивом user data не получится, т.к. 16 кБайт BRAM недостаточно, а увеличить нельзя.

Вот и необходимо сделать так: подали питание, загрузили bit с инициализированной BRAM, процессор вычитал в DDR elf с массивом user data и вычитал elf с основным ПО, выполнил elf с массивом user data (записал данные во FLASH), потом сбросили процессор и сказали ему выполнять код уже из основного elf файла. Как указать microblaze на указатель откуда в DDR выполнять код?

Share this post


Link to post
Share on other sites

Я так глубоко не копал, но по моему ELF формат тут не подойдет.

"ELF Executable and Linkable Format — формат исполнимых и компонуемых файлов"

Встраивать в bootloader разборщик/компоновщик ELF формата будет накладно. Нужно двоичный файл скомпилированый для адреса в DDR памяти.

Тогда bootloader просто скопирует данные в DDR и передаст управление на него.

Для передачи управления используется стандартная процедура вызова функции по указателю.

Сбрасывать процесор не нужно, он опять перейдет в boot.

Обычно в начале образа программы храниться таблица векторов прерываний.

Первый вектор, это как раз вектор по сбросу.

Надеюсь "старшие" товарищи подправят если ересь написал. ;-)

Share this post


Link to post
Share on other sites
1 hour ago, misyachniy said:

Я так глубоко не копал, но по моему ELF формат тут не подойдет.

Спасибо за ответ. У меня получается так: во флеш с нулевого адреса записывается bit файл с инициализированной bram. Инициализирована bram elf файлом, в котором программа просто находит elf файл по заданному указателю и вычитывает ИСПОЛНЯЕМЫЙ код  в ДДР. То есть компилировать в screc формат нет необходимости, т.к. это elf файл из BRAM вычитывает только исполняемую часть elf для DDR.

Share this post


Link to post
Share on other sites
3 hours ago, andrew_su said:

.....16 кБайт BRAM недостаточно, а увеличить нельзя......

Можно. Вот тут обсуждается

И еще на сайте Xilinx    https://www.xilinx.com/support/answers/52063.html

Конечно можно) К сожалению в проекте вся блочная память разделена между остальными ядрами и на процессор остается только 16 Кбайт

Share this post


Link to post
Share on other sites

Выложу исходники, может кому пригодится.

Получилось так, записываю:

 

во флеш по адресу 0х00000000 файл с проинициализированной BRAM:

          download.bit

 

По адресу 0х00440000 файл:

          first_elf.elf

 

по адресу 0х00840000 файл:

         second_elf.elf

 

При подаче питания запускается download.bit, потом загружается и исполняется first_elf.elf, и далее second_elf.elf.

 

Код для формирования bootloader'а download.bit взял от trenz electonics^

 

#include "spi_flash.h"
#include <stdio.h>
//-----------------------------------------------------------------------------
#define SSB_START_ADDR			0x00440000
#define XIL_BIT_SYNC			0x665599AA
#define ELF_EHSIZE				52
#define ELF_SHENTSIZE			40
#define ELFMAG					0x464C457F
#define SHT_PROGBITS			1
#define ELF_HDR_SHNUM_OFF		48
#define ELF_HDR_SHOFF_OFF		8
#define ELF_HDR_SHTYPE_OFF		4
#define ELF_HDR_SHADDR_OFF		3
#define ELF_HDR_SHOFFSET_OFF	4
#define ELF_HDR_SHSIZE_OFF		5
#define MEM_TEST_RANGE			0x1000
#define SPI_READ_CMD			0x0300
//-----------------------------------------------------------------------------
u8	e_shnum, section, sh_type;
u32	e_shoff, sh_addr, sh_offset, sh_size;
int (*reset_func) () = 0;
u32	int_read_buf[13];
u32	int_readtest_buf[64];
u8* char_readtest_buf = (u8*)int_readtest_buf;
u8* char_read_buf = (u8*)int_read_buf;
u8 *mem_section;
volatile u32 *ddr_mem = (u32*)XPAR_MIG_7SERIES_0_BASEADDR;
//-----------------------------------------------------------------------------
void pause(int p){
	volatile int v;
	for(v = 0; v < (400000 * p); v++);
}
//-----------------------------------------------------------------------------
int main(void){
	int i;

	print("\r\nTrenz Electronic ELF bootloader "__DATE__" "__TIME__"\r\n\r\n");
	spi_flash_init(XPAR_AXI_QUAD_SPI_0_DEVICE_ID);	// Init SPI Flash
	// Test memory before use it!
	for(i = 0; i < MEM_TEST_RANGE; i++)
		ddr_mem[i] = i;
	for(i = 0; i < MEM_TEST_RANGE; i++){
		if(ddr_mem[i] != i){
			xil_printf("ERROR: Memory test failed!\r\n");
			while(1);
		}
	}

	////////////////////////////////////
	// Read SSB
	spi_flash_read(SSB_START_ADDR, ELF_EHSIZE, char_read_buf);
	if(int_read_buf[0] != ELFMAG){
		xil_printf("ERROR: Boot image not found\r\n");
		while(1);
	}

	e_shnum	= char_read_buf[ELF_HDR_SHNUM_OFF];
	e_shoff = int_read_buf[ELF_HDR_SHOFF_OFF];

	for(section = 0; section < e_shnum; section++){	// Sections loop
		spi_flash_read((SSB_START_ADDR + e_shoff + section * ELF_SHENTSIZE),
			ELF_SHENTSIZE, char_read_buf);

		sh_type = char_read_buf[ELF_HDR_SHTYPE_OFF];
		sh_addr = int_read_buf[ELF_HDR_SHADDR_OFF];
		sh_offset = int_read_buf[ELF_HDR_SHOFFSET_OFF];
		sh_size = int_read_buf[ELF_HDR_SHSIZE_OFF];
		mem_section = (u8*)sh_addr;

		if(sh_type == SHT_PROGBITS){	// Process only sections with data
			if(sh_addr == 0){
				if(sh_size == 8)
					spi_flash_read((SSB_START_ADDR + sh_offset), sh_size,
						mem_section);
			}
			else	// Usual sections
				spi_flash_read((SSB_START_ADDR + sh_offset), sh_size,
					mem_section);
		}
	}	// Sections loop
	xil_printf("\r\nBoot...\r\n");
	pause(1);
	reset_func();	// Start Second Stage
	while(1);
}

 

Полученный при компиляции elf файл размещаю в BRAM и при прошивке ПЛИС получаю download.bit

 

Код для формирования first_elf.elf:

 

#include "spi_flash.h"
#include <stdio.h>
//-----------------------------------------------------------------------------
#define SSB_START_ADDR			0x00840000
#define XIL_BIT_SYNC			0x665599AA
#define ELF_EHSIZE				52
#define ELF_SHENTSIZE			40
#define ELFMAG					0x464C457F
#define SHT_PROGBITS			1
#define ELF_HDR_SHNUM_OFF		48
#define ELF_HDR_SHOFF_OFF		8
#define ELF_HDR_SHTYPE_OFF		4
#define ELF_HDR_SHADDR_OFF		3
#define ELF_HDR_SHOFFSET_OFF	4
#define ELF_HDR_SHSIZE_OFF		5
#define MEM_TEST_RANGE			0x1000
#define SPI_READ_CMD			0x0300
//-----------------------------------------------------------------------------
u8	e_shnum, section, sh_type;
u32	e_shoff, sh_addr, sh_offset, sh_size;
int (*reset_func) () = 0;
u32	int_read_buf[13];
u32	int_readtest_buf[64];
u8* char_readtest_buf = (u8*)int_readtest_buf;
u8* char_read_buf = (u8*)int_read_buf;
u8 *mem_section;
volatile u32 *ddr_mem = (u32*)XPAR_MIG_7SERIES_0_BASEADDR;
//-----------------------------------------------------------------------------
void pause(int p){
	volatile int v;
	for(v = 0; v < (400000 * p); v++);
}
//-----------------------------------------------------------------------------
int main(void){
	int i;

	print("\r\nTrenz Electronic ELF bootloader "__DATE__" "__TIME__"\r\n\r\n");
	spi_flash_init(XPAR_AXI_QUAD_SPI_0_DEVICE_ID);	// Init SPI Flash
	//////////////////////////////////////////////////////////
	////////// ANY USER APP /////////////////////////////////

	for(i = 0; i < 100; i ++){

		xil_printf("data from first app is %d", i);
	}




	///////////////////////////////////////////////////////
	//////////////// END ANY USER APP /////////////////////
	///////////////////////////////////////////////////////

	////////////////////////////////////
	// Read SSB
	spi_flash_read(SSB_START_ADDR, ELF_EHSIZE, char_read_buf);
	if(int_read_buf[0] != ELFMAG){
		xil_printf("ERROR: Boot image not found\r\n");
		while(1);
	}

	e_shnum	= char_read_buf[ELF_HDR_SHNUM_OFF];
	e_shoff = int_read_buf[ELF_HDR_SHOFF_OFF];

	for(section = 0; section < e_shnum; section++){	// Sections loop
		spi_flash_read((SSB_START_ADDR + e_shoff + section * ELF_SHENTSIZE),
			ELF_SHENTSIZE, char_read_buf);

		sh_type = char_read_buf[ELF_HDR_SHTYPE_OFF];
		sh_addr = int_read_buf[ELF_HDR_SHADDR_OFF];
		sh_offset = int_read_buf[ELF_HDR_SHOFFSET_OFF];
		sh_size = int_read_buf[ELF_HDR_SHSIZE_OFF];
		mem_section = (u8*)sh_addr;

		if(sh_type == SHT_PROGBITS){	// Process only sections with data
			if(sh_addr == 0){
				if(sh_size == 8)
					spi_flash_read((SSB_START_ADDR + sh_offset), sh_size,
						mem_section);
			}
			else	// Usual sections
				spi_flash_read((SSB_START_ADDR + sh_offset), sh_size,
					mem_section);
		}
	}	// Sections loop
	xil_printf("\r\nBoot...\r\n");
	pause(1);
	reset_func();	// Start Second Stage
	while(1);
}

По сути тот же bootloader только адрес указывает на расположение следующего elf файла (0x00840000) и файл разместил в DDR, но не с начального адреса, а со смещением.

 

Второй second_elf.elf это уже любой elf файл, размещенный в DDR с начального адреса.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now