tathagata 0 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба МК — MDR32F1QI. Необходимо в EEPROM особым образом подготовить две области: Страница (0x1F000) для счетчика ресурсов. При разметке должна быть инициализирована единицами, что в принципе уже делает Erase Full Chip. Страница (0x1E000) для хранения нескольких настроек. При разметке должна быть инициализирована нулями. Счетчик ресурсов работает по принципу ежеминутного обнуления очередного бита выделенной страницы — для этого и необходимо ее инициализировать единицами. Доступ к значениям настроек сейчас сделан так: #define ADDR_SETTINGS 0x0001E000 int32_t dat1_ __attribute__((at(ADDR_SETTINGS))); int32_t dat2_ __attribute__((at(ADDR_SETTINGS + 4))); uint32_t dat3_ __attribute__((at(ADDR_SETTINGS + 8))); // Переменые, хранящие эти значение в ходе работы программы. int32_t dat1; int32_t dat2; uint32_t dat3; // Считываение значений переменных из EEPROM при старте программы. void read_settings() { dat1 = dat1_; dat2 = dat2_; dat1 = dat3_; } // Запись измененных значений переменных в EEPROM void update_settings() { __disable_irq(); EEPROM_ErasePage(ADDR_SETTINGS, EEPROM_Main_Bank_Select); EEPROM_ProgramWord(&dat1_, EEPROM_Main_Bank_Select, dat1); EEPROM_ProgramWord(&dat2_, EEPROM_Main_Bank_Select, dat2); EEPROM_ProgramWord(&dat3_, EEPROM_Main_Bank_Select, dat3); // Или записать можно и так, наверное: // EEPROM_ProgramWord(ADDR_SETTINGS, EEPROM_Main_Bank_Select, dat1); // EEPROM_ProgramWord(ADDR_SETTINGS + 4, EEPROM_Main_Bank_Select, dat2); // EEPROM_ProgramWord(ADDR_SETTINGS + 8, EEPROM_Main_Bank_Select, dat3); __enable_irq(); } Ну, а с записью счетчика наработки все аналогично. С той лишь разницей, что при загрузке вычитывается последнее ненулевое слово из соответствующей страницы и по вычесленному адресу пишется измененное значение. Вопрос в том, как в скаттере описать эти две страницы в EEPROM. Сразу скажу, что при перепрошивке МК нет необходимости сохранять старые настройки и наработку (подобная ситуация часто поднимается в обсуждениях) — нужно лишь их нужным образом инициализировать (нулями и единицами соответственно). Сейчас скаттер имеет такой вид: ; ************************************************************* ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************************* LR_IROM1 0x00000000 0x00020000 { ; load region size_region ER_IROM1 0x00000000 0x00020000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00008000 { ; RW data .ANY (+RW +ZI) } RW_IRAM2 0x20100000 0x00004000 { mdr32f9qx_eeprom.o RAMFunction.o (+RO) .ANY (+RW +ZI) } } Подскажите, как его изменить, чтобы указанные страницы при прошивке были инициализированы правильным образом? А также интересует мнение, правильно ли я выбрал подход к доступу к настройкам. Они меняются крайне редко. А при первом запуске (после прошивки) должны вычитываться нулевые значения. При включении устройства EEPROM сразу переводится в программный режим. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 18 ноября, 2022 Опубликовано 18 ноября, 2022 (изменено) · Жалоба просто из практики любая flash или eeprom память при стирании страницы заполняется битами-единичками, а не нулями. 0xFF. Так что может стоит чуть пересмотреть алгоритм с целью избежать избыточного износа ячеек. Можете проверить и почитать содержимое после стирания страницы. Но это так, мысли вслух. Изменено 18 ноября, 2022 пользователем haker_fox Убрал либо ошибочно написанное слово, либо косвенное оскорбление. Если необходимо, автору сообщения предлагаю написать правильно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 31 minutes ago, tathagata said: А также интересует мнение, правильно ли я выбрал подход к доступу к настройкам. Они меняются крайне редко. А при первом запуске (после прошивки) должны вычитываться нулевые значения. Организуйте настройки в виде структуры с magic в начале и CRC в конце. При несовпадении magic или некорректной CRC - установка значений по умолчанию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tgruzd 11 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 8 минут назад, aaarrr сказал: А при первом запуске (после прошивки) должны вычитываться нулевые значения. сделайте инверсию внутри процедур чтения и записи 48 минут назад, tathagata сказал: Сразу скажу, что при перепрошивке МК нет необходимости сохранять старые настройки и наработку (подобная ситуация часто поднимается в обсуждениях) Вы "ресурс" прошивки считаете, да? Типа, "этот код уже достаточно поработал, заменим на другой")) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 12 minutes ago, tgruzd said: сделайте инверсию внутри процедур чтения и записи И не подумаю даже 🙂 Настройки должны иметь CRC, этого достаточно в том числе и для установки начального состояния. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tgruzd 11 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 4 минуты назад, aaarrr сказал: И не подумаю даже 🙂 извиняюсь, не то процитировал. Думал, что цитирую ТСа) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tathagata 0 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 58 минут назад, krux сказал: просто из практики любая flash или eeprom память при стирании страницы заполняется битами-единичками, а не нулями. 0xFF. На этом и основан наш алгоритм подсчета ресурса — я же выше указывал. Эту страницу достаточно просто стереть (заполнить единицами), а потом "гасить" очередные единички, не стирая всю страницу (т. е. без перезаписи). Так что в этом наши с вами подходы схожи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 1 hour ago, krux said: просто из практики любая flash или eeprom память при стирании страницы заполняется битами-единичками, а не нулями. 0xFF. К слову, не всегда так. Среди STM32 серии L есть экземпляры, у которых при стирании память FLASH заполняется нулями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tathagata 0 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 1 час назад, aaarrr сказал: Организуйте настройки в виде структуры с magic в начале и CRC в конце. При несовпадении magic или некорректной CRC - установка значений по умолчанию. Для хранения настроек как раз и не рассматривается необходимости использования контрольной суммы — полагаемся на корректную работу флеша) Вопрос в том, как правильно в скаттере прописать эти две области по заданным адресам, одна из которых (вся страница) будет инициализирована нулями, а вторая (тоже размером в страницу) — единичками. Со второй понятно, что полное стирание памяти перед прошивкой заполняет не инициализируемые другим способом ячейки памяти единицами. Кстати, порядок страниц принципиальной роли не играет (можно 0x1F000 — для счетчика, а 0x1E000 — для настроек, а можно и наоборот). 2 часа назад, tgruzd сказал: Вы "ресурс" прошивки считаете, да? Типа, "этот код уже достаточно поработал, заменим на другой")) Этот момент обсуждается. Разумеется, что правильно было бы отделить мух от котлет. Но тогда придется работать двумя скаттерами (один — для первоначальной прошивки с инициализацией областей хранения данных, а другой — для дальнейших возможных перепрошивок (с сохранением этих самых значений). Я правильно понял? Сейчас интересно хоть какое-то решение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 61 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 13 minutes ago, tathagata said: полагаемся на корректную работу флеша Святая наивность. 15 minutes ago, tathagata said: Но тогда придется работать двумя скаттерами Да хоть 23-мя. Сами стирайте, если значения неправильные. Некоторые умные мысли есть тут https://www.st.com/resource/en/application_note/an4894-eeprom-emulation-techniques-and-software-for-stm32-microcontrollers-stmicroelectronics.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 4 часа назад, tathagata сказал: А также интересует мнение, правильно ли я выбрал подход к доступу к настройкам. Они меняются крайне редко. Идеологически правильнее: Все настройки описать в виде единой структуры с CRC её содержимого; при старте программа должна проверить CRC и проверить допустимость всех членов структуры и, если CRC неверная или содержимое любого из членов недопустимое - сама инициализировать эту структуру необходимыми начальными данными и записать. Именно - сама, не полагаясь, что некий оператор при прошивке это сделает. Именно что - не только CRC подсчитать, но и допустимость значения каждого элемента структуры и допустимость их комбинаций. Также неплохо бы внутри структуры сохранять номер версии структуры. Чтобы потом, когда вдруг потребуется изменить формат структуры, и потом перешивать прошивку поверх старой, не было проблем. 4 часа назад, krux сказал: любая flash или eeprom память при стирании страницы заполняется битами-единичками, а не нулями. 0xFF. Подозреваю, что Вы не ознакомились со всеми существующими в мире моделями flash-памяти для столь категоричного заявления. 1 час назад, tathagata сказал: Для хранения настроек как раз и не рассматривается необходимости использования контрольной суммы — полагаемся на корректную работу флеша) Тогда готовьтесь в будущем получать люлей по полной программе. От "счастливых" пользоватей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tathagata 0 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба Что скажете о таком варианте? scatter.sct LR_IROM1 0x00000000 0x0001E000 { ; load region size_region ER_IROM1 0x00000000 0x0001E000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00008000 { ; RW data .ANY (+RW +ZI) } RW_IRAM2 0x20100000 0x00004000 { mdr32f9qx_eeprom.o RAMFunction.o (+RO) .ANY (+RW +ZI) } } LR_IROM2 0x0001E000 0x00002000 { ; отключаем LR_IROM2, если перепрошивка не должна затрагивать данные ER_IROM2 0x0001E000 0x00002000 { ; начало страницы инициализируется переменными из файла, остальное — 0xFF data_init.o (+RO) } } data_init.c const uint32_t data_array[3] __attribute__((used)) = {0x0, 0x0, 0x0}; data_init.h #ifndef DATA_INIT_H #define DATA_INIT_H extern const uint32_t data_init[3]; #endif // DATA_INIT_H 24 минуты назад, jcxz сказал: Все настройки описать в виде единой структуры с CRC её содержимого; при старте программа должна проверить CRC и проверить допустимость всех членов структуры и, если CRC неверная или содержимое любого из членов недопустимое - сама инициализировать эту структуру необходимыми начальными данными и записать. Именно - сама, не полагаясь, что некий оператор при прошивке это сделает. Именно что - не только CRC подсчитать, но и допустимость значения каждого элемента структуры и допустимость их комбинаций. Также неплохо бы внутри структуры сохранять номер версии структуры. Чтобы потом, когда вдруг потребуется изменить формат структуры, и потом перешивать прошивку поверх старой, не было проблем. Полностью согласен, что так идеологически правильнее. Кстати, это решило бы мою проблему с необходимостью инициализации нулями настроек при первой прошивке, поскольку 0xFFFFFF, считанные для всех переменных настроек не соответствовали бы CRC, так же равному 0xFFFFFF и тем самым запускали бы процесс принудительной инициализации значениями по-умолчанию (например, нулями в моем случае). Отличная мысль с CRC! Спасибо. В таком случае мой скаттер мог бы иметь такой вид: LR_IROM1 0x00000000 0x0001E000 { ; load region size_region ER_IROM1 0x00000000 0x0001E000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00008000 { ; RW data .ANY (+RW +ZI) } RW_IRAM2 0x20100000 0x00004000 { mdr32f9qx_eeprom.o RAMFunction.o (+RO) .ANY (+RW +ZI) } } LR_IROM2 0x0001E000 0x00002000 { ; отключаем LR_IROM2, если перепрошивка не должна затрагивать данные ER_IROM2 0x0001E000 0x00002000 { } } Поправьте меня, если я неправ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 20 минут назад, tathagata сказал: Полностью согласен, что так идеологически правильнее. Кстати, это решило бы мою проблему с необходимостью инициализации нулями настроек при первой прошивке, поскольку 0xFFFFFF, считанные для всех переменных настроек не соответствовали бы CRC, так же равному 0xFFFFFF и тем самым запускали бы процесс принудительной инициализации значениями по-умолчанию (например, нулями в моем случае). Отличная мысль с CRC! Спасибо. Ведь необязательно защищать CRC весь объём записываемого конфига. Если у Вас в нём имеется какая-то часть, в которой модифицируются битики в описанном Вами порядке, то можете эту часть вынести за пределы области структуры конфига, защищаемой CRC. Защищайте CRC только ту часть конфига, которая не участвует в подсчёте ресурса. Как-то подобно: __packed struct { enum {VERSION = 1}; __packed struct { u8 version; u16 key1; u8 key2 u32 key3; ... } crcProtected; u32 crc; __packed struct { u32 counters[NNN]; ... } resurs; }; PS: __packed - это для IAR, для Keil заменить аналогом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tathagata 0 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 2 минуты назад, jcxz сказал: Ведь необязательно защищать CRC весь объём записываемого конфига. Если у Вас в нём имеется какая-то часть, в которой модифицируются битики в описанном Вами порядке, то можете эту часть вынести за пределы области структуры конфига, защищаемой CRC. Защищайте CRC только ту часть конфига, которая не участвует в подсчёте ресурса. Да, именно так я себе это и представил: с помощью CRC защищаю данные настроек, а также использую этот hack для их первоначальной инициализации. А в странице с ресурсом наработки "гашу" биты, не используя контрольные суммы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 18 ноября, 2022 Опубликовано 18 ноября, 2022 · Жалоба 3 минуты назад, tathagata сказал: Да, именно так я себе это и представил: с помощью CRC защищаю данные настроек, а также использую этот hack для их первоначальной инициализации. А в странице с ресурсом наработки "гашу" биты, не используя контрольные суммы. Я говорю, что это "гашение" лучше делать в самой программе. Ведь она может определить факт своего первого старта по факту несовпадения CRC. И тогда никакой спец.скаттер для этого не понадобится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться