Jump to content

    
Sign in to follow this  
FLTI

Запись .jic файла в EPCS через программу из NIOS II.

Recommended Posts

Здравствуйте!

 

Хотел бы сделать возможность обновлять прошивку EPCS ( что-то типа Remote Update ) таким способом.

На плате имеется Cyclone IV с кофигурационной схемой AS с возможностью загрузки .jic файла через JTAG ( SFL ).

post-5832-1423481240_thumb.png

В EPCS находится единственный .jic файл, который был загружен туда через JTAG этой схеме.

При включении питания .jic файл из EPCS конфигурирует и инициализирует Cyclone IV.

Если этот .jic файл ( находящийся внутри EPCS ) нужно обновить ( сделать что-то типа Remote Update ), то можно ли это сделать через NIOS II не вручную, а в автоматическом режиме?

Например так - новый .jic файл передаётся с обновлением ПО, становится доступным для NIOS II и NIOS II перезаписывает новый .jic файл в EPCS, затирая предыдущий.

После следующего включения-выключения питания Cyclone IV конфигурируется и инициализируется уже с нового .jic файла.

 

Как это сделать?

Видимо это должна быть некая программа на C для NIOS II?

Есть ли где это описано у Альтеры, есть ли пример такой программы?

Share this post


Link to post
Share on other sites
Например так - новый .jic файл передаётся с обновлением ПО, становится доступным для NIOS II и NIOS II перезаписывает новый .jic файл в EPCS, затирая предыдущий.

После следующего включения-выключения питания Cyclone IV конфигурируется и инициализируется уже с нового .jic файла.

Давайте рассмотрим ситуацию, когда у Вас в процессе перезаписи EPCS'ки происходит сбой. В этом случае для приведения оборудования в чувство потребуется рукопашное вмешательство.

 

Обычно делают не так. Создается две прошивки - базовая (factory) и приложение (application). И обновление приложения осуществляется из factory-прошивки.

 

Почитать можно вот это: http://www.altera.com/literature/ug/ug_altremote.pdf

Ну и пример какой посмотреть: http://www.alterawiki.com/wiki/EPCS_based_...pdate%20example

 

Share this post


Link to post
Share on other sites
Как это сделать?

Видимо это должна быть некая программа на C для NIOS II?

Есть ли где это описано у Альтеры, есть ли пример такой программы?

Для записи EPCS/EPCQ используйте EPCS/EPCQx1 Flash Controller или ASMI Parallel. Учитесь читать/писать флэшку, далее принимаем/записываем праграмму (всё это делает функция "загрузчик"), стартуем FPGA. Когда всё заработает, смотрим - кто такой Remote Update, делаем всё, как написано выше.

Share this post


Link to post
Share on other sites
Для записи EPCS/EPCQ используйте EPCS/EPCQx1 Flash Controller или ASMI Parallel. Учитесь читать/писать флэшку, далее принимаем/записываем праграмму, стартуем FPGA. Когда всё заработает, смотрим - кто такой Remote Update, делаем всё, как написано выше.

Я что-то подобное и хотел сделать с использованием EPCS/EPCQx1 Flash Controller.

Как через NIOSII научиться читать/писать EPCS ( реально использую M25P16 ) ?

Это ведь проще, чем Remote Update? Хотя , конечно есть и риск из-за возможного сбоя.

 

Не понял Вашу фразу - Когда всё заработает, смотрим - кто такой Remote Update, делаем всё, как написано выше.

Ведь писать в EPCS через NIOSII - это и есть по сути Remote Update?

 

Давайте рассмотрим ситуацию, когда у Вас в процессе перезаписи EPCS'ки происходит сбой. В этом случае для приведения оборудования в чувство потребуется рукопашное вмешательство.

 

Обычно делают не так. Создается две прошивки - базовая (factory) и приложение (application). И обновление приложения осуществляется из factory-прошивки.

 

Почитать можно вот это: http://www.altera.com/literature/ug/ug_altremote.pdf

Ну и пример какой посмотреть: http://www.alterawiki.com/wiki/EPCS_based_...pdate%20example

 

В ug_altremote.pdf по Cyclone IV информация идёт с стр.23 и упоминается файл RSU.zip , который непонятно, откуда взять.

В директории Квартуса 13.1 его нет...

Не могли бы Вы его сюда запостить.

Share this post


Link to post
Share on other sites
Я что-то подобное и хотел сделать с использованием EPCS/EPCQx1 Flash Controller.

Как через NIOSII научиться читать/писать EPCS ( реально использую M25P16 ) ?

Это ведь проще, чем Remote Update? Хотя , конечно есть и риск из-за возможного сбоя.

