STM32F0的BOOT配置

问题来源:使用stm32f042时,本来设计的程序为USB端识别为键盘,但是每次插到电脑上都被枚举为DFU设备。

后来经过查找问题,因为stm32f042的boot0引脚被当做IO使用,并且外置了上拉电阻,根据启动选择,每次上电后会进入BootLoader(system memory)程序。

可以看出,对于STM32F04X和STM32F09X到底使用哪种配置方式取决于Boot_Sel选项位。对于非STM32F04X和STM32F09X的32F0系列芯片,配置方式只能使用第一种配置方式,此时Boot_Sel固定为1。

但是由于硬件设计原因,此处只能使用第二种方案:将Boot_Sel配置为0,nBoot0配置为1。

参考st官方应用笔记《STM32F09X不使用BOOT脚实现SYSTEMBOOTLOADER升级代码》,可以解决这个问题。但是st官方的程序是标准固件库版本的,我将其移植到了HAL库上。见以下代码:

参考笔记有:

《STM32F09X不使用BOOT脚实现SYSTEMBOOTLOADER升级代码》

《STM32F091从自举程序向应用程序跳转的问题与解决》

《STM32F091空片使用System Bootloader下载代码》

程序入口处调用:

    /* 以下两行代码,是将向量表映射为 Main Flash memory,否则从 Bootloader 跳转到用户 
    码时,将无法正常工作。如有不清楚之处,请参考另外一份文档: 
    《STM32F091 从自举程序向应用程序跳转的问题与解决》  */ 
    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
  SYSCFG->CFGR1 = (uint32_t)0x00000000;
 
    /* 此处调用子程序,用来判断 BOOT 的配置是否从 Main Flash memory 启动,如果不是,将 
     Option Bytes 中的BOOT 配置设置为从 Main Flash  memory 启动  */ 
  BOOTCONF_User(); 
 

 

在需要升级时调用:

BOOTCONF_System();

 

函数实现:

/**
  * @brief  Checks BOOT_SEL, nBOOT0, nBOOT1 and Reset.
  * @param  None
  * @retval None
  */
void BOOTCONF_User(void)
{
  HAL_StatusTypeDef status = HAL_OK;
  uint16_t ob[5];

  /* Get opiton bytes data */
  ob[0] = *(uint16_t*)(0x1FFFF800); //RDP
  ob[1] = *(uint16_t*)(0x1FFFF802);    //USER
  ob[2] = *(uint16_t*)(0x1FFFF804);    //DATA0
  ob[3] = *(uint16_t*)(0x1FFFF806);    //DATA1
  ob[4] = *(uint16_t*)(0x1FFFF808);    //WRP0

  /* Check boot configuration and correct */
  if((ob[1] & 0x0098) != 0x0018)
  {
    /* Unlock */
    HAL_FLASH_Unlock();
        HAL_FLASH_OB_Unlock();

    /* Erase and update Option bytes*/
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    if(status == HAL_OK)
    {   
      /* If the previous operation is completed, proceed to erase the option bytes */
      FLASH->CR |= FLASH_CR_OPTER;
      FLASH->CR |= FLASH_CR_STRT;
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
      /* If the erase operation is completed, disable the OPTER Bit */
      FLASH->CR &= ~FLASH_CR_OPTER;

      /* Update option bytes */
      ob[1] = (ob[1] & 0x6767) | 0x8018;
      /* Enable the Option Bytes Programming operation */
      FLASH->CR |= FLASH_CR_OPTPG;
      /* Restore the last read protection Option Byte value */
      OB->RDP = ob[0];
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
      if(status == HAL_TIMEOUT)
        while(1)    ;    //ERROR
      FLASH->CR &= ~FLASH_CR_OPTPG;
      FLASH->CR |= FLASH_CR_OPTPG;
      OB->USER = ob[1];
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
      if(status == HAL_TIMEOUT)
        while(1)    ;    //ERROR
      FLASH->CR &= ~FLASH_CR_OPTPG;
      FLASH->CR |= FLASH_CR_OPTPG;
      OB->DATA0 = ob[2];
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
      if(status == HAL_TIMEOUT)
         while(1)    ;    //ERROR
      FLASH->CR &= ~FLASH_CR_OPTPG;
      FLASH->CR |= FLASH_CR_OPTPG;
      OB->DATA1 = ob[3];
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
      if(status == HAL_TIMEOUT)
        while(1)    ;    //ERROR
      FLASH->CR &= ~FLASH_CR_OPTPG;
      FLASH->CR |= FLASH_CR_OPTPG;
      OB->WRP0 = ob[4];
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
      if(status == HAL_TIMEOUT)
        while(1)    ;    //ERROR
      FLASH->CR &= ~FLASH_CR_OPTPG;
    }
    else
    {
      if (status != HAL_TIMEOUT)
      {
        /* Disable the OPTPG Bit */
        FLASH->CR &= ~FLASH_CR_OPTPG;
      }
    }

    /* Lock */
    HAL_FLASH_OB_Lock();
    HAL_FLASH_Lock();

    /* Verify */
    if((*(uint16_t*)(0x1FFFF800)) != ob[0])
      while(1)    ;    //ERROR
    if((*(uint16_t*)(0x1FFFF802)) != ob[1])
      while(1)    ;    //ERROR
    if((*(uint16_t*)(0x1FFFF804)) != ob[2])
      while(1)    ;    //ERROR
    if((*(uint16_t*)(0x1FFFF806)) != ob[3])
      while(1)    ;       //ERROR
    if((*(uint16_t*)(0x1FFFF808)) != ob[4])
      while(1)    ;       //ERROR
    HAL_FLASH_OB_Launch();
  }
}

/**
  * @brief  Checks BOOT_SEL, nBOOT0, nBOOT1 and Reset.
  * @param  None
  * @retval None
  */
void BOOTCONF_System(void)
{
  HAL_StatusTypeDef status = HAL_OK;
  uint16_t ob[5];

  /* Get opiton bytes data */
  ob[0] = *(uint16_t*)(0x1FFFF800);     //RDP
  ob[1] = *(uint16_t*)(0x1FFFF802);    //USER
  ob[2] = *(uint16_t*)(0x1FFFF804);    //DATA0
  ob[3] = *(uint16_t*)(0x1FFFF806);    //DATA1
  ob[4] = *(uint16_t*)(0x1FFFF808);    //WRP0

  /* Unlock */
  HAL_FLASH_Unlock();
    HAL_FLASH_OB_Unlock();
  /* Erase and update Option bytes*/
  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
  if(status == HAL_OK)
  {   
    /* If the previous operation is completed, proceed to erase the option bytes */
    FLASH->CR |= FLASH_CR_OPTER;
    FLASH->CR |= FLASH_CR_STRT;
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    /* If the erase operation is completed, disable the OPTER Bit */
    FLASH->CR &= ~FLASH_CR_OPTER;

    /* Update option bytes */
    ob[1] = (ob[1] & 0xFFF7) | 0x0800;
    /* Enable the Option Bytes Programming operation */
    FLASH->CR |= FLASH_CR_OPTPG;
    /* Restore the last read protection Option Byte value */
    OB->RDP = ob[0];
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    if(status == HAL_TIMEOUT)
      while(1)    ;    //ERROR
    FLASH->CR &= ~FLASH_CR_OPTPG;
    FLASH->CR |= FLASH_CR_OPTPG;
    OB->USER = ob[1];
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    if(status == HAL_TIMEOUT)
      while(1)    ;    //ERROR
    FLASH->CR &= ~FLASH_CR_OPTPG;
    FLASH->CR |= FLASH_CR_OPTPG;
    OB->DATA0 = ob[2];
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    if(status == HAL_TIMEOUT)
      while(1)    ;    //ERROR
    FLASH->CR &= ~FLASH_CR_OPTPG;
    FLASH->CR |= FLASH_CR_OPTPG;
    OB->DATA1 = ob[3];
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    if(status == HAL_TIMEOUT)
      while(1)    ;    //ERROR
    FLASH->CR &= ~FLASH_CR_OPTPG;
    FLASH->CR |= FLASH_CR_OPTPG;
    OB->WRP0 = ob[4];
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    if(status == HAL_TIMEOUT)
      while(1)    ;    //ERROR
    FLASH->CR &= ~FLASH_CR_OPTPG;
    }
    else
    {
        if (status != HAL_TIMEOUT)
        {
            /* Disable the OPTPG Bit */
            FLASH->CR &= ~FLASH_CR_OPTPG;
        }
    }

    /* Lock */
    HAL_FLASH_OB_Lock();
  HAL_FLASH_Lock();

    /* Verify */
    if((*(uint16_t*)(0x1FFFF800)) != ob[0])
        while(1)    ;    //ERROR
    if((*(uint16_t*)(0x1FFFF802)) != ob[1])
        while(1)    ;    //ERROR
    if((*(uint16_t*)(0x1FFFF804)) != ob[2])
        while(1)    ;    //ERROR
    if((*(uint16_t*)(0x1FFFF806)) != ob[3])
        while(1)    ;       //ERROR
    if((*(uint16_t*)(0x1FFFF808)) != ob[4])
        while(1)    ;       //ERROR
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值