Главная » Микроконтроллеры
Призовой фонд
на июль 2018 г.
1. Регулируемый паяльник 60 Вт
Паяльник
2. 200 руб.
От пользователей

Защита памяти EEPROM

Многие модели AVR раннего времени выпуска, как и другие микроконтроллеры семейства MCS-51, производимые фирмой Atmel, имели один существенный недостаток. Их память EEPROM была очень не надежной. Без каких-либо на то оснований ее содержимое могло изменится до неузнаваемости; имелись проблемы, при записи данных. В дальнейшем технология производства была улучшена и  положение вещей со временем, конечно, изменилось. Но, не смотря на это, ошибки при работе с EEPROM все-таки иногда случаются. Практика показывает, что наиболее распространенными причинами повреждения памяти являются импульсные помехи и сбои в цепях питания. Кроме того разрушение EEPROM может произойти на этапе программирования (даже если команды касаются только работы с fuse-битами или FLASH-памятью программ). Таким образом, для повышения достоверности хранимой в EEPROM информации иногда могут понадобиться дополнительные программные средства.

Проще всего это сделать, если отвести сохраняемой переменной несколько ячеек энергонезависимой памяти. Вероятность того, что все ячейки повредятся одновременно намного меньше. Хранить одно значение по двум адресам имеет смысл тогда, когда необходимо выявить только саму ошибку, но никак не восстановить утерянные данные. Дублирование по трем и более адресам EEPROM уже дает возможность найти и устранить проблему, когда один или несколько байтов случайно претерпели изменения. Подпрограммы, приведенные ниже, производят восстановление 8-разрядной величины, для хранения которой отведено 4 б памяти EEPROM. При считывании, сначала, проверяется условие равенства всех байтов памяти. Если значение хотя бы одного из них отличается от остальных, то данные были повреждены. В этом случае производится по парное сравнение между собой содержимого всех ячеек (всего 6 операций сравнения). В случае равенства хотя бы одной пары число, размещенное в этих двух ячейках, считается уцелевшим. Иначе данные не подлежат восстановлению.

    .def data  = R16 ;регистр c байтом данных
    .def eadrl = R24 ;регистр с младший байтом адреса EEPROM 
    .def eadrh = R25 ;регистр со старшим байтом адреса EEPROM
    .
	ldi   data,0x55         ;записываем число 0x55 в 
	ldi   eadrh,high(_var)  ;переменную _var из EEPROM-памяти
     ldi   eadrl,low(_var)   ;продублированную в 4-х байтах
     rcall ee_write_check
    . 
     ldi   eadrh,high(_var)  ;считываем переменную _var из
     ldi   eadrl,low(_var)   ;EEPROM-памяти 
	rcall ee_read_check
    .

           .eseg
           .org  0
       _var: .byte 4 ;4 зарезервированных ячейки в EEPROM-памяти 

;     Подпрограмм записи переменной в EEPROM-память 
; R16 – регистр с байтом для записи на входе из подпрограммы
; R25:R24 – регистровая пара для передачи адреса переменной 
;  EEPROM-памяти при входе в подпрограмму
; R17 – регистр для промежуточных операций
                        
ee_write_check:
     ldi   R17,4      ;инициализируем счетчик записанных байт
wc1: sbic  EECR,EEWE  ;ожидаем пока запись не будет закончена
     rjmp  wc1
     out   EEARH,R25  ;передаем адрес по которому 
     out   EEARL,R24  ;будет записано число
     out   EEDR,R16   ;передаем число
     sbi   EECR,EEMWE ;разрешаем запись
     sbi   EECR,EEWE  ;начинаем запись байта в EEPROM
     adiw  R24,1      ;увеличиваем адрес на 1
     dec   R17        ;производим запись числа во все 4 ячейки
     brne  wc1
     ret

;     Подпрограмм чтения переменной из EEPROM-памяти 
; R16 – регистр с прочитанным байтом на выходе из подпрограммы
; R25:R24 – регистровая пара для передачи адреса переменной 
;  EEPROM-памяти при входе в подпрограмму
; R17,R18,R19 – регистры для промежуточных операций
;   На выходе во Флаге T находится признак ошибки. Если T=0, то 
; данные успешно считаны, если T=1, то данные повреждены и не
; подлежат восстановлению                          

