Решил я тут разобраться с тем, как ИАР реализовал свои функции работы с EEPROM, потому что раньше применял свои функции, а теперь решил применить ИАРовские. Почитал документы, поизучал исходники, посмотрел конференцию. Нашел сообщения и файл коллеги
IgorKossak который он всем рекомендует. И как-то из последних сообщений выходит, что у ИАРа библиотеки неправильные.
Решил я поэтому опубликовать свои выводы, поскольку получается, что библиотеки то правильные (
здесь я не говорю об их ошибке с записью long long - ошибка она и есть ошибка), просто
границы применимости у них различные.
Возмем, к примеру, чтение и запись char в eeprom, размером более 256 байт.
Оригинальная библиотека ИАР АВР 4.21А (если убрать все лишние переходы):
Код
?eewait:
SBIC EECR,EEWE
RJMP ?eewait
RET
__eeget8_16:
RCALL ?eewait
OUT EEARL,r20
OUT EEARH,r21
SBI EECR,EERE
IN r16,EEDR
RET
__eeput8_16:
IN r0,SREG
RCALL ?eewait
OUT EEDR,r16
OUT EEARL,r20
OUT EEARH,r21
CLI
SBI EECR,EEMWE
SBI EECR,EEWE
OUT SREG,r0
RET
Анализируя этот код можно определить область применимости этих процедур:
Эти функции можно применять (без дополнительного запрещения прерываний)
только в одном потоке, т.е. или в main или в прерываниях одного уровня. Применение даже только чтения и в основном цикле и в прерывании периодически будет приводить к краху чтения. Дополнительное ограничение - функцию записи нельзя применять при наличии самопрограммирования флеша (команд SPM) в другом потоке.
Возмем теперь исправленный вариант от
IgorKossak. Исправления следующие:
Цитата(IgorKossak @ May 18 2006, 13:31)

описание (исправлений) можно свести к двум пунктам:
1) любая критическая работа с ЕЕПРОМ (за исключением кристаллов AT86RF401), требующая непрерываемости, обрамлена в обёртку типа:
сохранить SREG
CLI
критическая работа с ЕЕПРОМ
восстановить SREG
2) исправлена ошибка в подпрограмме записи в ЕЕПРОМ 64-битных чисел.
Код
?eewait:
CLI
SBIS EECR,EEWE
RET
OUT SREG,r0
RJMP ?eewait
__eeget8_16:
PUSH r0
IN r0,SREG
RCALL ?eewait
OUT EEARL,r20
OUT EEARH,r21
SBI EECR,EERE
IN r16,EEDR
OUT SREG,r0
POP r0
RET
__eeput8_16:
IN r0,SREG
RCALL ?eewait
OUT EEDR,r16
OUT EEARL,r20
OUT EEARH,r21
SBI EECR,EEMWE
SBI EECR,EEWE
OUT SREG,r0
RET
Запрещение прерываний на все время работы функций вместе и изящным решением "прозрачного" для прерываний ожидания готовности. Расширение границ применяемости налицо. Теперь работу с EEPROM можно производить в нескольких параллельных потоках. То, что при этом может происходить "замирание" обработки прерывания на время ожидания готовности - дело программиста: применять или нет.
Теперь любой, кому придет в голову эта бредовая идея, может писать EEPROM в прерываниях без фатальных последствий для своей программы
А вот проверки готовности флеша (от SPM) тут тоже нет. И это нужно помнить.
Так что применять можно все, только нужно хорошо понимать что делаешь
з.ы. меня сначала смутил тот момент, что сохранение регистра r0,
IgorKossak добавил только в __eeget8_16
Но при проверке оказалось, что компилятор не проверяет asm файл с текстом неоригинальной программы, а тупо смотрит на имя функции. Если в прерывании есть __eeput8_16, то сохраняет r0, хотя вы его в своей функции можете и не применять, а применять кучу других регистров, которые компилятор и не подумает сохранить. А если видит __eeget8_16, то r0 не сохраняет (в оригинальной функции его нет).