Как предотвратить сбой на STM32H7 при замене флэш-накопителей

#embedded #stm32 #cortex-m #stm32h743

Вопрос:

Я использую STM32H753, который имеет два банка флэш-памяти. Для обновления прошивки я использую функцию обмена банковскими картами, чтобы микроконтроллер загружался в правильную версию.

Когда я меняю банки местами, микроконтроллер выходит из строя. Никаких сбоев или каких-либо других исключений. Отладчик сообщает мне, что ПК находится на 0x72c269e, а SP-на 0xbf00d7b4, но раньше они были другими, и я предполагаю, что эти адреса являются случайными.

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

Вот код, который делает это:

 pub fn swap_bank(flash: amp;mut stm32h7xx_hal::stm32::FLASH) -> Result<(), amp;'static str> {
    assert!(flash.optcr().read().optlock().bit_is_clear());

    // Get the current config
    let current_bank = get_current_bank(flash) != 1;
    let swapped_bank = !current_bank;

    // Config the new bank
    flash
        .optsr_prg()
        .modify(|_, w| w.swap_bank_opt().bit(swapped_bank));

    // Start the config write
    flash.optcr().modify(|_, w| w.optstart().set_bit());
    
    // Wait for the change to propegate
    while flash.optsr_cur().read().opt_busy().bit_is_set() {
        cortex_m::asm::nop();
    }

    // We're done, now we need to reboot
    Ok(())
}

pub fn get_current_bank(flash: amp;mut stm32h7xx_hal::stm32::FLASH) -> u8 {
    flash.optcr().read().swap_bank().bit() as u8   1
}
 

Если я помещу инструкцию bkpt перед циклом while, она будет выполнена оба раза (и если я затем продолжу, оба раза не произойдет сбоя).
Если я помещу инструкцию bkpt после цикла while, она не попадет при первой замене.

В справочном руководстве (4.3.13) говорится следующее:

  1. Разблокируйте бит OPTLOCK, если он еще не разблокирован.
  2. Установите новое желаемое значение SWAP_BANK_OPT в регистре FLASH_OPTSR_PRG.
  3. Запустите последовательность изменения байта опции, установив бит OPTSTART в регистре FLASH_OPTCR.
  4. Как только изменение байта опции завершено, FLASH_OPTSR_CUR содержит ожидаемое значение SWAP_BANK_OPT, но бит SWAP_BANK во FLASH_OPTCR еще не изменен, и замена банка еще не вступила в силу.
  5. Принудительный сброс системы или POR. Когда произойдет сброс, произойдет замена банка (значение SWAP_BANK обновлено во FLASH_OPTCR), и будет выполнена новая прошивка.

Я думаю, что делаю это правильно. Я также проверил ошибки, и в старом кремнии были проблемы с переключением банка, но я использую новейшую V версию.

Я надеюсь, что кто-нибудь сможет дать мне совет.

Комментарии:

1. Вы пытаетесь записать на флэш-память из того же банка, в котором находится драйвер флэш-памяти? Я не знаю подробностей этой конкретной части, но микроконтроллерам в целом не нравится, когда вы это делаете. Поэтому, если вы пытаетесь реализовать какой-либо загрузчик для программирования банка 1 или 2, вам необходимо разместить идентичный код драйвера флэш-памяти в обоих банках и выполнить из того, который не программируется.

2. Программа полностью расположена в одном банке. Обновление прошивки записывается во второй банк, после чего банки меняются местами и происходит перезагрузка для запуска новой прошивки. Только память второго банка записывается и стирается.

3. Что именно вы пишете во флэш-банке 2 ?

4. @GabrielT Итак, банк 1 содержит прошивку v1.0.0. Затем у меня появилась новая версия v1.0.1. Сервер запускает обновление и отправляет более 1.0.1. Устройство поместит данные в банк 2. Когда все будет закончено, сервер отправит CRC данных. Когда устройство подтвердит правильность CRC полученных и сохраненных данных в банке 2, оно инициирует обмен и перезагрузку. Версия, которую он запускает, теперь 1.0.1

5. Если он правильно работает с точкой останова, то, возможно, существует проблема с синхронизацией, которую можно избежать, когда точка останова вызывает задержку. Попробуйте добавить короткую задержку (возможно, nop(s)) перед циклом while.