Remote Update для "просто" перезаписать прошивку не нужен, а нужен для возможности переключения между двумя хранимыми в памяти прошивками.

Не понял Вашу фразу - Когда всё заработает, смотрим - кто такой Remote Update, делаем всё, как написано выше.

Ведь писать в EPCS через NIOSII - это и есть по сути Remote Update?

Это к тому, что сначала разбираетесь, как писать/читать EPCS при помощи EPCS Controller-a, а потом разбираетесь с Remote Update (тут Remote Update - название IP-ядра, к записи прошивки отношения не имеет, только переключает прошивки, позволяет выбрать нужную при старте FPGA).

Share this post


Link to post
Share on other sites

Ок, понятно, надо писать в EPCS, но в другую её область, чтобы не затереть исходную прошивку.

Где доступнее всего описано с примером ( в том числе с программой на С для NIOSа ) - как писать/читать EPCS через NIOS при помощи EPCS Controller-a ?

Share this post


Link to post
Share on other sites
Где доступнее всего описано с примером ( в том числе с программой на С для NIOSа ) - как писать/читать EPCS через NIOS при помощи EPCS Controller-a ?

Можете взять в качестве примера немного подправив (используются только ф-ии alt_epcs_flash_init(), alt_epcs_flash_erase_block(), alt_epcs_flash_write_block(), ну и если читать надо, тогда - alt_epcs_flash_read_block()):

#include "altera_avalon_epcs_flash_controller.h"

static alt_flash_epcs_dev epcs_flash =
{
{
	ALT_LLIST_ENTRY,
	EPCS_FLASH_CONTROLLER_NAME,
	NULL,
	NULL,
	alt_epcs_flash_write,
	alt_epcs_flash_read,
	alt_epcs_flash_get_info,
	alt_epcs_flash_erase_block,
	alt_epcs_flash_write_block,
	((void*)(EPCS_FLASH_CONTROLLER_BASE))
},
(EPCS_FLASH_CONTROLLER_REGISTER_OFFSET + EPCS_FLASH_CONTROLLER_BASE)
};

short factory_cb(unsigned char *data, unsigned short size, unsigned short idx)
{
static int block_offset;
static int data_offset;
static unsigned long sec_addr = 0;
static unsigned int prev_idx;

if(idx == 1)
{
	alt_epcs_flash_init(&epcs_flash);
	block_offset = FACTORY_PAGE_START_ADDRESS;
	data_offset = FACTORY_PAGE_START_ADDRESS;

	prev_idx = 0;
	sec_addr = FACTORY_PAGE_START_ADDRESS;
}

if(idx % 128 == 1) // 512*128 = 65536 = 64 kbyte
{
	alt_epcs_flash_erase_block(&epcs_flash.dev, sec_addr);
	sec_addr += CONFIG_DEV_SECTOR_SIZE;
}

if(size)
{
	unsigned char buffer[512];
	for(int i = 0; i < size; i++)
	{
		swap_bits(&data[i]);
		buffer[i] = data[i];
	}
	alt_epcs_flash_write_block(&epcs_flash.dev, block_offset, data_offset, buffer, size);
	data_offset += size;
	if((data_offset % CONFIG_DEV_SECTOR_SIZE) == 0)
	{
		block_offset += CONFIG_DEV_SECTOR_SIZE;
	}
}

prev_idx = idx;

return 1;
}

 

Ранее, для загрузки по CAN, использовался немного другой вариант:

#include "alt_types.h"
#include "system.h"

#define ALT_USE_EPCS_FLASH

#include "altera_avalon_epcs_flash_controller.h"
#include "epcs_loader.h"
#include "include/MCP2515.h"

ALTERA_AVALON_EPCS_FLASH_CONTROLLER_INSTANCE(EPCS_FLASH_CONTROLLER_0, epcs_flash);

void epcs_loader(unsigned int *data)
{
int i;
static int block_offset;
static int data_offset;

unsigned long tmp[2];
char buf[8];

if(data[0] == BOOT_START_CMD && data[1] == BOOT_START_CMD)
{
	ALTERA_AVALON_EPCS_FLASH_CONTROLLER_INIT(EPCS_FLASH_CONTROLLER_0, epcs_flash);
	block_offset = 0;
	data_offset = 0;
	for(i = 0; i < EPCS_NUMBER_SECTORS; i++)
	{
		alt_epcs_flash_erase_block(&epcs_flash.dev, block_offset);
		block_offset += EPCS_SECTOR_BYTES;
	}
	block_offset = 0;
	tmp[0] = BOOT_OK_RESPONSE;
	tmp[1] = BOOT_OK_RESPONSE;
	CmdTx(0, CAN_BOOT_API_ID, (alt_u16*) tmp, 8);
}
else if(data[0] == BOOT_END_CMD && data[1] == BOOT_END_CMD)
{
	block_offset = 0;
	data_offset = 0;

	tmp[0] = BOOT_END_RESPONSE;
	tmp[1] = BOOT_END_RESPONSE;
	CmdTx(0, CAN_BOOT_API_ID, (alt_u16*) tmp, 8);
}
else
{
	for(i = 0; i < 4; i++)
	{
		//buf[i] = (data[0] >> (8 * i)) & 0xFF;
		//buf[i + 4] = (data[1] >> (8 * i)) & 0xFF;
		buf[i] = data[0] & 0xFF;
		buf[i + 4] = data[1] & 0xFF;
		data[0] = data[0] >> 8;
		data[1] = data[1] >> 8;
		swap_bits(&buf[i]);
		swap_bits(&buf[i + 4]);

	}
	alt_epcs_flash_write_block(&epcs_flash.dev, block_offset, data_offset, buf, 8);
	data_offset += 8;
	if((data_offset % EPCS_SECTOR_BYTES) == 0)
	{
		block_offset += EPCS_SECTOR_BYTES;
	}

	tmp[0] = BOOT_OK_RESPONSE;
	tmp[1] = BOOT_OK_RESPONSE;
	CmdTx(0, CAN_BOOT_API_ID, (alt_u16*) &tmp, 8);
}
}

 

 

Ок, понятно, надо писать в EPCS, но в другую её область, чтобы не затереть исходную прошивку.

Чтобы FPGA стартовала - записываете прошивку с адреса 0.

Share this post


Link to post
Share on other sites
Тут ещё вот какая засада притаилась: http://www.altera.com/support/kdb/solution...182014_477.html

Установите q14.0 (на ftp есть таблетка) и всё точно будет работать.

Share this post


Link to post
Share on other sites
Можете взять в качестве примера немного подправив (используются только ф-ии alt_epcs_flash_init(), alt_epcs_flash_erase_block(), alt_epcs_flash_write_block(), ну и если читать надо, тогда - alt_epcs_flash_read_block()):

Спасибо за пример, в Эклипсе скомпилировался без ошибок!

Я в С не силён, разбираюсь сейчас по тексту.

Нет ли у Вас этого исходника с комментариями?

Если нет, то поясните пожалуйста, что такое idx?

Share this post


Link to post
Share on other sites
Спасибо за пример, в Эклипсе скомпилировался без ошибок!

Я в С не силён, разбираюсь сейчас по тексту.

Нет ли у Вас этого исходника с комментариями?

Если нет, то поясните пожалуйста, что такое idx?

idx - это номер блока данных (прошивка в данном случае передаётся по TFTP, размер блока данных 512 байт, последний блок может быть меньше 512).

Вам необходимо просто при приёме прошивки правильно формировать адреса, куда будут ложиться данные. Перед записью данных необходимо стирать страницу, которая будет записана. Можно стереть сразу всю область памяти занимаемую прошивкой, но это долго, для варианта с TFTP не подходит (не дождётся ответа). Для второго варианта (загрузка по CAN, ждем ответа о выполнении стирания сколь угодно долго) использовалось полное стирание памяти перед началом записи.

Особого внимания приведённому коду уделять не стоит, просто пример функций используемых для записи EPCS/EPCQ.

Share this post


Link to post
Share on other sites
Давайте рассмотрим ситуацию, когда у Вас в процессе перезаписи EPCS'ки происходит сбой. В этом случае для приведения оборудования в чувство потребуется рукопашное вмешательство.

Насколько высока вероятность сбоя в процессе перезаписи EPCS'ки?

Это перестраховка или реально частые сбои?

Обычно делают не так. Создается две прошивки - базовая (factory) и приложение (application). И обновление приложения осуществляется из factory-прошивки.

Вот какая у меня ситуация.

Factory прошивка, которую надо обновлять у клиента, была залита в EPCS16 в виде .jic файла. Схема конфигурации - Active Serial.

 

Вот как выглядит .map файл от .jic файла:

BLOCK START ADDRESS END ADDRESS

Page_0 0x00000000 0x00068E4A

- All the addresses in this file are byte addresses

Размер .jic файла примерно 420 Кбайт, т.е примерно 1/4 от размера EPCS16.

 

Я планировал сделать так:

1). Записать с помощью NIOS-а ( используя соответствующие команды драйвера epcs_commands.h ) начиная с адреса 0x00080000 в EPCS16 новую Application прошивку в виде нового .jic файла.

2). Задать ( пока не выяснил - где именно ), чтобы при включении питания загрузка прошивки происходила не с адреса 0x00000000 ( там находится прошивка Factory ), а с адреса 0x00080000 ( там находится прошивка Application ).

 

