ESP8266 / Arduino: Почему необходимо добавить макрос ICACHE_RAM_ATTR к ISR и функциям, вызываемым оттуда? - PullRequest
0 голосов
/ 26 сентября 2019

Я прочитал, что мне необходимо добавить макрос ICACHE_RAM_ATTR для прерывания процедур обслуживания (ISR) и к каждой функции, которая вызывается оттуда в моем коде Arduino для ESP8266, чтобы предотвратить случайноесбои.Я также нашел объяснение того, что макрос ICACHE_RAM_ATTR делает , хотя я не уверен, что объяснение, которое относится к Espressif ESP8266 SDK, также верно для Arduino на ESP8266.И я не понял, почему мне нужно добавить макрос в ISR.

Первый вопрос: Почему мне нужно добавить макрос ICACHE_RAM_ATTR в ISR и все функции, вызываемые оттуда?

Следующий вопрос: что произойдет, если я принудительно вставлю функцию, вызываемую из ISR:

inline void doStuff() __attribute__((__always_inline__)) { // <-- necessary to add ICACHE_RAM_ATTR here?
    // no more function calls here
}

void ICACHE_RAM_ATTR handleInterrupt() {
    doStuff();
}

Второй вопрос: Нужно ли добавить макрос ICACHE_RAM_ATTR вфункции, которые вынуждены быть встроенными?

1 Ответ

1 голос
/ 27 сентября 2019

ICACHE_RAM_ATTR и ICACHE_FLASH_ATTR являются атрибутами компоновщика.Скомпилировав эскиз, вы можете сказать, должна ли функция храниться в ОЗУ или во флэш-памяти (обычно вы ничего не устанавливаете: нет кэша).

ESP8266 является многозадачным, а ESP32 имеет 2 ядра.Таким образом, вы можете выполнять свой код как многопоточность - поскольку он использует ОСРВ.

И теперь проблема: вся программа используется для программы и хранилища.Чтение и запись на флэш-память могут выполняться только через 1 поток.Если вы попытаетесь получить доступ к флэш-памяти одновременно через 2 разных потока, ваш ESP, вероятно, потерпит крах.

Это потому, что вы можете поместить свою функцию в ОЗУ вместо флэш-памяти.Таким образом, даже если вы что-то записываете в EEPROM или на флэш-память, эту функцию можно вызывать без доступа к флэш-памяти.

С помощью ICACHE_RAM_ATTR вы помещаете эту функцию в ОЗУ.

С помощью ICACHE_FLASH_ATTR Вы поместили функцию на FLASH (для экономии оперативной памяти).

Функции прерывания должны использовать ICACHE_RAM_ATTR.Функция, которая вызывается часто, не должна использовать какой-либо атрибут кэша.

Важно: НИКОГДА не получайте доступ к вашей флэш-памяти внутри прерывания!Прерывание может произойти во время доступа к флеш-памяти, поэтому, если вы попытаетесь получить доступ к флеш-памяти в одно и то же время, произойдет сбой (а иногда это происходит через 1-2 часа после использования устройства).

Поскольку у вас есть только 32 КБ IRAM (оперативной памяти), вам следует попытаться поместить в оперативную память только функции прерывания, а не все ваши функции, даже если это возможно.

Второй вопрос: НЕТ, абсолютно нет!inline - это еще один флаг компилятора, так что компилятор попытается поместить всю вашу функцию внутрь функции вызывающей функции => преобразовать вызов функции в код c ++ внутри вашей main.Это не значит, что компилятор сделает это, просто попробуйте.Вы не можете попросить поместить функцию в ОЗУ, если функция больше не существует после компиляции эскиза.

...