STM8 ASM безопасно выполнить WFE
Я запустил c-код из ОЗУ в режиме низкого энергопотребления (поэтому прерывания не обрабатываются). Этот режим включен по кодовой последовательности:
- перейти в RAM
- SIM
- выключите внутреннюю вспышку и регулятор мощности, переключитесь на низкоскоростной источник тактовой частоты (LSE)
- поработать с режимом WFE (режим ожидания с низким энергопотреблением)
- включить регулятор мощности и вспышку, восстановить источник синхронизации
- RIM
- перейти к вспышке
Таким образом, нет никаких проблем с инструкцией WFE, описанной в листе ошибок. Проблема с этой конструкцией, это может быть причиной блокировки процессора в режиме ожидания с низким энергопотреблением навсегда:
while nbit(TIM1_SR1,CC3IF) asm("wfe");
это разборка как:
000035 720252B602 BTJT TIM1_SR1, #1, 0xB6
00003A 728F WFE
Событие от таймера имеет вероятностный характер, и этот код не гарантирует, что это произойдет после выполнения инструкции WFE:
- BTJT инструкция выполняется в 2 цикла и имеет длину 5;
- код, выполняемый из ОЗУ, может быть не непрерывным, поскольку состояния "выборки" приостанавливают выполнение на несколько циклов
Я использую руководство PM0044, и на странице 26 оно содержит довольно симпатичную таблицу:
Было 2 случая, когда выполнение кода останавливалось на 3 циклах. Поэтому я не уверен, что мое событие асинхронного пробуждения не произойдет между инструкциями BTJT и WFE.
Есть ли способы обеспечить строгую логическую последовательность (проверьте условие> wfe > событие wakeup)?
2 ответа
Решение, найденное ОП:
Я прочитал опечатки (спасибо Россу Риджу) несколько раз внимательнее, и это главная идея:
Общее решение состоит в том, чтобы гарантировать, что во время выполнения или повторного выполнения команды WFE не будет возникать запрос или событие прерывания с помощью надлежащей синхронизации приложения.
Если ваши проблемы с блокировкой вызваны ошибками WFE, о которых я упоминал, тогда должно быть более простое решение, чем попытка добиться "правильной синхронизации приложения".
Ошибки, предоставленные STMicroelectronics, гласят:
Могут возникнуть два типа сбоев:
Случай 1:
В случае, если инструкция WFE помещена в два старших бита 32-битного слова в памяти, событие, которое происходит во время цикла выполнения WFE или цикла повторного выполнения (при возврате из обработчика ISR), приведет к неправильному выполнению кода.Случай 2:
Запрос прерывания, который происходит во время цикла выполнения WFE, приведет к некорректному выполнению кода. Это также верно для цикла повторного выполнения WFE при возврате из обработчика ISR.
Случай 2 не должен применяться в вашем случае, поскольку вы говорите: "Прерывания не обрабатываются, потому что я использую режим работы с низким энергопотреблением". Если прерывания не могут произойти во время инструкции WFE, только сбой, описанный в первом случае, мог вызвать ваши блокировки.
Случай 1 применяется только в том случае, если инструкция WFE находится в определенном выравнивании в 32-битном слове в памяти. Поэтому, если вы можете быть уверены, что инструкция WFE никогда не появится в выровненном коде, вы не столкнетесь с этой ошибкой. Если ваш ассемблер поддерживает директиву выравнивания, вы можете использовать ее для достижения этого, возможно, вместе с меткой и переходом, если ассемблер не вставляет NOP. Однако более простое решение дается как "специальный обходной путь", например:
Заменить инструкцию WFE на
WFE JRA next next:
Похоже, что это помогает обойти ошибку, помещая то, что составляет 2-байтовый NOP после инструкции WFE. Я предполагаю, что ошибка приводит к тому, что ЦП не выполняет инструкцию, следующую непосредственно за инструкцией WFE, вместо этого пропуская два байта до инструкции (если есть) в начале следующего 32-битного мира. Пропуск 2-байтового NOP в пропущенном месте означает, что не имеет значения, произошел сбой или нет.