Поскольку прошивка в виде .jic файла содержит ядро PCIe, то у меня сделано так, что конфигурирование и инициализация Cyclone 4 GX выполняется за время менее 0,1 секунды ( иначе плата с ядром PCIe не будет опознана в ПК ).

Я хотел бы понять, смогу ли я использовать Remote System Update, учитывая это ограничение по времени?

 

Дело в том, что имеющаяся в Remote System Update проверка того, загрузилась ли нормально Application прошивка с адреса 0x00080000 или нет, и не надо ли вернуться к прошивке Factory не имеет смысла, т.к при этом время 0,1 с ( за которое должен успеть сконфигурироваться и инициализироваться Cyclone 4 GX ) будет упущено.

По этой же причине не имеет смысла вариант когда сначала грузится прошивка Factory, а затем она грузит Application прошивку.

 

Значит остаётся только вариант писать новую Application прошивку в виде нового .jic файла с помощью NIOS-а ( используя соответствующие команды драйвера epcs_commands.h ) начиная с адреса 0x00000000 в EPCS16., т.е затирая при этом Factory прошивку?

Какие могут быть при этом сбои?

Ведь можно после записи прошивки сделать её чтение и проверить, а если были ошибки, то перезаписать неправильные байты заново.

Остаётся только риск того, что отключится питание во время записи или что-то ещё может произойти из-за чего новая прошивкка не перезапишется на место Factory?

 

Share this post


Link to post
Share on other sites
2). Задать ( пока не выяснил - где именно ), чтобы при включении питания загрузка прошивки происходила не с адреса 0x00000000 ( там находится прошивка Factory ), а с адреса 0x00080000 ( там находится прошивка Application ).

Это всё делается через регистры ядра RSU.

 

Поскольку прошивка в виде .jic файла содержит ядро PCIe, то у меня сделано так, что конфигурирование и инициализация Cyclone 4 GX выполняется за время менее 0,1 секунды ( иначе плата с ядром PCIe не будет опознана в ПК ).

Я хотел бы понять, смогу ли я использовать Remote System Update, учитывая это ограничение по времени?

 

Дело в том, что имеющаяся в Remote System Update проверка того, загрузилась ли нормально Application прошивка с адреса 0x00080000 или нет, и не надо ли вернуться к прошивке Factory не имеет смысла, т.к при этом время 0,1 с ( за которое должен успеть сконфигурироваться и инициализироваться Cyclone 4 GX ) будет упущено.

Для управления ядром RSU я делал user IP для Ниоса, всё управление RSU выполняет софт. Тут времени понадобится больше. Если сделать железный контроллер для управления RSU, думаю, в 100 мс вполне уложится (ещё, правда, от конфигурационного девайса будет зависеть и файл прошивки ужать. Можно поставить epcq-флэшку для загрузки в режиме 4х).

Share this post


Link to post
Share on other sites
Если сделать железный контроллер для управления RSU, думаю, в 100 мс вполне уложится (ещё, правда, от конфигурационного девайса будет зависеть и файл прошивки ужать. Можно поставить epcq-флэшку для загрузки в режиме 4х).

Железный контроллер для управления RSU придётся делать с нуля или у Альтеры есть что-то готовое?

У меня и так с учётом компрессии и прочих ухищрений ( отдельный клок 40 МГц через CLKUSR вход и ещё кое-что ) это время на пределе ( примерно 80 мс ), но всё работает устойчиво.

То есть на что-то ещё дополнительно остаётся 10 -15 мс.

В итоге получается, что остаётся только рискованный способ - без RSU напрямую писать по нулевому адресу EPCS?

 

Какие приёмы обычно используют, чтобы надёжно писать в EPCS?

Я буду писать со стороны ПК через промежуточную On-chip memory ( dual-clock / dual-port ) размером чуть меньше 1Кбайт ( 1Кбайт минус 16 байт ) .

С одной стороны в эту память ПК пишет данные из RPD-файла ( примерно 500Кбайт ), а с другой НИОС читает эти данные и через команду epcs_write_buffer ( из драйвера epcs_commands.h ) записывает их кусками ( 1Кбайт минус 16 байт ) в EPCS.

Поскольку память при одновременным доступе на запись и на чтение по одному и тому же адресу ( а это может произойти ) возвращает значение Don't care , то как обычно делают, чтобы избежать этой проблемы?

Если использовать биты готовности ( для handshake ) , то в отношении их тоже есть вероятность того, что произойдёт одновременный доступ по адресу, где находится этот бит готовности.

Как тут быть?

Есть ли тут какое-нибудь стандартное решение?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this