Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: как записать параметр во Flash МК?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
NikP

В процессе разработки появилась идея сохранять параметры (состояние перед выключением устройства) во Flash контроллера. Контроллер Миландровский 1986ВЕ1Т (аналог STM - F103).
В описании МК сказано, что при работе с Flash МК программа из неё выполняться не может, значит надо поместить некий обработчик( загрузчик ) в оперативку , записать то что надо, и снова отдавать управление основной программе.
Из описания МК я понял, что основная программа размещается с адреса 0х00000000 по 0х00100000, а для загрузчика можно использовать адреса 0х20100000 по 0х20104000.

К сожалению, программист из меня , мягко говоря, чуть ниже среднего. Поэтому просьба подсказать следующее:
1. Как можно в Кейле скомпилировать модуль (загрузчик), который можно целиком записать в нужную область SRAM? ( Сделать его как функцию?)
2. Как этот модуль загрузить в нужную область памяти ? ( конкретно - с адреса 0х20100000) и запустить его?
3. Как из модуля передать управление основной программе?
4. Может есть другие варианты решения данной задачи?

Олег Гаврильченко
Здравствуйте. Я, к сожалению, не работал с МК Миландр, деталей их устройства я не знаю. Но я программирую микроконтроллеры STM ARM ST32F4x и STM32F1x. И для них я я решал ту же задачу, записывал настройки во Flash память. Я опишу, как я делал это у себя. Flash память МК поделена на сектора разного размера(16, 32, 64 Кбайт) Стереть можно только сектор целиком. В Reference Manual не ясно написано, должна ли программа при записи во flash выполняться из SRAM или просто из другого Flash сектора. Я посмотрел примеры от ST, в них в SRAM ничего не записывалось и процедура стирания Flash была записана просто в другой Flash сектор. Я так и делаю у себя и это работает.
То есть, если я стираю/записываю сектор 10, то программа может выполнятся из Flash, но не в секторе 10.
Вот пример того, как я стираю/записываю flash у себя в STM32F4x

CODE
/**
* @brief Запись блока во flash
* @dst Адрес назначения(куда копировать)
* @src Адрес источника(откуда копировать)
* @num Кол-во байт для копирования
* @retval dst
*/
void* flash_memcpy(void* dst, void* src, int num)
{
int i;

irq_disable();

FLASH_Unlock();

for(i = 0; i < num; i++)
{
FLASH_ProgramByte((uint32_t)(dst) + i,
((uint8_t*)src)[i]);
FLASH_WaitForLastOperation();
}

FLASH_Lock();

irq_enable();

return dst;
}

/**
* @brief Стереть содержимое flash-памяти
*/
void flash_erase(void)
{
irq_disable();
FLASH_Unlock();

FLASH_EraseSector(FLASH_Sector_11, VoltageRange_3);

FLASH_Lock();

irq_enable();
}


Если же Вам все же нужно выполнять программу из SRAM, то в Keil проще всего воспользоваться функциональностью scatter/loader, например, как описано вот здесь. http://www.keil.com/support/docs/3723.htm
esaulenka
Цитата(Олег Гаврильченко @ May 10 2017, 12:07) *
Но я программирую микроконтроллеры STM

А я тут как-то атмегу вспоминал. Интерфейс программирования атмеги похож на миландровский примерно так же, как и STM'овский - никак.

А в данном случае надо определиться с терминологией, слегка почитать документацию и чуть-чуть погуглить.

Загрузчик, или bootloader - программа, стартующая при запуске процессора. В нормальном режиме просто запускает основную программу, в режиме обновления получает откуда-то извне и перезаписывает основную программу.

А тут нужно просто написать свои функции стирания и записи страницы флеши (последовательность действий расписана в документации), поместить их в ОЗУ (да, присвоив им нужные атрибуты и отредактировав скаттер; дальше кейл всё сделает сам).
Ну и саму структуру с настройками надо придумать. И методику предусмотреть на случай "мы включились, а в прошлый раз вместо настроек какой-то мусор записался".

И ещё можно вот сюда подсматривать: http://forum.milandr.ru/viewtopic.php?f=34...tart=300#p11419
HardEgor
Цитата(NikP @ May 10 2017, 15:03) *
В процессе разработки появилась идея сохранять параметры (состояние перед выключением устройства) во Flash контроллера. Контроллер Миландровский 1986ВЕ1Т (аналог STM - F103).
В описании МК сказано, что при работе с Flash МК программа из неё выполняться не может, значит надо поместить некий обработчик( загрузчик ) в оперативку , записать то что надо, и снова отдавать управление основной программе.

Ничего такого не надо.
Надо просто подпрограмму записи во Flash разместить в RAM, в Keil это ключевое слово _RAMFUNC.. И при её вызове из основной программы запретить прерывания. При возврате - прерывания разрешить.
Примеры можно посмотреть в SPL( в файле MDR32F9Qx_eeprom.c) , который можно скачать здесь
ivan24190
NikP, либо можно создать отдельный файл например, "RamFunc.c", в котором написать функцию записи данных во Flash, а потом правой кнопкой мыши по этому файлу в дереве проекта: выбрать поле < Options for File "RamFunc.c" >, и в открывшемся окне найти метку < Memory Assignment > под которой три поля, нужно выбрать поле < Code / Const > и уже в нем выставить месторасположение данной функции в RAM, например, IRAM1 [0x20000000-0x20001FFFF].
Затем все скомпилировать. При вызове данной функции она будет исполняться из RAM.
NikP
Всем большое спасибо за дельные советы!
linuxbergi
Что-то я не понял. Зачем SRAM? Пиши в свободную флэш из программы, там имеется контроллер внутренней флэш, у него регисты флаги, записывай читай.
etoja
Программа программирования флеш-памяти Миландра должна выполняться в ОЗУ.
ViKo
А как код функции попадет в ОЗУ? Что и когда скопирует этот код из флэш-памяти? Я с таким делом не сталкивался, интересуюсь. Может, компилятор сам сделает? После сброса.
Kibi
Ну к примеру __ramfunc void flash_write(unsigned int address, unsigned int *pBuffer,unsigned int command)
ключевое слово __ramfunc говорит о том, что линкер разместит функцию в RAM, по адресу рам.
Фактически в рам нужно разместить только запись команды в регистр работы с флешем и ожидания снятия флага записи.
adnega
Цитата(ViKo @ Aug 18 2017, 09:21) *
А как код функции попадет в ОЗУ? Что и когда скопирует этот код из флэш-памяти? Я с таким делом не сталкивался, интересуюсь. Может, компилятор сам сделает? После сброса.

Компилятор и линкер все сделают с необходимыми адресами.
Перед вызовом main делается инициализация переменных (data и bss).
В этот момент подготовленный для ОЗУ код скопируется из flash по нужным адресам ОЗУ.
Для этого в скрипте линкера дополняем секцию data
Код
    .data : AT ( _sidata )
    {
        . = ALIGN(4);
        _sdata = .;
        *(.data)
        *(.data.*)
        *(.ramfunc)
        . = ALIGN(4);
        _edata = .;
    } >RAM

А ОЗУ-шные функции описываем так (для gcc)
Код
void ram_table_save(void) __attribute__(( section(".ramfunc") ));
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.