Общий порядок прошивки описан в Documentation/fpga/debugfs.txt. Просто заполняете файлы "flags", "config_complete_timeout_us". Потом на выбор: либо пишите путевое имя файла в "firmware_name", либо записываете вручную сам файлик прошивки в "image". В первом случае, обратите внимание, файл должен лежать в /lib/firmware, и его путевое имя начинается именно с этого пути. По сути ничего сложного, вот моя версия кода загрузки прошивки:
Файл прошивки храню где мне удобно, потом создаю симлинк в /lib/firmware. После заполняю указанные файлы. После заполнения файла "firmware_name" загрузка прошивки начинается автоматически.
Код
struct fw_names
{
//! абсолютное путевое имя файла прошивки
char* storage_fw_file;
//! абсолютный путь к директории прошивок с которой работает ядреный
// фреймворк
char* fw_path;
//! абсолютное путевое имя ссылки на файл прошивки
char* fw_path_file;
/*! путевое имя символлльной ссылки на файл прошивки относительно
* /lib/firmware
*/
char* fw_framework_dir;
//! структура флагов слежения за выделением памяти
struct
{
uint8_t storage_fw_file : 1;
uint8_t fw_path : 1;
uint8_t fw_path_file : 1;
uint8_t fw_framework_dir : 1;
uint8_t : 4;
} allocated_mask;
};
/*! путевое имя файла конфигурации флагов для прошивки FPGA в ядре 4.x */
#define DFS_FLAG_NAME \
"/sys/kernel/debug/fpga_manager/fpga0/flags"
/*! путевое имя файла конфигурации таймаута для прошивки FPGA в ядре 4.x */
#define DFS_TIMEOUT_NAME \
"/sys/kernel/debug/fpga_manager/fpga0/config_complete_timeout_us"
/*! путевое имя файла прошивки для прошивки FPGA в ядре 4.x */
#define DFS_FIRMWARE_NAME \
"/sys/kernel/debug/fpga_manager/fpga0/firmware_name"
/*! значение флага для конфигурации fpgamngr в ядре 4.x */
#define FLAG_STATE "2"
/*! значение таймера для конфигурации fpgamngr в ядре 4.x */
#define TIMEOUT_VAL "5"
/* псевдокод назначения имен */
struct fw_names fw_names;
/*
* расположение файла прошивки в файловой системе/ У меня он лежит в
* директории /boot
*/
fw_names.storage_fw_file = "/boot/your_wirmware_name.rbf";
/*
* путь к директории в которую надо положить файлик прошивки для того чтоб
* ядро нашло нашу файл. Директория "your_dir" - Ваша собственная, можно,
* конечно, без нее, просто кинуть файл прошивки непосредственно в
* /lib/firmware/
*/
fw_names.fw_path = "/lib/firmware/your_dir/";
fw_names.fw_path_file = "/lib/firmware/your_dir/";
fw_names.fw_framework_dir = "your_dir/your_wirmware_name.rbf";
/*****************************************************************************/
/*!
* \brief Функция записывает указанную строку в файл.
*
* \param [in] in_string Записываемая строка
* \param [in] len_string Длина записываемой строки
* \param [in] file_str Указатель на файловый поток
*
* \retval SLOGG_SUCCESS | SLOGG_EWRITE
*/
/*****************************************************************************/
int write_string2file_str(
const char* in_string,
size_t len_string,
FILE* file_str
)
{
int ret_value;
ret_value = fwrite(
in_string,
len_string,
1,
file_str
);
if(!ret_value)
{
ret_value = SLOGG_EWRITE;
#ifdef DEBUG_MODE
slogger_print(
"Не удалось записать строку %s в файловый поток",
in_string
);
#endif /* DEBUG_MODE */
}
return(SLOGG_SUCCESS);
}
/*****************************************************************************/
/*!
* \brief Функция осуществляет загрузку прошивки в FPGA manager через debugfs
* используемую начитная с 4.x версии ядра
*
* \param [in] fw_names Стукрура c именами файлов прошивки, управления
* FPGA mngr.
*/
/*****************************************************************************/
int load_fpga_image_over_dbfs(
struct fw_names* fw_names
)
{
int ret_value;
FILE* flag_str;
FILE* timeout_str;
FILE* firmware_name_str;
/*
* Следуя алгортму работы с ядреным фреймворком файлы с прошивками должны
* находится в директории /lib/firmware. Создадим суб-директорию и
* символьные ссылки на файлы прошивки
*/
ret_value = mkdir(
fw_names->fw_path,
0600
);
if(ret_value && errno != EEXIST)
{
slogger_wrerr(
"mkdir: ",
errno,
strerror
);
ret_value = SLOGG_ERET;
goto close_firm_loader;
}
ret_value = symlink(
fw_names->storage_fw_file,
fw_names->fw_path_file
);
if(ret_value && errno != EEXIST)
{
slogger_wrerr(
"symlink: ",
errno,
strerror
);
ret_value = SLOGG_ERET;
goto close_firm_loader;
}
flag_str = fopen(
DFS_FLAG_NAME,
"w"
);
if(!flag_str)
{
slogger_wrerr(
"fopen(flag_str): ",
errno,
strerror
);
ret_value = SLOGG_ERET;
goto close_firm_loader;
}
timeout_str = fopen(
DFS_TIMEOUT_NAME,
"w"
);
if(!timeout_str)
{
slogger_wrerr(
"fopen(timeout_str): ",
errno,
strerror
);
ret_value = SLOGG_ERET;
goto close_flag_str;
}
firmware_name_str = fopen(
DFS_FIRMWARE_NAME,
"w"
);
if(!firmware_name_str)
{
slogger_wrerr(
"fopen(firmware_name_str): ",
errno,
strerror
);
ret_value = SLOGG_ERET;
goto close_timeout_str;
}
/* Запишем флаги */
ret_value = write_string2file_str(
FLAG_STATE,
sizeof(FLAG_STATE),
flag_str
);
if(ret_value != SLOGG_SUCCESS)
{
goto close_firmware_name_str;
}
/* Запишем значение таймера */
ret_value = write_string2file_str(
TIMEOUT_VAL,
sizeof(TIMEOUT_VAL),
timeout_str
);
if(ret_value != SLOGG_SUCCESS)
{
goto close_firmware_name_str;
}
/* Запишем имя файла прошивки */
ret_value = write_string2file_str(
fw_names->fw_framework_dir,
MAX_LEN_OF_NAME,
firmware_name_str
);
if(ret_value != SLOGG_SUCCESS)
{
goto close_firmware_name_str;
}
ret_value = SLOGG_SUCCESS;
close_firmware_name_str:
fclose(firmware_name_str);
close_timeout_str:
fclose(timeout_str);
close_flag_str:
fclose(flag_str);
close_firm_loader:
return(ret_value);
}