fix firmware update functionality

This commit is contained in:
marqs 2025-05-03 16:14:58 +03:00
parent 30d403f157
commit 6198ce7d9e
13 changed files with 1174 additions and 264 deletions

View File

@ -130,7 +130,7 @@ alt_u32 I2C_read(alt_u32 base,alt_u32 last)
int I2C_write int I2C_write
assumes that any addressing and start assumes that any addressing and start
has already been done. has already been done.
writes one byte of data from the slave. writes one byte of data from the slave.
If last is set the stop bit set. If last is set the stop bit set.
inputs inputs
base = the base address of the component base = the base address of the component
@ -182,7 +182,7 @@ alt_u32 I2C_write(alt_u32 base,alt_u8 data, alt_u32 last)
} }
void SPI_read(alt_u32 base, alt_u8 *rdata, int len) void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_read(alt_u32 base, alt_u8 *rdata, int len)
{ {
int i; int i;
@ -197,7 +197,7 @@ void SPI_read(alt_u32 base, alt_u8 *rdata, int len)
} }
} }
void SPI_write(alt_u32 base, const alt_u8 *wdata, int len) void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_write(alt_u32 base, const alt_u8 *wdata, int len)
{ {
int i; int i;

View File

@ -10,7 +10,7 @@
<user_name>Page_0</user_name> <user_name>Page_0</user_name>
<page_flags>1</page_flags> <page_flags>1</page_flags>
<bit0> <bit0>
<sof_filename>output_files/ossc.sof</sof_filename> <sof_filename>output_files/ossc.sof<compress_bitstream>1</compress_bitstream></sof_filename>
</bit0> </bit0>
</sof_data> </sof_data>
<hex_block> <hex_block>

View File

@ -258,4 +258,5 @@ set_global_assignment -name SEARCH_PATH rtl
set_global_assignment -name SEARCH_PATH software/sys_controller/mem_init/ set_global_assignment -name SEARCH_PATH software/sys_controller/mem_init/
set_global_assignment -name SEARCH_PATH ip/ibex_qsys/rtl_extra set_global_assignment -name SEARCH_PATH ip/ibex_qsys/rtl_extra
set_global_assignment -name VERILOG_MACRO "SYNTHESIS=<None>" set_global_assignment -name VERILOG_MACRO "SYNTHESIS=<None>"
set_global_assignment -name STRATIXIII_UPDATE_MODE REMOTE
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@ -82,6 +82,11 @@ avinput_t target_input;
alt_u8 pcm1862_active; alt_u8 pcm1862_active;
flash_ctrl_dev flashctrl_dev = {.regs = (volatile gen_flash_if_regs*)INTEL_GENERIC_SERIAL_FLASH_INTERFACE_TOP_0_AVL_CSR_BASE,
.flash_size = 0x0200000};
rem_update_dev rem_reconfig_dev = {.regs = (volatile rem_update_regs*)0x0002a000};
uint8_t sl_def_iv_x, sl_def_iv_y; uint8_t sl_def_iv_x, sl_def_iv_y;
alt_u32 read_it2(alt_u32 regaddr); alt_u32 read_it2(alt_u32 regaddr);
@ -951,6 +956,9 @@ int main()
// Start system timer // Start system timer
alt_timestamp_start(); alt_timestamp_start();
// Write-protect flash
flash_write_protect(&flashctrl_dev, 1);
init_stat = init_hw(); init_stat = init_hw();
if (init_stat >= 0) { if (init_stat >= 0) {

View File

@ -20,6 +20,7 @@
#ifndef FIRMWARE_H_ #ifndef FIRMWARE_H_
#define FIRMWARE_H_ #define FIRMWARE_H_
#include <stdint.h>
#include "alt_types.h" #include "alt_types.h"
#include "sysconfig.h" #include "sysconfig.h"
@ -40,23 +41,29 @@
#define FW_UPDATE_RETRIES 3 #define FW_UPDATE_RETRIES 3
#define FW_IMAGE_ERROR 100
#define FW_HDR_ERROR 101
#define FW_HDR_CRC_ERROR 102
#define FW_DATA_CRC_ERROR 103
#define FW_UPD_CANCELLED 104
typedef struct { typedef struct {
char fw_key[4]; char fw_key[4];
alt_u8 version_major; uint8_t version_major;
alt_u8 version_minor; uint8_t version_minor;
char version_suffix[8]; char version_suffix[8];
alt_u32 hdr_len; uint32_t hdr_len;
alt_u32 data_len; uint32_t data_len;
alt_u32 data_crc; uint32_t data_crc;
alt_u32 hdr_crc; char padding[482];
} fw_hdr; uint32_t hdr_crc;
} __attribute__((packed)) fw_hdr;
typedef struct {
uint32_t unused[29];
uint32_t reconfig_start;
} rem_update_regs;
typedef struct {
volatile rem_update_regs *regs;
} rem_update_dev;
int fw_update(); int fw_update();
void fw_update_commit(uint32_t* cluster_idx, uint8_t* databuf, uint32_t bytes_to_copy, uint16_t fs_csize, uint16_t fs_startsec);
#endif #endif

View File

@ -30,190 +30,223 @@
#include "lcd.h" #include "lcd.h"
#include "utils.h" #include "utils.h"
#include "menu.h" #include "menu.h"
#include "ff.h"
#include "file.h"
#include "altera_avalon_pio_regs.h" #include "altera_avalon_pio_regs.h"
extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1]; extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS]; extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
extern SD_DEV sdcard_dev; extern SD_DEV sdcard_dev;
extern alt_u32 sys_ctrl; extern alt_u32 sys_ctrl;
extern flash_ctrl_dev flashctrl_dev;
extern rem_update_dev rem_reconfig_dev;
static int check_fw_header(alt_u8 *databuf, fw_hdr *hdr) //int fw_update(char *dirname, char *filename) {
{ int fw_update() {
alt_u32 crcval, tmp; FIL fw_file;
strncpy(hdr->fw_key, (char*)databuf, 4);
if (strncmp(hdr->fw_key, "OSSC", 4))
return FW_IMAGE_ERROR;
hdr->version_major = databuf[4];
hdr->version_minor = databuf[5];
strncpy(hdr->version_suffix, (char*)(databuf+6), 8);
hdr->version_suffix[7] = 0;
memcpy(&tmp, databuf+14, 4);
hdr->hdr_len = bswap32(tmp);
memcpy(&tmp, databuf+18, 4);
hdr->data_len = bswap32(tmp);
memcpy(&tmp, databuf+22, 4);
hdr->data_crc = bswap32(tmp);
// Always at bytes [508-511]
memcpy(&tmp, databuf+508, 4);
hdr->hdr_crc = bswap32(tmp);
if (hdr->hdr_len < 26 || hdr->hdr_len > 508)
return FW_HDR_ERROR;
crcval = crc32(databuf, hdr->hdr_len, 1);
if (crcval != hdr->hdr_crc)
return FW_HDR_CRC_ERROR;
return 0;
}
static int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_u8 *tmpbuf)
{
alt_u32 crcval=0, i, bytes_to_read;
SDRESULTS res; SDRESULTS res;
char dirname_root[10];
fw_hdr hdr;
int retval;
unsigned bytes_read, bytes_to_copy;
uint32_t crcval, hdr_len, btn_vec;
uint32_t cluster_idx[100]; // enough for >=4kB cluster size
uint8_t databuf[SD_BLK_SIZE]; // temp buffer for data
uint16_t fs_csize, fs_startsec, cl_iter, cl_soffs;
for (i=0; i<size; i=i+SD_BLK_SIZE) { retval = file_mount();
bytes_to_read = ((size-i < SD_BLK_SIZE) ? (size-i) : SD_BLK_SIZE);
res = SD_Read(&sdcard_dev, tmpbuf, (offset+i)/SD_BLK_SIZE, 0, bytes_to_read);
if (res != SD_OK)
return -res;
crcval = crc32(tmpbuf, bytes_to_read, (i==0));
}
if (crcval != golden_crc)
return FW_DATA_CRC_ERROR;
return 0;
}
int fw_update()
{
int retval, i;
int retries = FW_UPDATE_RETRIES;
char *errmsg;
alt_u8 databuf[SD_BLK_SIZE];
alt_u32 btn_vec;
alt_u32 bytes_to_rw;
fw_hdr fw_header;
#ifdef CHECK_STACK_USE
// estimate stack usage, assuming around here is the worst case (due to 512B databuf)
alt_u32 sp;
asm volatile("mv %0, sp" : "=r"(sp));
sniprintf(menu_row1, LCD_ROW_LEN+1, "Stack size:");
sniprintf(menu_row2, LCD_ROW_LEN+1, "%lu bytes", (ONCHIP_MEMORY2_0_BASE+ONCHIP_MEMORY2_0_SIZE_VALUE)-sp);
ui_disp_menu(1);
usleep(1000000);
#endif
retval = check_sdcard(databuf);
SPI_CS_High();
if (retval != 0) { if (retval != 0) {
retval = -retval; printf("SD card not detected %d\n", retval);
goto failure; return -1;
} }
retval = check_fw_header(databuf, &fw_header); //sniprintf(dirname_root, sizeof(dirname_root), "/%s", dirname);
if (retval != 0) sniprintf(dirname_root, sizeof(dirname_root), "/");
goto failure; f_chdir(dirname_root);
sniprintf(menu_row1, LCD_ROW_LEN+1, "Validating data"); if (!file_open(&fw_file, "ossc.bin")) {
sniprintf(menu_row2, LCD_ROW_LEN+1, "%u bytes", (unsigned)fw_header.data_len); strlcpy(menu_row1, "Checking FW", LCD_ROW_LEN+1);
ui_disp_menu(1); strlcpy(menu_row2, "Please wait...", LCD_ROW_LEN+1);
retval = check_fw_image(512, fw_header.data_len, fw_header.data_crc, databuf); ui_disp_menu(1);
if (retval != 0)
goto failure;
sniprintf(menu_row1, LCD_ROW_LEN+1, "%u.%.2u%s%s", fw_header.version_major, fw_header.version_minor, (fw_header.version_suffix[0] == 0) ? "" : "-", fw_header.version_suffix); if (f_read(&fw_file, &hdr, sizeof(hdr), &bytes_read) != F_OK) {
strncpy(menu_row2, "Update? 1=Y, 2=N", LCD_ROW_LEN+1); printf("FW hdr read error\n");
ui_disp_menu(1); retval = -3;
goto close_file;
while (1) {
btn_vec = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (btn_vec == rc_keymap[RC_BTN1]) {
break;
} else if (btn_vec == rc_keymap[RC_BTN2]) {
retval = FW_UPD_CANCELLED;
goto failure;
} }
usleep(WAITLOOP_SLEEP_US); hdr_len = bswap32(hdr.hdr_len);
if (strncmp(hdr.fw_key, "OSSC", 4) || (hdr_len < 26 || hdr_len > 508)) {
printf("Invalid FW header\n");
retval = -4;
goto close_file;
}
crcval = crc32((unsigned char *)&hdr, hdr_len, 1);
hdr.hdr_len = bswap32(hdr.hdr_len);
hdr.data_len = bswap32(hdr.data_len);
hdr.data_crc = bswap32(hdr.data_crc);
hdr.hdr_crc = bswap32(hdr.hdr_crc);
if (crcval != hdr.hdr_crc) {
printf("Invalid FW header CRC (0x%.8x instead of 0x%.8x)\n", crcval, hdr.hdr_crc);
retval = -5;
goto close_file;
}
printf("Firmware %u.%u%s%s\n", hdr.version_major, hdr.version_minor, hdr.version_suffix[0] ? "-" : "", hdr.version_suffix);
bytes_to_copy = hdr.data_len;
printf(" Image: %u bytes, crc 0x%.8x\n", hdr.data_len, hdr.data_crc);
if (hdr.data_len >= 16*FLASH_SECTOR_SIZE) {
printf("Image exceeds flash allocation\n");
retval = -6;
goto close_file;
}
sniprintf(menu_row1, LCD_ROW_LEN+1, "v%u.%u%s%s", hdr.version_major, hdr.version_minor, hdr.version_suffix[0] ? "-" : "", hdr.version_suffix);
sniprintf(menu_row2, LCD_ROW_LEN+1, "Update? 1=Y, 2=N");
ui_disp_menu(1);
while (1) {
btn_vec = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (btn_vec == rc_keymap[RC_BTN1]) {
break;
} else if (btn_vec == rc_keymap[RC_BTN2]) {
//set_func_ret_msg("Cancelled");
retval = 1;
goto close_file;
}
usleep(WAITLOOP_SLEEP_US);
}
strlcpy(menu_row2, "Please wait...", LCD_ROW_LEN+1);
ui_disp_menu(1);
// check if 512-byte header is on first or second cluster
fs_startsec = fw_file.obj.fs->database;
fs_csize = fw_file.obj.fs->csize;
if (fs_csize == 1) {
cl_iter = 1;
cl_soffs = 0;
cluster_idx[0] = fw_file.obj.sclust;
} else {
cl_iter = 0;
cl_soffs = 1;
}
// record cluster IDs to an array
if ((f_read_cc(&fw_file, &cluster_idx[cl_iter], bytes_to_copy, &bytes_read, (sizeof(cluster_idx)/sizeof(cluster_idx[0]))-1) != F_OK) || (bytes_read != bytes_to_copy)) {
printf("FW cluster error\n");
retval = -7;
goto close_file;
}
file_close(&fw_file);
f_chdir("/");
printf("Checking copied data...\n");
while (bytes_to_copy > 0) {
bytes_read = (bytes_to_copy > SD_BLK_SIZE) ? SD_BLK_SIZE : bytes_to_copy;
res = SD_Read(&sdcard_dev, databuf, ((cluster_idx[cl_iter]-2)*fs_csize+fs_startsec+cl_soffs), 0, bytes_read);
if (res != SD_OK) {
printf("FW data read error\n");
retval = -8;
goto close_file;
}
crcval = crc32((unsigned char *)&databuf, bytes_read, (bytes_to_copy==hdr.data_len));
bytes_to_copy -= bytes_read;
cl_soffs += 1;
if (cl_soffs == fs_csize) {
cl_iter += 1;
cl_soffs = 0;
}
}
if (crcval != hdr.data_crc) {
printf("Image: Invalid CRC (0x%.8x)\n", crcval);
retval = -9;
goto close_file;
}
printf("Starting update procedure...\n");
strlcpy(menu_row1, "Updating", LCD_ROW_LEN+1);
ui_disp_menu(1);
//disable video output
tvp_powerdown();
sys_ctrl |= VIDGEN_OFF;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
usleep(10000);
// No return from here
fw_update_commit(cluster_idx, databuf, hdr.data_len, fs_csize, fs_startsec);
return 0;
} else {
printf("FW file not found\n");
f_chdir("/");
return -2;
} }
//disable video output close_file:
tvp_powerdown(); file_close(&fw_file);
sys_ctrl |= VIDGEN_OFF; f_chdir("/");
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl); return retval;
usleep(10000); }
strncpy(menu_row1, "Updating FW", LCD_ROW_LEN+1); // commit FW update. Do not call functions located in flash during update
update_init: void __attribute__((noinline, flatten, noreturn, __section__(".text_bram"))) fw_update_commit(uint32_t* cluster_idx, uint8_t* databuf, uint32_t bytes_to_copy, uint16_t fs_csize, uint16_t fs_startsec) {
strncpy(menu_row2, "please wait...", LCD_ROW_LEN+1); int i, sectors;
ui_disp_menu(1); SDRESULTS res;
uint16_t cl_iter, cl_soffs;
/*retval = copy_sd_to_flash(512/SD_BLK_SIZE, 0, fw_header.data_len, databuf); uint32_t addr, bytes_read;
if (retval != 0) uint32_t *data_to;
goto failure;
flash_write_protect(&flashctrl_dev, 0);
strncpy(menu_row1, "Verifying flash", LCD_ROW_LEN+1);
ui_disp_menu(1); // Erase sectors
retval = verify_flash(0, fw_header.data_len, fw_header.data_crc, databuf); addr = 0;
if (retval != 0) sectors = (bytes_to_copy/FLASH_SECTOR_SIZE) + ((bytes_to_copy % FLASH_SECTOR_SIZE) != 0);
goto failure;*/ data_to = (uint32_t*)(INTEL_GENERIC_SERIAL_FLASH_INTERFACE_TOP_0_AVL_MEM_BASE);
SPI_CS_High(); for (i=0; i<sectors; i++) {
flash_sector_erase(&flashctrl_dev, addr);
strncpy(menu_row1, "Firmware updated", LCD_ROW_LEN+1); addr += FLASH_SECTOR_SIZE;
strncpy(menu_row2, "please restart", LCD_ROW_LEN+1); }
ui_disp_menu(1);
while (1) {} if (fs_csize == 1) {
cl_iter = 1;
return 0; cl_soffs = 0;
} else {
failure: cl_iter = 0;
SPI_CS_High(); cl_soffs = 1;
}
switch (retval) {
case SD_NOINIT: // Write data
errmsg = "No SD card det."; while (bytes_to_copy > 0) {
break; bytes_read = (bytes_to_copy > SD_BLK_SIZE) ? SD_BLK_SIZE : bytes_to_copy;
case FW_IMAGE_ERROR: res = SD_Read(&sdcard_dev, databuf, ((cluster_idx[cl_iter]-2)*fs_csize+fs_startsec+cl_soffs), 0, bytes_read);
errmsg = "Invalid image"; //TODO: retry if read fails
break;
case FW_HDR_ERROR: bytes_to_copy -= bytes_read;
errmsg = "Invalid header"; for (i=0; i<bytes_read; i++)
break; databuf[i] = bitswap8(databuf[i]);
case FW_HDR_CRC_ERROR: for (i=0; i<bytes_read; i+=4)
errmsg = "Invalid hdr CRC"; *data_to++ = *((uint32_t*)&databuf[i]);
break;
case FW_DATA_CRC_ERROR: cl_soffs += 1;
errmsg = "Invalid data CRC"; if (cl_soffs == fs_csize) {
break; cl_iter += 1;
case FW_UPD_CANCELLED: cl_soffs = 0;
errmsg = "Update cancelled"; }
break; }
default:
errmsg = "SD/Flash error"; // flush command FIFO before FPGA reconfiguration start
break; *(volatile uint32_t*)(INTEL_GENERIC_SERIAL_FLASH_INTERFACE_TOP_0_AVL_MEM_BASE);
}
strncpy(menu_row2, errmsg, LCD_ROW_LEN+1); rem_reconfig_dev.regs->reconfig_start = 1;
ui_disp_menu(1);
usleep(1000000); while (1) {}
// Critical error, retry update
if ((retval < 0) && (retries > 0)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Retrying update");
retries--;
goto update_init;
}
render_osd_page();
return -1;
} }

View File

@ -208,9 +208,7 @@ MENU(menu_scanlines, P99_PROTECT({ \
{ "Sl. alternating", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_altern, OPT_WRAP, SETTING_ITEM(off_on_desc) } } }, { "Sl. alternating", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_altern, OPT_WRAP, SETTING_ITEM(off_on_desc) } } },
{ LNG("Sl. alignment","スキャンラインポジション"), OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_id, OPT_WRAP, SETTING_ITEM(sl_id_desc) } } }, { LNG("Sl. alignment","スキャンラインポジション"), OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_id, OPT_WRAP, SETTING_ITEM(sl_id_desc) } } },
{ LNG("Sl. type","スキャンラインルイ"), OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_type, OPT_WRAP, SETTING_ITEM(sl_type_desc) } } }, { LNG("Sl. type","スキャンラインルイ"), OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_type, OPT_WRAP, SETTING_ITEM(sl_type_desc) } } },
#ifndef DEBUG
{ "< Custom Sl. >", OPT_SUBMENU, { .sub = { &menu_cust_sl, NULL, NULL } } }, { "< Custom Sl. >", OPT_SUBMENU, { .sub = { &menu_cust_sl, NULL, NULL } } },
#endif
})) }))
MENU(menu_postproc, P99_PROTECT({ \ MENU(menu_postproc, P99_PROTECT({ \
@ -251,11 +249,9 @@ MENU(menu_settings, P99_PROTECT({ \
{ LNG("<Load profile >","<プロファイルロード >"), OPT_FUNC_CALL, { .fun = { load_profile, &profile_arg_info } } }, { LNG("<Load profile >","<プロファイルロード >"), OPT_FUNC_CALL, { .fun = { load_profile, &profile_arg_info } } },
{ LNG("<Save profile >","<プロファイルセーブ >"), OPT_FUNC_CALL, { .fun = { save_profile, &profile_arg_info } } }, { LNG("<Save profile >","<プロファイルセーブ >"), OPT_FUNC_CALL, { .fun = { save_profile, &profile_arg_info } } },
{ LNG("<Reset settings>","<セッテイヲショキカ >"), OPT_FUNC_CALL, { .fun = { set_default_avconfig, NULL } } }, { LNG("<Reset settings>","<セッテイヲショキカ >"), OPT_FUNC_CALL, { .fun = { set_default_avconfig, NULL } } },
#ifndef DEBUG
{ LNG("<Import sett. >","<セッテイヨミコミ >"), OPT_FUNC_CALL, { .fun = { import_userdata, NULL } } }, { LNG("<Import sett. >","<セッテイヨミコミ >"), OPT_FUNC_CALL, { .fun = { import_userdata, NULL } } },
{ LNG("<Export sett. >","<セッテイカキコミ >"), OPT_FUNC_CALL, { .fun = { export_userdata, NULL } } }, { LNG("<Export sett. >","<セッテイカキコミ >"), OPT_FUNC_CALL, { .fun = { export_userdata, NULL } } },
{ LNG("<Fw. update >","<ファームウェアアップデート>"), OPT_FUNC_CALL, { .fun = { fw_update, NULL } } }, { LNG("<Fw. update >","<ファームウェアアップデート>"), OPT_FUNC_CALL, { .fun = { fw_update, NULL } } },
#endif
})) }))

View File

@ -25,7 +25,7 @@
#include "sysconfig.h" #include "sysconfig.h"
#include "io.h" #include "io.h"
inline unsigned char bitswap8(unsigned char v) inline __attribute__((flatten, __section__(".text_bram"))) unsigned char bitswap8(unsigned char v)
{ {
return ((v * 0x0802LU & 0x22110LU) | return ((v * 0x0802LU & 0x22110LU) |
(v * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; (v * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;

View File

@ -94,11 +94,11 @@ DWORD __SD_Power_Of_Two(BYTE e)
return(partial); return(partial);
} }
inline void __SD_Assert(void){ inline void __attribute__((flatten, __section__(".text_bram"))) __SD_Assert(void){
SPI_CS_Low(); SPI_CS_Low();
} }
inline void __SD_Deassert(void){ inline void __attribute__((flatten, __section__(".text_bram"))) __SD_Deassert(void){
SPI_CS_High(); SPI_CS_High();
} }
@ -107,7 +107,7 @@ void __SD_Speed_Transfer(BYTE throttle) {
else SPI_Freq_Low(); else SPI_Freq_Low();
} }
BYTE __SD_Send_Cmd(BYTE cmd, DWORD arg) BYTE __attribute__((noinline, flatten, __section__(".text_bram"))) __SD_Send_Cmd(BYTE cmd, DWORD arg)
{ {
BYTE wiredata[10]; BYTE wiredata[10];
BYTE crc, res; BYTE crc, res;
@ -361,7 +361,7 @@ SDRESULTS SD_Init(SD_DEV *dev)
#endif #endif
} }
SDRESULTS SD_Read(SD_DEV *dev, void *dat, DWORD sector, WORD ofs, WORD cnt) SDRESULTS __attribute__((noinline, flatten, __section__(".text_bram"))) SD_Read(SD_DEV *dev, void *dat, DWORD sector, WORD ofs, WORD cnt)
{ {
#if defined(_M_IX86) // x86 #if defined(_M_IX86) // x86
// Check the sector query // Check the sector query

View File

@ -15,11 +15,11 @@ void SPI_Init (void) {
I2C_init(SD_SPI_BASE,ALT_CPU_FREQ,400000); I2C_init(SD_SPI_BASE,ALT_CPU_FREQ,400000);
} }
void SPI_W(const BYTE *wd, int len) { void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_W(const BYTE *wd, int len) {
SPI_write(SD_SPI_BASE, wd, len); SPI_write(SD_SPI_BASE, wd, len);
} }
void SPI_R(BYTE *rd, int len) { void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_R(BYTE *rd, int len) {
SPI_read(SD_SPI_BASE, rd, len); SPI_read(SD_SPI_BASE, rd, len);
} }
@ -34,16 +34,17 @@ BYTE SPI_RW (BYTE d) {
return w; return w;
} }
void SPI_Release (void) { void __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_Release (void) {
SPI_CS_High();
return; return;
} }
inline void SPI_CS_Low (void) { inline void __attribute__((flatten, __section__(".text_bram"))) SPI_CS_Low (void) {
sys_ctrl &= ~SD_SPI_SS_N; sys_ctrl &= ~SD_SPI_SS_N;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl); IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
} }
inline void SPI_CS_High (void){ inline void __attribute__((flatten, __section__(".text_bram"))) SPI_CS_High (void){
sys_ctrl |= SD_SPI_SS_N; sys_ctrl |= SD_SPI_SS_N;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl); IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
} }
@ -56,7 +57,7 @@ inline void SPI_Freq_Low (void) {
I2C_init(SD_SPI_BASE,ALT_CPU_FREQ,400000); I2C_init(SD_SPI_BASE,ALT_CPU_FREQ,400000);
} }
int SPI_Timer_On (WORD ms) { int __attribute__((noinline, flatten, __section__(".text_bram"))) SPI_Timer_On (WORD ms) {
if (!sd_timer_ts) { if (!sd_timer_ts) {
sd_timer_ts = alt_timestamp() + ms*(TIMER_0_FREQ/1000); sd_timer_ts = alt_timestamp() + ms*(TIMER_0_FREQ/1000);
return 0; return 0;
@ -64,11 +65,11 @@ int SPI_Timer_On (WORD ms) {
return 1; return 1;
} }
inline BOOL SPI_Timer_Status (void) { inline BOOL __attribute__((flatten, __section__(".text_bram"))) SPI_Timer_Status (void) {
return alt_timestamp() < sd_timer_ts; return alt_timestamp() < sd_timer_ts;
} }
inline void SPI_Timer_Off (void) { inline void __attribute__((flatten, __section__(".text_bram"))) SPI_Timer_Off (void) {
sd_timer_ts = 0; sd_timer_ts = 0;
return; return;
} }

View File

@ -293,6 +293,27 @@
type = "int"; type = "int";
} }
} }
element remote_update_0
{
datum _sortIndex
{
value = "16";
type = "int";
}
}
element remote_update_0.avl_csr
{
datum _lockedAddress
{
value = "1";
type = "boolean";
}
datum baseAddress
{
value = "172032";
type = "String";
}
}
element sc_config_0 element sc_config_0
{ {
datum _sortIndex datum _sortIndex
@ -578,6 +599,21 @@
<parameter name="SYNCHRONOUS_EDGES" value="deassert" /> <parameter name="SYNCHRONOUS_EDGES" value="deassert" />
<parameter name="USE_RESET_REQUEST" value="0" /> <parameter name="USE_RESET_REQUEST" value="0" />
</module> </module>
<module
name="remote_update_0"
kind="altera_remote_update"
version="24.1"
enabled="1">
<parameter name="AUTO_DEVICE_SPEEDGRADE" value="8" />
<parameter name="CBX_AUTO_BLACKBOX" value="ALL" />
<parameter name="DEVICE" value="EP4CE15E22C8" />
<parameter name="DEVICE_FAMILY" value="Cyclone IV E" />
<parameter name="GUI_config_device" value="EPCS16" />
<parameter name="check_app_pof" value="false" />
<parameter name="check_avalon_interface" value="true" />
<parameter name="m_support_write_config_check" value="false" />
<parameter name="operation_mode" value="REMOTE" />
</module>
<module name="sc_config_0" kind="sc_config" version="1.0" enabled="1" /> <module name="sc_config_0" kind="sc_config" version="1.0" enabled="1" />
<module name="timer_0" kind="altera_avalon_timer" version="24.1" enabled="1"> <module name="timer_0" kind="altera_avalon_timer" version="24.1" enabled="1">
<parameter name="alwaysRun" value="false" /> <parameter name="alwaysRun" value="false" />
@ -672,6 +708,15 @@
<parameter name="baseAddress" value="0x00020100" /> <parameter name="baseAddress" value="0x00020100" />
<parameter name="defaultConnection" value="false" /> <parameter name="defaultConnection" value="false" />
</connection> </connection>
<connection
kind="avalon"
version="24.1"
start="ibex_0.avalon_master_bus_data"
end="remote_update_0.avl_csr">
<parameter name="arbitrationPriority" value="1" />
<parameter name="baseAddress" value="0x0002a000" />
<parameter name="defaultConnection" value="false" />
</connection>
<connection <connection
kind="avalon" kind="avalon"
version="24.1" version="24.1"
@ -816,6 +861,11 @@
version="24.1" version="24.1"
start="clk_27.clk" start="clk_27.clk"
end="i2c_opencores_1.clock" /> end="i2c_opencores_1.clock" />
<connection
kind="clock"
version="24.1"
start="clk_27.clk"
end="remote_update_0.clock" />
<connection <connection
kind="clock" kind="clock"
version="24.1" version="24.1"
@ -894,6 +944,11 @@
version="24.1" version="24.1"
start="clk_27.clk_reset" start="clk_27.clk_reset"
end="intel_generic_serial_flash_interface_top_0.reset" /> end="intel_generic_serial_flash_interface_top_0.reset" />
<connection
kind="reset"
version="24.1"
start="clk_27.clk_reset"
end="remote_update_0.reset" />
<connection <connection
kind="reset" kind="reset"
version="24.1" version="24.1"

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<EnsembleReport name="sys" kind="sys" version="1.0" fabric="QSYS"> <EnsembleReport name="sys" kind="sys" version="1.0" fabric="QSYS">
<!-- Format version 24.1 1077 (Future versions may contain additional information.) --> <!-- Format version 24.1 1077 (Future versions may contain additional information.) -->
<!-- 2025.04.18.22:02:06 --> <!-- 2025.05.03.12:04:14 -->
<!-- A collection of modules and connections --> <!-- A collection of modules and connections -->
<parameter name="AUTO_GENERATION_ID"> <parameter name="AUTO_GENERATION_ID">
<type>java.lang.Integer</type> <type>java.lang.Integer</type>
<value>1745002926</value> <value>1746263054</value>
<derived>false</derived> <derived>false</derived>
<enabled>true</enabled> <enabled>true</enabled>
<visible>false</visible> <visible>false</visible>
@ -402,6 +402,12 @@ parameters are a RESULT of the module parameters. -->
<slaveName>clock</slaveName> <slaveName>clock</slaveName>
<name>i2c_opencores_1.clock</name> <name>i2c_opencores_1.clock</name>
</clockDomainMember> </clockDomainMember>
<clockDomainMember>
<isBridge>false</isBridge>
<moduleName>remote_update_0</moduleName>
<slaveName>clock</slaveName>
<name>remote_update_0.clock</name>
</clockDomainMember>
<clockDomainMember> <clockDomainMember>
<isBridge>false</isBridge> <isBridge>false</isBridge>
<moduleName>sc_config_0</moduleName> <moduleName>sc_config_0</moduleName>
@ -3314,6 +3320,14 @@ parameters are a RESULT of the module parameters. -->
<baseAddress>131328</baseAddress> <baseAddress>131328</baseAddress>
<span>256</span> <span>256</span>
</memoryBlock> </memoryBlock>
<memoryBlock>
<isBridge>false</isBridge>
<moduleName>remote_update_0</moduleName>
<slaveName>avl_csr</slaveName>
<name>remote_update_0.avl_csr</name>
<baseAddress>172032</baseAddress>
<span>128</span>
</memoryBlock>
<memoryBlock> <memoryBlock>
<isBridge>false</isBridge> <isBridge>false</isBridge>
<moduleName>intel_generic_serial_flash_interface_top_0</moduleName> <moduleName>intel_generic_serial_flash_interface_top_0</moduleName>
@ -10799,6 +10813,604 @@ parameters are a RESULT of the module parameters. -->
</port> </port>
</interface> </interface>
</module> </module>
<module
name="remote_update_0"
kind="altera_remote_update"
version="24.1"
path="remote_update_0">
<!-- Describes a single module. Module parameters are
the requested settings for a module instance. -->
<parameter name="DEVICE_FAMILY">
<type>java.lang.String</type>
<value>CYCLONEIVE</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
<sysinfo_type>DEVICE_FAMILY</sysinfo_type>
</parameter>
<parameter name="DEVICE">
<type>java.lang.String</type>
<value>EP4CE15E22C8</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
<sysinfo_type>DEVICE</sysinfo_type>
</parameter>
<parameter name="CBX_AUTO_BLACKBOX">
<type>java.lang.String</type>
<value>ALL</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="operation_mode">
<type>java.lang.String</type>
<value>REMOTE</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="GUI_config_device">
<type>java.lang.String</type>
<value>EPCS16</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="m_support_write_config_check">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="check_avalon_interface">
<type>boolean</type>
<value>true</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="check_app_pof">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="config_device_addr_width">
<type>int</type>
<value>24</value>
<derived>true</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="is_epcq">
<type>boolean</type>
<value>false</value>
<derived>true</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="in_data_width">
<type>int</type>
<value>24</value>
<derived>true</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="out_data_width">
<type>int</type>
<value>24</value>
<derived>true</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="AUTO_DEVICE_SPEEDGRADE">
<type>java.lang.String</type>
<value>8</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
<sysinfo_type>DEVICE_SPEEDGRADE</sysinfo_type>
</parameter>
<parameter name="deviceFamily">
<type>java.lang.String</type>
<value>UNKNOWN</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="generateLegacySim">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<interface name="avl_csr" kind="avalon_slave" version="24.1">
<!-- The connection points exposed by a module instance for the
particular module parameters. Connection points and their
parameters are a RESULT of the module parameters. -->
<assignment>
<name>embeddedsw.configuration.isFlash</name>
<value>0</value>
</assignment>
<assignment>
<name>embeddedsw.configuration.isMemoryDevice</name>
<value>0</value>
</assignment>
<assignment>
<name>embeddedsw.configuration.isNonVolatileStorage</name>
<value>0</value>
</assignment>
<assignment>
<name>embeddedsw.configuration.isPrintableDevice</name>
<value>0</value>
</assignment>
<parameter name="addressAlignment">
<type>com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment</type>
<value>DYNAMIC</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="addressGroup">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="addressSpan">
<type>java.math.BigInteger</type>
<value>128</value>
<derived>true</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="addressUnits">
<type>com.altera.sopcmodel.avalon.EAddrBurstUnits</type>
<value>WORDS</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="alwaysBurstMaxBurst">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="associatedClock">
<type>java.lang.String</type>
<value>clock</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="associatedReset">
<type>java.lang.String</type>
<value>reset</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="bitsPerSymbol">
<type>int</type>
<value>8</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="bridgedAddressOffset">
<type>java.math.BigInteger</type>
<value>0</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="bridgesToMaster">
<type>com.altera.entityinterfaces.IConnectionPoint</type>
<value></value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="burstOnBurstBoundariesOnly">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="burstcountUnits">
<type>com.altera.sopcmodel.avalon.EAddrBurstUnits</type>
<value>WORDS</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="constantBurstBehavior">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="explicitAddressSpan">
<type>java.math.BigInteger</type>
<value>0</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="holdTime">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>false</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="interleaveBursts">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="isBigEndian">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="isFlash">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="isMemoryDevice">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="isNonVolatileStorage">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="linewrapBursts">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="maximumPendingReadTransactions">
<type>int</type>
<value>1</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="maximumPendingWriteTransactions">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>false</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="minimumUninterruptedRunLength">
<type>int</type>
<value>1</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="printableDevice">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="readLatency">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>false</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="readWaitStates">
<type>int</type>
<value>1</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="readWaitTime">
<type>int</type>
<value>1</value>
<derived>false</derived>
<enabled>false</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="registerIncomingSignals">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="registerOutgoingSignals">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="setupTime">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>false</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="timingUnits">
<type>com.altera.sopcmodel.avalon.TimingUnits</type>
<value>Cycles</value>
<derived>false</derived>
<enabled>false</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="transparentBridge">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="wellBehavedWaitrequest">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="writeLatency">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="writeWaitStates">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="writeWaitTime">
<type>int</type>
<value>0</value>
<derived>false</derived>
<enabled>false</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="deviceFamily">
<type>java.lang.String</type>
<value>UNKNOWN</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="generateLegacySim">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<type>avalon</type>
<isStart>false</isStart>
<port>
<name>avl_csr_write</name>
<direction>Input</direction>
<width>1</width>
<role>write</role>
</port>
<port>
<name>avl_csr_read</name>
<direction>Input</direction>
<width>1</width>
<role>read</role>
</port>
<port>
<name>avl_csr_writedata</name>
<direction>Input</direction>
<width>32</width>
<role>writedata</role>
</port>
<port>
<name>avl_csr_readdata</name>
<direction>Output</direction>
<width>32</width>
<role>readdata</role>
</port>
<port>
<name>avl_csr_readdatavalid</name>
<direction>Output</direction>
<width>1</width>
<role>readdatavalid</role>
</port>
<port>
<name>avl_csr_waitrequest</name>
<direction>Output</direction>
<width>1</width>
<role>waitrequest</role>
</port>
<port>
<name>avl_csr_address</name>
<direction>Input</direction>
<width>5</width>
<role>address</role>
</port>
</interface>
<interface name="clock" kind="clock_sink" version="24.1">
<!-- The connection points exposed by a module instance for the
particular module parameters. Connection points and their
parameters are a RESULT of the module parameters. -->
<parameter name="externallyDriven">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="ptfSchematicName">
<type>java.lang.String</type>
<value></value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>
<valid>true</valid>
</parameter>
<parameter name="deviceFamily">
<type>java.lang.String</type>
<value>UNKNOWN</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="generateLegacySim">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<type>clock</type>
<isStart>false</isStart>
<port>
<name>clock</name>
<direction>Input</direction>
<width>1</width>
<role>clk</role>
</port>
</interface>
<interface name="reset" kind="reset_sink" version="24.1">
<!-- The connection points exposed by a module instance for the
particular module parameters. Connection points and their
parameters are a RESULT of the module parameters. -->
<parameter name="associatedClock">
<type>java.lang.String</type>
<value>clock</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="synchronousEdges">
<type>com.altera.sopcmodel.reset.Reset$Edges</type>
<value>DEASSERT</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="deviceFamily">
<type>java.lang.String</type>
<value>UNKNOWN</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="generateLegacySim">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<type>reset</type>
<isStart>false</isStart>
<port>
<name>reset</name>
<direction>Input</direction>
<width>1</width>
<role>reset</role>
</port>
</interface>
</module>
<module name="sc_config_0" kind="sc_config" version="1.0" path="sc_config_0"> <module name="sc_config_0" kind="sc_config" version="1.0" path="sc_config_0">
<!-- Describes a single module. Module parameters are <!-- Describes a single module. Module parameters are
the requested settings for a module instance. --> the requested settings for a module instance. -->
@ -12666,6 +13278,57 @@ parameters are a RESULT of the module parameters. -->
<endModule>intel_generic_serial_flash_interface_top_0</endModule> <endModule>intel_generic_serial_flash_interface_top_0</endModule>
<endConnectionPoint>avl_csr</endConnectionPoint> <endConnectionPoint>avl_csr</endConnectionPoint>
</connection> </connection>
<connection
name="ibex_0.avalon_master_bus_data/remote_update_0.avl_csr"
kind="avalon"
version="24.1"
start="ibex_0.avalon_master_bus_data"
end="remote_update_0.avl_csr">
<parameter name="arbitrationPriority">
<type>int</type>
<value>1</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="baseAddress">
<type>java.math.BigInteger</type>
<value>0x0002a000</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="defaultConnection">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="deviceFamily">
<type>java.lang.String</type>
<value>UNKNOWN</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="generateLegacySim">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<startModule>ibex_0</startModule>
<startConnectionPoint>avalon_master_bus_data</startConnectionPoint>
<endModule>remote_update_0</endModule>
<endConnectionPoint>avl_csr</endConnectionPoint>
</connection>
<connection <connection
name="ibex_0.avalon_master_bus_data/intel_generic_serial_flash_interface_top_0.avl_mem" name="ibex_0.avalon_master_bus_data/intel_generic_serial_flash_interface_top_0.avl_mem"
kind="avalon" kind="avalon"
@ -13602,6 +14265,33 @@ parameters are a RESULT of the module parameters. -->
<endModule>i2c_opencores_1</endModule> <endModule>i2c_opencores_1</endModule>
<endConnectionPoint>clock</endConnectionPoint> <endConnectionPoint>clock</endConnectionPoint>
</connection> </connection>
<connection
name="clk_27.clk/remote_update_0.clock"
kind="clock"
version="24.1"
start="clk_27.clk"
end="remote_update_0.clock">
<parameter name="deviceFamily">
<type>java.lang.String</type>
<value>UNKNOWN</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="generateLegacySim">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<startModule>clk_27</startModule>
<startConnectionPoint>clk</startConnectionPoint>
<endModule>remote_update_0</endModule>
<endConnectionPoint>clock</endConnectionPoint>
</connection>
<connection <connection
name="clk_27.clk/sc_config_0.clock_sink" name="clk_27.clk/sc_config_0.clock_sink"
kind="clock" kind="clock"
@ -14012,6 +14702,33 @@ parameters are a RESULT of the module parameters. -->
<endModule>intel_generic_serial_flash_interface_top_0</endModule> <endModule>intel_generic_serial_flash_interface_top_0</endModule>
<endConnectionPoint>reset</endConnectionPoint> <endConnectionPoint>reset</endConnectionPoint>
</connection> </connection>
<connection
name="clk_27.clk_reset/remote_update_0.reset"
kind="reset"
version="24.1"
start="clk_27.clk_reset"
end="remote_update_0.reset">
<parameter name="deviceFamily">
<type>java.lang.String</type>
<value>UNKNOWN</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<parameter name="generateLegacySim">
<type>boolean</type>
<value>false</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>true</visible>
<valid>true</valid>
</parameter>
<startModule>clk_27</startModule>
<startConnectionPoint>clk_reset</startConnectionPoint>
<endModule>remote_update_0</endModule>
<endConnectionPoint>reset</endConnectionPoint>
</connection>
<connection <connection
name="clk_27.clk_reset/onchip_memory2_0.reset1" name="clk_27.clk_reset/onchip_memory2_0.reset1"
kind="reset" kind="reset"
@ -14277,7 +14994,7 @@ parameters are a RESULT of the module parameters. -->
<version>1.0</version> <version>1.0</version>
</plugin> </plugin>
<plugin> <plugin>
<instanceCount>15</instanceCount> <instanceCount>16</instanceCount>
<name>clock_sink</name> <name>clock_sink</name>
<type>com.altera.entityinterfaces.IElementClass</type> <type>com.altera.entityinterfaces.IElementClass</type>
<subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype> <subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype>
@ -14285,7 +15002,7 @@ parameters are a RESULT of the module parameters. -->
<version>24.1</version> <version>24.1</version>
</plugin> </plugin>
<plugin> <plugin>
<instanceCount>16</instanceCount> <instanceCount>17</instanceCount>
<name>reset_sink</name> <name>reset_sink</name>
<type>com.altera.entityinterfaces.IElementClass</type> <type>com.altera.entityinterfaces.IElementClass</type>
<subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype> <subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype>
@ -14293,7 +15010,7 @@ parameters are a RESULT of the module parameters. -->
<version>24.1</version> <version>24.1</version>
</plugin> </plugin>
<plugin> <plugin>
<instanceCount>16</instanceCount> <instanceCount>17</instanceCount>
<name>avalon_slave</name> <name>avalon_slave</name>
<type>com.altera.entityinterfaces.IElementClass</type> <type>com.altera.entityinterfaces.IElementClass</type>
<subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype> <subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype>
@ -14420,6 +15137,14 @@ parameters are a RESULT of the module parameters. -->
<displayName>Reset Bridge</displayName> <displayName>Reset Bridge</displayName>
<version>24.1</version> <version>24.1</version>
</plugin> </plugin>
<plugin>
<instanceCount>1</instanceCount>
<name>altera_remote_update</name>
<type>com.altera.entityinterfaces.IElementClass</type>
<subtype>com.altera.entityinterfaces.IModule</subtype>
<displayName>Remote Update Intel FPGA IP</displayName>
<version>24.1</version>
</plugin>
<plugin> <plugin>
<instanceCount>1</instanceCount> <instanceCount>1</instanceCount>
<name>sc_config</name> <name>sc_config</name>
@ -14437,7 +15162,7 @@ parameters are a RESULT of the module parameters. -->
<version>24.1</version> <version>24.1</version>
</plugin> </plugin>
<plugin> <plugin>
<instanceCount>21</instanceCount> <instanceCount>22</instanceCount>
<name>avalon</name> <name>avalon</name>
<type>com.altera.entityinterfaces.IElementClass</type> <type>com.altera.entityinterfaces.IElementClass</type>
<subtype>com.altera.entityinterfaces.IConnection</subtype> <subtype>com.altera.entityinterfaces.IConnection</subtype>
@ -14445,7 +15170,7 @@ parameters are a RESULT of the module parameters. -->
<version>24.1</version> <version>24.1</version>
</plugin> </plugin>
<plugin> <plugin>
<instanceCount>15</instanceCount> <instanceCount>16</instanceCount>
<name>clock</name> <name>clock</name>
<type>com.altera.entityinterfaces.IElementClass</type> <type>com.altera.entityinterfaces.IElementClass</type>
<subtype>com.altera.entityinterfaces.IConnection</subtype> <subtype>com.altera.entityinterfaces.IConnection</subtype>
@ -14461,7 +15186,7 @@ parameters are a RESULT of the module parameters. -->
<version>24.1</version> <version>24.1</version>
</plugin> </plugin>
<plugin> <plugin>
<instanceCount>15</instanceCount> <instanceCount>16</instanceCount>
<name>reset</name> <name>reset</name>
<type>com.altera.entityinterfaces.IElementClass</type> <type>com.altera.entityinterfaces.IElementClass</type>
<subtype>com.altera.entityinterfaces.IConnection</subtype> <subtype>com.altera.entityinterfaces.IConnection</subtype>

View File

@ -20,6 +20,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -35,6 +36,18 @@
#define FW_HDR_LEN 26 #define FW_HDR_LEN 26
typedef struct {
char fw_key[4];
uint8_t version_major;
uint8_t version_minor;
char version_suffix[8];
uint32_t hdr_len;
uint32_t data_len;
uint32_t data_crc;
char padding[482];
uint32_t hdr_crc;
} __attribute__((packed)) fw_header;
static uint32_t crc32_tab[] = { static uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
@ -94,99 +107,170 @@ uint32_t crc32(uint32_t crc, const void *buf, size_t size)
return crc ^ ~0U; return crc ^ ~0U;
} }
void bitswap8_buf(unsigned char *buf, size_t length)
{
for (size_t i=0; i<length; i++)
buf[i] = ((buf[i] * 0x0802LU & 0x22110LU) | (buf[i] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
unsigned char block; unsigned char block;
int fd_i, fd_o; int fd_i[2], fd_o;
struct stat fileinfo; struct stat fileinfo[2];
char fw_bin_name[MAX_FILENAME]; char fw_bin_name[MAX_FILENAME];
char hdrbuf[HDR_SIZE];
char rdbuf[BUF_SIZE]; char rdbuf[BUF_SIZE];
unsigned fw_version_major; fw_header hdr = {0};
unsigned fw_version_minor; unsigned fw_version_major, fw_version_minor;
uint32_t hdr_crc; int legacy_mode = 0;
uint32_t crc = 0; uint32_t bin_offset, padding;
unsigned int i, bytes_read, bytes_written, tot_bytes_read = 0; unsigned int i, bytes_read, bytes_written, tot_bytes_read[3] = {0, 0, 0};
if ((argc < 3) || (argc > 4)) { if ((argc < 3) || (argc > 6)) {
printf("Usege: %s rbf version [version_suffix]\n", argv[0]); printf("Usage: %s rbf bin bin_offset version [version_suffix]\nLegacy usage: %s rbf version [version_suffix]\n", argv[0], argv[0]);
return -1;
}
if ((fd_i = open(argv[1], O_RDONLY)) == -1 || fstat(fd_i, &fileinfo) == -1) {
printf("Couldn't open input file\n");
return -1; return -1;
} }
if (argc < 5)
snprintf(fw_bin_name, MAX_FILENAME-1, "ossc_%s%s%s.bin", argv[2], (argc == 4) ? "-" : "", (argc == 4) ? argv[3] : ""); legacy_mode = 1;
if ((fd_o = open(fw_bin_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) { if ((fd_i[0] = open(argv[1], O_RDONLY)) == -1 || fstat(fd_i[0], &fileinfo[0]) == -1) {
printf("Couldn't open input RBF file\n");
return -1;
}
if (!legacy_mode) {
if ((fd_i[1] = open(argv[2], O_RDONLY)) == -1 || fstat(fd_i[1], &fileinfo[1]) == -1) {
printf("Couldn't open input BIN file\n");
return -1;
}
}
if (legacy_mode)
snprintf(fw_bin_name, MAX_FILENAME-1, "ossc_%s%s%s.bin", argv[2], (argc == 4) ? "-" : "", (argc == 4) ? argv[3] : "");
else
snprintf(fw_bin_name, MAX_FILENAME-1, "ossc_%s%s%s.bin", argv[4], (argc == 6) ? "-" : "", (argc == 6) ? argv[5] : "");
if ((fd_o = open(fw_bin_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
printf("Couldn't open output file\n"); printf("Couldn't open output file\n");
return -1; return -1;
} }
if ((sscanf(argv[2], "%u.%u", &fw_version_major, &fw_version_minor) != 2) || (fw_version_major > 255) || (fw_version_minor > 255)) { if ((sscanf(legacy_mode ? argv[2] : argv[4], "%u.%u", &fw_version_major, &fw_version_minor) != 2) || (fw_version_major > 255) || (fw_version_minor > 255)) {
printf("Invalid version format specified\n"); printf("Invalid version format specified\n");
return -1; return -1;
} }
//printf("%s, %u.%u\n", argv[2], fw_version_major, (uint8_t)fw_version_minor);
memset(hdrbuf, 0x00, HDR_SIZE); snprintf(hdr.fw_key, FW_KEY_SIZE+1, "OSSC");
snprintf(hdrbuf, FW_KEY_SIZE+1, "OSSC"); hdr.version_major = (uint8_t)fw_version_major;
hdrbuf[4] = (uint8_t)fw_version_major; hdr.version_minor = (uint8_t)fw_version_minor;
hdrbuf[5] = (uint8_t)fw_version_minor; snprintf(hdr.version_suffix, FW_SUFFIX_MAX_SIZE, legacy_mode ? ((argc == 4) ? argv[3] : "") : ((argc == 6) ? argv[5] : ""));
snprintf(hdrbuf+6, FW_SUFFIX_MAX_SIZE+1, (argc == 4) ? argv[3] : ""); hdr.hdr_len = htobe32(FW_HDR_LEN);
*((uint32_t*)(hdrbuf+6+FW_SUFFIX_MAX_SIZE)) = htonl(FW_HDR_LEN);
*((uint32_t*)(hdrbuf+6+FW_SUFFIX_MAX_SIZE+4)) = htonl((uint32_t)fileinfo.st_size);
// data CRC if (legacy_mode) {
while ((bytes_read = read(fd_i, rdbuf, BUF_SIZE)) > 0) { hdr.data_len = htobe32((uint32_t)fileinfo[0].st_size);
crc = crc32(crc, rdbuf, bytes_read);
tot_bytes_read += bytes_read; // data CRC (rbf)
while ((bytes_read = read(fd_i[0], rdbuf, BUF_SIZE)) > 0) {
hdr.data_crc = crc32(hdr.data_crc, rdbuf, bytes_read);
tot_bytes_read[0] += bytes_read;
}
} else {
bin_offset = (uint32_t)strtol(argv[3], NULL, 16);
// data CRC (rbf)
while ((bytes_read = read(fd_i[0], rdbuf, BUF_SIZE)) > 0) {
hdr.data_crc = crc32(hdr.data_crc, rdbuf, bytes_read);
tot_bytes_read[0] += bytes_read;
}
// data CRC (padding)
memset(rdbuf, 0xff, sizeof(rdbuf));
padding = bin_offset - tot_bytes_read[0];
while (tot_bytes_read[1] < padding) {
bytes_read = ((padding-tot_bytes_read[1]) > sizeof(rdbuf)) ? sizeof(rdbuf) : (padding-tot_bytes_read[1]);
hdr.data_crc = crc32(hdr.data_crc, rdbuf, bytes_read);
tot_bytes_read[1] += bytes_read;
}
// data CRC (bin)
while ((bytes_read = read(fd_i[1], rdbuf, BUF_SIZE)) > 0) {
bitswap8_buf(rdbuf, bytes_read);
hdr.data_crc = crc32(hdr.data_crc, rdbuf, bytes_read);
tot_bytes_read[2] += bytes_read;
}
hdr.data_len = htobe32((uint32_t)fileinfo[0].st_size+padding+(uint32_t)fileinfo[1].st_size);
} }
*((uint32_t*)(hdrbuf+6+FW_SUFFIX_MAX_SIZE+8)) = htonl(crc);
// header CRC // header CRC
hdr_crc = crc32(0, hdrbuf, FW_HDR_LEN); hdr.data_crc = htobe32(hdr.data_crc);
*((uint32_t*)(hdrbuf+HDR_SIZE-4)) = htonl(hdr_crc); hdr.hdr_crc = crc32(0, &hdr, FW_HDR_LEN);
hdr.hdr_crc = htobe32(hdr.hdr_crc);
if (tot_bytes_read != fileinfo.st_size) { if ((tot_bytes_read[0] != fileinfo[0].st_size) || (!legacy_mode && (tot_bytes_read[2] != fileinfo[1].st_size))) {
printf("Incorrect size output file\n"); printf("Incorrect size input data read\n");
return -1; return -1;
} }
printf("version %u.%u%s%s: %u bytes\n", fw_version_major, fw_version_minor, (argc == 4) ? "-" : "", hdrbuf+6, fileinfo.st_size); printf("version %u.%u%s%s: %u bytes\n", fw_version_major, fw_version_minor, (argc == 4+2*!legacy_mode) ? "-" : "", hdr.version_suffix, tot_bytes_read[0]+tot_bytes_read[1]+tot_bytes_read[2]);
printf("Header CRC32: %.8x\n", hdr_crc); printf("Header CRC32: %.8x\n", htobe32(hdr.hdr_crc));
printf("Data CRC32: %.8x\n", crc); printf("Data CRC32: %.8x\n", htobe32(hdr.data_crc));
bytes_written = write(fd_o, hdrbuf, HDR_SIZE); bytes_written = write(fd_o, &hdr, HDR_SIZE);
if (bytes_written != HDR_SIZE) { if (bytes_written != HDR_SIZE) {
printf("Couldn't write output file\n"); printf("Couldn't write output file\n");
return -1; return -1;
} }
tot_bytes_read = 0; tot_bytes_read[0] = 0;
lseek(fd_i, 0, SEEK_SET); lseek(fd_i[0], 0, SEEK_SET);
while ((bytes_read = read(fd_i, rdbuf, BUF_SIZE)) > 0) { while ((bytes_read = read(fd_i[0], rdbuf, BUF_SIZE)) > 0) {
bytes_written = write(fd_o, rdbuf, bytes_read); bytes_written = write(fd_o, rdbuf, bytes_read);
if (bytes_written != bytes_read) { if (bytes_written != bytes_read) {
printf("Couldn't write output file\n"); printf("Couldn't write output file\n");
return -1; return -1;
} }
tot_bytes_read += bytes_read; tot_bytes_read[0] += bytes_read;
} }
if (tot_bytes_read != fileinfo.st_size) { if (tot_bytes_read[0] != fileinfo[0].st_size) {
printf("Incorrect size output file\n"); printf("Incorrect size output file\n");
return -1; return -1;
}
if (!legacy_mode) {
memset(rdbuf, 0xff, sizeof(rdbuf));
while (tot_bytes_read[1] > 0) {
bytes_read = (tot_bytes_read[1] > sizeof(rdbuf)) ? sizeof(rdbuf) : tot_bytes_read[1];
bytes_written = write(fd_o, rdbuf, bytes_read);
if (bytes_written != bytes_read) {
printf("Couldn't write output file\n");
return -1;
}
tot_bytes_read[1] -= bytes_read;
}
tot_bytes_read[2] = 0;
lseek(fd_i[1], 0, SEEK_SET);
while ((bytes_read = read(fd_i[1], rdbuf, BUF_SIZE)) > 0) {
bitswap8_buf(rdbuf, bytes_read);
bytes_written = write(fd_o, rdbuf, bytes_read);
if (bytes_written != bytes_read) {
printf("Couldn't write output file\n");
return -1;
}
tot_bytes_read[2] += bytes_read;
}
if (tot_bytes_read[2] != fileinfo[1].st_size) {
printf("Incorrect size output bin file\n");
return -1;
}
} }
printf("Firmware image written to %s\n", fw_bin_name); printf("Firmware image written to %s\n", fw_bin_name);
close(fd_o); close(fd_o);
close(fd_i); close(fd_i[0]);
if (!legacy_mode)
close(fd_i[1]);
return 0; return 0;
} }