Jump to content

    
Sign in to follow this  
makc

На STM32F072 при включенном RDP не работает NRST

Recommended Posts

Всем привет!

Имеется МК 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: Не то чтобы эта особенность очень мешает жить, но хочется разобраться в этом странном поведении МК.

Share this post


Link to post
Share on other sites

Приветствую!
 

Цитата

После отдачи команды 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 в нуле.

Share this post


Link to post
Share on other sites

Можно попробовать передернуть питание после установки защиты.

Нужно проверить, что все option-биты описаны для данного МК верно.

Share this post


Link to post
Share on other sites
11 минут назад, Arlleex сказал:

Ну а чего Вы хотели, как бы?

Чтобы ресет работал, как обычно. Сам по себе HardFault у меня вопросов не вызывает.

12 минут назад, Arlleex сказал:

Надо бы осциллом глянуть, не держит ли сам МК NRST в нуле.

Проверял, не держит. Такое впечатление, что у него этот пин вообще оказывается отключён. Отсюда напрашивается вопрос: как они это делают? Как можно через регистры замаскировать внешний ресет?

4 минуты назад, adnega сказал:

Можно попробовать передернуть питание после установки защиты.

Это помогает, но неудобно до жути. В качестве альтернативы я сейчас использую запись в регистр FLASH_CR, которая одновременно обновляет действующее состояние RDP.

5 минут назад, adnega сказал:

Нужно проверить, что все option-биты описаны для данного МК верно.

Что Вы имеете в виду?

Есть, кстати, подобный вопрос на SourceForge: https://sourceforge.net/p/openocd/tickets/179/

Только на него нет ни одного ответа.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

С другой стороны из описания регистра 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

 

Share this post


Link to post
Share on other sites

У меня так и не получилось через OBL_LAUNCH перезагрузить. Только передергивание питания помогает.

Пару раз словил нетикающий SysTick, пока не сбросишь питание.

Share this post


Link to post
Share on other sites
3 минуты назад, adnega сказал:

У меня так и не получилось через OBL_LAUNCH перезагрузить. Только передергивание питания помогает.

В OpenOCD перед записью нужно сделать poll off. После этого запись OBL_LAUNCH во FLASH_CR проходит нормально и МК успешно перезагружается. Если не сделать poll off, то после записи получаем новый HardFault и естественно ничего не работает.

8 минут назад, adnega сказал:

Пару раз словил нетикающий SysTick, пока не сбросишь питание.

За два дня экспериментов ни разу не наблюдалось таких проблем. Все тикает как надо.

Кстати, после сброса с помощью OBL_LAUNCH NRST снова начинает работать как ни в чем не бывало.

Share this post


Link to post
Share on other sites
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();
  }
}


Она после первого включения устройства настраивает байты опций, в том числе ставит защиту от чтения/записи.

Share this post


Link to post
Share on other sites
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 дергает за ресет). МК находится в "подвешенном" состоянии, пока не передернешь питание.

Share this post


Link to post
Share on other sites
5 часов назад, Baser сказал:

МК находится в "подвешенном" состоянии, пока не передернешь питание

Коллеги, простите, я правильно понял, что не работает внешняя железная нога сброса?????

Share this post


Link to post
Share on other sites
1 час назад, MrBearManul сказал:

Коллеги, простите, я правильно понял, что не работает внешняя железная нога сброса?????

Да, именно так. Я пробовал сбрасывать МК с помощью шупа, подключенного к земле и не было никакой реакции.

7 часов назад, Baser сказал:

МК находится в "подвешенном" состоянии, пока не передернешь питание.

Или пока не сбросишь с помощью OBL_LAUNCH.

Пробовал генерировать внутренний сигнал сброса через NVIC, но это ничего не дало. Хотя сегодня ещё проверю, может быть при этом я забыл отключить poll в OpenOCD.

Share this post


Link to post
Share on other sites
49 минут назад, makc сказал:

Да, именно так. Я пробовал сбрасывать МК с помощью шупа, подключенного к земле и не было никакой реакции.

Удивительно! Это бросает вызов моей системе знаний об устройстве мира. Выходит, что в некоторых ситуациях внешний сторожевой пёс не сможет привести устройство в норму?

Share this post


Link to post
Share on other sites
6 минут назад, makc сказал:

Но есть ведь и внутренний.

Внутреннему эту работу не доверяю, т.к. от момента старта процессора до выполнения собственной программы с инициализацией сторожевика проходит время. А за это время процессор может повиснуть по ряду причин. Например, из-за бага в программе загрузчика.

8 минут назад, makc сказал:

А вообще надёжнее чем передёргивание питания ничего нет. :boredom:

Ох, где-то я уже слышали или читал об этом... Видимо, да, вы правы!

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this