В семействе STM8 заложена очень полезная возможность экономии энергии в случае, когда быстрые и критичные ко времени обработки выполняются по прерываниям, а низкоприоритетные задачи работают в фоновом режиме. Для этого используется бит AL в регистре GCR и машинная команда WFI. Однако здесь был обнаружен подводный камень, не описанный в текущей версии errata на кристалл.
Данная проблема была обнаружена на кристалле stm8l152c6t6, установленном на STM8L-Discovery board.
В основном процессе был инициализирован таймер TIM4 для работы по прерываниям. Обработчик прерывания для него практически пустой (ну за исключением процедуры сброса бита TIM_SR1_UIF в регистре TIM4->SR1). Далее в основном процессе была разрешена запись в EEPROM путем разблокировки MASS и инициирована процедура записи байта с генерацией IRQ по ее окончании. После чего в регистре GCR был установлен бит AL и выполнена команда WFI.
В обработчике прерываний по завершению операции записи в EEPROM после чтения содержимого FLASH->IAPSR понижается приоритет выполняемого кода командой RIM или комбинацией PUSH #val/POP CC. Т.е. внутри EEPROM ISR разрешаются все остальные прерывания. И было обнаружено следующее: если EEPROM ISR была прервана другим прерыванием, то после возврата из вложенного прерывания выполнение обработки EEPROM ISR прекращается (т.е. такое впечатление, что CPU core переходит в состояние WFI, выполненное основным процессом).
Данная ошибка проявляется только при наличии следующих условий:
- Перед выполнением WFI в основном процессе бит AL в регистре GCR был установлен
- Приоритет EEPROM IRQ оставлен по умолчанию (т.е. содержимое регистра ITC->ISPR1 равно 0xFF)
Возможные workarounds:
- В основном процессе до выполнения инструкции WFI сбросить бит AL в GCR. При этом после каждого прерывания основной процесс будет возобновлять свое выполнение, что не очень хорошо скажется на энергопотреблении.
- Перед понижением приоритета внутри EEPROM ISR (т.е. до команд RIM или PUSH #val/POP CC) также сбросить бит AL в GCR. Опять-таки, в этом случае после завершения EEPROM ISR основной процесс продолжит свое выполнение, что не очень хорошо скажется на энергопотреблении.
- Изменить приоритет EEPROM IRQ в регистре ITC->ISPR1, например записав в него значение 0b11110111. Что самое непонятное, после этого начинают нормально работать команды RIM или PUSH #val/POP CC внутри EEPROM ISR (т.е. после возврата из вложенного прерывания обработка EEPROM ISR возобновляется).
Господа, у кого есть желание/возможность, попробуйте воспроизвести этот баг на других кристаллах семейства STM8/STM8L. Ибо если этот баг действительно воспроизводим, то надо пнуть STM на предмет его исправления или хотя бы внесения в errata sheet.
Автор: Vedga