-Tумблер- 0 23 марта, 2005 Опубликовано 23 марта, 2005 · Жалоба лет и ничто не дало мне повод усомниться в EEPROM как именно в памяти. Пожалуйста - простой пример: Прибор время от времени должен спасать некоторые значения в EEPROM в процессе работы. Которые должны запоминаться. Это как раз и есть назначение этой области памяти, не так ли ? Итак, спасение началось. Спасаются...ммм.. 10 значений float. Посто "так надо". В этот момент пропадает питание..кратковременно. Срабатывает системный монитор. Например MAX1232. По достижении питания 4.5 V. Что получилось ? Например, первые два значения спасены целиком правильно, 3-е - прописалось частично (первые 2 байта), остальные значения остались прежними. Пропадание питания было кратковременным. По достижении питания >4.5 V прибор нормально стартует. И что же в итоге ? Данные частично новые, частично старые, частично разрушены. Допустим, речь идет о...новогодней гирлянде. Это не опастно, просто неприятно - праздник как-никак. Но в самолет с таким контроллером я добровольно не полезу. А то какя то вспышка молнии, и автопилот так руль заложит, что мало не покажется. :huh: Получается, что Вам везет. А мне обычно - не везет. Поэтому я использую эту память как внешнее устройство. Замечу, что все эти соображения не относятся именно к AVR. Это относится к любым EEPROM-ам вообще. Кстати, мне попался процессор с "битым" байтом в области EEPROM. Данные там стабильно пропадают ~30 мин. Так вот - прибор с этим процессором работает правильно, и я не стал его выкусывать. $3 экономии - пустячок, а приятно. "Красивый алгоритм - гимнастика ума". :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 23 марта, 2005 Опубликовано 23 марта, 2005 · Жалоба -Tумблер-, Вы похоже очень спешите читать пост и в результате читаете не весь. Я говорил о комплексном подходе (...различные hints и recomendations как программистские, так и конструкторские.). Когда же я столкнулся с проблемой похожей на Вашу (правда не в самолёте, а в газовом хозяйстве, что не умаляет ответственности), где была необходимость "спасать" около 2 кБайт данных, и не в EEPROM, а в DATAFLASH (что более геморройно), то зная это заранее, предусмотрел и особую схему питания с суперконденсаторами и ранним предупреждением, и специальные программные трюки с контрольными суммами, дублированиями и восстановлениями. И надёжность работы устройства уж никак не зависила от взгляда или отношения к тому или иному ресурсу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alex_St 0 23 марта, 2005 Опубликовано 23 марта, 2005 · Жалоба 2 Тумблер: А что в таком случае мешает использовать CRC или прочие алгоритмы контроля целостности данных? И для особо важных данных писать резервные копии? А то, что Вы привели, относится к любым типам памяти, будь то RAM, eeprom или HDD. А не к способу их описания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
-Tумблер- 0 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба А что в таком случае мешает использовать CRC или прочие алгоритмы контроля целостности данных? И для особо важных данных писать резервные копии? Совершенно верно. Так делаю я - также как и Билли Гейтс. Делаем резервные копии в количестве N штук. Снабжаем каждую CRC16. Хочется CRC32, но для avr это все таки затруднительно. Фактически, алгоритм такой же (или очень похожий) как у FAT. А теперь попробуйте описать это переменной вида: int my_var; Конечно, можно попытаться. Но это черезвычайно не удобно. Эта переменная должна быть удвоена, утроена и.т.п. Как обратится к ее конкретному образу? :huh: Или придется описывать класс MY_INT_VAR и перегружать все операции. Или что-то вроде: int my_var_1; int my_var_2; /* где то далеко от _1 - но ГДЕ ? */ ... А потом массив указателей. Что-то это все не красиво. Гораздо легче и понятней: #define ADDR_MY_VAR 0x..... #define OFFSET1 0x... #define OFFSET2 0x... а потом write_eerpom (word addr, byte dat, word offset); byte read_eerpom (word addr, word offset); Все просто, понятно и точно известно - где каждая переменная и где каждая из таблиц данных (я решил сохранить это определение, поскольку воспользовался алгоритмом как у FAT) А то, что Вы привели, относится к любым типам памяти, будь то RAM, eeprom или HDD. А не к способу их описания. Мне кажется, вы сами себе противоречите. :) Уж конечно, описание переменной в RAM сильно отличается от того, что на HD. То, что на HD вообще как бы и не описывается - туда доступ "описанием" нельзя обеспечить. К HD можно обратиться, как к внешнему устройству. И к eeprom я предлагаю обращаться также. Кроме того, RAM с одной стороны и HD, eeprom с другой - существенно разные памяти по степени "опастности". Дело в том, что в случае сбоя и после перезапуска RAM обновляется и все OK. А HD и eeprom запоминают неверный результат и в этом все дело. Вот и получается, что для работы с ними я выбрал сходные алгоритмы. По моему, это естественно. На мой взгляд, странно предложить другое. :) Применив "FAT-алгоритм" мы вдруг с удивлением обнаружим что: 1. мы можем работать с частично разрушенным физически (навсегда) eeprom 2. мы можем восстанавливать разрушенные (по любым причинам)участки eeprom 3. мы можем не ставить больше системный монитор (экономия $0.5/шт) 4. мы не нуждаемся в средствах бесперебойного питания 5. мы можем наслаждаться красивым алгоритмом который изобрели сами (увы - мы были не первые, но все-таки) Кстати - "FAT-алгоритм" работает в IBM-PC, да еще как!!!!! Просто мы не знаем об этом. Но однажды, когда посыпался мой Fujitsu - 20гб, я вдруг получил сообщение: что то вроде: "Обе фат коррупт, не могу починить..." После этого диск я сдал назад в Техмаркет, а сам стал делать от 3 до 6 дублей в eeprom <_< Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 24 марта, 2005 Опубликовано 24 марта, 2005 · Жалоба Совершенно верно. Так делаю я - также как и Билли Гейтс. Делаем резервные копии в количестве N штук. Снабжаем каждую CRC16. Хочется CRC32, но для avr это все таки затруднительно. [...] Или придется описывать класс MY_INT_VAR и перегружать все операции. А чем не нравится класс? Гораздо легче и понятней: #define ADDR_MY_VAR 0x..... #define OFFSET1 0x... #define OFFSET2 0x... а потом write_eerpom (word addr, byte dat, word offset); byte read_eerpom (word addr, word offset); Все просто, понятно и точно известно - где каждая переменная и где каждая из таблиц данных (я решил сохранить это определение, поскольку воспользовался алгоритмом как у FAT) И чем это лучше? Неслабое нагромождение кода в глобаном scope. В то время как, написав класс, где для вашей переменной объявить массив копий в EEPROM, который и обслуживать: class TMyEEPROM_Var { public: TMyEEPROM_Var(); TMyEEPROM_Var(typename x); ... // остальной интерфейс private: __eeprom typename CopyArray[N]; }; Тут уж и проверки сделать при обращениях, и журналирование, и все необходимые операции определить. Т.ч. снаружи это будет просто как обычная переменная. А если уж хочется и отдельные копии смотреть, то и для них функцию определить - типа: typename TMyEEPROM_Var::get_copy(byte intex) { return CopyArray[intex]; } Но обращаться именно в EEPROM посредством __eeprom. Только это будет тоже скрыто внутри класса. А функции явные ee_read, ee_write - это явно излишне. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
-Tумблер- 0 25 марта, 2005 Опубликовано 25 марта, 2005 · Жалоба А чем не нравится класс? Обьясню - чем не нравится класс. 1 Как быть с внешними eeprom-ами ? Концепцию менять каждый раз ? Вдобавок, в некоторых проектах использовались оба типа. :huh: 2. Использую то я C. Так вышло, мне часто приходится переходить с процессора на процессор. С с++ бывают проблемы - например для Fujitsu просто нет. С переносимостью программ на С проблем (у меня) не было до сих пор. С пол-оборота всегда и везде все работает. А вот теперь серьезно: 3. Если мы озабочены сохранностью данных eeprom, то делать приходится вот что: разные таблицы-копии располагаются на разном смещении, обязательно с "проплешинами" между собой. Чтобы не портились сразу две таблицы. Дело в том, что "исследования" показали - когда данные портятся, то они и расположены рядом. Т.е. портятся смежные байты. Поэтому совет расположить подряд N копий не кажется мне удачным. Кроме того, возникнут большие затруднения написания подсчета CRC в такой концепции. В предложенном мной варианте известен начальный адрес таблицы и ее размер. А это значит удобно обратиться к такой таблице как к массиву. Причем, к любому. Хотите - к байтовому, хотите - к вордовому. Подсчет CRC дело циклическое и "длительное". Удобство доступа всерьез повлияет на скорость процедуры. Любое прямое описание переменной в С приводит к ее автоматическому размещению компилятором. Собственно, это одно из больших достоинств этого языка. Как раз это, на мой взгляд, и мешает при работе с eeprom. В этом случае удобно распределить память самому. Это не сложно, поскольку таких данных сравнительно немного. И это приведет скорей к более компактной программе - это же к ассемблеру ближе, чем к c++ ... Неслабое нагромождение кода в глобаном scope. Извините - я этот вопрос просто не понял . :huh: Понятно, что я описал идею, а не приводил в конференции исходных текстов коммерческих программ. "..Идею дал? - Наморщи ум..". Я так понял - мы оба согласились сделать "ЭТО", но с разным описанием переменных. Но это значит, размеры исполнимых кодов у нас не сильно отличаются. Причем точно известно - дополнительная "оплата" размером за ооп обязательно будет. Полагаю от 5% - 10 %. Так что кодов больше будет у Вас. Вот исходных текстов может быть больше у меня. Но это мне не тяжко. Написал отдельный модуль один раз + .def файл макроопределений. Этот модуль кочует из проекта в проект. Как впрочем и многие другие. :glare: Удачи ! :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 25 марта, 2005 Опубликовано 25 марта, 2005 · Жалоба А чем не нравится класс? Обьясню - чем не нравится класс. 1 Как быть с внешними eeprom-ами ? Концепцию менять каждый раз ? Вдобавок, в некоторых проектах использовались оба типа. :huh: Какая разница? С внешним все равно не так работаете. И тут можно другую реализацию сделать. Впрочем, это к делу не относится. :) 2. Использую то я C. Так вышло, мне часто приходится переходить с процессора на процессор. С с++ бывают проблемы - например для Fujitsu просто нет. С переносимостью программ на С проблем (у меня) не было до сих пор. С пол-оборота всегда и везде все работает. Да, переносимость - это единственное серьезное возражение, тут спорить не буду. Если она рулит, то деваться некуда. :) Но не удержусь от замечания, что С++ все больше и больше завоевывает позиции, и, как следствие, компиляторов тоже все больше и больше. Причем почти полноценных - с шаблонами, неймспейсами. А вот теперь серьезно: 3. Если мы озабочены сохранностью данных eeprom, то делать приходится вот что: разные таблицы-копии располагаются на разном смещении, [...] В предложенном мной варианте известен начальный адрес таблицы и ее размер. А это значит удобно обратиться к такой таблице как к массиву. Причем, к любому. Хотите - к байтовому, хотите - к вордовому. Подсчет CRC дело циклическое и "длительное". Удобство доступа всерьез повлияет на скорость процедуры. Да нет вопросов - хочется располагать со смещением - располагайте. Хочется работать с отдельными байтами - пожалуйста, никто не запрещает. Я не понимаю, как это конфликтует с объявлением переменной с квалификатором __eeprom? Класс-то ведь не в EEPROM живет, он - в обычной памяти. А внутри него забиты адреса данных в EEPROM'е. Просто всю работу он инкапсулирует внутри себя. А данные создаете в EEPROM с помощью слова __eeprom с последующей инициализацией представления класса, где в конструкторе прописываете адреса на EEPROM. При этом нет проблем с созданием многобайтных типов (предположим, Вам понадобилось плавучку в EEPROM хранить или вообще разномастные данные - структуры). И полный статический (т.е. на этапе компиляции) контроль типов. Любое прямое описание переменной в С приводит к ее автоматическому размещению компилятором. Собственно, это одно из больших достоинств этого языка. Как раз это, на мой взгляд, и мешает при работе с eeprom. В этом случае удобно распределить память самому. Это не сложно, поскольку таких данных сравнительно немного. Ну и распределяйте, никто не возражает. Только почему бы это не делать с помощью __eeprom. Речь о том, чтобы не лазить в EEPROM руками - для этого использовать интерфейсный объект. Но данные разместить (память выделить) отдельно руками, объявив все необходимое с помощью __eeprom, и проинициализировать интерфейсный объект адресами этих данных в EEPROM. Т.е. внутри класса должны быть указатели типа __eeprom typename *. Конструктор объекта должен требовать определенное количество и тип аргументов-адресов - если забудете что-то ему передать, компилятор ругнется. Безопасность использования выше. ... Неслабое нагромождение кода в глобаном scope. Извините - я этот вопрос просто не понял . :huh: Понятно, что я описал идею, а не приводил в конференции исходных текстов коммерческих программ. "..Идею дал? - Наморщи ум..". Дело не в том, что там было не полное определение реализации дано, а только идея. Дело в том, что согласно тому стилю, присущему С, в глобальной области видимости появится куча достаточно низкоуровневого кода (функции, переменные), работа с которыми, во-первых, неудобна (надо при работе постоянно держать в голове кучу левых сущностей), во-вторых, небезопасна (т.е. через некоторое время начинаешь забывать, что там к чему и легко что-то напутать). В случае класса вся работа сокрыта внутри - снаружи как раз простой и формализованный интерфейс - пользователь не видит всего этого внутреннего "ужаса" :), который не "грузит" ему мозги и не провоцирует на ошибки. :) К тому же, можно класс слелать шаблоном и не переписывать все это для разных типов. Один раз написал, и используй для разных типов. __eeprom тут попадает, как говорится, "в струю". :) В общем, не агитирую, по опыту знаю, это дело не нужное, т.к. каждый работает, опираясь на собственный опыт и знания. Но точку зрения изложил, может она послужит поводом где-то и пересмотреть позицию. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 28 марта, 2005 Опубликовано 28 марта, 2005 · Жалоба Далеко не единственный случай, когда программист не доверяет тому инструменту (компилятору, линкеру), которым пользуется. Причём, под доверием я имею в виду не слепую веру, а точное знание того, как он работает и уверенность в этом. Мне достаточно часто приходится работать с программистами, которые приходят к C после долгой работы на ассемблере. И едва ли не у каждого из них существует подобная проблема - они теряются от того, что не управляют вручную расположением переменных. Это мне напомнило один случай из жизни: я спросил у одной подруги: "У тебя есть машина, почему же ты не водишь?", на что она мне ответила: "Когда я сажусь за руль, я колёс не вижу". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
-Tумблер- 0 28 марта, 2005 Опубликовано 28 марта, 2005 · Жалоба Я не понимаю, как это конфликтует с объявлением переменной с квалификатором __eeprom? Если происходит обьявление __eeprom int value; то как раз размещением переменных занимается компилятор. Это как раз мне и не подходит - для данного случая. Но я и не предполагал, что некоторая дискуссия о сохранении данных в eeprom плавно перейдет в дискуссию о применении ооп... :) Эти два вопроса совершенно не связаны друг с другом - каждый сам по себе. Подумав как следует - пришел я к выводу: можно было бы конечно написать класс. Но не для переменной. Класс - таблица. С параметром конструктора "TABLEi_OFFSET". Это еще "куда ни шло". Полагаю в этом случае оплата за ООП будет минимальной. А как вы собираетесь считать CRC в вашей концепции ? :glare: Составлять массив указателей на классы-переменные или делать связной список из них ? Или разименовывать поочереди ? :tongue: В случае класса вся работа сокрыта внутри - снаружи как раз простой и формализованный интерфейс - пользователь не видит всего этого внутреннего "ужаса" :), который не "грузит" ему мозги и не провоцирует на ошибки. :) Да это я знаю.. (ворчливо). Пользуемся, как же - когда это всерьез выгодно (шас пойдет реклама): http://spiprog.narod.ru Извинением мне служит только то, что обращаю ваше внимание на исходные тексты, а не на что либо иное. Действительно, ООП в этом конкретном случае дает огромный выигрыш в производительности труда. И это меня волнует больше всего. Теперь о триллере. Эпиграф: "..Тебе страшно? Мне-нет...". "Малыш и Карлсон", мультфильм. И где же тут ужас: my_important_var.save_me_please (); // это у вас save_my_important_var (); // это у меня. Мне кажется, что ваши "страхи" на программу в 8К (а на самом деле в 4- инструкции AVR 16-битные) слегка преувеличены. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться