Радиотехнический сайт RADIOTRACT

Радиотехника и электроника для разработчиков и радиолюбителей

Информация

 

 

Справочные данные на радиоэлектронные компоненты, приборы, средства связи и измерений. Радиотехническая литература.

Общая

Микроконтроллеры

ПЛИС

Измерения

Радиостанции

Библиотека

Справочники

Доска объявлений

Объявления о покупке и продаже радиокомпонентов. Спрос и предложение на различные радиодетали и приборы.

Куплю

Продам

Магазин

Программы

Полезные программы для радиолюбителей и разработчиков радиоэлектроники.

Радиотехника

Интернет

Калькуляторы

Другие

Мы в соцсетях

  

ПЛИС

ПЛИС\Удаленная прошивка ПЛИС\Драйвер Remote Update System

Драйвер Remote Update System для процессора NIOS

//****************************************** //****************************************** // Драйвер Remote Update System // Devices: Arria GX, Stratix II, Stratix II GX, Stratix III, Cyclone III, Cyclone IV // Configuration Mode: Active Serial (AS) //****************************************** //****************************************** // Описание аргументов функций //****************************************** // s2_ru_base_addr - Базовый адрес регистров управления // s2_ru_num_par - Номер параметра // s2_ru_val_par - Значение параметра // s2_ru_wdt_tomeout - Значение тайм-аута сторожевого таймера = s2_ru_wdt_tomeout * 2^17 // В функции S2Ru_TryReconfigToApplication, если s2_ru_wdt_tomeout равен 0, то сторожевой таймер не используется. // s2_ru_config_page - Биты адреса страницы памяти // s2_ru_config_mode - Признак типа прошивки (0 - Factory, 1 - Application) // ru_addr_reconfig - Адрес Application-прошивки, которую требуется загрузить: // Для Arria GX, Stratix II, Stratix II GX : StartAddress[23..0] = {1'b0, PGM[6..0], 16'b0} // Для Stratix III : StartAddress[23..0] = {PGM[23..0]} // Для Cyclone III : StartAddress[23..0] = {PGM[21..0], 2'b0} // где PGM[] - значение, загружаемое в регистр (передаваемое через переменную ru_addr_reconfig) // eeprom_status_config_addr - адрес байта-признака прошивки в памяти EEPROM // epcs_application_config_addr - Адрес Application-прошивки, которую требуется загрузить (идентичен описанию аргумента ru_addr_reconfig) // ru_wdt_timeout - Значение тайм-аута сторожевого таймера (идентичен описанию аргумента s2_ru_wdt_tomeout) //****************************************** // Parameters //****************************************** //Глобальные параметры #define RU_STRATIX_II 1 #define RU_STRATIX_II_GX 1 #define RU_ARRIA_GX 1 #define RU_STRATIX_III 2 #define RU_CYCLONE_III 3 #define RU_CYCLONE_IV 4 #include "main.h" //Можно отключить, если не используется драйвер EEPROM как в примере ниже (если не определено USE_RU_CONFIG_LIB1) //Настройки драйвера #ifndef RU_DEVICE_FAMILY //Если не задано семейство ПЛИС, по умолчанию используется Stratix II #define RU_DEVICE_FAMILY RU_STRATIX_II #endif //#define USE_RU_CONFIG_LIB1 - Использовать библиотеку готовых функций (требуется наличие драйвера EEPROM) //#define ENABLE_NSTATUS_CHECKING - признать ошибкой, если nSTATUS активирован внешним устройством как результат ошибки //#define ENABLE_LOGIC_CHECKING - признать ошибкой, если текущая конфигурация была инициирована логикой //#define ENABLE_NCONFIG_CHECKING - признать ошибкой, если текущая конфигурация была инициирована внешним сбросом (выводом nCONFIG) //Настройки контроллера #define NUM_PARAMETERS 8 #define ADDR_PARAMETERS 0 #define ADDR_PAR_SPAN (NUM_PARAMETERS-ADDR_PARAMETERS) #define ADDR_FLAG_STATUS 8 #define MASK_RU_DATA 0x7FFFFFFF #define MASK_RU_BUSY 0x80000000 #define FLAG_RU_READY 0 #define FLAG_RU_BUSY 1 #define SET_BIT_WDT_RESET 1 #define SET_BIT_RECONFIG 2 // Global Variables alt_u32 s2_ru_base_addr; // Регистрация драйвера и инициализация inline void S2Ru_InitDriver(alt_u32 s2_ru_base_address) { s2_ru_base_addr = s2_ru_base_address; return; } // Чтение регистра статуса inline alt_u32 S2Ru_GetStatus(void) { alt_u32 temp_var1 = IORD(s2_ru_base_addr,ADDR_FLAG_STATUS); return temp_var1; } // Ожидание готовности контроллера inline void S2Ru_WaitForReady(void) { alt_u32 temp_var1 = 0xFFFFFFFF; while (temp_var1 != 0) { temp_var1 = IORD(s2_ru_base_addr,ADDR_FLAG_STATUS); temp_var1 = temp_var1 & MASK_RU_BUSY; } return; } // Чтение параметра alt_u32 S2Ru_ReadParameter(alt_u32 s2_ru_num_par) { if (s2_ru_num_par > ADDR_PAR_SPAN) //проверка на допустимый диапазон номера параметра s2_ru_num_par = ADDR_PAR_SPAN; S2Ru_WaitForReady(); alt_u32 s2_ru_val_par = IORD(s2_ru_base_addr,s2_ru_num_par); S2Ru_WaitForReady(); s2_ru_val_par = IORD(s2_ru_base_addr,ADDR_FLAG_STATUS); s2_ru_val_par = s2_ru_val_par & MASK_RU_DATA; return s2_ru_val_par; } // Запись параметра void S2Ru_WriteParameter(alt_u32 s2_ru_num_par,alt_u32 s2_ru_val_par) { if (s2_ru_num_par > ADDR_PAR_SPAN) //проверка на допустимый диапазон номера параметра s2_ru_num_par = ADDR_PAR_SPAN; S2Ru_WaitForReady(); IOWR(s2_ru_base_addr,s2_ru_num_par,s2_ru_val_par); return; } // Сброс сторожевого таймера inline void S2Ru_ResetWDT(void) { //Перед сбросом WDT готовность можно не проверять IOWR(s2_ru_base_addr,ADDR_FLAG_STATUS,SET_BIT_WDT_RESET); return; } // Запуск реконфигурации inline void S2Ru_Reconfig(void) { S2Ru_WaitForReady(); IOWR(s2_ru_base_addr,ADDR_FLAG_STATUS,SET_BIT_RECONFIG); return; } // Определение причины реконфигурации // Бит 0: crcerror_source: произошла ошибка CRC прикладной конфигурации // Бит 1: nstatus_source: nSTATUS активирован внешним устройством как результат ошибки // Бит 2: runconfig_source: конфигурация была инициирована массивом логики // Бит 3: nconfig_source: конфигурация была инициирована внешним сбросом (выводом nCONFIG) // Бит 4: wdtimer_source: тайм-аут пользовательского сторожевого таймера #if RU_DEVICE_FAMILY == RU_CYCLONE_III inline alt_u32 S2Ru_GetSourceOfReconfig(void) { alt_u32 temp_var1 = S2Ru_ReadParameter(7); temp_var1 = temp_var1 & 0x0000001F; switch (temp_var1) { case 0: temp_var1 = 2; break; case 1: temp_var1 = 4; break; case 2: temp_var1 = 1; break; case 3: temp_var1 = 0; break; case 4: temp_var1 = 3; break; default: break; } return temp_var1; } #else inline alt_u32 S2Ru_GetSourceOfReconfig(void) { alt_u32 temp_var1 = S2Ru_ReadParameter(0); temp_var1 = temp_var1 & 0x0000001F; return temp_var1; } #endif // Чтение значения тайм-аута сторожевого таймера inline alt_u32 S2Ru_GetTimeoutWDT(void) { alt_u32 temp_var1 = S2Ru_ReadParameter(2); temp_var1 = temp_var1 & 0x00000FFF; return temp_var1; } // Установка значения тайм-аута сторожевого таймера // Значение тайм-аута сторожевого таймера имеет разрядность 12 бит, // старшие разряды игнорируются inline void S2Ru_SetTimeoutWDT(alt_u32 s2_ru_wdt_tomeout) { s2_ru_wdt_tomeout = s2_ru_wdt_tomeout & 0x00000FFF; S2Ru_WriteParameter(2,s2_ru_wdt_tomeout); return; } // Чтение значения флага разрешения работы сторожевого таймера inline alt_u32 S2Ru_GetEnableFlagWDT(void) { alt_u32 temp_var1 = S2Ru_ReadParameter(3); temp_var1 = temp_var1 & 0x00000001; return temp_var1; } // Разрешение работы сторожевого таймера inline void S2Ru_EnableWDT(void) { S2Ru_WriteParameter(3,1); return; } // Запрет работы сторожевого таймера inline void S2Ru_DisableWDT(void) { S2Ru_WriteParameter(3,0); return; } // Выбор страницы памяти // Для AS Configuration Devices - разрядность 7, биты [6..0] формируют биты [22..16] 24-битного стартового адреса, // другие 17 бит установлены в 0. // Для Enhanced Configuration Devices - разрядность 3. inline void S2Ru_SetConfigPage(alt_u32 s2_ru_config_page) { S2Ru_WriteParameter(4,s2_ru_config_page); return; } // Получение статуса конфигурационной прошивки // 0 - Factory (заводская, базовая прошивка) // 1 - Application (прикладная, рабочая прошивка) // 3 - Application с включенным сторожевым таймером (только для Cyclone III и Cyclone IV) #if RU_DEVICE_FAMILY == RU_CYCLONE_III || RU_DEVICE_FAMILY == RU_CYCLONE_IV inline alt_u32 S2Ru_GetConfigMode(void) { alt_u32 temp_var1 = S2Ru_ReadParameter(0); temp_var1 = temp_var1 & 0x00000003; return temp_var1; } #else inline alt_u32 S2Ru_GetConfigMode(void) { alt_u32 temp_var1 = S2Ru_ReadParameter(5); temp_var1 = temp_var1 & 0x00000001; return temp_var1; } #endif // Установка статуса конфигурационной прошивки // 0 - Factory (заводская, базовая прошивка) // 1 - Application (прикладная, рабочая прошивка) // Рекомендуется его установить в "1" перед загрузкой страницы Application-прошивки inline void S2Ru_SetConfigMode(alt_u8 s2_ru_config_mode) { S2Ru_WriteParameter(5,s2_ru_config_mode); return; } // Принудительная досрочная проверка CONF_DONE (Cd_early) - Только для Cyclone III и Cyclone IV #if RU_DEVICE_FAMILY == RU_CYCLONE_III || RU_DEVICE_FAMILY == RU_CYCLONE_IV inline alt_u8 C2Ru_GetConfDoneStatus(void) { alt_u32 temp_var1 = S2Ru_ReadParameter(1); temp_var1 = temp_var1 & 0x00000001; return temp_var1; } #endif //****************************************** // Библиотека функций удаленного конфигурирования //****************************************** // Проверка текущей конфигурации. Если Factory и не было ошибок загрузки (т.е. это первая загрузка с момента включения), // то инициировать загрузку конфигурации Application, иначе ничего не делать и выдать статус. // Если s2_ru_wdt_tomeout равен 0, то сторожевой таймер не используется и отключен. // Функция возвращает статус - причину невозможности загрузки Application-конфигурации: // 0 - Реконфигурация не произошла, т.к. текущая конфигурация уже является Application // 1 - Реконфигурация инициирована функцией, но по какой-то причине не произошла (аппаратные проблемы); // 2 - Произошла ошибка CRC Application-конфигурации; // 3 - nSTATUS активирован внешним устройством как результат ошибки (при предопределённом параметре ENABLE_NSTATUS_CHECKING); // 4 - Текущая конфигурация была инициирована логикой (при предопределённом параметре ENABLE_LOGIC_CHECKING); // 5 - Текущая конфигурация была инициирована внешним сбросом (выводом nCONFIG) (при предопределённом параметре ENABLE_NCONFIG_CHECKING) // 6 - Текущая конфигурация была инициирована по тайм-ауту пользовательского сторожевого таймера #if RU_DEVICE_FAMILY == RU_CYCLONE_III //Для Cyclone III alt_u32 S2Ru_TryReconfigToApplication(alt_u32 ru_addr_reconfig,alt_u32 s2_ru_wdt_tomeout) { alt_u32 ru_status; alt_u32 ru_enable_reconfig = 0; alt_u32 ru_temp_var2 = S2Ru_GetConfigMode(); if (ru_temp_var2 == 0) //Factory { ru_temp_var2 = S2Ru_GetSourceOfReconfig(); ru_status = ru_temp_var2 + 2; //т.к. коды статуса ровно на 2 больше возвращаемых функцией S2Ru_GetSourceOfReconfig значений ru_enable_reconfig = 1; if (ru_temp_var2 == 0) ru_enable_reconfig = 0; #ifdef ENABLE_NSTATUS_CHECKING if (ru_temp_var2 == 1) ru_enable_reconfig = 0; #endif #ifdef ENABLE_LOGIC_CHECKING if (ru_temp_var2 == 2) ru_enable_reconfig = 0; #endif #ifdef ENABLE_NCONFIG_CHECKING if (ru_temp_var2 == 3) ru_enable_reconfig = 0; #endif if (ru_temp_var2 == 4) ru_enable_reconfig = 0; if (ru_enable_reconfig == 1) { S2Ru_WriteParameter(1,0); //Не использовать принудительную досрочную проверку CONF_DONE S2Ru_WriteParameter(6,0); //Не использовать внутренний тактовый генератор в качестве тактов машины состояний S2Ru_SetConfigPage(ru_addr_reconfig); //Выбор страницы памяти c Application-конфигурацией if (s2_ru_wdt_tomeout == 0) { S2Ru_DisableWDT(); } else { S2Ru_SetTimeoutWDT(s2_ru_wdt_tomeout); //Установка тайм-аута WDT S2Ru_ResetWDT(); S2Ru_EnableWDT(); } ru_status = 1; S2Ru_Reconfig(); } } else //Application { ru_status = 0; } return ru_status; } #elif RU_DEVICE_FAMILY == RU_CYCLONE_IV //Для Cyclone IV alt_u32 S2Ru_TryReconfigToApplication(alt_u32 ru_addr_reconfig,alt_u32 s2_ru_wdt_tomeout) { alt_u32 ru_status; alt_u32 ru_enable_reconfig = 0; alt_u32 ru_temp_var2 = S2Ru_GetConfigMode(); if (ru_temp_var2 == 0) //Factory { ru_temp_var2 = S2Ru_GetSourceOfReconfig(); ru_status = ru_temp_var2 + 2; //т.к. коды статуса ровно на 2 больше возвращаемых функцией S2Ru_GetSourceOfReconfig значений ru_enable_reconfig = 1; if (ru_temp_var2 == 0) ru_enable_reconfig = 0; #ifdef ENABLE_NSTATUS_CHECKING if (ru_temp_var2 == 1) ru_enable_reconfig = 0; #endif #ifdef ENABLE_LOGIC_CHECKING if (ru_temp_var2 == 2) ru_enable_reconfig = 0; #endif #ifdef ENABLE_NCONFIG_CHECKING if (ru_temp_var2 == 3) ru_enable_reconfig = 0; #endif if (ru_temp_var2 == 4) ru_enable_reconfig = 0; if (ru_enable_reconfig == 1) { S2Ru_WriteParameter(1,0); //Не использовать принудительную досрочную проверку CONF_DONE S2Ru_WriteParameter(6,0); //Не использовать внутренний тактовый генератор в качестве тактов машины состояний S2Ru_SetConfigPage(ru_addr_reconfig); //Выбор страницы памяти c Application-конфигурацией if (s2_ru_wdt_tomeout == 0) { S2Ru_DisableWDT(); } else { S2Ru_SetTimeoutWDT(s2_ru_wdt_tomeout); //Установка тайм-аута WDT S2Ru_ResetWDT(); S2Ru_EnableWDT(); } ru_status = 1; S2Ru_Reconfig(); } } else //Application { ru_status = 0; } return ru_status; } #else //Для остальных alt_u32 S2Ru_TryReconfigToApplication(alt_u32 ru_addr_reconfig,alt_u32 s2_ru_wdt_tomeout) { alt_u32 ru_status; alt_u32 ru_enable_reconfig = 0; alt_u32 ru_temp_var2 = S2Ru_GetConfigMode(); if (ru_temp_var2 == 0) //Factory { ru_temp_var2 = S2Ru_GetSourceOfReconfig(); ru_status = ru_temp_var2 + 2; //т.к. коды статуса ровно на 2 больше возвращаемых функцией S2Ru_GetSourceOfReconfig значений ru_enable_reconfig = 1; if (ru_temp_var2 == 0) ru_enable_reconfig = 0; #ifdef ENABLE_NSTATUS_CHECKING if (ru_temp_var2 == 1) ru_enable_reconfig = 0; #endif #ifdef ENABLE_LOGIC_CHECKING if (ru_temp_var2 == 2) ru_enable_reconfig = 0; #endif #ifdef ENABLE_NCONFIG_CHECKING if (ru_temp_var2 == 3) ru_enable_reconfig = 0; #endif if (ru_temp_var2 == 4) ru_enable_reconfig = 0; if (ru_enable_reconfig == 1) { S2Ru_SetConfigMode(1); //Установка признака Application-конфигурации S2Ru_SetConfigPage(ru_addr_reconfig); //Выбор страницы памяти c Application-конфигурацией if (s2_ru_wdt_tomeout == 0) { S2Ru_DisableWDT(); } else { S2Ru_SetTimeoutWDT(s2_ru_wdt_tomeout); //Установка тайм-аута WDT S2Ru_ResetWDT(); S2Ru_EnableWDT(); } ru_status = 1; S2Ru_Reconfig(); } } else //Application { ru_status = 0; } return ru_status; } #endif //************************************************************************* // Пример использования в универсальной конфигурации (Factory/Application) //************************************************************************* // В EEPROM хранится байт-признак: // 0xFF - Application-конфигурация отсутствует // 0x00 - Application-конфигурация имеется, но ещё не запускалась ни разу (не проверена на работоспособность) // 0x01 - Application-конфигурация имеется и уже успешно запускалась (работоспособна) // 0x02 - Application-конфигурация имеется, но не работоспособна (была неуспешная попытка запуска) - код может быть замененн на 0xFF // // ********** Менеджер конфигураций (Factory/Application - универсальная конфигурация) ********** // Код вставляется после инициализации и перед основным циклом программы (до разрешения прерываний) #ifdef USE_RU_CONFIG_LIB1 void Ru_CheckAndLoadApplication(eeprom_status_config_addr,epcs_application_config_addr,ru_wdt_timeout) { ReadEeprom(eeprom_status_config_addr,1); //Чтение из EEPROM статуса (байта-признака) alt_u32 status_config = EepromReadBuffer(0); if ((status_config == 0) || (status_config == 1)) //если имеется Application-прошивка, то попытаться её загрузить { alt_u32 reconfig_res = S2Ru_TryReconfigToApplication(epcs_application_config_addr,ru_wdt_timeout); if ((reconfig_res == 0) && (status_config == 0)) //если текущая конфигурация - Application и это её первый запуск, то обновить байт-признак в EEPROM { EepromWriteToBuffer(0,0x01); //Запись в EEPROM признака "0x01" WriteEeprom(eeprom_status_config_addr,1); } if (reconfig_res != 0) //Ошибка реконфигурации { EepromWriteToBuffer(0,0xFF); //Запись в EEPROM признака "0xFF" WriteEeprom(eeprom_status_config_addr,1); } } return; //нормальный выход из программы, если заглужена Application-конфигурация или её не удалось загрузить } #endif // Перед началом записи в EPCS-конфигуратор новой Application-конфигурации, в EEPROM по адресу eeprom_status_config_addr // записывается код 0xFF. Далее производится запись в EPCS-конфигуратор новой Application-конфигурации. // После успешной записи в EEPROM по адресу eeprom_status_config_addr записывается код 0x00. // После этого, если требуется загрузка новой конфигурации, выполняется команда сброса. //************************************************************


Комментарии

comments powered by Disqus