ee_read_check:
     set             ;при входе устанавливаем флаг ошибки
     rcall read_byte ;считываем 1-ый байт блока памяти
     in    R16,EEDR  ;EEPROM и размещаем его в R16
     rcall read_byte ;считываем 2-ой байт блока памяти 
     in    R17,EEDR  ;EEPROM и размещаем его в R17
     rcall read_byte ;считываем 3-ий байт блока памяти 
     in    R18,EEDR  ;EEPROM и размещаем его в R18
     rcall read_byte ;считываем 4-ый байт блока памяти 
     in    R19,EEDR  ;EEPROM и размещаем его в R19
     sbiw  R24,4     ;восстанавливаем адрес 
     push  R16       ;сохраняем регистр с 1-ым байтом
     and   R16,R17   ;сравниваем четыре байта 
     and   R16,R18   
     and   R16,R19 
     pop   R16       ;восстанавливаем регистр с 1-ым байтом
     brne  rc1       ;если все они равны между собой, то 
     clt             ;очищаем флаг ошибки и выходим из
     ret             ;подпрограммы с байтом в R16
rc1: cp    R16,R17   ;сравниваем 1-ый и 2-ой байты  
     brne  rc2       ;если они не равны то продолжаем сравнение  
     push  R16
     rjmp  rc7
rc2: cp    R16,R18   ;сравниваем 1-ый и 3-ий байты  
     brne  rc3       ;если они не равны то продолжаем сравнение  
     push  R16       
     rjmp  rc7
rc3: cp    R16,R19   ;сравниваем 1-ый и 4-ый байты  
     brne  rc4       ;если они не равны то продолжаем сравнение  
     push  R16
     rjmp  rc7
rc4: cp    R17,R18   ;сравниваем 2-ой и 3-ий байты  
     brne  rc5       ;если они не равны то продолжаем сравнение  
     push  R17
     rjmp  rc7
rc5: cp    R17,R19   ;сравниваем 2-ой и 4-ый байты
     brne  rc6       ;если они не равны то продолжаем сравнение  
     push  R17
     rjmp  rc7
rc6: cpse  R18,R19   ;сравниваем 3-ий и 4-ый байты и если
     ret             ;они не равны, то данные утеряны  
     push  R18
rc7: pop   R16       ;если найдена хотя бы одна одинаковая пара 
     rcall ee_write_check ;чисел, то восстанавливаем их в памяти 
     clt             ;и очищаем флаг ошибки на выходе  
     ret	       

read_byte:
     sbic  EECR,EEWE ;ожидаем пока запись не будет закончена
     rjmp  read_byte
     out   EEARH,R25 ;передаем адрес числа для чтения 
     out   EEARL,R24 
     adiw  R24,1     ;увеличиваем адрес на 1
     sbi   EECR,EERE ;разрешаем чтение
     ret

Перейти к следующей части:

Теги:

Котов Игорь Юрьевич Опубликована: 2012 г. 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (2) | Я собрал (0) | Подписаться

0
denis110674 #
Этот кусок кода на равенство всех четырёх бйтов не корректно работает.
......
push R16 ;сохраняем регистр с 1-ым байтом
and R16,R17 ;сравниваем четыре байта
and R16,R18
and R16,R19
pop R16 ;восстанавливаем регистр с 1-ым байтом
brne rc1 ;если все они равны между собой, то
clt ;очищаем флаг ошибки и выходим из
ret ;подпрограммы с байтом в R16
.....
Флаг Z должен подняться, если все 4 байта равны?
Но с командой and Rr,Rr при равенстве байтов этого не происходит.
Проверку на равенство всех 4-х байтов я сделал так:
mov r2,r16
eor r16,r17
mov r16,r2
eor r16,r18
mov r16,r2
eor r16,r19
mov r16,r2
brne cp_1;
clt
ret
Ответить
0
denis110674 #
Прошу прощения, был не прав, ерунду написал выше. Не работает.
Вот так работает:

cp r16,r17
brne cp_1
cp r17,r18
brne cp_1
cp r18,r19
brne cp_1;
clt;
ret
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
Конструктор для сборки: предусилитель на лампе 6N3 Печатная плата для усилителя "LM3886 + AD825"
вверх