Перейти к системному загрузчику из кода пользователя с STM32F042K6 - PullRequest
0 голосов
/ 04 марта 2019

РЕДАКТИРОВАТЬ: В соответствии с решением Девана, мне удается выскочить загрузчик системы из кода пользователя с STM32F042K6.

boot.h

/* boot.h */
#include "stm32f0xx_hal.h"

#if defined(STM32F042x6) || defined(STM32F048xx) 
    #define SYSTEM_MEMORY_ADDRESS       0x1FFFC400
#elif defined(STM32F070xB)
    #define SYSTEM_MEMORY_ADDRESS   0x1FFFC800
#elif defined(STM32F070x6)
    #define SYSTEM_MEMORY_ADDRESS       0x1FFFC400
#endif

HAL_StatusTypeDef SystemBootloaderJump(void);

boot.c

/* boot.c */
#include "boot.h"

/* I just re-write this code -> https://electronics.stackexchange.com/questions/312303/stm32f091-jump-to-bootloader-from-application */
HAL_StatusTypeDef SystemBootloaderJump(void)
{
    typedef void (*pFunction)(void);
    pFunction JumpToApplication;

    __HAL_RCC_USART1_FORCE_RESET();
    HAL_Delay(5);
    __HAL_RCC_USART1_RELEASE_RESET();
    HAL_Delay(5);

    HAL_RCC_DeInit();

    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

    /**
     * Step: Disable all interrupts
     */
    __disable_irq();

    /* ARM Cortex-M Programming Guide to Memory Barrier Instructions.*/
    __DSB();

    __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();

    /* Remap is bot visible at once. Execute some unrelated command! */
    __DSB();
    __ISB();

    /** Get option bytes. 
        *   More info at -> RM0091 Reference manual STM32F0x1/STM32F0x2/STM32F0x8 advanced ARM®-based 32-bit MCUs
        *   4 Option byte 
        *           There are up to 8 option bytes. They are configured by the end user depending on the
        *       application requirements. 
        *       ...
        *       ...
        *           4.1 Option byte description
        *               4.1.1 User and read protection option byte
        *                   Flash memory address: 0x1FFF F800
        *                   ...
        *                   Bits 23:16 USER: User option byte (stored in FLASH_OBR[15:8])
        *                       Bit 23: BOOT_SEL
        *                           0: BOOT0 signal is defined by nBOOT0 option bit
        *                           1: BOOT0 signal is defined by BOOT0 pin value (legacy mode)
        *                       Available on STM32F04x and STM32F09x devices only. Considered as “1” on other devices.
        *                       ...
        *                       ...
        *                       Bit 19: nBOOT0
        *                       When BOOT_SEL is cleared, nBOOT0 bit defines BOOT0 signal value used to select the
        *                       device boot mode. Refer to Section 2.5: Boot configuration for more details.
        *                       Available on STM32F04x and STM32F09x devices only.
        */
    FLASH_OBProgramInitTypeDef pOBInit;
    /* Get the Option byte configuration */
    HAL_FLASHEx_OBGetConfig(&pOBInit);

    /* BOOT_SEL = 0 */
    pOBInit.USERConfig &= ~(OB_BOOT_SEL_SET);
    /* nBOOT0=1 */
    pOBInit.USERConfig |= OB_BOOT0_SET;


    /** HAL_FLASHEx_OBProgram && HAL_FLASHEx_OBErase
      * HAL_FLASH_OB_Unlock() should be called before to unlock the options bytes
      */
    if(HAL_FLASH_OB_Unlock() != HAL_OK)
    {
        return HAL_ERROR;
    }

    /*We need to erase option bytes before write. */
    if(HAL_FLASHEx_OBErase() != HAL_OK)
    {
        return HAL_ERROR;
    }

    /* Write changed option bytes */
    if(HAL_FLASHEx_OBProgram(&pOBInit))
    {
        return HAL_ERROR;
    }

    JumpToApplication = (void (*)(void)) (*((uint32_t *) ((SYSTEM_MEMORY_ADDRESS + 4))));

    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) SYSTEM_MEMORY_ADDRESS);

    JumpToApplication();
    return HAL_OK;
}

Как выполнить сброс микроконтроллера STM32 после удаления флэш-страницы?

