GD32移植STM32工程详细教程

文章目录

  • 一、前言
  • 二、差异性
  • 三、软件移植部分
  • 1.前期准备
  • 1.1 安装GD32固件库
  • 1.2 选择所用芯片
  • 2.修改程序
  • 2.1 启动时间(内部时钟可不改)
  • 2.2 主频
  • 2.2.1 系统时钟配置
  • 2.2.2 108MHz宏定义
  • 第一处
  • 第二处
  • 第三处
  • 第四处
  • 第五处
  • 2.2.3 串口
  • 2.2.4 FLASH
  • 四、总结

  • 一、前言

    在一个慵懒的日子里,我因为不想花费太多时间和精力,直接将原来为STM32编写的工程进行了修改,使其适用于GD32工程。这个过程并不复杂,只需要对一些特定的代码进行替换和调整,以适应GD32的硬件架构和指令集。然而,由于我对STM32和GD32之间的差异了解不够深入,这个过程也让我犯了一些错误。最终,经过一番努力,我终于成功地将工程从STM32移植到了GD32。

    经过这次移植的经历,我深刻体会到了GD32和STM32之间的差异,并积累了一定的经验。因此,我决定将这次移植的经验分享出来,希望能够帮助更多的人在面对类似移植问题时能够更加顺利地完成移植工作。

    二、差异性

    可以从下面表格看出主要的硬件差异是供电以及主频大小等。

    MCU STM32F103VCT6 GD32F103VCT6
    内核 Cortex-M3内核 Cortex-M3内核
    程序存储容量 256KB 256KB
    RAM总容量 48KB 48KB
    GPIO端口数量 80 80
    工作电压范围 2V~3.6V 2.6V~3.6V
    内核的供电电压 1.2V 1.8V
    CPU最大主频 72MHz 108MHz
    程序存储器类型 FLASH FLASH
    工作温度范围 -40℃~+85℃ -40℃~+85℃
    ADC(位数) 12bit 12bit
    DAC(位数) 12bit 12bit

    三、软件移植部分

    这里我使用的GD芯片是GD32F103VCT6,移植的程序来源自STM32F103VCT6,采用的是STM32的标准库。

    1.前期准备

    1.1 安装GD32固件库

    进入兆易创新GD32 MCU官网下载keil支持包,下载完成后双击进行安装。

    1.2 选择所用芯片

    这里我用的是keil5,所以我选择安装 GigaDevice.GD32F10x_DFP.2.1.0 pack Keil5 在线支持包,安装完成后点击keil的魔术棒会出现GD32F10x Series。

    最后,选择我们需要的MCU型号,前期准备工作完成,接下来开始移植程序。

    2.修改程序

    2.1 启动时间(内部时钟可不改)

    HSE_STARTUP_TIMEOUT是用于定义外部高速时钟(HSE)启动的超时时间。我用的是内部时钟,所以也可以不改。

    代码如下(示例):

    /**
     * @brief In the following line adjust the External High Speed oscillator (HSE) Startup 
       Timeout value 
       */
    #define HSE_STARTUP_TIMEOUT   ((uint16_t)0xFFFF) /*!< Time out for HSE start up */ //STM32 0x0500
    

    2.2 主频

    2.2.1 系统时钟配置

    通过上面的差异性比较,我们知道GD32的最高主频为108MHZ,那么在STM32工程中要有哪些修改呢?

    请接着往下看

    1.在SystemClock_Config系统时钟配置函数中选择我们需要的时钟,这里用的是内部时钟HSI,有同学可能对底下这个宏定义 #define RCC_PLLMul_27 ((uint32_t)0x08280000)感到疑惑,下面就解释下。

    根据官方GD32F10x User Manual 2.6版本用户手册的资料显示(中文P84-P87,英文P87-P91),要配置108MHZ,PLL时钟倍频因子需要配置为PLL源时钟x27,由于我们在RCC_PLLConfig函数选择RCC_PLLSource_HSI_Div2,HSI刚好是8MHZ,一半的HSI是4MHZ,4×27=108MHZ

    PLLMF[3:0]为第21位到18位,(PLL源时钟 x 27)为11010,第一个1其实是第27位,所以时钟配置寄存器 0(RCU_CFG0)最后的值为0x0000 1000 0010 1000 XXXX(补零)=0x08280000


    代码如下(示例):

     #define RCC_PLLMul_27                   ((uint32_t)0x08280000)
     
    /*******************************************************************************
     * 函数名:SystemClock_Config
     * 描述  :系统时钟配置
     * 输入  :void
     * 输出  :void
     * 调用  :初始化
     * 备注  :
    *******************************************************************************/
    void SystemClock_Config(void)
    {
      /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/   
      /* RCC system reset(for debug purpose) */
      RCC_DeInit();
      /* Enable HSI */
      RCC_HSICmd(ENABLE);
      /* Wait till HSI is ready */
      while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET)
      {}
      /* Enable Prefetch Buffer */
      FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
      /* Flash 2 wait state */
      FLASH_SetLatency(FLASH_Latency_2);
      /* HCLK = SYSCLK */
      RCC_HCLKConfig(RCC_SYSCLK_Div1); 
      /* PCLK2 = HCLK */
      RCC_PCLK2Config(RCC_HCLK_Div1); 
      /* PCLK1 = HCLK/2 */
      RCC_PCLK1Config(RCC_HCLK_Div2);
    #ifdef STM32F10X_CL
      /* Configure PLLs *********************************************************/
      /* PLL2 configuration: PLL2CLK = (HSI / 2) * 4 = 16 MHz */
      RCC_PREDIV2Config(RCC_PREDIV2_Div2);
      RCC_PLL2Config(RCC_PLL2Mul_4);
      /* Enable PLL2 */
      RCC_PLL2Cmd(ENABLE);
      /* Wait till PLL2 is ready */
      while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET)
      {}
      /* PLL configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */ 
      RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);
      RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);
    #else
      /* PLLCLK = 4MHz * 27 = 72 MHz */
      RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_27); // HSI is divided by 2 to have 4MHz then multiply by 27 to have 108MHz
    #endif
      /* Enable PLL */ 
      RCC_PLLCmd(ENABLE);
      /* Wait till PLL is ready */
      while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
      {
      }
      /* Select PLL as system clock source */
      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
      /* Wait till PLL is used as system clock source */
      while(RCC_GetSYSCLKSource() != 0x08)
      {
      }
    }
    
    2.2.2 108MHz宏定义

    在system_stm32f10x.c文件中找到SYSCLK_FREQ_72MHz的位置,一共有5处,全部注释掉,并且换成SYSCLK_FREQ_108MHz。

    代码如下(示例):

    第一处
    #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    /* #define SYSCLK_FREQ_HSE    HSE_VALUE */
     #define SYSCLK_FREQ_24MHz  24000000
    #else
    /* #define SYSCLK_FREQ_HSE    HSE_VALUE */
    /* #define SYSCLK_FREQ_24MHz  24000000 */ 
    /* #define SYSCLK_FREQ_36MHz  36000000 */
    /* #define SYSCLK_FREQ_48MHz  48000000 */
    /* #define SYSCLK_FREQ_56MHz  56000000 */
    /* #define SYSCLK_FREQ_72MHz  72000000 */
       #define SYSCLK_FREQ_108MHz  108000000
    #endif
    
    第二处
    /*******************************************************************************
    *  Clock Definitions
    *******************************************************************************/
    #ifdef SYSCLK_FREQ_HSE
      uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_24MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_36MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_48MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_56MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_72MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */
    	#elif defined SYSCLK_FREQ_108MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_108MHz;        /*!< System Clock Frequency (Core Clock) */
    #else /*!< HSI Selected as System Clock source */
      uint32_t SystemCoreClock         = HSI_VALUE;        /*!< System Clock Frequency (Core Clock) */
    #endif
    
    第三处
    #ifdef SYSCLK_FREQ_HSE
      static void SetSysClockToHSE(void);
    #elif defined SYSCLK_FREQ_24MHz
      static void SetSysClockTo24(void);
    #elif defined SYSCLK_FREQ_36MHz
      static void SetSysClockTo36(void);
    #elif defined SYSCLK_FREQ_48MHz
      static void SetSysClockTo48(void);
    #elif defined SYSCLK_FREQ_56MHz
      static void SetSysClockTo56(void);  
    #elif defined SYSCLK_FREQ_72MHz
      static void SetSysClockTo72(void);
    #elif defined SYSCLK_FREQ_108MHz
      static void SetSysClockTo108(void);	
    #endif
    
    第四处
    /**
      * @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
      * @param  None
      * @retval None
      */
    static void SetSysClock(void)
    {
    #ifdef SYSCLK_FREQ_HSE
      SetSysClockToHSE();
    #elif defined SYSCLK_FREQ_24MHz
      SetSysClockTo24();
    #elif defined SYSCLK_FREQ_36MHz
      SetSysClockTo36();
    #elif defined SYSCLK_FREQ_48MHz
      SetSysClockTo48();
    #elif defined SYSCLK_FREQ_56MHz
      SetSysClockTo56();  
    #elif defined SYSCLK_FREQ_72MHz
      SetSysClockTo72();
    #elif defined SYSCLK_FREQ_108MHz
      SetSysClockTo108();
    #endif 
    }
    
    第五处
    #elif defined SYSCLK_FREQ_108MHz
    /**
      * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2 
      *         and PCLK1 prescalers. 
      * @note   This function should be used only after reset.
      * @param  None
      * @retval None
      */
    static void SetSysClockTo108(void)
    {
      __IO uint32_t StartUpCounter = 0, HSEStatus = 0;  
      /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
      /* Enable HSE */    
      RCC->CR |= ((uint32_t)RCC_CR_HSEON); 
      /* Wait till HSE is ready and if Time out is reached exit */
      do
      {
        HSEStatus = RCC->CR & RCC_CR_HSERDY;
        StartUpCounter++;  
      } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
      if ((RCC->CR & RCC_CR_HSERDY) != RESET)
      {
        HSEStatus = (uint32_t)0x01;
      }
      else
      {
        HSEStatus = (uint32_t)0x00;
      }  
      if (HSEStatus == (uint32_t)0x01)
      {
        /* Enable Prefetch Buffer */
        FLASH->ACR |= FLASH_ACR_PRFTBE;
        /* Flash 2 wait state */
        FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
        FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;     
        /* HCLK = SYSCLK */
        RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;      
        /* PCLK2 = HCLK */
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;    
        /* PCLK1 = HCLK/2 */
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
    #ifdef STM32F10X_CL
        /* Configure PLLs ------------------------------------------------------*/
        /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
        /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */        
        RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                                  RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
        RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                                 RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);  
        /* Enable PLL2 */
        RCC->CR |= RCC_CR_PLL2ON;
        /* Wait till PLL2 is ready */
        while((RCC->CR & RCC_CR_PLL2RDY) == 0)
        {
        }    
        /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
        RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
        RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                                RCC_CFGR_PLLMULL9); 
    #else    
        /*  PLL configuration: PLLCLK = HSE/2 * 27 = 108 MHz */
        RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                            RCC_CFGR_PLLMULL));
        RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL27);
    #endif /* STM32F10X_CL */
    
        /* Enable PLL */
        RCC->CR |= RCC_CR_PLLON;
    
        /* Wait till PLL is ready */
        while((RCC->CR & RCC_CR_PLLRDY) == 0)
        {
        }    
        /* Select PLL as system clock source */
        RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
        RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
        /* Wait till PLL is used as system clock source */
        while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
        {
        }
      }
      else
      { /* If HSE fails to start-up, the application will have wrong clock 
             configuration. User can add here some code to deal with this error */
      }
    }
    #endif
    
    2.2.3 串口

    一开始我改完时钟108MHZ,试了串口,然后发现乱码,后面查了资料,才知道在stm32f10x_rcc.c文件中RCC_GetClocksFreq函数要新增以下代码。

    if(RCC->CFGR & 0x08000000)这行代码用于检查RCC->CFGR寄存器中特定位(第27位)的值。如果该位为1,就会执行pllmull += 15;,即将pllmull变量的值增加15,变成27倍频刚好对应上面的108MHZ。

    代码如下(示例):

    /**
      * @brief  Returns the frequencies of different on chip clocks.
      * @param  RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold
      *         the clocks frequencies.
      * @note   The result of this function could be not correct when using 
      *         fractional value for HSE crystal.  
      * @retval None
      */
    void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
    {
      uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;
    
    #ifdef  STM32F10X_CL
      uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
    #endif /* STM32F10X_CL */
    
    #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
      uint32_t prediv1factor = 0;
    #endif    
      /* Get SYSCLK source -------------------------------------------------------*/
      tmp = RCC->CFGR & CFGR_SWS_Mask;
      switch (tmp)
      {
        case 0x00:  /* HSI used as system clock */
          RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
          break;
        case 0x04:  /* HSE used as system clock */
          RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
          break;
        case 0x08:  /* PLL used as system clock */
          /* Get PLL clock source and multiplication factor ----------------------*/
          pllmull = RCC->CFGR & CFGR_PLLMull_Mask;
          pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;      
    #ifndef STM32F10X_CL      
          pllmull = ( pllmull >> 18) + 2;      
    	  if(RCC->CFGR & 0x08000000)//取27位
          {
    				pllmull += 15;
    	  }						
          if (pllsource == 0x00)
          {/* HSI oscillator clock divided by 2 selected as PLL clock entry */
            RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
          }
          else
          {
     #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
           prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
           /* HSE oscillator clock selected as PREDIV1 clock entry */
           RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull; 
     #else
            /* HSE selected as PLL clock entry */
            if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET)
            {/* HSE oscillator clock divided by 2 */
              RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull;
            }
            else
            {
              RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull;
            }
     #endif
          }
    #else
          pllmull = pllmull >> 18;      
          if (pllmull != 0x0D)
          {
             pllmull += 2;
          }
          else
          { /* PLL multiplication factor = PLL input clock * 6.5 */
            pllmull = 13 / 2; 
          }            
          if (pllsource == 0x00)
          {/* HSI oscillator clock divided by 2 selected as PLL clock entry */
            RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
          }
          else
          {/* PREDIV1 selected as PLL clock entry */        
            /* Get PREDIV1 clock source and division factor */
            prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC;
            prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;        
            if (prediv1source == 0)
            { /* HSE oscillator clock selected as PREDIV1 clock entry */
              RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;          
            }
            else
            {/* PLL2 clock selected as PREDIV1 clock entry */          
              /* Get PREDIV2 division factor and PLL2 multiplication factor */
              prediv2factor = ((RCC->CFGR2 & CFGR2_PREDIV2) >> 4) + 1;
              pll2mull = ((RCC->CFGR2 & CFGR2_PLL2MUL) >> 8 ) + 2; 
              RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;                         
            }
          }
    #endif /* STM32F10X_CL */ 
          break;
        default:
          RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
          break;
      }
      /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
      /* Get HCLK prescaler */
      tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;
      tmp = tmp >> 4;
      presc = APBAHBPrescTable[tmp];
      /* HCLK clock frequency */
      RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;
      /* Get PCLK1 prescaler */
      tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
      tmp = tmp >> 8;
      presc = APBAHBPrescTable[tmp];
      /* PCLK1 clock frequency */
      RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
      /* Get PCLK2 prescaler */
      tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;
      tmp = tmp >> 11;
      presc = APBAHBPrescTable[tmp];
      /* PCLK2 clock frequency */
      RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
      /* Get ADCCLK prescaler */
      tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;
      tmp = tmp >> 14;
      presc = ADCPrescTable[tmp];
      /* ADCCLK clock frequency */
      RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;
    }
    
    2.2.4 FLASH

    因为GD的Flash是自己的专利技术,而ST的Flash则是由第三方提供的,所以,当进行Flash取值操作时,GD32F10X芯片可以达到零等待周期的响应时间,而ST芯片则需要等待两个周期。另一方面,GD芯片的Flash擦除和编程时间可能会比ST芯片长一些。

    所以针对这个不同需要增加两个空循环__NOP();指令进行等待。

    代码如下(示例):

    /**
      * @brief  Erases the FLASH option bytes.
      * @note   This functions erases all option bytes except the Read protection (RDP). 
      * @note   This function can be used for all STM32F10x devices.
      * @param  None
      * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
      *         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
      */
    FLASH_Status FLASH_EraseOptionBytes(void)
    {
      uint16_t rdptmp = RDP_Key;
      FLASH_Status status = FLASH_COMPLETE;
      /* Get the actual read protection Option Byte value */ 
      if(FLASH_GetReadOutProtectionStatus() != RESET)
      {
        rdptmp = 0x00;  
      }
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastOperation(EraseTimeout);
      if(status == FLASH_COMPLETE)
      {
        /* Authorize the small information block programming */
        FLASH->OPTKEYR = FLASH_KEY1;
        FLASH->OPTKEYR = FLASH_KEY2;    
        __NOP();
        __NOP();    
        /* if the previous operation is completed, proceed to erase the option bytes */
        FLASH->CR |= CR_OPTER_Set;
        FLASH->CR |= CR_STRT_Set;
        /* Wait for last operation to be completed */
        status = FLASH_WaitForLastOperation(EraseTimeout);    
        if(status == FLASH_COMPLETE)
        {
          /* if the erase operation is completed, disable the OPTER Bit */
          FLASH->CR &= CR_OPTER_Reset;       
          /* Enable the Option Bytes Programming operation */
          FLASH->CR |= CR_OPTPG_Set;
          /* Restore the last read protection Option Byte value */
          OB->RDP = (uint16_t)rdptmp; 
          /* Wait for last operation to be completed */
          status = FLASH_WaitForLastOperation(ProgramTimeout);
          if(status != FLASH_TIMEOUT)
          {
            /* if the program operation is completed, disable the OPTPG Bit */
            FLASH->CR &= CR_OPTPG_Reset;
          }
        }
        else
        {
          if (status != FLASH_TIMEOUT)
          {
            /* Disable the OPTPG Bit */
            FLASH->CR &= CR_OPTPG_Reset;
          }
        }  
      }
      /* Return the erase status */
      return status;
    }
    

    除了FLASH_EraseOptionBytes函数外,还有下面三个函数也需要增加 __NOP();

    FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
    FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);
    FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);
    

    GD芯片的Flash擦除和编程时间可能会比ST芯片长一些,所以把擦除和编程时间变长些。

    /* Delay definition */   
    #define EraseTimeout          ((uint32_t)0x000fffff)//0x000B0000   
    #define ProgramTimeout        ((uint32_t)0x0000ffff)//0x00002000
    

    四、总结

    今天是STM32到GD32的工程移植经验分享,附件是移植好的工程。感谢你的观看,谢谢!

    物联沃分享整理
    物联沃-IOTWORD物联网 » GD32移植STM32工程详细教程

    发表评论