makc 0 Posted February 10, 2021 · Report post Всем привет! Имеется МК STM32F072RBT6, который программируется и отлаживается с помощью OpenOCD через кабель на базе FT2232H. Всё прекрасно работает, пока не выполняется включение защиты от чтения. После отдачи команды lock 0 через OpenOCD (установка защиты от чтения RDP Level 1) начинаются странные эффекты: команда reset halt в OpenOCD перестает работать, при этом МК уходит в HardFault: > reset halt adapter speed: 1000 kHz SWD DPIDR 0x0bb11477 target halted due to debug-request, current mode: Handler HardFault xPSR: 0xc1000003 pc: 0xfffffffe msp: 0xfffffffc И после этого начинается самое интересное: МК перестаёт реагировать на внешний сигнал NRST. При этом его по-прежнему возможно отресетить путем записи в память, например, с помощью команды mww 0x40022010 0x2080, которая устанавливает бит OBL_LAUNCH в регистре FLASH_CR и перезагружает МК изнутри. При этом повторный reset halt приводит МК в то же самое состояние. Что это может быть? Это проявление какого-то встроенного механизма защиты STM32, который блокирует ресет при попытке чтения внутренней памяти? PS: Не то чтобы эта особенность очень мешает жить, но хочется разобраться в этом странном поведении МК. Quote Ответить с цитированием Share this post Link to post Share on other sites
Arlleex 0 Posted February 10, 2021 · Report post Приветствую! Цитата После отдачи команды lock 0 (установка защиты от чтения RDP Level 1) команда reset halt в OpenOCD перестает работать, при этом МК уходит в HardFault... Ну а чего Вы хотели, как бы? Цитата Level 1: read protection ...Debug, boot RAM and boot loader modes In debug mode (with SWD) or when code is running from boot RAM or boot loader, the main Flash memory and the backup registers (RTC_BKPxR in the RTC) are totally inaccessible. In these modes, even a simple read access generates a bus error and a Hard Fault interrupt. The main Flash memory is program/erase protected to prevent malicious or unauthorized users from reprogramming any of the user code with a dump routine. Any attempted program/erase operation sets the PGERR flag of Flash status register (FLASH_SR)... То, что сбросить по внешней ноге NRST невозможно - это да, есть такое. Скорее всего, баг. Надо бы осциллом глянуть, не держит ли сам МК NRST в нуле. Quote Ответить с цитированием Share this post Link to post Share on other sites
adnega 0 Posted February 10, 2021 · Report post Можно попробовать передернуть питание после установки защиты. Нужно проверить, что все option-биты описаны для данного МК верно. Quote Ответить с цитированием Share this post Link to post Share on other sites
makc 0 Posted February 10, 2021 · Report post 11 минут назад, Arlleex сказал: Ну а чего Вы хотели, как бы? Чтобы ресет работал, как обычно. Сам по себе HardFault у меня вопросов не вызывает. 12 минут назад, Arlleex сказал: Надо бы осциллом глянуть, не держит ли сам МК NRST в нуле. Проверял, не держит. Такое впечатление, что у него этот пин вообще оказывается отключён. Отсюда напрашивается вопрос: как они это делают? Как можно через регистры замаскировать внешний ресет? 4 минуты назад, adnega сказал: Можно попробовать передернуть питание после установки защиты. Это помогает, но неудобно до жути. В качестве альтернативы я сейчас использую запись в регистр FLASH_CR, которая одновременно обновляет действующее состояние RDP. 5 минут назад, adnega сказал: Нужно проверить, что все option-биты описаны для данного МК верно. Что Вы имеете в виду? Есть, кстати, подобный вопрос на SourceForge: https://sourceforge.net/p/openocd/tickets/179/ Только на него нет ни одного ответа. Quote Ответить с цитированием Share this post Link to post Share on other sites
Arlleex 0 Posted February 10, 2021 · Report post 4 минуты назад, makc сказал: Это помогает, но неудобно до жути... Видимо, не зря они сами пишут об этом Цитата 3.3.1 Read protection The read protection is activated by setting the RDP option byte and then, by applying a system reset to reload the new RDP option byte.Note: If the read protection is set while the debugger is still connected through SWD, apply a POR (power-on reset) instead of a system reset. Quote Ответить с цитированием Share this post Link to post Share on other sites
makc 0 Posted February 10, 2021 · Report post С другой стороны из описания регистра FLASH_CR: Цитата Bit 13 OBL_LAUNCH: Force option byte loading When set to 1, this bit forces the option byte reloading. This operation generates a system reset. 0: Inactive 1: Active Quote Ответить с цитированием Share this post Link to post Share on other sites
adnega 0 Posted February 10, 2021 · Report post У меня так и не получилось через OBL_LAUNCH перезагрузить. Только передергивание питания помогает. Пару раз словил нетикающий SysTick, пока не сбросишь питание. Quote Ответить с цитированием Share this post Link to post Share on other sites
makc 0 Posted February 10, 2021 · Report post 3 минуты назад, adnega сказал: У меня так и не получилось через OBL_LAUNCH перезагрузить. Только передергивание питания помогает. В OpenOCD перед записью нужно сделать poll off. После этого запись OBL_LAUNCH во FLASH_CR проходит нормально и МК успешно перезагружается. Если не сделать poll off, то после записи получаем новый HardFault и естественно ничего не работает. 8 минут назад, adnega сказал: Пару раз словил нетикающий SysTick, пока не сбросишь питание. За два дня экспериментов ни разу не наблюдалось таких проблем. Все тикает как надо. Кстати, после сброса с помощью OBL_LAUNCH NRST снова начинает работать как ни в чем не бывало. Quote Ответить с цитированием Share this post Link to post Share on other sites
Arlleex 0 Posted February 10, 2021 · Report post 1 час назад, adnega сказал: У меня так и не получилось через OBL_LAUNCH перезагрузить. Только передергивание питания помогает. У меня в загрузчике практически первой стартует функция #define LockNVMOp() FLASH->CR = FLASH_CR_LOCK #define UnlockROMOp() FLASH->KEYR = 0x45670123, FLASH->KEYR = 0xCDEF89AB #define UnlockOptOp() FLASH->OPTKEYR = 0x45670123, FLASH->OPTKEYR = 0xCDEF89AB #define ClrROMOpSReg() FLASH->SR = FLASH_SR_PGERR | FLASH_SR_WRPERR | FLASH_SR_EOP #define UpdSysOpt() FLASH->CR = FLASH_CR_OBL_LAUNCH #define isROMBsy() (FLASH->SR & FLASH_SR_BSY) void hw_InitOpt(void) { #define RDP_LVL0 0xAA #define RDP_LVL1 0x12 #define WRP_SECT (B1 | B0) #define RDP(t) (OPT(t)[0]) #define WRP (&OPT(u16)[4]) #define OPT(t) ((volatile t *)MCU_OPT_BEG) if(RDP(u8) == RDP_LVL0) { UnlockROMOp(); UnlockOptOp(); FLASH->CR |= FLASH_CR_OPTER; FLASH->CR |= FLASH_CR_STRT; while(isROMBsy()){} ClrROMOpSReg(); FLASH->CR = FLASH_CR_OPTPG | FLASH_CR_OPTWRE; RDP(u16) = RDP_LVL1; while(isROMBsy()){} ClrROMOpSReg(); WRP[0] = WRP_SECT << 8 | (u8)~WRP_SECT; while(isROMBsy()){} ClrROMOpSReg(); LockNVMOp(); UpdSysOpt(); } } Она после первого включения устройства настраивает байты опций, в том числе ставит защиту от чтения/записи. Quote Ответить с цитированием Share this post Link to post Share on other sites
Baser 0 Posted February 10, 2021 · Report post 5 часов назад, Arlleex сказал: Видимо, не зря они сами пишут об этом Цитата 3.3.1 Read protection The read protection is activated by setting the RDP option byte and then, by applying a system reset to reload the new RDP option byte.Note: If the read protection is set while the debugger is still connected through SWD, apply a POR (power-on reset) instead of a system reset. Сильно не разбирался, но действительно, когда прошиваю STM32L151 через SWD при помощи консольного варианта ST-Link и установкой защиты Level 1, в конце программирования команда рестарта МК не выполняется (хотя есть, и ST-Link дергает за ресет). МК находится в "подвешенном" состоянии, пока не передернешь питание. Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted February 11, 2021 · Report post 5 часов назад, Baser сказал: МК находится в "подвешенном" состоянии, пока не передернешь питание Коллеги, простите, я правильно понял, что не работает внешняя железная нога сброса????? Quote Ответить с цитированием Share this post Link to post Share on other sites
makc 0 Posted February 11, 2021 · Report post 1 час назад, MrBearManul сказал: Коллеги, простите, я правильно понял, что не работает внешняя железная нога сброса????? Да, именно так. Я пробовал сбрасывать МК с помощью шупа, подключенного к земле и не было никакой реакции. 7 часов назад, Baser сказал: МК находится в "подвешенном" состоянии, пока не передернешь питание. Или пока не сбросишь с помощью OBL_LAUNCH. Пробовал генерировать внутренний сигнал сброса через NVIC, но это ничего не дало. Хотя сегодня ещё проверю, может быть при этом я забыл отключить poll в OpenOCD. Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted February 11, 2021 · Report post 49 минут назад, makc сказал: Да, именно так. Я пробовал сбрасывать МК с помощью шупа, подключенного к земле и не было никакой реакции. Удивительно! Это бросает вызов моей системе знаний об устройстве мира. Выходит, что в некоторых ситуациях внешний сторожевой пёс не сможет привести устройство в норму? Quote Ответить с цитированием Share this post Link to post Share on other sites
makc 0 Posted February 11, 2021 · Report post Получается что так. Но есть ведь и внутренний. А вообще надёжнее чем передёргивание питания ничего нет. Quote Ответить с цитированием Share this post Link to post Share on other sites
MrBearManul 0 Posted February 11, 2021 · Report post 6 минут назад, makc сказал: Но есть ведь и внутренний. Внутреннему эту работу не доверяю, т.к. от момента старта процессора до выполнения собственной программы с инициализацией сторожевика проходит время. А за это время процессор может повиснуть по ряду причин. Например, из-за бага в программе загрузчика. 8 минут назад, makc сказал: А вообще надёжнее чем передёргивание питания ничего нет. Ох, где-то я уже слышали или читал об этом... Видимо, да, вы правы! Quote Ответить с цитированием Share this post Link to post Share on other sites