murmur 0 7 февраля, 2016 Опубликовано 7 февраля, 2016 (изменено) · Жалоба Коллеги, есть проблемка. Сохраняю настройки во флеш. Есть функция, которая читает настройки при старте и в случае их некорректности (порча ячейки) устанавливает дефолтное значение. Эта функция за время жизни устройства запускается как минимум один раз - при первой прошивке настройки пусты, программа понимает, что в ячейке бред, устанавливает дефолтное значение и пишет его во флеш. В одной из ячеек хранится float. Его корректность проверяется следующим образом: flash_data=flash_read(page_address+8); // Читаем OPTIONS_VAR.VoltageMAX=UintToFloat(flash_data); //Преобразуем во float if ((OPTIONS_VAR.VoltageMAX<12) || (OPTIONS_VAR.VoltageMAX>20)) // проверяем диапазон и если там некорректные данные то... { OPTIONS_VAR.VoltageMAX=14; // ставим дефолт OPTIONS_FLASH_ERROR=1; // ставим флаг ошибки, ориентируясь на который программа в дальшейшем пытается записать во флеш правильное значение } Но вот беда, при пустом флеше в ячейке располагается нечто, что будучи преобразованным при помощи UintToFloat отображается в отладчике как " -1.#QNAN ". Это полбеды, настоящая беда в том, что вышеприведенная функция считает что данные корректны и не считает нужным их исправлять. То есть " -1.#QNAN " удовлетворяет условиям if ((OPTIONS_VAR.VoltageMAX<12) || (OPTIONS_VAR.VoltageMAX>20)) Что делать? Добавлено спустя 1 минуту Кто-нибудь объяснит феномен, по которому над проблемой бьешся час, не находишь решения, потом задаешь вопрос на форуме, после чего решение, не дожидаясь ответов, приходит в голову немедленно? Изменено 7 февраля, 2016 пользователем murmur Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nixon 4 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Правильно заданный вопрос содержит половину ответа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба по стилю написания: 1. никогда не используйте в тексте "магические числа", определяйте все такие величины заранее . В Вашем случае- неплохо иметь файл "defaults.h" и в нем дефайны вроде #define CONFIG_V_MIN 12 ; минимально допустимая величина напряжения в конфиге 2. Подавляющее большинство программописателей четко разграничивает использование прописных(заглавных) и строчных букв в именах. Например, имена констант состоят из заглавных букв, имена глобальных переменных начинаются с заглавной буквы, имена локальных переменных начинаются с строчной буквы. Такие простые правила очень повышают читабельность кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
toweroff 1 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Проверять корректность блока данных по значению какой-то отдельной переменной, на мой взгляд, не есть гуд Не проще добавить дополнительное поле с CRC? Достоверность в разы повысится Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 79 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Эта функция за время жизни устройства запускается как минимум один раз - при первой прошивке настройки пусты, программа понимает, что в ячейке бред, устанавливает дефолтное значение и пишет его во флеш. Что делать? Стирайте флэш перед записью программы. Тогда будете из ячейки читать 0xFF А можно еще в программе описать константы в заданный регион флэша и они попадут в прошивку. Кто-нибудь объяснит феномен, по которому над проблемой бьешся час, не находишь решения, потом задаешь вопрос на форуме, после чего решение, не дожидаясь ответов, приходит в голову немедленно? Не помню как называется, но при описании проблемы ручками на бумаге или какому-нибудь собеседнику, мысли выстраиваются в логическую цепочку и формулируют законченный вопрос, в котором как известно, уже есть 50% ответа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
murmur 0 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Проверять корректность блока данных по значению какой-то отдельной переменной, на мой взгляд, не есть гуд Не проще добавить дополнительное поле с CRC? Достоверность в разы повысится Была такая мысль. Но из-за одного испорченного байта сбрасывать в дефолт все настройки? Не есть гуд. Можно конечно поставить цель меганадежного хранения данных, тогда нужно писать три копии переменных и сверять их содержимое, то есть будет возможность восстановления данных. Но это не самоцель. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба void load_settings() { int i; uint32_t v_data; uint32_t * v_settings_src = addr_flash_sector_11; uint32_t * v_settings_dst = &m_settings; CRC->CR |= CRC_CR_RESET; for (i = 0; i < sizeof(m_settings) / sizeof(uint32_t); i++) { v_data = *v_settings_src++; *v_settings_dst++ = v_data; CRC->DR = v_data; } m_is_settings_valid = *v_settings_src++ == CRC->DR; if (!m_is_settings_valid) load_default_settings(); } феномен эгрегор Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Но из-за одного испорченного байта сбрасывать в дефолт все настройки? Не есть гуд. Конечно, ибо у вас не будет гарантии, что настройка корректные. Например, в вашем примере переменная может изменятся от 12 до 20 с дефолтом 17. Для корректной работы, например, нужно не менее 15. В результате ЧЕГО-ТО настройка стала некорректной, но попадающей в диапазон от 12 до 20, например, 13. Для вас это нормально?! Скажем так: вероятность потерять настройки ооочень низкая. Вряд ли вы когда получите события несовпадения CRC и сброса всех настроек к дефолту. При этом CRC позволяет легко и надежно контролировать корректность настроек. Можно хранить несколько упорядоченных копий, и если в последней CRC битая, то брать предыдущий набор, у которого CRC будет валидной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
toweroff 1 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Но из-за одного испорченного байта сбрасывать в дефолт все настройки? Не есть гуд. ооочень спорно если что-то похерилось в настройках, значит прибор будет работать не так, как нужно? или я что-то не понимаю? определите тогда некую критическую секцию и считайте CRC для нее, а все остальное будет болтаться, как Бог на душу положит Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
murmur 0 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба если что-то похерилось в настройках, значит прибор будет работать не так, как нужно? или я что-то не понимаю? В целом может быть вы и правы. В моем случае, если настройки сбросятся, ничего страшного не произойдет. Их просто нужно будет поставить на место. И таким образом имеем два варианта 1. Ваш - прикручиваем CRC, загружаемся, ловим ошибку CRC - дальше что делаем? Наверное то же что делаю я - ставим безопасные настройки. Причем все, вы ведь по CRC всю структуру будете браковать? 2. Мой вариант - проверяем корректность настроек поштучно. Ставим по дефолту только тот параметр, который невменяем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Однозначно надо CRC дела. А по поводу NaN https://ru.wikipedia.org/wiki/NaN http://stackoverflow.com/questions/4617796/1-qnan-error-c Очень странным кажется то, что это число проходит проверку... Такого быть не должно, где-то тут ошибка с выводами. Возможно не чисто поставлен эксперимент... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
murmur 0 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба Очень странным кажется то, что это число проходит проверку... Это не число проходит проверку, это ошибка логики. Условие сформировано так что идет проверка не лежит ли число в пределах, отличных от рассматриваемого? То есть не находится ли оно в пределах от 0 до 12 и от 20 до 65535. Естественно оно в этих пределах не находится, поскольку не является числом. Отсюда программа делает ошибочный вывод, что расссматриваемое число лежит в пределах от 12 до 20 ти. Правильно нужно было сделать так if ((!(OPTIONS_VAR.VoltageMAX>=12)) && (!(OPTIONS_VAR.VoltageMAX<=20))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 7 февраля, 2016 Опубликовано 7 февраля, 2016 · Жалоба неправильно логика в том, что если у вас накрылся хотя бы один байт, то нет никаких гарантий, что не накрылись остальные пусть даже они всё ещё находятся в допустимом диапазоне так что 1. проверяйте контрольный код всего блока настроек 2. если не совпадает, грузите настройки с зеркальной копии и отправляйте предупреждение 3. если зеркала нет, грузите настройки с последней валидной резервной копии и переходите в режим конфигурации пользователем 4. если резервной копии нет, грузите дефолтовые настройки и переходите в режим конфигурации пользователем Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 8 февраля, 2016 Опубликовано 8 февраля, 2016 · Жалоба А, понял. Не присмотрелся к услови. Т.е. для вас результат сравнения == false является позитивным ответом и считается, ошибки нет и все ок. if ((!(OPTIONS_VAR.VoltageMAX>=12)) && (!(OPTIONS_VAR.VoltageMAX<=20))) ну в целом идея хорошая, только не ясно зачем отрицание ! ? Потому что если это не опечатка и в программе именно так, то это отрицание всё испортит. Если оба сравнения вернут false(а с NAN так и будет), то оператору && достанутся два true(благодаря отрицанию) и опять получится ерунда. Но все это не важно, надеюсь будет CRC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 23 8 февраля, 2016 Опубликовано 8 февраля, 2016 · Жалоба Была такая мысль. Но из-за одного испорченного байта сбрасывать в дефолт все настройки? Не есть гуд. Можно конечно поставить цель меганадежного хранения данных, тогда нужно писать три копии переменных и сверять их содержимое, то есть будет возможность восстановления данных. Но это не самоцель. Достаточно двух в разных сегментах. Очень сложно будет угробить их одновременно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться