VSCode下 搭建 ARM Cortex-M 開發(fā)環(huán)境 -- Part 1 編譯環(huán)境搭建

  • Part 0 開發(fā)工具安裝
  • Part 1 編譯環(huán)境搭建
  • Part 2 調試環(huán)境搭建

VSCode下 搭建 ARM Cortex-M 開發(fā)環(huán)境 -- Part 1 編譯環(huán)境搭建

前言

本章旨在記錄如何在VSCode下搭建編譯環(huán)境盛杰, 具體包含以下幾個部分:

  1. Project架構搭建
  2. VSCode下創(chuàng)建同名Project
  3. 移植和編寫程序
  4. VSCode下C環(huán)境配置
  5. Makefile編譯
  6. VSCode下Terminal配置
  7. 編譯程序
  8. 程序燒寫和運行

Project架構搭建

  • 首先,我們需要在搭建項目的文件夾下創(chuàng)建項目文件夾咆槽。
    例如下圖中爷贫,在E:\STMicroelectronics\workspace\stm32f429\projects下創(chuàng)建一個名為HAL_demo的文件夾钾腺。后續(xù)用到的所有文件等都會放到HAL_demo文件夾下

    項目文件夾.png

  • 然后,在項目文件夾下創(chuàng)建后續(xù)所需用到的各個模塊的文件夾临谱。
    例如下圖中,在HAL_demo文件下創(chuàng)建APP奴璃、CMSIS悉默、Kernel、lib苟穆、LinkerScripts抄课、Startup、STM32F4xx_HAL_Driver雳旅、STM32F4xx_System跟磨、STM32F429I-Discovery、tools這些文件夾攒盈。

    各個模塊文件夾.png

    .vscode文件夾是VSCode自動生成的保持settings的文件夾抵拘,無需創(chuàng)建
    out文件夾下放的是待會build出來的elf文件、bin文件等型豁,在編譯程序過程中會自動生產該文件夾僵蛛,無需創(chuàng)建
    Makefile文件是整個Project的總Makefile文件,后續(xù)會詳細介紹該文件迎变,所以后續(xù)章節(jié)再創(chuàng)建即可

  • 簡單介紹下各個模塊文件夾的含義墩瞳。
    APP: 與application相關的文件都會放到APP文件夾下,例如main.c等

    CMSIS: ARM Cortex? 微控制器軟件接口標準(CMSIS:Cortex Microcontroller Software Interface Standard) 是 Cortex-M 處理器系列的與供應商無關的硬件抽象層氏豌。所以喉酌,CMSIS文件夾下會放ARM Cortex-M 所需的硬件抽象層文件,例如core_cm4.h等

    Kernel: OS相關的文件都會放到Kernel文件夾下,例如FreeRTOS相關的文件

    lib: GNU toolchain中pre-build好的一些lib都會放到lib文件夾下,例如libc.a泪电、libg.a般妙、libgcc.a等

    LinkerScripts: arm-none-eabi-ld所需要的memory layout文件都會放到LinkerScripts文件夾下

    Startup: ARM chip所需的 startup文件會放到Startup文件夾下,例如startup_stm32f429_439xx.s

    STM32F4xx_HAL_Driver: 與STM32F429芯片相關的Hardware driver程序文件都會放在STM32F4xx_HAL_Driver文件夾下相速,例如stm32f4xx_hal_gpio.c等

    STM32F4xx_System: 與STM32F429芯片相關的system level程序文件都會放在STM32F4xx_System文件夾下碟渺,例如system_stm32f4xx.c等

    STM32F429I-Discovery: 與STM32F429I-Discovery板子相關的程序文件都會放在STM32F429I-Discovery文件夾下,例如stm32f429i_discovery_eeprom.c等

    tools: tool所需的文件或者所需的tool文件都放在tools文件夾下

  • 至此,整個Project的架構已經搭建完畢突诬。接下來章節(jié)所需做的就是:具體實現(xiàn)各個模塊文件夾中的內容苫拍。

VSCode下創(chuàng)建同名Project

搭建完整個Project架構后,我們可以通過VSCode的Project+ 這個插件構建一個同名Project旺隙,方便以后在不同Projects之間來回切換绒极。

  • 首先,在VSCode內按下F1快捷鍵顯示所有命令蔬捷。


    顯示所有命名.png
  • 然后垄提,在窗口中輸入如下command,進入到project edit界面 周拐。
>projects:Edit Configuration
project edit界面.png
  • 接著铡俐,創(chuàng)建一個name為STM32的group。然后在group的projects下創(chuàng)建一個name為HAL demo的project,并且把path設為剛才創(chuàng)建的HAL_demo這個文件夾的路徑妥粟。


    創(chuàng)建Project.png
  • 完成上述步驟审丘,即可在VSCode側邊欄中的PROJECTS下見到我們剛才創(chuàng)建的那個Project。以后需要切換到這個project只需右擊該project選擇open or open in New Window即可勾给。
    Project.png

    右擊切換Project.png

移植和編寫程序

搭建完Project架構和在VSCode下創(chuàng)建好Project以后备恤,接下來要做就是本文最重要的部分:移植和編寫各個module文件夾下的程序了。

  • CMSIS 文件夾下內容實現(xiàn)

CMSIS文件夾下主要需要移植ARM Cortex-M 所需的硬件抽象層文件

  1. 把STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS下所有內容 都復制到 CMSIS文件夾下
    STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS下所有內容.png

    CMSIS下所有內容.png

    至此锦秒,CMSIS 文件夾下內容已經全部實現(xiàn)露泊。我們后續(xù)所用到文件 其實都在CMSIS\Include下,例如cmsis_gcc.h中會包含__disable_irq 和 __enable_irq這些內聯(lián)匯編旅择。
    CMSIS文件夾下實際使用到的文件.png
  • Startup 文件夾下內容實現(xiàn)

Startup文件夾下主要需要移植一個startup_stm32f429_439xx.s文件
startup_stm32f429_439xx.s文件主要實現(xiàn)以下功能:

  1. 初始化SP和PC值惭笑;
  2. 設置Vector Table;
  3. 初始化.data 和 .bss section在memory上的data生真;
  4. 初始化C library所需環(huán)境沉噩,初始化system環(huán)境,jump到main函數(shù)等柱蟀。
  1. 在Startup文件夾下創(chuàng)建一個gcc 文件夾川蒙。Makefile 和 module.mk文件后續(xù)章節(jié)會介紹
    gcc文件夾.png
  2. 把之前安裝好的STM32Cube中的startup_stm32f429.s(具體路徑見下圖,STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\gcc)復制到 剛才創(chuàng)建的gcc文件夾下并且命名為startup_stm32f429_439xx.s(見下下圖)长已。
    STM32Cube中的startup_stm32f429文件.png

    復制的startup_stm32f429_439xx.s文件.png
  3. 對gcc文件夾中的startup_stm32f429_439xx.s文件作如下改動:把bl __libc_init_array 這行mask掉畜眨。
    startup_stm32f429_439xx.s文件的改動.png

    至此昼牛,Startup文件夾下的內容已經完成。startup.s文件 從第一行code到最后一行code 主要就是為了實現(xiàn)如下的開機FLOW
    STM32 GCC 開機Flow.png
  • STM32F4xx_HAL_Driver 文件夾下內容實現(xiàn)

STM32F4xx_HAL_Driver文件夾下主要需要移植STM32Cube中提供的那些HAL driver文件康聂,例如uart贰健、i2c、spi恬汁、adc等硬件設備的驅動程序伶椿。

  1. 在STM32F4xx_HAL_Driver 文件夾下分別創(chuàng)建inc和src文件夾Makefile 和 module.mk文件后續(xù)章節(jié)會介紹
    創(chuàng)建inc和src文件夾.png
  2. STM32Cube_FW_F4_V1.18.0\Drivers\STM32F4xx_HAL_Driver\Inc下的所有頭文件和子文件夾 復制 到STM32F4xx_HAL_Driver\inc下
    移植頭文件.png
  3. STM32Cube_FW_F4_V1.18.0\Drivers\STM32F4xx_HAL_Driver\Src下的所有C文件 復制 到STM32F4xx_HAL_Driver\src下
    移植C文件.png
  4. STM32F4xx_HAL_Driver\inc下stm32_assert_template.h和stm32f4xx_hal_conf_template.h刪除
  5. stm32f4xx_ll_rcc.h做如下修改:#define HSE_VALUE (25000000U) 改為 #define HSE_VALUE (8000000U)
    修改HSE_VALUE.png
  6. STM32F4xx_HAL_Driver\src下stm32f4xx_hal_msp_template.c氓侧、stm32f4xx_hal_timebase_rtc_alarm_template.c脊另、stm32f4xx_hal_timebase_rtc_wakeup_template.c 和 stm32f4xx_hal_timebase_tim_template.c刪除
  7. stm32f4xx_hal.c做如下修改:mask掉HAL_InitTick(TICK_INT_PRIORITY)這行
    因為FreeRTOS中會對systick進行配置,所以這邊無需call HAL_InitTick去配置systick约巷。如果是裸機開發(fā)偎痛,無需mask這行code。
    Mask HAL_InitTick.png

    至此载庭,STM32F4xx_HAL_Driver文件夾下的內容已經完成。在應用程序中call STM32F4xx_HAL_Driver下各個文件中的API 即可實現(xiàn)對Hardware的控制廊佩,不再需要直接去control hardware registers了
  • STM32F4xx_System 文件夾下內容實現(xiàn)

STM32F4xx_System文件夾下主要需要移植一些STM32 System Level所依賴的文件囚聚,例如:

  1. system_stm32f4xx.c 中的functions實現(xiàn)System Clock setting,
  2. stm32f4xx_it.c 中的functions實現(xiàn)各個Interrupt handler,
  3. stm32f4xx_hal_msp.c 中的functions實現(xiàn)low level hardware initialization,例如Uart Port GPIO Pinmux Setting等标锄。
  1. 在STM32F4xx_System文件夾下分別創(chuàng)建inc和src文件夾顽铸。Makefile 和 module.mk文件后續(xù)章節(jié)會介紹
    STM32F4xx_System文件夾.png
  2. STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include下的stm32f4xx.h、stm32f429xx.h以及system_stm32f4xx.h 復制 到 STM32F4xx_System\inc下
    所需復制的stm32f4xx相關頭文件.png

    復制到STM32F4xx_System\inc.png
  3. STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates下的system_stm32f4xx.c 復制到 STM32F4xx_System\src下
    所需復制的system_stm32f4xx C文件.png

    復制到STM32F4xx_System\src.png
  4. 按照如下代碼料皇,修改STM32F4xx_System\src 下的 system_stm32f4xx.c,主要是為了正確地設置system clock谓松。
/**
  ******************************************************************************
  * @file    system_stm32f4xx.c
  * @author  MCD Application Team
  * @brief   CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
  *
  *   This file provides two functions and one global variable to be called from 
  *   user application:
  *      - SystemInit(): This function is called at startup just after reset and 
  *                      before branch to main program. This call is made inside
  *                      the "startup_stm32f4xx.s" file.
  *
  *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
  *                                  by the user application to setup the SysTick 
  *                                  timer or configure other parameters.
  *                                     
  *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
  *                                 be called whenever the core clock is changed
  *                                 during program execution.
  *
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2017 STMicroelectronics </center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/** @addtogroup CMSIS
  * @{
  */

/** @addtogroup stm32f4xx_system
  * @{
  */  
  
/** @addtogroup STM32F4xx_System_Private_Includes
  * @{
  */

#include "stm32f4xx.h"

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE    ((uint32_t)8000000) /*!< Default value of the External oscillator in Hz */
#endif /* HSE_VALUE */

#if !defined  (HSI_VALUE)
  #define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */

/**
  * @}
  */

/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
  * @{
  */

/**
  * @}
  */

/** @addtogroup STM32F4xx_System_Private_Defines
  * @{
  */

/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to use external SDRAM mounted
     on DK as data memory  */
/* #define DATA_IN_ExtSDRAM */

/*!< Uncomment the following line if you need to relocate your vector Table in
     Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field. 
                                   This value must be a multiple of 0x200. */
/******************************************************************************/

/************************* PLL Parameters *************************************/
/* Select the PLL clock source */

// #define PLL_SOURCE_HSI        // HSI (~16 MHz) used to clock the PLL, and the PLL is used as system clock source
#define PLL_SOURCE_HSE        // HSE (8MHz) used to clock the PLL, and the PLL is used as system clock source
// #define PLL_SOURCE_HSE_BYPASS   // HSE bypassed with an external clock (8MHz, coming from ST-Link) used to clock
                                // the PLL, and the PLL is used as system clock source


/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#if defined  (PLL_SOURCE_HSI)
#define PLL_M      16
#else
#define PLL_M      8
#endif
#define PLL_N      360

/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2

/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7

/******************************************************************************/



/**
  * @}
  */

/** @addtogroup STM32F4xx_System_Private_Macros
  * @{
  */

/**
  * @}
  */

/** @addtogroup STM32F4xx_System_Private_Variables
  * @{
  */
  /* This variable is updated in three ways:
      1) by calling CMSIS function SystemCoreClockUpdate()
      2) by calling HAL API function HAL_RCC_GetHCLKFreq()
      3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency 
         Note: If you use this function to configure the system clock; then there
               is no need to call the 2 first functions listed above, since SystemCoreClock
               variable is updated automatically.
  */
uint32_t SystemCoreClock = 180000000;
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8]  = {0, 0, 0, 0, 1, 2, 3, 4};
/**
  * @}
  */
  
/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
  * @{
  */

static void SetSysClock(void);
#if defined (DATA_IN_ExtSDRAM)
  static void SystemInit_ExtMemCtl(void); 
#endif /* DATA_IN_ExtSDRAM */

/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
  * @{
  */

/**
  * @}
  */

/** @addtogroup STM32F4xx_System_Private_Functions
  * @{
  */

/**
  * @brief  Setup the microcontroller system
  *         Initialize the FPU setting, vector table location and External memory 
  *         configuration.
  * @param  None
  * @retval None
  */
void SystemInit(void)
{
  /* FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
     SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
  #endif
  /* Reset the RCC clock configuration to the default reset state ------------*/
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset CFGR register */
  RCC->CFGR = 0x00000000;

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x24003010;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Disable all interrupts */
  RCC->CIR = 0x00000000;
  
#if defined (DATA_IN_ExtSDRAM)
  SystemInit_ExtMemCtl(); 
#endif /* DATA_IN_ExtSDRAM */
         
  /* Configure the System clock source, PLL Multiplier and Divider factors, 
     AHB/APBx prescalers and Flash settings ----------------------------------*/
  SetSysClock();

  /* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}

/**
   * @brief  Update SystemCoreClock variable according to Clock Register Values.
  *         The SystemCoreClock variable contains the core clock (HCLK), it can
  *         be used by the user application to setup the SysTick timer or configure
  *         other parameters.
  *           
  * @note   Each time the core clock (HCLK) changes, this function must be called
  *         to update SystemCoreClock variable value. Otherwise, any configuration
  *         based on this variable will be incorrect.         
  *     
  * @note   - The system frequency computed by this function is not the real 
  *           frequency in the chip. It is calculated based on the predefined 
  *           constant and the selected clock source:
  *             
  *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
  *                                              
  *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
  *                          
  *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 
  *             or HSI_VALUE(*) multiplied/divided by the PLL factors.
  *         
  *         (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
  *             16 MHz) but the real value may vary depending on the variations
  *             in voltage and temperature.   
  *    
  *         (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
  *              depends on the application requirements), user has to ensure that HSE_VALUE
  *              is same as the real frequency of the crystal used. Otherwise, this function
  *              may have wrong result.
  *                
  *         - The result of this function could be not correct when using fractional
  *           value for HSE crystal.
  *     
  * @param  None
  * @retval None
  */
void SystemCoreClockUpdate(void)
{
  uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
  
  /* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & RCC_CFGR_SWS;

  switch (tmp)
  {
    case 0x00:  /* HSI used as system clock source */
      SystemCoreClock = HSI_VALUE;
      break;
    case 0x04:  /* HSE used as system clock source */
      SystemCoreClock = HSE_VALUE;
      break;
    case 0x08:  /* PLL used as system clock source */

      /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
         SYSCLK = PLL_VCO / PLL_P
         */    
      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
      pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
      
      if (pllsource != 0)
      {
        /* HSE used as PLL clock source */
        pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
      }
      else
      {
        /* HSI used as PLL clock source */
        pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
      }

      pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
      SystemCoreClock = pllvco/pllp;
      break;
    default:
      SystemCoreClock = HSI_VALUE;
      break;
  }
  /* Compute HCLK frequency --------------------------------------------------*/
  /* Get HCLK prescaler */
  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
  /* HCLK frequency */
  SystemCoreClock >>= tmp;
}

/**
  * @brief  Configures the System clock source, PLL Multiplier and Divider factors, 
  *         AHB/APBx prescalers and Flash settings
  * @Note   This function should be called only once the RCC clock configuration  
  *         is reset to the default reset state (done in SystemInit() function).   
  * @param  None
  * @retval None
  */
static void SetSysClock(void)
{
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  

#ifdef PLL_SOURCE_HSI

      /* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSI) | (PLL_Q << 24);

#else /* PLL_SOURCE_HSE_BYPASS or PLL_SOURCE_HSE */

  /* Enable HSE */
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
#ifdef PLL_SOURCE_HSE_BYPASS
    /* Enable HSE */
  RCC->CR |= ((uint32_t)RCC_CR_HSEBYP);
#endif   /* PLL_SOURCE_HSE_BYPASS */
  /* 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)
  {
    /* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

  }
    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 /*PLL_SOURCE_HSI*/
  
      /* Select regulator voltage output Scale 1 mode, System frequency up to 180 MHz */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    PWR->CR |= PWR_CR_VOS;

    /* HCLK = SYSCLK / 1*/
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    
    /* PCLK1 = HCLK / 4*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

    /* Enable the main PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till the main PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
    PWR->CR |= PWR_CR_ODEN;
    while((PWR->CSR & PWR_CSR_ODRDY) == 0)
    {
    }
    PWR->CR |= PWR_CR_ODSWEN;
    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
    {
    } 
     
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

    /* Select the main PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL;

    /* Wait till the main PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL)
    {
    }
}

#if defined (DATA_IN_ExtSDRAM)
/**
  * @brief  Setup the external memory controller.
  *         Called in startup_stm32f4xx.s before jump to main.
  *         This function configures the external memories (SDRAM)
  *         This SDRAM will be used as program data memory (including heap and stack).
  * @param  None
  * @retval None
  */
void SystemInit_ExtMemCtl(void)
{
  register uint32_t tmpreg = 0, timeout = 0xFFFF;
  register __IO uint32_t index;

  /* Enable GPIOB, GPIOC, GPIOD, GPIOE, GPIOF and GPIOG interface 
  clock */
  RCC->AHB1ENR |= 0x0000007E;

  /* Connect PBx pins to FMC Alternate function */
  GPIOB->AFR[0]  = 0x0CC00000;
  GPIOB->AFR[1]  = 0x00000000;
  /* Configure PBx pins in Alternate function mode */ 
  GPIOB->MODER   = 0x00002A80;
  /* Configure PBx pins speed to 100 MHz */
  GPIOB->OSPEEDR = 0x00003CC0;
  /* Configure PBx pins Output type to push-pull */
  GPIOB->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PBx pins */ 
  GPIOB->PUPDR   = 0x00000100;

  /* Connect PCx pins to FMC Alternate function */
  GPIOC->AFR[0]  = 0x0000000C;
  GPIOC->AFR[1]  = 0x00000000;
  /* Configure PCx pins in Alternate function mode */ 
  GPIOC->MODER   = 0x00000002;
  /* Configure PCx pins speed to 100 MHz */
  GPIOC->OSPEEDR = 0x00000003;
  /* Configure PCx pins Output type to push-pull */
  GPIOC->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PCx pins */ 
  GPIOC->PUPDR   = 0x00000000;

  /* Connect PDx pins to FMC Alternate function */
  GPIOD->AFR[0]  = 0x000000CC;
  GPIOD->AFR[1]  = 0xCC000CCC;
  /* Configure PDx pins in Alternate function mode */ 
  GPIOD->MODER   = 0xA02A000A;
  /* Configure PDx pins speed to 100 MHz */
  GPIOD->OSPEEDR = 0xF03F000F;
  /* Configure PDx pins Output type to push-pull */
  GPIOD->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PDx pins */ 
  GPIOD->PUPDR   = 0x00000000;

  /* Connect PEx pins to FMC Alternate function */
  GPIOE->AFR[0]  = 0xC00000CC;
  GPIOE->AFR[1]  = 0xCCCCCCCC;
  /* Configure PEx pins in Alternate function mode */ 
  GPIOE->MODER   = 0xAAAA800A;
  /* Configure PEx pins speed to 100 MHz */
  GPIOE->OSPEEDR = 0xFFFFC00F;
  /* Configure PEx pins Output type to push-pull */
  GPIOE->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PEx pins */ 
  GPIOE->PUPDR   = 0x00000000;
  
  /* Connect PFx pins to FMC Alternate function */
  GPIOF->AFR[0]  = 0x00CCCCCC;
  GPIOF->AFR[1]  = 0xCCCCC000;
  /* Configure PFx pins in Alternate function mode */ 
  GPIOF->MODER   = 0xAA800AAA;
  /* Configure PFx pins speed to 100 MHz */
  GPIOF->OSPEEDR = 0xFFC00FFF;
  /* Configure PFx pins Output type to push-pull */
  GPIOF->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PFx pins */ 
  GPIOF->PUPDR   = 0x00000000;
  
  /* Connect PGx pins to FMC Alternate function */
  GPIOG->AFR[0]  = 0x00CC00CC;
  GPIOG->AFR[1]  = 0xC000000C;
  /* Configure PGx pins in Alternate function mode */ 
  GPIOG->MODER   = 0x80020A0A;
  /* Configure PGx pins speed to 100 MHz */
  GPIOG->OSPEEDR = 0xC0030F0F;
  /* Configure PGx pins Output type to push-pull */
  GPIOG->OTYPER  = 0x00000000;
  /* No pull-up, pull-down for PGx pins */ 
  GPIOG->PUPDR   = 0x00000000;

  /* FMC Configuration */
  /* Enable the FMC interface clock */
  RCC->AHB3ENR |= 0x00000001;
  
  /* Configure and enable SDRAM bank2 */
  FMC_Bank5_6->SDCR[0] = 0x00002ED0;
  FMC_Bank5_6->SDCR[1] = 0x000001D4;
  FMC_Bank5_6->SDTR[0] = 0x0F1F6FFF;
  FMC_Bank5_6->SDTR[1] = 0x01010361;
  
  /* SDRAM initialization sequence */
  /* Clock enable command */
  FMC_Bank5_6->SDCMR = 0x00000009; 
  tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }

  /* Delay */
  for (index = 0; index<1000; index++);
  
  /* PALL command */
  FMC_Bank5_6->SDCMR = 0x0000000A;     
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }
  
  /* Auto refresh command */
  FMC_Bank5_6->SDCMR = 0x0000006B;
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }
 
  /* MRD register program */
  FMC_Bank5_6->SDCMR = 0x0004620C;
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  } 
  
  /* Set refresh count */
  tmpreg = FMC_Bank5_6->SDRTR;
  FMC_Bank5_6->SDRTR = (tmpreg | (0x0000056A<<1));
  
  /* Disable write protection */
  tmpreg = FMC_Bank5_6->SDCR[1]; 
  FMC_Bank5_6->SDCR[1] = (tmpreg & 0xFFFFFDFF);
}
#endif /* DATA_IN_ExtSDRAM */

/**
  * @}
  */

/**
  * @}
  */
  
/**
  * @}
  */    
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  1. STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc下的stm32f4xx_it.h 復制到 STM32F4xx_System\inc下
    所需復制的stm32f4xx_it頭文件.png

    復制到STM32F4xx_System\inc.png
  2. 修改STM32F4xx_System\inc下的stm32f4xx_it.h:把 #include "main.h" 替換為 #include "stm32f429xx.h"
    因為main.h會放到APP文件夾下,所以不希望這邊直接include APP下的東西
    修改stm32f4xx_it.h.png
  3. STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Src下的stm32f4xx_it.c 復制到 STM32F4xx_System\src下
    所需復制的stm32f4xx_it C文件.png

    復制到STM32F4xx_System\src.png
  4. 修改STM32F4xx_System\src下的stm32f4xx_it.c
    1) 把 #include "main.h" 這行刪除
    刪除main.h.png

    2) 對SVC_Handler, PendSV_Handler, SysTick_Handler做如下改動:
    修改exception handler.png

    這幾個function都對應著ARM Cortex-M架構下的幾種exception, 在startup_stm32f429_439xx.s中定義vector table的時候會用到這幾個function的起始address践剂,而FreeRTOS 下portable部分會另外實作這幾個function鬼譬。為了避免Linking階段發(fā)生重定義錯誤,所以特別在stm32f4xx_it.c中的這幾個function前面加上weak屬性逊脯,這樣待會產生可執(zhí)行文件的時候會優(yōu)先使用FreeRTOS中的實作优质,而不會使用stm32f4xx_it.c中的實作
  5. STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc下的main.h 復制到 STM32F4xx_System\inc下并且 重名為 stm32f4xx_hal_msp.h
    所需復制的main頭文件.png

    復制到STM32F4xx_System\inc并且重命名.png
  6. 按照如下代碼军洼,修改STM32F4xx_System\inc下的stm32f4xx_hal_msp.h
/**
  ******************************************************************************
  * @file    UART/UART_TwoBoards_ComPolling/Inc/main.h 
  * @author  MCD Application Team
  * @brief   Header for main.c module
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4XX_HAL_MSP_H
#define __STM32F4XX_HAL_MSP_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* User can use this section to tailor USARTx/UARTx instance used and associated 
   resources */
/* Definition for USARTx clock resources */
#define USARTx                           USART1
#define USARTx_CLK_ENABLE()              __HAL_RCC_USART1_CLK_ENABLE();
#define USARTx_RX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE() 

#define USARTx_FORCE_RESET()             __HAL_RCC_USART2_FORCE_RESET()
#define USARTx_RELEASE_RESET()           __HAL_RCC_USART2_RELEASE_RESET()

/* Definition for USARTx Pins */
#define USARTx_TX_PIN                    GPIO_PIN_9
#define USARTx_TX_GPIO_PORT              GPIOA  
#define USARTx_TX_AF                     GPIO_AF7_USART1
#define USARTx_RX_PIN                    GPIO_PIN_10
#define USARTx_RX_GPIO_PORT              GPIOA 
#define USARTx_RX_AF                     GPIO_AF7_USART1

/* Exported functions ------------------------------------------------------- */

#endif /* __STM32F4XX_HAL_MSP_H */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

stm32f4xx_hal_msp.h 主要來自于main.h巩螃。在stm32f4xx_hal_msp.h中我們主要需要實現(xiàn)待會吐log所用的Uart Port的相關定義。

  1. STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Src下的stm32f4xx_hal_msp.c 復制到 STM32F4xx_System\src下
    所需復制的stm32f4xx_hal_msp C文件.png

    復制到STM32F4xx_System\src.png
  2. 修改STM32F4xx_System\src下的stm32f4xx_hal_msp.c: 把#include "main.h" 改為 #include "stm32f4xx_hal_msp.h"
    修改include.png

    至此匕争,STM32F4xx_System文件夾下的內容已經完成避乏。
    如果需要配置Fault/Exception/Interrupt handler, 只需修改stm32f4xx_it.c;
    如果需要修改System Clock, 只需修改system_stm32f4xx.c甘桑;
    如果需要修改Log口Hardware配置拍皮,只需修改stm32f4xx_hal_msp.c
    歹叮。
  • STM32F429I-Discovery 文件夾下內容實現(xiàn)

STM32F429I-Discovery文件夾下主要需要移植STM32F429I_DISCOVERY Board相關的device driver, 例如板子上的lcd春缕、gyroscope device等設備的驅動程序

  1. 在STM32F429I-Discovery文件夾下分別創(chuàng)建inc和src文件夾盗胀。其他文件和文件夾后續(xù)章節(jié)會介紹
    創(chuàng)建inc和src文件夾.png
  2. STM32Cube_FW_F4_V1.18.0\Drivers\BSP\STM32F429I-Discovery下 所有H文件 復制到 STM32F429I-Discovery\inc下
    STM32Cube_FW_F4_V1.18.0\Drivers\BSP\STM32F429I-Discovery下所有H文件.png

    復制所有H文件.png
  3. STM32Cube_FW_F4_V1.18.0\Drivers\BSP\STM32F429I-Discovery下 所有C文件 復制到 STM32F429I-Discovery\src下
    STM32Cube_FW_F4_V1.18.0\Drivers\BSP\STM32F429I-Discovery下所有C文件.png

    復制所有C文件.png
  4. STM32Cube_FW_F4_V1.18.0\Drivers\BSP下 Components文件夾 直接復制到 STM32F429I-Discovery文件夾下
    STM32Cube_FW_F4_V1.18.0\Drivers\BSP下Components文件夾.png

    STM32F429I-Discovery文件夾下Components文件夾.png
  5. STM32Cube_FW_F4_V1.18.0\Utilities下 Fonts文件夾 直接復制到 STM32F429I-Discovery文件夾下
    STM32Cube_FW_F4_V1.18.0\Utilities下Fonts文件夾.png

    STM32F429I-Discovery文件夾下Fonts文件夾.png
  6. 修改STM32F429I-Discovery\src\stm32f429i_discovery_lcd.c 和 STM32F429I-Discovery\src\stm32f429i_discovery_lcd.h 文件:把其中所有 "../../../Utilities/" 替換為 ".."
    H文件中的修改.png

    C文件中的修改.png

    修改這部分是因為我們Project中的Fonts文件夾和STM32Cube中的路徑不一致,如果不按照上述方式修改會發(fā)生build error锄贼。
    至此票灰,STM32F429I-Discovery 文件夾下內容已經全部實現(xiàn),如果板子是用的是STM32F429I_DISCOVERY Board宅荤,可以使用該文件夾下的設備驅動屑迂,例如待會會使用BSP_LED_Init/BSP_LED_Toggle 這些API去控制板子上的LED燈
  • Kernel 文件夾下內容實現(xiàn)

Kernel文件夾下主要需要移植FreeRTOS操作系統(tǒng)

  1. 在Kernel文件夾下創(chuàng)建FreeRTOS文件夾冯键。其他文件后續(xù)章節(jié)會介紹
    創(chuàng)建FreeRTOS文件夾.png
  2. 進入下載好的FreeRTOS Source Code路徑下的Source文件夾下惹盼,例如我這邊的E:\FreeRTOS\Source_Code\FreeRTOSV8.2.3\FreeRTOS\Source
    Source文件夾.png
  3. Source文件夾下的所有文件和文件夾都 復制到 Kernel/FreeRTOS下
    圖片.png
  4. 進入到Kernel/FreeRTOS/portable下,把除了 GCC文件夾惫确、MemMang文件夾 和 readme 以外的所有的東西都刪除掉
    portable文件夾.png
  5. 進入到Kernel/FreeRTOS/portable/GCC下席函,把除了 ARM_CM4F文件夾 以外的所有的東西都刪除掉
    如果讀者使用的CPU不是Cortex-M4 Core的話淘邻,那么就只需要在GCC下保留對應的CPU架構的文件夾,其他架構的文件夾都不需要。例如Cortex-M0的話锻全,就留ARM_CM0就好了
    GCC文件夾.png

    至此副编,F(xiàn)reeRTOS Kernel已經移植好了闻书,待會在APP文件夾下添加一個FreeRTOSConfig.h文件楞黄,整個Project即可使用FreeRTOS了。
  • lib 文件夾下內容實現(xiàn)

lib文件夾下主要存放pre-build好的一些lib句旱,例如libc.a阳藻、libg.a、libgcc.a等

  1. 打開{ARM GNU ToolChain 文件夾}\share\doc\gcc-arm-none-eabi\readme.txt發(fā)現(xiàn)谈撒,CM4F所使用的lib是放在v7e-m/fpv4-sp/hard下的lib
    前提是使用Hard FP
    查看ReadMe.png

    Hard FP.png
  2. 進入到{ARM GNU ToolChain 文件夾}\lib\gcc下腥泥,把整個arm-none-eabi文件夾 復制到 lib 文件夾下
    lib\gcc下arm-none-eabi文件夾.png

    lib文件夾下arm-none-eabi文件夾.png
  3. 待會會用到lib\arm-none-eabi\6.3.1\thumb\v7e-m\fpv4-sp\hard下的libgcc.a
    libgcc.png
  4. 進入到{ARM GNU ToolChain 文件夾}\arm-none-eabi\lib\thumb下,把整個v7e-m文件夾 復制到 lib 文件夾下


    arm-none-eabi\lib\thumb下v7e-m文件夾.png

    lib文件夾下v7e-m文件夾.png
  5. 待會會用到lib\v7e-m\fpv4-sp\hard下的libc.a 和 libg.a
    libc.a 和 libg.a.png
  6. 進入到{ARM GNU ToolChain 文件夾}\arm-none-eabi文件夾下,把整個include文件夾 復制到 lib 文件夾下
    arm-none-eabi文件夾下include文件夾.png

    lib 文件夾下include文件夾.png

    至此,lib下內容已經完全實現(xiàn)啃匿。待會build code時候用到的lib, 例如libc.a道川、libg.a、libgcc.a等立宜,都會在lib\arm-none-eabi\6.3.1\thumb\v7e-m/fpv4-sp/hard or lib\v7e-m/fpv4-sp/hard
  • APP 文件夾下內容實現(xiàn)

APP文件夾主要實現(xiàn)main.c 和 syscall.c(提供libc所需的system calls, 例如_exit等)

  1. 在APP文件夾下分別創(chuàng)建inc和src文件夾冒萄。其他文件后續(xù)章節(jié)會介紹
    創(chuàng)建inc和src文件夾.png
  2. 在inc文件夾下 創(chuàng)建 main.h,具體內容如下(主要參考STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc\main.h):
    main.h文件.png
/**
  ******************************************************************************
  * @file    UART/UART_TwoBoards_ComPolling/Inc/main.h 
  * @author  MCD Application Team
  * @brief   Header for main.c module
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "stm32f429i_discovery.h"
#include "stm32f4xx_hal_msp.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "croutine.h"
#include "event_groups.h"
#include "semphr.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* User can use this section to tailor USARTx/UARTx instance used and associated 
   resources */
/* Size of Transmission buffer */
#define TXBUFFERSIZE                     (COUNTOF(aTxBuffer) - 1)
/* Size of Reception buffer */
#define RXBUFFERSIZE                     TXBUFFERSIZE

/* Exported macro ------------------------------------------------------------*/
#define COUNTOF(__BUFFER__)   (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))

/* Exported functions ------------------------------------------------------- */

#endif /* __MAIN_H */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  1. 在inc文件夾下 創(chuàng)建 FreeRTOSConfig.h橙数,具體內容如下(主要參考FreeRTOSV8.2.3\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK\FreeRTOSConfig.h):
    FreeRTOSConfig.h.png
/*
    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
    All rights reserved

    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.

    This file is part of the FreeRTOS distribution.

    FreeRTOS is free software; you can redistribute it and/or modify it under
    the terms of the GNU General Public License (version 2) as published by the
    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.

    ***************************************************************************
    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
    >>!   distribute a combined work that includes FreeRTOS without being   !<<
    >>!   obliged to provide the source code for proprietary components     !<<
    >>!   outside of the FreeRTOS kernel.                                   !<<
    ***************************************************************************

    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
    link: http://www.freertos.org/a00114.html

    ***************************************************************************
     *                                                                       *
     *    FreeRTOS provides completely free yet professionally developed,    *
     *    robust, strictly quality controlled, supported, and cross          *
     *    platform software that is more than just the market leader, it     *
     *    is the industry's de facto standard.                               *
     *                                                                       *
     *    Help yourself get started quickly while simultaneously helping     *
     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
     *    tutorial book, reference manual, or both:                          *
     *    http://www.FreeRTOS.org/Documentation                              *
     *                                                                       *
    ***************************************************************************

    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
    the FAQ page "My application does not run, what could be wrong?".  Have you
    defined configASSERT()?

    http://www.FreeRTOS.org/support - In return for receiving this top quality
    embedded software for free we request you assist our global community by
    participating in the support forum.

    http://www.FreeRTOS.org/training - Investing in training allows your team to
    be as productive as possible as early as possible.  Now you can receive
    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
    Ltd, and the world's leading authority on the world's leading RTOS.

    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
    compatible FAT file system, and our tiny thread aware UDP/IP stack.

    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.

    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
    licenses offer ticketed support, indemnification and commercial middleware.

    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
    engineered and independently SIL3 certified version for use in safety and
    mission critical applications that require provable dependability.

    1 tab == 4 spaces!
*/


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/

/* Ensure stdint is only used by the compiler, and not the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif

#define configUSE_PREEMPTION            1
#define configUSE_IDLE_HOOK             0
#define configUSE_TICK_HOOK             1
#define configCPU_CLOCK_HZ              ( SystemCoreClock )
#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES            ( 5 )
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 30 * 1024 ) )
#define configMAX_TASK_NAME_LEN         ( 16 )
#define configUSE_TRACE_FACILITY        1
#define configUSE_16_BIT_TICKS          0
#define configIDLE_SHOULD_YIELD         0

#define configUSE_MUTEXES               1
#define configQUEUE_REGISTRY_SIZE       8
//#define configCHECK_FOR_STACK_OVERFLOW    2
#define configUSE_RECURSIVE_MUTEXES     1
#define configUSE_MALLOC_FAILED_HOOK    0
#define configUSE_APPLICATION_TASK_TAG  0
#define configUSE_COUNTING_SEMAPHORES   1

#define configUSE_STATS_FORMATTING_FUNCTIONS    1
//#define configSUPPORT_DYNAMIC_ALLOCATION 1


/* Co-routine definitions. */
#define configUSE_CO_ROUTINES       0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Software timer definitions. */
#define configUSE_TIMERS                1
#define configTIMER_TASK_PRIORITY       ( 2 )
#define configTIMER_QUEUE_LENGTH        10
#define configTIMER_TASK_STACK_DEPTH    ( configMINIMAL_STACK_SIZE * 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet        1
#define INCLUDE_uxTaskPriorityGet       1
#define INCLUDE_vTaskDelete             1
#define INCLUDE_vTaskCleanUpResources   0
#define INCLUDE_vTaskSuspend            1
#define INCLUDE_vTaskDelayUntil         1
#define INCLUDE_vTaskDelay              1
#define INCLUDE_pcTaskGetTaskName       1


/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
    /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
    #define configPRIO_BITS             __NVIC_PRIO_BITS
#else
    #define configPRIO_BITS             4        /* 15 priority levels */
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         0xf

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
    
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } 
    
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */
  1. STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc下的stm32f4xx_hal_conf.h文件 復制到 APP\inc
    原stm32f4xx_hal_conf.h.png

    APP\inc下stm32f4xx_hal_conf.h.png
  2. 對APP\inc下的stm32f4xx_hal_conf.h文件做如下修改
    stm32f4xx_hal_conf.h中的修改.png
  3. 在APP\src 下創(chuàng)建 syscalls.c 文件尊流,用于完成C lib所需的system calls。具體內容如下:
    圖片.png
#include <errno.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stm32f4xx.h>

#undef errno
extern int errno;

// extern int __io_putchar(int ch) __attribute__((weak));
// extern int __io_getchar(void) __attribute__((weak));

int __io_putchar(int ch)
{
    // return(ITM_SendChar(ch));
    extern UART_HandleTypeDef UartHandle;
    extern HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

    HAL_UART_Transmit(&UartHandle, (uint8_t*)&ch, 1, 10);
    return 0;
}

int __io_getchar(void)
{
    // return(ITM_ReceiveChar());
    return 0;
}

int _close(int file)
{
    return -1;
}

int _stat(char *file, struct stat *st)
{
    st->st_mode = S_IFCHR;
    return 0;
}

int _fstat(int file, struct stat *st)
{
    st->st_mode = S_IFCHR;
    return 0;
}

int _isatty(int file)
{
    return 1;
}

int _lseek(int file, int ptr, int dir)
{
    return 0;
}

int _open(const char *name, int flags, int mode)
{
    return -1;
}

int _read(int file, char *ptr, int len)
{
    // int DataIdx;

    // for (DataIdx = 0; DataIdx < len; DataIdx++) {
    //     __io_putchar('+');
    //     *ptr++ = __io_getchar();
    //     __io_putchar('-');
    // }

    // return len;
    return 0;
}

int _write(int file, char *ptr, int len)
{
    // int DataIdx;

    // for (DataIdx = 0; DataIdx < len; DataIdx++) {
    //     __io_putchar(*ptr++);
    // }
    extern UART_HandleTypeDef UartHandle;
    extern HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
    HAL_UART_Transmit(&UartHandle, (uint8_t*)ptr, len, 10);
    return len;
}

caddr_t _sbrk_r(struct _reent *r, size_t nbytes)
{
    extern char end;       /* Defined by linker */
    static char *heap_end; /* Previous end of heap or 0 if none */
    char        *prev_heap_end;
    char        *stack;

    __asm volatile("MRS %0, msp\n" : "=r"(stack));

    if (0 == heap_end) {
        heap_end = &end; /* Initialize first time round */
    }

    prev_heap_end = heap_end;

    if (stack < (prev_heap_end + nbytes)) {
     /* heap would overlap the current stack depth.
        * Future:  use sbrk() system call to make simulator grow memory beyond
        * the stack and allocate that
        */
        //errno = ENOMEM;
        return (char *) - 1;
    }
    heap_end += nbytes;

    return (caddr_t) prev_heap_end;
}

int _execve(char *name, char **argv, char **env)
{
    errno = ENOTSUP;
    return -1;
}

int _fork(void)
{
    errno = ENOTSUP;
    return -1;
}
/*
 * * getpid -- only one process, so just return 1.
 * */
#define __MYPID 1
int _getpid()
{
    return __MYPID;
}


/*
 * * kill -- go out via exit...
 * */
int _kill(int pid, int sig)
{
    errno = ENOTSUP;
    return -1;
}

int _wait(int *status)
{
    errno = ENOTSUP;
    return -1;
}

void _exit(int __status)
{
    errno = ENOTSUP;
    // return -1;
}

int _link(char *old, char *new)
{
    errno = EMLINK;
    return -1;
}

int _unlink(char *name)
{
    errno = EMLINK;
    return -1;
}

  1. 在syscall.c中特別有去把_write function 接到 HAL UART API上灯帮。這樣崖技,待會程序跑起來以后逻住,所有call printf 吐出的log 都會通過UART口吐出來。所以迎献,待會程序測試的時候可以用串口工具軟件查看LOG方便調試瞎访。
    把printf接到UART上.png
  2. 在APP\src 下創(chuàng)建 main.c 文件,用于完成整個Project的主要功能吁恍。具體內容如下:
    main.c文件.png
/**
  ******************************************************************************
  * @file    UART/UART_TwoBoards_ComPolling/Src/main.c
  * @author  MCD Application Team
  * @brief   This sample code shows how to use STM32F4xx UART HAL API to transmit
  *          and receive a data buffer with a communication process based on
  *          polling transfer.
  *          The communication is done using 2 Boards.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"


/** @addtogroup STM32F4xx_HAL_Examples
  * @{
  */

/** @addtogroup UART_TwoBoards_ComPolling
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define TRANSMITTER_BOARD

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* UART handler declaration */
UART_HandleTypeDef UartHandle;

/* Buffer used for transmission */
uint8_t aTxBuffer[] = " **** UART_TwoBoards_ComPolling ****  **** UART_TwoBoards_ComPolling ****  **** UART_TwoBoards_ComPolling **** \r\n";

/* Buffer used for reception */
uint8_t aRxBuffer[RXBUFFERSIZE];

static TaskHandle_t xHandleTaskLED3 = NULL;
static TaskHandle_t xHandleTaskLED4 = NULL;

/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void Error_Handler(void);
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
static void vTaskLED3(void *pvParameters);
static void vTaskLED4(void *pvParameters);
/* Private functions ---------------------------------------------------------*/
void vApplicationTickHook(void)
{
    uint32_t i = 0;
    for(i=0; i < portTICK_PERIOD_MS; i++)
    {
        HAL_IncTick();
    }
}


/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{

    /* STM32F4xx HAL library initialization:
        - Configure the Flash prefetch, instruction and Data caches
        - Configure the Systick to generate an interrupt each 1 msec
        - Set NVIC Group Priority to 4
        - Global MSP (MCU Support Package) initialization
        */
    HAL_Init();

    printf("hello,world\r\n");

    /* Configure LED3 and LED4 */
    BSP_LED_Init(LED3);
    BSP_LED_Init(LED4);

    /* Configure the system clock to 180 MHz */
    //SystemClock_Config();

    /*##-1- Configure the UART peripheral ######################################*/
    /* Put the USART peripheral in the Asynchronous mode (UART Mode) */
    /* UART1 configured as follow:
        - Word Length = 8 Bits
        - Stop Bit = One Stop bit
        - Parity = None
        - BaudRate = 9600 baud
        - Hardware flow control disabled (RTS and CTS signals) */
    UartHandle.Instance          = USARTx;

    UartHandle.Init.BaudRate     = 115200;
    UartHandle.Init.WordLength   = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits     = UART_STOPBITS_1;
    UartHandle.Init.Parity       = UART_PARITY_NONE;
    UartHandle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
    UartHandle.Init.Mode         = UART_MODE_TX_RX;
    UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

    if(HAL_UART_Init(&UartHandle) != HAL_OK)
    {
        Error_Handler();
    }

    xTaskCreate(vTaskLED3, "vTaskLED3", 512, NULL, 2, &xHandleTaskLED3 );

    xTaskCreate(vTaskLED4, "vTaskLED4", 512, NULL, 2, &xHandleTaskLED4 );

    vTaskStartScheduler();

    /* Infinite loop */
    while (1)
    {
    }


#if 0
#ifdef TRANSMITTER_BOARD

  /* Configure USER Button */
  BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO);

    while(1)
    {
        while (BSP_PB_GetState(BUTTON_KEY) == RESET)
        {
        }

        /* The board sends the message and expects to receive it back */

        /*##-2- Start the transmission process #####################################*/
        /* While the UART in reception process, user can transmit data through
        "aTxBuffer" buffer */
        if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000)!= HAL_OK)
        {
          Error_Handler();
        }

        /* Turn LED3 on: Transfer in transmission process is correct */
        /* then Off for next transmission */
        BSP_LED_On(LED3);
        HAL_Delay(200);
        BSP_LED_Off(LED3);

        printf("hello,world\r\n");
    }

  /* Wait for USER Button press before starting the Communication */
  while (BSP_PB_GetState(BUTTON_KEY) == RESET)
  {
  }

  /* The board sends the message and expects to receive it back */

  /*##-2- Start the transmission process #####################################*/
  /* While the UART in reception process, user can transmit data through
     "aTxBuffer" buffer */
  if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000)!= HAL_OK)
  {
    Error_Handler();
  }

  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
  BSP_LED_On(LED3);
  HAL_Delay(200);
  BSP_LED_Off(LED3);

  /*##-3- Put UART peripheral in reception process ###########################*/
  if(HAL_UART_Receive(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 5000) != HAL_OK)
  {
    Error_Handler();
  }

  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
  BSP_LED_On(LED3);
  HAL_Delay(200);
  BSP_LED_Off(LED3);

#else

  /* The board receives the message and sends it back */

  /*##-2- Put UART peripheral in reception process ###########################*/
  if(HAL_UART_Receive(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 5000) != HAL_OK)
  {
    Error_Handler();
  }

  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
  BSP_LED_On(LED3);
  HAL_Delay(200);
  BSP_LED_Off(LED3);

  /*##-3- Start the transmission process #####################################*/
  /* While the UART in reception process, user can transmit data through
     "aTxBuffer" buffer */
  if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000)!= HAL_OK)
  {
    Error_Handler();
  }

  /* Turn LED3 on: Transfer in transmission process is correct */
  /* then Off for next transmission */
  BSP_LED_On(LED3);
  HAL_Delay(200);
  BSP_LED_Off(LED3);

#endif /* TRANSMITTER_BOARD */

  /*##-4- Compare the sent and received buffers ##############################*/
  if(Buffercmp((uint8_t*)aTxBuffer,(uint8_t*)aRxBuffer,RXBUFFERSIZE))
  {
    Error_Handler();
  }

  /* Infinite loop */
  while (1)
  {
    /* Toggle LED3 */
    BSP_LED_Toggle(LED3);

    /* Wait for 40ms */
    HAL_Delay(40);
  }
#endif
}

static void vTaskLED3(void *pvParameters)
{
    while(1)
    {
        BSP_LED_Toggle(LED3);
        printf("I am in Task LED3\r\n");
        vTaskDelay(250/portTICK_PERIOD_MS);
    }
}

static void vTaskLED4(void *pvParameters)
{
    while(1)
    {
        BSP_LED_Toggle(LED4);
        printf("I am in Task LED4\r\n");
        vTaskDelay(100/portTICK_PERIOD_MS);
    }
}

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow :
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 180000000
  *            HCLK(Hz)                       = 180000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 4
  *            APB2 Prescaler                 = 2
  *            HSE Frequency(Hz)              = 8000000
  *            PLL_M                          = 8
  *            PLL_N                          = 360
  *            PLL_P                          = 2
  *            PLL_Q                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale1 mode
  *            Flash Latency(WS)              = 5
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_OscInitTypeDef RCC_OscInitStruct;

    /* Enable Power Control clock */
    __HAL_RCC_PWR_CLK_ENABLE();

    /* The voltage scaling allows optimizing the power consumption when the device is
        clocked below the maximum system frequency, to update the voltage scaling value
        regarding system frequency refer to product datasheet.  */
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /* Enable HSE Oscillator and activate PLL with HSE as source */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 360;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 7;
    if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /* Activate the Over-Drive mode */
    HAL_PWREx_EnableOverDrive();

    /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
        clocks dividers */
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
    {
        Error_Handler();
    }
}

/**
  * @brief  UART error callbacks
  * @param  UartHandle: UART handle
  * @note   This example shows a simple way to report transfer error, and you can
  *         add your own implementation.
  * @retval None
  */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
{
  /* Turn LED4 on: Transfer error in reception/transmission process */
  BSP_LED_On(LED4);
}

/**
  * @brief  Compares two buffers.
  * @param  pBuffer1, pBuffer2: buffers to be compared.
  * @param  BufferLength: buffer's length
  * @retval 0  : pBuffer1 identical to pBuffer2
  *         >0 : pBuffer1 differs from pBuffer2
  */
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
  while (BufferLength--)
  {
    if ((*pBuffer1) != *pBuffer2)
    {
      return BufferLength;
    }
    pBuffer1++;
    pBuffer2++;
  }

  return 0;
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* Turn LED4 on */
  BSP_LED_On(LED4);
  while(1)
  {
  }
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  1. main.c 文件主要創(chuàng)建了兩個不同frequency的task扒秸。在這兩個task中會吐不同的log和control不同的LED燈。


    兩個不同task.png
  2. 同時冀瓦,在FreeRTOSConfig.h中有特意打開systick hook, 而在main.c中有特別實作這個Tick Hook伴奥。這是因為:STM32 HAL API是要基于Tick Count去計算Timeout Error的。為了保證HAL API正常使用翼闽,特意在systick hook中call HAL_IncTick去增加STM32 HAL API所依賴的Tick Count值
    enable systick hook.png

    Tick Hook.png

    至此拾徙,APP文件下的內容已經實現(xiàn)。待會程序編譯好后感局,可以看到開發(fā)板上兩個LED燈以不同頻率閃動尼啡,并且COM Port上可以正確收到不同LOG。
  • LinkerScripts文件夾下內容實現(xiàn)

LinkerScripts文件夾主要存放memory layout文件

  1. STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\SW4STM32\STM32F429I-Discovery下的 STM32F429ZITx_FLASH.ld 復制到 LinkerScripts文件夾下询微。
    原STM32F429ZITx_FLASH.ld.png

    LinkerScripts文件夾下STM32F429ZITx_FLASH.ld.png

    至此崖瞭,LinkerScripts文件夾下內容已經實現(xiàn)。待會編譯程序的時候拓提,Linker會根據該文件夾下的STM32F429ZITx_FLASH.ld文件去 鏈接 其他各個module文件build出來的目標文件和庫文件 構成 可執(zhí)行文件读恃。

VSCode下C環(huán)境配置

  • 完成上述整個Project程序的移植和編寫以后隧膘,會發(fā)現(xiàn)VSCode提示很多如下的Error:


    Errors.png
  • 無需擔心代态,點擊下“小燈泡”,選擇Edit "IncludePath" settings疹吃,進入到c_cpp_properties.json(見下圖)配置下include path即可蹦疑。


    c_cpp_properties.json.png
  • 按照下圖修改c_cpp_properties.json后就不會出現(xiàn)上述Error了。


    圖片.png

Makefile編寫

Warning: 由于筆者對Makefile這塊不熟悉萨驶,對CMake這些Makefile管理工具也不熟悉歉摧,所以本章所用到的Makefile文件都是筆者自己寫的,所以質量比較挫腔呜,大家將就用吧H隆!核畴!
整個Project的Code都準備好了以后膝但,接下來就得寫Makefile去編譯整個Project了。

  • APP模塊文件夾下分別創(chuàng)建Makefile和module.mk文件
    創(chuàng)建Makefile和module.mk文件.png

Makefile文件用于:把這個模塊文件下的源碼(.c or .s)編譯出目標文件(.o)

CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar

CUR_DIR = $(shell pwd)
SRCDIR  = ./src
INCDIR  = ./inc
OBJDIR  = ../out/objects
###########################################
# vpath %.c src  
CFLAGS  = -g -O0 -Wall
CFLAGS += -mthumb -mcpu=cortex-m4
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -mlittle-endian  -mthumb-interwork

CFLAGS += -I../APP/inc
CFLAGS += -I../CMSIS/Include
CFLAGS += -I../STM32F4xx_HAL_Driver/inc -I../STM32F4xx_System/inc -I../STM32F429I-Discovery/inc
CFLAGS += -I../Kernel/FreeRTOS/include -I../Kernel/FreeRTOS/portable/GCC/ARM_CM4F
CFLAGS += -I$(INCDIR)

CFLAGS += -DSTM32F429xx -DUSE_HAL_DRIVER

SRCS = $(notdir $(wildcard ${SRCDIR}/*.c))
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))

.PHONY: all

all: $(OBJS)
$(OBJDIR)/%.o : $(SRCDIR)/%.c
    $(CC) $^ $(CFLAGS) -c -o $@

clean: 
    rm -f $(OBJS)

module.mk文件用于:告訴頂層Makefile文件在這個模塊文件夾下哪些目標文件需要被鏈接

APP_SRCDIR = $(PWD)/APP/src
C_FILES += $(notdir $(wildcard ${APP_SRCDIR}/*.c))
  • Kernel模塊文件夾下分別創(chuàng)建Makefile和module.mk文件
    Makefile和module.mk文件.png

    Makefile文件用于:把這個模塊文件下的源碼(.c or .s)編譯出目標文件(.o)

CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar

CUR_DIR = $(shell pwd)
SRCDIR  = ./FreeRTOS
INCDIR  = ./FreeRTOS/include
OBJDIR  = ../out/objects
###########################################
# vpath %.c src  
CFLAGS  = -g -O1 -Wall
CFLAGS += -mthumb -mcpu=cortex-m4
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -mlittle-endian  -mthumb-interwork

CFLAGS += -I../APP/inc
CFLAGS += -I../CMSIS/Include
CFLAGS += -I../STM32F4xx_HAL_Driver/inc -I../STM32F4xx_System/inc -I../STM32F429I-Discovery/inc
CFLAGS += -I./FreeRTOS/portable/GCC/ARM_CM4F
CFLAGS += -I$(INCDIR)



SRCS = $(notdir $(wildcard ${SRCDIR}/*.c))
SRCS += $(notdir $(wildcard ${SRCDIR}/portable/GCC/ARM_CM4F/*.c))
SRCS += $(notdir $(wildcard ${SRCDIR}/portable/MemMang/heap_4.c))
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))

.PHONY: all

all: $(OBJS)
$(OBJDIR)/%.o : $(SRCDIR)/%.c
    $(CC) $^ $(CFLAGS) -c -o $@

$(OBJDIR)/%.o : $(SRCDIR)/portable/GCC/ARM_CM4F/%.c
    $(CC) $^ $(CFLAGS) -c -o $@

$(OBJDIR)/heap_4.o : $(SRCDIR)/portable/MemMang/heap_4.c
    $(CC) $^ $(CFLAGS) -c -o $@    

clean: 
    rm -f $(OBJS)

module.mk文件用于:告訴頂層Makefile文件在這個模塊文件夾下哪些目標文件需要被鏈接

C_FILES += event_groups.c
C_FILES += list.c
C_FILES += queue.c
C_FILES += tasks.c
C_FILES += timers.c
C_FILES += port.c
C_FILES += heap_4.c
  • Startup模塊文件夾下分別創(chuàng)建Makefile和module.mk文件
    Makefile和module.mk文件.png

    Makefile文件用于:把這個模塊文件下的源碼(.c or .s)編譯出目標文件(.o)

CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar
AS=arm-none-eabi-as

CUR_DIR = $(shell pwd)
SRCDIR  = ./gcc
INCDIR  = ./
OBJDIR  = ../out/objects
###########################################
# vpath %.c src  
CFLAGS  = -g -O1 -Wall
CFLAGS += -mthumb -mcpu=cortex-m4
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -mlittle-endian  -mthumb-interwork
# CFLAGS += -ffreestanding -nostdlib
# CFLAGS += -DSTM32F429_439xx -DUSE_STDPERIPH_DRIVER
# CFLAGS += -I../STM32F4xx_StdPeriph_Driver/inc -I../STM32F4xx/ -I../CMSIS/Include -I../STM32F429I-Discovery
# CFLAGS += -I../Include
# CFLAGS += -I../FreeRTOS/include -I../FreeRTOS/portable/GCC/ARM_CM4F
ASFLAGS = 

SRCS = $(notdir $(wildcard ${SRCDIR}/*.s))
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.s=.o))

.PHONY: all

all: $(OBJS)
$(OBJDIR)/%.o : $(SRCDIR)/%.s
    $(AS) $^ $(ASFLAGS) -o $@

clean: 
    rm -f $(OBJS)

module.mk文件用于:告訴頂層Makefile文件在這個模塊文件夾下哪些目標文件需要被鏈接

# S_FILES += startup_stm32f429_439xx.s
STARTUP_SRCDIR = $(PWD)/Startup/gcc
S_FILES += $(notdir $(wildcard $(STARTUP_SRCDIR)/*.s))
  • STM32F4xx_HAL_Driver模塊文件夾下分別創(chuàng)建Makefile和module.mk文件
    Makefile和module.mk文件.png

    Makefile文件用于:把這個模塊文件下的源碼(.c or .s)編譯出目標文件(.o)

CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar

CUR_DIR = $(shell pwd)
SRCDIR  = ./src
INCDIR  = ./inc
OBJDIR  = ../out/objects
###########################################
# vpath %.c src  
CFLAGS  = -g -O0 -Wall
CFLAGS += -mthumb -mcpu=cortex-m4
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -mlittle-endian  -mthumb-interwork

CFLAGS += -I../CMSIS/Include
CFLAGS += -I../STM32F4xx_HAL_Driver/inc -I../STM32F4xx_System/inc -I../STM32F429I-Discovery/inc
CFLAGS += -I$(INCDIR) -I$(INCDIR)/Legacy
CFLAGS += -I../APP/inc

CFLAGS += -DSTM32F429xx -DUSE_HAL_DRIVER

SRCS = $(notdir $(wildcard ${SRCDIR}/*.c))
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))

.PHONY: all

all: $(OBJS)
$(OBJDIR)/%.o : $(SRCDIR)/%.c
    $(CC) $^ $(CFLAGS) -c -o $@

clean: 
    rm -f $(OBJS)

module.mk文件用于:告訴頂層Makefile文件在這個模塊文件夾下哪些目標文件需要被鏈接

STM32F4XX_HAL_SRCDIR = $(PWD)/STM32F4xx_HAL_Driver/src
C_FILES += $(notdir $(wildcard ${STM32F4XX_HAL_SRCDIR}/*.c))
  • STM32F4xx_System模塊文件夾下分別創(chuàng)建Makefile和module.mk文件
    創(chuàng)建Makefile和module.mk文件.png

    Makefile文件用于:把這個模塊文件下的源碼(.c or .s)編譯出目標文件(.o)

CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar

CUR_DIR = $(shell pwd)
SRCDIR  = ./src
INCDIR  = ./inc
OBJDIR  = ../out/objects
###########################################
# vpath %.c src  
CFLAGS  = -g -O0 -Wall
CFLAGS += -mthumb -mcpu=cortex-m4
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -mlittle-endian  -mthumb-interwork

CFLAGS += -I../CMSIS/Include
CFLAGS += -I../STM32F4xx_HAL_Driver/inc -I../STM32F4xx_System/inc -I../STM32F429I-Discovery/inc
CFLAGS += -I$(INCDIR)
CFLAGS += -I../APP/inc

CFLAGS += -DSTM32F429xx -DUSE_HAL_DRIVER

SRCS = $(notdir $(wildcard ${SRCDIR}/*.c))
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))

.PHONY: all

all: $(OBJS)
$(OBJDIR)/%.o : $(SRCDIR)/%.c
    $(CC) $^ $(CFLAGS) -c -o $@

clean: 
    rm -f $(OBJS)

module.mk文件用于:告訴頂層Makefile文件在這個模塊文件夾下哪些目標文件需要被鏈接

STM32F4XX_SYSTEM_SRCDIR = $(PWD)/STM32F4xx_System/src
C_FILES += $(notdir $(wildcard ${STM32F4XX_SYSTEM_SRCDIR}/*.c))
  • STM32F429I-Discovery模塊文件夾下分別創(chuàng)建Makefile和module.mk文件
    Makefile和module.mk文件.png

    Makefile文件用于:把這個模塊文件下的源碼(.c or .s)編譯出目標文件(.o)

CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar

CUR_DIR = $(shell pwd)
SRCDIR  = ./src
INCDIR  = ./inc
OBJDIR  = ../out/objects
###########################################
# vpath %.c src  
CFLAGS  = -g -O0 -Wall
CFLAGS += -mthumb -mcpu=cortex-m4
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -mlittle-endian  -mthumb-interwork

CFLAGS += -I../CMSIS/Include
CFLAGS += -I../STM32F4xx_HAL_Driver/inc -I../STM32F4xx_System/inc -I../STM32F429I-Discovery/inc
CFLAGS += -I$(INCDIR)
CFLAGS += -I../APP/inc

CFLAGS += -DSTM32F429xx -DUSE_HAL_DRIVER

SRCS = $(notdir $(wildcard ${SRCDIR}/*.c))
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))

.PHONY: all

all: $(OBJS)
$(OBJDIR)/%.o : $(SRCDIR)/%.c
    $(CC) $^ $(CFLAGS) -c -o $@

clean: 
    rm -f $(OBJS)

module.mk文件用于:告訴頂層Makefile文件在這個模塊文件夾下哪些目標文件需要被鏈接

STM32F4XX_DISCOVERY_SRCDIR = $(PWD)/STM32F429I-Discovery/src
C_FILES += $(notdir $(wildcard ${STM32F4XX_DISCOVERY_SRCDIR}/*.c))
  • 在Project rootpath下創(chuàng)建一個頂層Makefile文件(代碼見下)
    頂層Makefile文件.png

    頂層Makefile文件用于:1)進入到各個模塊文件夾下編譯出目標文件 2)鏈接所有需要使用的目標文件和庫文件生產可執(zhí)行文件 3)把可執(zhí)行文件轉換成dis文件谤草、map文件跟束、bin文件和hex文件

PWD= $(shell pwd)
PROJ_NAME  = HAL_demo
OUTPATH = out
OBJPATH = objects
LOGPATH = logs
LIBPATH := ./lib

CC=arm-none-eabi-gcc
AS=arm-none-eabi-as
LD=arm-none-eabi-ld
AR=arm-none-eabi-ar
OBJCOPY=arm-none-eabi-objcopy
OBJDUMP=arm-none-eabi-objdump

CFLAGS  = -g -O2 -Wall
CFLAGS += -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -mlittle-endian  -mthumb-interwork
CFLAGS += --specs=nosys.specs

CFLAGS += -DSTM32F429xx -DUSE_HAL_DRIVER

CFLAGS += -I../CMSIS/Include
CFLAGS += -I../STM32F4xx_HAL_Driver/inc -I../STM32F4xx_System/inc -I../STM32F429I-Discovery/inc
CFLAGS += -I../APP/inc

# LDFLAGS = --specs=nano.specs -lnosys -nostartfiles
# LDFLAGS += -Wl,-wrap=malloc -Wl,-wrap=calloc -Wl,-wrap=realloc -Wl,-wrap=free
# LDFLAGS += -Wl,-T./LinkerScripts/STM32F429ZI_FLASH.ld -Wl,--gc-sections
LDFLAGS += -nostartfiles --gc-sections
# LDFLAGS += --gc-sections

LDFLAGS += -L$(LIBPATH)/v7e-m/fpv4-sp/hard -lc
LDFLAGS += -L$(LIBPATH)/v7e-m/fpv4-sp/hard -lg
# LDFLAGS += -L$(LIBPATH)/arm-none-eabi/6.3.1/hard -lgcc
LDFLAGS += -L$(LIBPATH)/arm-none-eabi/6.3.1/thumb/v7e-m/fpv4-sp/hard -lgcc
LDFLAGS += -T./LinkerScripts/STM32F429ZI_FLASH.ld
LDFLAGS += -Map=$(OUTPATH)/$(PROJ_NAME).map

C_FILES :=
S_FILES :=

include ./APP/module.mk
include ./Kernel/module.mk
include ./Startup/module.mk
include ./STM32F4xx_HAL_Driver/module.mk
include ./STM32F4xx_System/module.mk
include ./STM32F429I-Discovery/module.mk

C_OBJS := $(addprefix $(OUTPATH)/$(OBJPATH)/, $(C_FILES:.c=.o))
S_OBJS += $(addprefix $(OUTPATH)/$(OBJPATH)/, $(S_FILES:.s=.o))
LIB_OBJS := libc.a

subdirs :=
subdirs += ./Startup ./STM32F4xx_System ./STM32F4xx_HAL_Driver ./STM32F429I-Discovery ./Kernel ./APP

all:
    @mkdir $(OUTPATH)
    @mkdir $(OUTPATH)/$(OBJPATH)
    @mkdir $(OUTPATH)/$(LOGPATH)
    @echo building $(S_OBJS) $(C_OBJS) $(LIB_OBJS)
    for d in $(subdirs); do make -C $$d || exit 1; done
    # for d in $(subdirs); do make -C $$d || exit 1; done > $(OUTPATH)/$(LOGPATH)/build.log
    @echo building $(OUTPATH)/$(PROJ_NAME).elf
    $(LD) $(C_OBJS) $(S_OBJS) $(LDFLAGS) -o $(OUTPATH)/$(PROJ_NAME).elf
    @$(OBJDUMP) -D $(OUTPATH)/$(PROJ_NAME).elf > $(OUTPATH)/$(PROJ_NAME).dis
    @$(OBJCOPY) -O ihex $(OUTPATH)/$(PROJ_NAME).elf $(OUTPATH)/$(PROJ_NAME).hex
    @$(OBJCOPY) -O binary $(OUTPATH)/$(PROJ_NAME).elf $(OUTPATH)/$(PROJ_NAME).bin
    @echo Done 

clean:
    @echo clean $(S_OBJS) $(C_OBJS) $(LIB_OBJS)
    for d in $(subdirs); do make -C $$d $@; done
    @echo cleaning $(OUTPATH)/$(PROJ_NAME).elf
    @rm -rf $(OUTPATH)

至此莺奸,整個Makefile系統(tǒng)已經搭建完畢。在Terminal(Cygwin)下輸入make指令就可以build code了冀宴。

VSCode下Terminal配置

VSCode是帶有Terminal交換面板的灭贷。在Windows下,VSCode默認使用的terminal是cmd或者powershell略贮。由于Cygwin更好使用甚疟,所有得把VSCode默認的terminal改成Cygwin
具體修改方式如下:

  • 編輯系統(tǒng)環(huán)境變量刨肃,把{Cygwin安裝路徑}\bin 加到PATH里面
    編輯系統(tǒng)環(huán)境變量.png
  • 進入到用戶設置界面古拴,然后把terminal.integrated.shell.windows 設置為 按照好的Cygwin的bash.exe
    修改Terminal.png
  • 修改好Terminal后,按下 “Ctrl + ` ” 快捷鍵即可發(fā)現(xiàn)默認的終端已經成功切換為Cygwin了


    Cygwin Terminal.png

編譯程序

  • gcc下編譯過程如下圖所示:

.c文件 經過 arm-none-eabi-gcc 編譯成 .o文件
.s文件 經過 arm-none-eabi-as 編譯成 .o文件
.o文件 和 .a文件 經過 arm-none-eabi-ld 鏈接成 .elf文件
.elf文件 經過 arm-none-eabi-objcopy 和 arm-none-eabi-objdump 轉換成 hex文件/dis文件
arm-none-eabi-gdb 使用 .elf文件 進行debug

gcc.png
  • 在Terminal下輸入make指令真友,即會開始build程序

    make指令.png

    編譯過程.png

  • 編譯完成后黄痪,生成的所有文件都會放在out文件夾下

    out文件夾.png

  • 如果改了source code,需要重新編譯程序盔然,那就得先執(zhí)行make clean指令去刪除之前build好的所有東西桅打。然后重新執(zhí)行make指令即可

程序燒寫和運行

完成上面所有步驟愈案,可以得到hex文件挺尾。我們只需要把hex文件download到STM32F429內部的FLASH上,就可以執(zhí)行程序查看效果了站绪。

  • 程序燒寫
  1. 把板子連接上電腦


    ST-Link Debug.png
  2. 打開STM32 ST-LINK Utility遭铺,連上ST-Link


    連上ST-Link.png
  3. 擦除FLASH上所有數(shù)據


    擦除FLASH上所有數(shù)據.png
  4. 選擇out文件夾下的hex文件,download到FLASH里面


    download.png

    至此恢准,程序已經成功download到FLASH上了魂挂。

  • 程序運行
  1. 查看LED等閃爍


    IMG_20180222_215111.jpg
  2. 查看串口LOG


    LOG.png

本章總結

本章的主要目的:在VSCode下搭建編譯環(huán)境

  • 架構Project搭建
  • 移植和編寫各個模塊文件夾下的程序
  • Makefile編譯
  • 編譯程序
  • 程序燒寫和運行

在下一章中,會向大家介紹如何在VSCode下搭建調試環(huán)境

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末馁筐,一起剝皮案震驚了整個濱河市涂召,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敏沉,老刑警劉巖果正,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盟迟,居然都是意外死亡秋泳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門攒菠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迫皱,“玉大人,你說我怎么就攤上這事要尔∩岫牛” “怎么了新娜?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長既绩。 經常有香客問我概龄,道長,這世上最難降的妖魔是什么饲握? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任私杜,我火速辦了婚禮,結果婚禮上救欧,老公的妹妹穿的比我還像新娘衰粹。我一直安慰自己,他們只是感情好笆怠,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布铝耻。 她就那樣靜靜地躺著,像睡著了一般蹬刷。 火紅的嫁衣襯著肌膚如雪瓢捉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天办成,我揣著相機與錄音泡态,去河邊找鬼。 笑死迂卢,一個胖子當著我的面吹牛某弦,可吹牛的內容都是我干的。 我是一名探鬼主播而克,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼靶壮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拍摇?” 一聲冷哼從身側響起亮钦,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤馆截,失蹤者是張志新(化名)和其女友劉穎充活,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜡娶,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡混卵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了窖张。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幕随。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖宿接,靈堂內的尸體忽然破棺而出赘淮,到底是詐尸還是另有隱情辕录,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布梢卸,位于F島的核電站走诞,受9級特大地震影響,放射性物質發(fā)生泄漏蛤高。R本人自食惡果不足惜蚣旱,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望戴陡。 院中可真熱鬧塞绿,春花似錦、人聲如沸恤批。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喜庞。三九已至涧黄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赋荆,已是汗流浹背笋妥。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窄潭,地道東北人春宣。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像嫉你,于是被迫代替她去往敵國和親月帝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容