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 в пропущенном месте означает, что не имеет значения, произошел сбой или нет.

Другие вопросы по тегам