Поменьше писать - максимально редко и, возможно, максимально сжимая. А то что пишется, сдвигать по кольцу. И ничего большего программно не придумать.
_________________ Платы для HLDI - установки лазерной засветки фоторезиста. ФоторезистыOrdyl Alpha 350 и AM 140. Жидкое олово для лужения плат (видео) - самое лучшее и только у меня. Паяльная маска XV501T-4 и KSM-S6189 (5 цветов). Заказ печатных плат - pcbsmac@gmail.com
В устройстве есть STM32L052 и два драйвера RS485. Не считая клемм и светодиодов.
Данные это разные параметры установки, которые воемя от времени оператор меняет. Это и байты, и 16-битные, и float-ы... Разные. И нет никаких закономерностей их изменения, кроме того, что все они вводятся вручную и приходят в МК по модбасу. Т.е. никогда не будет (кроме первой инициализации) записи чаще, чем 1 раз в несколько секунд, т.к. физически быстрее ввести данные невозможно.
Самый простейший способ, который сразу приходит в голову: В начале EEPROM храним сами переменные (предположим = 10 байт), а в оставшейся части - журнал изменений. При получении нового значения переменной - пишем его в журнал (добавляя к нему идентификатор). Когда журнал доходит до края EEPROM и поступает новое значение - все данные из журнала (последнее значение каждой переменной) переписываем в начальный блок переменных. Журнал стираем чтобы потом начать его заполнение вновь. Вот и всё. Ресурс уже увеличен на величину журнала.
Кстати - кроме уменьшения износа. этот способ также даёт устойчивость к сбоям питания. В виде бонуса. А не как вы привыкли - на авось.
Также можно разбить EEPROM на ячейки одинакового размера. С идентификаторами содержимого и счётчиками записей. И писать переменные в них. Там где минимальный счётчик. И периодически проводить процедуру выравнивания для всего массива - переписывать давно лежащие без движения ячейки (у которых счётчик износа значительно меньше максимального из других ячеек) в более изношенные ячейки. Типа как в SSD. Но этот способ сложнее журналирования.
Последний раз редактировалось jcxz Вт мар 04, 2025 20:52:34, всего редактировалось 2 раз(а).
Прошу подробнее, что вы подразумеваете под журналом? Что туда писать? Я как-то не уловил, как потом читать данные? Из журнала, разыскивая самое свежее значение? Тогда нафига вообще первый блок?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Прошу подробнее, что вы подразумеваете под журналом? Что туда писать?
Пишем: "Новое значение переменной X равно Y". Вроде как очевидно. Каждой переменной дать ID (имя). Числовое. Запись закодировать COBS и записать в журнал по-байтно.
Идея с журналом занятная. Но интуитивно представляется ужасно геморной в реализации... С учетом того, что значения-то разные по длине... Это целая файловая система получается.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
С учетом того, что значения-то разные по длине... Это целая файловая система получается.
Ничего там сложного нет: байт_идентификатора, за ним - байты переменной. Итого общая длина записи = 2...5 байт. Кодируем COBS получаем = 3...6 байт. Дописывает в хвост журнала. С отступом в один байт от предыдущей записи журнала. куда уж проще?
При старте программы создаём в ОЗУ копию текущих данных: читаем сами начальные данные с EEPROM, затем пробегаемся по журналу, внося изменения согласно каждой записи журнала. Все модификации (при поступлении новые значений) производим над копией данных в ОЗУ, а потом - пишем в журнал.
В качестве разделителей записей журнала (кодированных COBS) лучше использовать стёртое состояние ячеек. Если оно =0 - всё ок, пишем записи COBS как есть. Если стёртое значение ячеек == 0xFF, то после COBS-кодирования инвертируем данные кодированные COBS перед записью в EEPROM. Ну и обратно - перед COBS-декодированием.
Последний раз редактировалось jcxz Вт мар 04, 2025 20:46:47, всего редактировалось 1 раз.
Мой предшественник так не думал... Но то, как он эту проблему решал, меня немного расстроило... И я решил переделать.
За идею с журналом спасибо, я буду в этом направлении думать.
Получается, первичный блок вообще не нужен: начальную инициализацию делаем в виде записей журнала, и далее всю память по кругу заполняем журналом... Как-то так...
Добавлено after 2 minutes 56 seconds: Даже начальную инициализацию можно вообще в коде прописать...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Получается, первичный блок вообще не нужен: начальную инициализацию делаем в виде записей журнала, и далее всю память по кругу заполняем журналом... Как-то так...
Нет. Первичный блок нужен, если у вас переменные изменяются с разной частотой. Может ведь оказаться, что одна переменная изменилась 100 раз, а другие - ни одного. И тогда записи одной часто меняющейся переменной, в конце концов вытеснят из журнала записи других переменных. Вот для этого и нужно при каждом полном заполнении журнала скидывать все данные в начальное хранилище. А потом - стирать журнал и по новой.
Я выше неправильно написал - это не кольцевой журнал, а линейный. От одного края свободного пространства EEPROM до другого края. "Заполнение журнала" -это достижение им конца выделенного под него пространства. После чего следует сброс его содержимого в Начальное Хранилище и стирание журнала. За один цикл прохождения журнала переписываются по разу все ячейки EEPROM - износ их выровнен.
Не знаю как в L0, но во внешних лучше писать стирать страницами. По первому байту страницы (не ff) можно быстро найти крайнюю запись.
Конечно. Для внешних. Там можно и по 256КБ-секторам искать. Чтобы быстрее. И кольцо сделать в несколько десятков МБ размером. Но ARV говорил про внутреннюю EEPROM.
Не решается. Потому как сразу после иголки вызвавшей сброс, может воспоследовать уже обычное выключение.
Прикольно. Сначала Вы пишете фразу "без выкл.питания", и я с её учётом делаю вывод, описывая только этот момент. Но потом Вы резко переобуваетесь в воздухе, дописывая причину, которую исключили сами же постом выше Я же даже в цитате выделил жирным Вашу фразу
Прикольно. Сначала Вы пишете фразу "без выкл.питания", и я с её учётом делаю вывод, описывая только этот момент. Но потом Вы резко переобуваетесь в воздухе, дописывая причину, которую исключили сами же постом выше
В чём именно "переобуваюсь"?? не понял... И ничего я не исключал. Сперва происходит сброс процессора без выключения питания, просто сброс от помехи. Потом, с малым интервалом после, пока программа стартует, происходит выкл.питания. В чём здесь переобувка??? Сброс от помехи не исключает же возможность выключения питания сразу после него? И старт программы происходит не мгновенно.
Я выше неправильно написал - это не кольцевой журнал, а линейный.
В запись журнала, кроме идентификатора переменной и её значения, можно писать ещё и счётчик номера записи. По этому счётчику можно будет определять последнюю запись в журнале при включении питания. Тогда журнал можно сделать кольцевым и его не надо будет очищать целиком за раз. Для предотвращения ошибок определения (после переполнения кольца), ёмкость этого счетчика должна быть больше максимального количества записей журнала.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения