В недавней публикации разработчик Дэниел Мэнгам описал случай, с которым столкнулся при отладке микроконтроллера Nordic nRF54LM20 на ядре Cortex-M33. Он читал и записывал значения в разных сценариях, и поначалу всё шло без нареканий. Однако в какой-то момент отладчик GDB начал возвращать значения, из которых будто бы следовало, что предыдущая операция не выполнилась. На деле же причиной оказались устаревшие данные, отдававшиеся из кеша.

Отладочная плата с микроконтроллером Nordic nRF54LM20

реклама кормит Уточку 🦆

Дальше следует подробный низкоуровневый разбор того, как этот микроконтроллер устроен внутри — особенно его криптографических функций и блока управления ключами (Key Management Unit), где хранится конфиденциальная информация. Самое любопытное, что закешированные данные можно обойти, если явно указать порт доступа, адрес памяти и ряд других параметров.

реклама кормит Уточку 🦆

Команда ReadMemAP, поддерживаемая сервером JLinkGDBServer, показывала корректное значение, тогда как обычная команда чтения x в GDB упорно возвращала данные из кеша. Возник вопрос, какой именно кеш за это отвечает. Прямое чтение через порт доступа AHB-AP работало исправно, поэтому подозрение пало на собственное кеширование программного обеспечения J-Link — и запуск без него действительно снял проблему.

реклама кормит Уточку 🦆

У J-Link и раньше встречались сложности, связанные с аппаратной частью, но этот случай указывает на неприятную программную ошибку, которая способна отнять немало времени во время сеанса отладки. К счастью, здесь баг удалось быстро распознать и найти простой способ его обойти — прямое чтение памяти в обход кеша.