Моя цель - запустить системный загрузчик с флэш-памяти пользователя с микроконтроллером STM32F042K6. Но в AN2606 Замечание по применению Режим загрузки системной памяти микроконтроллера STM32 говорит:

Из-за пустого механизма проверки, присутствующего на этом продукте, невозможно перейти с кода пользователя на системный загрузчик.Такой переход приведет к возврату к пользовательскому флеш-пространству.Но если первые 4 байта пользовательской флэш-памяти (в 0x0800 0000) пусты в момент перехода (т. Е. Стереть первый сектор перед переходом или выполнить код из SRAM, когда Flash пуст), тогда системный загрузчик будет выполнен при переходе к.

Итак, я поместил свои функции, кроме main (), в ROM 0x08007C00 - 0x08007FFF (последняя страница моей флэш-памяти).В моей основной функции я вызываю функцию стирания, расположенную на последней странице флэш-памяти моего микроконтроллера, и стираю первую страницу.Первая страница удаляется успешно, но после этого я не могу сбросить свой микроконтроллер в программном обеспечении или не могу перейти к системному загрузчику.Микроконтроллер где-то застрял, но я не смог найти.Но когда я перезагружаю микроконтроллер с помощью кнопки сброса, он загружается с системного загрузчика.Это значит, что если я смогу каким-то образом сбросить микроконтроллер, я достигну своей цели.

Я открыт другими решениями.Мой код такой:

/* main.c located at 0x0800 0000 - 0x0800 7BFF */
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM16_Init();

  StartBoot();

  while(1){}
 }

/* boot.c located at 0x0800 7C00 - 0x0800 7FFF */

#define ADDR_FLASH_PAGE_0     ((uint32_t)0x08000000) /* Base @ of Page 0, 1 Kbyte */

void StartBoot(void)
{
    if(ErasePage(ADDR_FLASH_PAGE_0) == HAL_OK)
    {
        HAL_FLASH_Lock();
        NVIC_SystemReset();
    }
}

HAL_StatusTypeDef ErasePage(uint32_t address)
{
/* Unlock the Flash to enable the flash control register access */
  HAL_FLASH_Unlock();

  /* Erase the user Flash area */

  /* Fill EraseInit structure*/
  EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
  EraseInitStruct.PageAddress = address;
  EraseInitStruct.NbPages     = 1; /* Erase 1 Page */

  /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
     you have to make sure that these data are rewritten before they are accessed during code
     execution. If this cannot be done safely, it is recommended to flush the caches by setting the
     DCRST and ICRST bits in the FLASH_CR register. */
  if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)
  {
    /*
      Error occurred while page erase.
      User can add here some code to deal with this error.
      PAGEError will contain the faulty page and then to know the code error on this page,
      user can call function 'HAL_FLASH_GetError()'
    */
        HAL_FLASH_Lock();
        return HAL_ERROR;

  }
    return HAL_OK;
}

1 Ответ

0 голосов
/ 04 марта 2019

Это примечание к приложению немного странно.Я работал с серией STM32F042, включая STM32F042K6 специально.По моему опыту, единственное странное поведение по сравнению с другими частями семейства STM32 заключается в том, что загрузчик принудительно запускает бит BOOT_SEL во время выполнения, а не только при загрузке чипа после сброса.

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

Чтобы обойти это,Вы можете установить BOOT_SEL=0 и nBOOT0=1 в байтах опции, чтобы при загрузке он всегда загружался с основной флэш-памяти, как показано в таблице ниже: Table 3. Boot Modes, from section 2.5 of RM0091

После установкиОпция байтов таким образом, вы можете воспользоваться обычным подходом remap-memory-and-jump-to-bootloader , который уже был рассмотрен несколько раз.

(Примечание:Загрузочная память серии STM32F042 живет в 0x1FFFC400, в отличие от 0x1FFFC800, показанного в примере STM32F072).

В качестве предостережения, отключение проверки булавки BOOT не позволит вам использовать BOOT pчтобы заставить чип в загрузчик.Возможно, вы захотите добавить свою собственную проверку программного обеспечения, чтобы прочитать пин BOOT0 в начале загрузки и перейти к загрузчику.

...