Cortex-M0+ не отвечает на PendSV

Я использую Raspberry Pi Pico (RP2040, ядро ​​Cortex-M0+, отладка через VSCode cortex-debug с помощью JLink SWD), и я наблюдаю странное поведение в отношении PendSV.

Непосредственно перед этим обработчик исключений SVCall запросил PendSV через регистр ICSR. Но при возврате исключения, а не в хвостовой цепочке PendSV, выполнение вместо этого возвращается к вызывающему коду и продолжает выполнение без исключения.

Все это время регистр ICSR показывает ожидающий PendSV, даже если инструкции кода потока повторяются неоднократно. Все приоритеты системных обработчиков равны нулю, приоритеты IRQ ниже.

Согласно справочному руководству ARMv6-M, PendSV нельзя отключить.

Итак, что мне не хватает, что могло бы вызвать такое поведение?

Отредактировано для добавления:

Возможно, это взаимодействие отладчика? Программное обеспечение JLink (v4.95d) все еще находится в стадии бета-тестирования ...

Я вижу, что отладчик может фактически отключить PendSV и Systick - C1.5.1 Debug Stepping: «По желанию отладчик может установить DHCSR.C_MASKINTS на 1, чтобы предотвратить возникновение PendSV, SysTick и внешних настраиваемых прерываний. Это называется маскированием этих прерываний. . Таблица C1-7 на странице C1-326 обобщает пошаговое управление инструкциями ".

2 ответа

Оказывается, проблема вызвана пошаговым выполнением инструкции, которая записывает в бит PENDSVSET в ICSR: бит установлен, и поле VECTPENDING показывает 0xe, но PendSV никогда не срабатывает.

Если запустить эту инструкцию до более поздней точки останова, PendSV сработает правильно.

Так что это действительно взаимодействие отладчика.

Связано ли это с запретом прерываний, как предлагает @cooperised, неясно - бит C_MASKINTS DHCSR везде читается как ноль, но то, как этот бит манипулируется во время фактической пошаговой операции, на этом уровне не видно.

Это заставляет меня задаться вопросом, вызывает ли то, как JLink выполняет шаг, непредсказуемое / неопределенное поведение - например, согласно предупреждению в описании C_MASKINTS. Или, возможно, это просто то, что происходит в M0+ при этих обстоятельствах, и я никогда раньше не выполнял эту инструкцию одношагово.

В любом случае обходной путь состоит в том, чтобы просто не выполнять пошаговую инструкцию, устанавливающую PENDSVSET.

Отредактировано для добавления:

Наконец, @cooperised был правильным.

Если уделить больше внимания тому, чтобы точно различать пошаговое выполнение (включая переход через вызовы функций) и выполнение (включая переход к самой следующей инструкции), становится ясно, что пошаговое выполнение отключает прерывания, включая PendSV.

То же самое произошло и со мной, но я обнаружил, что причина в том, что я не закрывал предыдущее прерывание PensSV, возвращаясь через LR, содержащий 0xFFFFFFFF9. Вместо этого я возвращался через ПК на обратный адрес предыдущей процедуры.

Поскольку я не возвращался через 0xFFFFFFF9, он неправильно закрывал предыдущий PendSV и не распознавал последующие.

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