- 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)境盛杰, 具體包含以下幾個部分:
- Project架構搭建
- VSCode下創(chuàng)建同名Project
- 移植和編寫程序
- VSCode下C環(huán)境配置
- Makefile編譯
- VSCode下Terminal配置
- 編譯程序
- 程序燒寫和運行
Project架構搭建
-
首先,我們需要在搭建項目的文件夾下創(chuàng)建項目文件夾咆槽。
例如下圖中爷贫,在E:\STMicroelectronics\workspace\stm32f429\projects下創(chuàng)建一個名為HAL_demo的文件夾钾腺。后續(xù)用到的所有文件等都會放到HAL_demo文件夾下。
-
然后,在項目文件夾下創(chuàng)建后續(xù)所需用到的各個模塊的文件夾临谱。
例如下圖中,在HAL_demo文件下創(chuàng)建APP奴璃、CMSIS悉默、Kernel、lib苟穆、LinkerScripts抄课、Startup、STM32F4xx_HAL_Driver雳旅、STM32F4xx_System跟磨、STM32F429I-Discovery、tools這些文件夾攒盈。
.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快捷鍵顯示所有命令蔬捷。
- 然后垄提,在窗口中輸入如下command,進入到project edit界面 周拐。
>projects:Edit Configuration
-
接著铡俐,創(chuàng)建一個name為STM32的group。然后在group的projects下創(chuàng)建一個name為HAL demo的project,并且把path設為剛才創(chuàng)建的HAL_demo這個文件夾的路徑妥粟。
- 完成上述步驟审丘,即可在VSCode側邊欄中的PROJECTS下見到我們剛才創(chuàng)建的那個Project。以后需要切換到這個project只需右擊該project選擇open or open in New Window即可勾给。
移植和編寫程序
搭建完Project架構和在VSCode下創(chuàng)建好Project以后备恤,接下來要做就是本文最重要的部分:移植和編寫各個module文件夾下的程序了。
- CMSIS 文件夾下內容實現(xiàn)
CMSIS文件夾下主要需要移植ARM Cortex-M 所需的硬件抽象層文件
-
把STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS下所有內容 都復制到 CMSIS文件夾下
至此锦秒,CMSIS 文件夾下內容已經全部實現(xiàn)露泊。我們后續(xù)所用到文件 其實都在CMSIS\Include下,例如cmsis_gcc.h中會包含__disable_irq 和 __enable_irq這些內聯(lián)匯編旅择。
- Startup 文件夾下內容實現(xiàn)
Startup文件夾下主要需要移植一個startup_stm32f429_439xx.s文件
startup_stm32f429_439xx.s文件主要實現(xiàn)以下功能:
- 初始化SP和PC值惭笑;
- 設置Vector Table;
- 初始化.data 和 .bss section在memory上的data生真;
- 初始化C library所需環(huán)境沉噩,初始化system環(huán)境,jump到main函數(shù)等柱蟀。
-
在Startup文件夾下創(chuàng)建一個gcc 文件夾川蒙。Makefile 和 module.mk文件后續(xù)章節(jié)會介紹
- 把之前安裝好的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(見下下圖)长已。
- 對gcc文件夾中的startup_stm32f429_439xx.s文件作如下改動:把bl __libc_init_array 這行mask掉畜眨。
至此昼牛,Startup文件夾下的內容已經完成。startup.s文件 從第一行code到最后一行code 主要就是為了實現(xiàn)如下的開機FLOW:
- STM32F4xx_HAL_Driver 文件夾下內容實現(xiàn)
STM32F4xx_HAL_Driver文件夾下主要需要移植STM32Cube中提供的那些HAL driver文件康聂,例如uart贰健、i2c、spi恬汁、adc等硬件設備的驅動程序伶椿。
- 在STM32F4xx_HAL_Driver 文件夾下分別創(chuàng)建inc和src文件夾。Makefile 和 module.mk文件后續(xù)章節(jié)會介紹
- 把STM32Cube_FW_F4_V1.18.0\Drivers\STM32F4xx_HAL_Driver\Inc下的所有頭文件和子文件夾 復制 到STM32F4xx_HAL_Driver\inc下
- 把STM32Cube_FW_F4_V1.18.0\Drivers\STM32F4xx_HAL_Driver\Src下的所有C文件 復制 到STM32F4xx_HAL_Driver\src下
- 把STM32F4xx_HAL_Driver\inc下stm32_assert_template.h和stm32f4xx_hal_conf_template.h刪除
- 對stm32f4xx_ll_rcc.h做如下修改:#define HSE_VALUE (25000000U) 改為 #define HSE_VALUE (8000000U)
- 把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刪除
- 對stm32f4xx_hal.c做如下修改:mask掉HAL_InitTick(TICK_INT_PRIORITY)這行
因為FreeRTOS中會對systick進行配置,所以這邊無需call HAL_InitTick去配置systick约巷。如果是裸機開發(fā)偎痛,無需mask這行code。
至此载庭,STM32F4xx_HAL_Driver文件夾下的內容已經完成。在應用程序中call STM32F4xx_HAL_Driver下各個文件中的API 即可實現(xiàn)對Hardware的控制廊佩,不再需要直接去control hardware registers了
- STM32F4xx_System 文件夾下內容實現(xiàn)
STM32F4xx_System文件夾下主要需要移植一些STM32 System Level所依賴的文件囚聚,例如:
- system_stm32f4xx.c 中的functions實現(xiàn)System Clock setting,
- stm32f4xx_it.c 中的functions實現(xiàn)各個Interrupt handler,
- stm32f4xx_hal_msp.c 中的functions實現(xiàn)low level hardware initialization,例如Uart Port GPIO Pinmux Setting等标锄。
- 在STM32F4xx_System文件夾下分別創(chuàng)建inc和src文件夾顽铸。Makefile 和 module.mk文件后續(xù)章節(jié)會介紹
- 把STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include下的stm32f4xx.h、stm32f429xx.h以及system_stm32f4xx.h 復制 到 STM32F4xx_System\inc下
- 把STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates下的system_stm32f4xx.c 復制到 STM32F4xx_System\src下
- 按照如下代碼料皇,修改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>© 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****/
- 把STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc下的stm32f4xx_it.h 復制到 STM32F4xx_System\inc下
-
修改STM32F4xx_System\inc下的stm32f4xx_it.h:把 #include "main.h" 替換為 #include "stm32f429xx.h"
因為main.h會放到APP文件夾下,所以不希望這邊直接include APP下的東西
- 把STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Src下的stm32f4xx_it.c 復制到 STM32F4xx_System\src下
-
修改STM32F4xx_System\src下的stm32f4xx_it.c:
1) 把 #include "main.h" 這行刪除
2) 對SVC_Handler, PendSV_Handler, SysTick_Handler做如下改動:
這幾個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中的實作。 - 把STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc下的main.h 復制到 STM32F4xx_System\inc下并且 重名為 stm32f4xx_hal_msp.h
- 按照如下代碼军洼,修改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>© 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的相關定義。
- 把STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Src下的stm32f4xx_hal_msp.c 復制到 STM32F4xx_System\src下
-
修改STM32F4xx_System\src下的stm32f4xx_hal_msp.c: 把#include "main.h" 改為 #include "stm32f4xx_hal_msp.h"
至此匕争,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等設備的驅動程序
- 在STM32F429I-Discovery文件夾下分別創(chuàng)建inc和src文件夾盗胀。其他文件和文件夾后續(xù)章節(jié)會介紹
- 把STM32Cube_FW_F4_V1.18.0\Drivers\BSP\STM32F429I-Discovery下 所有H文件 復制到 STM32F429I-Discovery\inc下
- 把STM32Cube_FW_F4_V1.18.0\Drivers\BSP\STM32F429I-Discovery下 所有C文件 復制到 STM32F429I-Discovery\src下
- 把STM32Cube_FW_F4_V1.18.0\Drivers\BSP下 Components文件夾 直接復制到 STM32F429I-Discovery文件夾下
- 把STM32Cube_FW_F4_V1.18.0\Utilities下 Fonts文件夾 直接復制到 STM32F429I-Discovery文件夾下
-
修改STM32F429I-Discovery\src\stm32f429i_discovery_lcd.c 和 STM32F429I-Discovery\src\stm32f429i_discovery_lcd.h 文件:把其中所有 "../../../Utilities/" 替換為 ".."
修改這部分是因為我們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)
- 在Kernel文件夾下創(chuàng)建FreeRTOS文件夾冯键。其他文件后續(xù)章節(jié)會介紹
-
進入下載好的FreeRTOS Source Code路徑下的Source文件夾下惹盼,例如我這邊的E:\FreeRTOS\Source_Code\FreeRTOSV8.2.3\FreeRTOS\Source
- 把Source文件夾下的所有文件和文件夾都 復制到 Kernel/FreeRTOS下
-
進入到Kernel/FreeRTOS/portable下,把除了 GCC文件夾惫确、MemMang文件夾 和 readme 以外的所有的東西都刪除掉
-
進入到Kernel/FreeRTOS/portable/GCC下席函,把除了 ARM_CM4F文件夾 以外的所有的東西都刪除掉
如果讀者使用的CPU不是Cortex-M4 Core的話淘邻,那么就只需要在GCC下保留對應的CPU架構的文件夾,其他架構的文件夾都不需要。例如Cortex-M0的話锻全,就留ARM_CM0就好了
至此副编,F(xiàn)reeRTOS Kernel已經移植好了闻书,待會在APP文件夾下添加一個FreeRTOSConfig.h文件楞黄,整個Project即可使用FreeRTOS了。
- lib 文件夾下內容實現(xiàn)
lib文件夾下主要存放pre-build好的一些lib句旱,例如libc.a阳藻、libg.a、libgcc.a等
- 打開{ARM GNU ToolChain 文件夾}\share\doc\gcc-arm-none-eabi\readme.txt發(fā)現(xiàn)谈撒,CM4F所使用的lib是放在v7e-m/fpv4-sp/hard下的lib
前提是使用Hard FP
-
進入到{ARM GNU ToolChain 文件夾}\lib\gcc下腥泥,把整個arm-none-eabi文件夾 復制到 lib 文件夾下
- 待會會用到lib\arm-none-eabi\6.3.1\thumb\v7e-m\fpv4-sp\hard下的libgcc.a
-
進入到{ARM GNU ToolChain 文件夾}\arm-none-eabi\lib\thumb下,把整個v7e-m文件夾 復制到 lib 文件夾下
- 待會會用到lib\v7e-m\fpv4-sp\hard下的libc.a 和 libg.a
-
進入到{ARM GNU ToolChain 文件夾}\arm-none-eabi文件夾下,把整個include文件夾 復制到 lib 文件夾下
至此,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等)
- 在APP文件夾下分別創(chuàng)建inc和src文件夾冒萄。其他文件后續(xù)章節(jié)會介紹
- 在inc文件夾下 創(chuàng)建 main.h,具體內容如下(主要參考STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc\main.h):
/**
******************************************************************************
* @file UART/UART_TwoBoards_ComPolling/Inc/main.h
* @author MCD Application Team
* @brief Header for main.c module
******************************************************************************
* @attention
*
* <h2><center>© 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****/
- 在inc文件夾下 創(chuàng)建 FreeRTOSConfig.h橙数,具體內容如下(主要參考FreeRTOSV8.2.3\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK\FreeRTOSConfig.h):
/*
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 */
- 把STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\Inc下的stm32f4xx_hal_conf.h文件 復制到 APP\inc下
- 對APP\inc下的stm32f4xx_hal_conf.h文件做如下修改:
-
在APP\src 下創(chuàng)建 syscalls.c 文件尊流,用于完成C lib所需的system calls。具體內容如下:
#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;
}
-
在syscall.c中特別有去把_write function 接到 HAL UART API上灯帮。這樣崖技,待會程序跑起來以后逻住,所有call printf 吐出的log 都會通過UART口吐出來。所以迎献,待會程序測試的時候可以用串口工具軟件查看LOG方便調試瞎访。
-
在APP\src 下創(chuàng)建 main.c 文件,用于完成整個Project的主要功能吁恍。具體內容如下:
/**
******************************************************************************
* @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>© 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****/
-
main.c 文件主要創(chuàng)建了兩個不同frequency的task扒秸。在這兩個task中會吐不同的log和control不同的LED燈。
- 同時冀瓦,在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值
至此拾徙,APP文件下的內容已經實現(xiàn)。待會程序編譯好后感局,可以看到開發(fā)板上兩個LED燈以不同頻率閃動尼啡,并且COM Port上可以正確收到不同LOG。
- LinkerScripts文件夾下內容實現(xiàn)
LinkerScripts文件夾主要存放memory layout文件
- 把STM32Cube_FW_F4_V1.18.0\Projects\STM32F429I-Discovery\Examples\UART\UART_TwoBoards_ComPolling\SW4STM32\STM32F429I-Discovery下的 STM32F429ZITx_FLASH.ld 復制到 LinkerScripts文件夾下询微。
至此崖瞭,LinkerScripts文件夾下內容已經實現(xiàn)。待會編譯程序的時候拓提,Linker會根據該文件夾下的STM32F429ZITx_FLASH.ld文件去 鏈接 其他各個module文件build出來的目標文件和庫文件 構成 可執(zhí)行文件读恃。
VSCode下C環(huán)境配置
-
完成上述整個Project程序的移植和編寫以后隧膘,會發(fā)現(xiàn)VSCode提示很多如下的Error:
-
無需擔心代态,點擊下“小燈泡”,選擇Edit "IncludePath" settings疹吃,進入到c_cpp_properties.json(見下圖)配置下include path即可蹦疑。
-
按照下圖修改c_cpp_properties.json后就不會出現(xiàn)上述Error了。
Makefile編寫
Warning: 由于筆者對Makefile這塊不熟悉萨驶,對CMake這些Makefile管理工具也不熟悉歉摧,所以本章所用到的Makefile文件都是筆者自己寫的,所以質量比較挫腔呜,大家將就用吧H隆!核畴!
整個Project的Code都準備好了以后膝但,接下來就得寫Makefile去編譯整個Project了。
- 在APP模塊文件夾下分別創(chuàng)建Makefile和module.mk文件
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文件用于:把這個模塊文件下的源碼(.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文件用于:把這個模塊文件下的源碼(.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文件用于:把這個模塊文件下的源碼(.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文件
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文件用于:把這個模塊文件下的源碼(.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文件用于: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里面
- 進入到用戶設置界面古拴,然后把terminal.integrated.shell.windows 設置為 按照好的Cygwin的bash.exe
-
修改好Terminal后,按下 “Ctrl + ` ” 快捷鍵即可發(fā)現(xiàn)默認的終端已經成功切換為Cygwin了
編譯程序
- 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
-
在Terminal下輸入make指令真友,即會開始build程序
-
編譯完成后黄痪,生成的所有文件都會放在out文件夾下
如果改了source code,需要重新編譯程序盔然,那就得先執(zhí)行make clean指令去刪除之前build好的所有東西桅打。然后重新執(zhí)行make指令即可。
程序燒寫和運行
完成上面所有步驟愈案,可以得到hex文件挺尾。我們只需要把hex文件download到STM32F429內部的FLASH上,就可以執(zhí)行程序查看效果了站绪。
- 程序燒寫
-
把板子連接上電腦
-
打開STM32 ST-LINK Utility遭铺,連上ST-Link
-
擦除FLASH上所有數(shù)據
-
選擇out文件夾下的hex文件,download到FLASH里面
至此恢准,程序已經成功download到FLASH上了魂挂。
- 程序運行
-
查看LED等閃爍
-
查看串口LOG
本章總結
本章的主要目的:在VSCode下搭建編譯環(huán)境
- 架構Project搭建
- 移植和編寫各個模塊文件夾下的程序
- Makefile編譯
- 編譯程序
- 程序燒寫和運行
在下一章中,會向大家介紹如何在VSCode下搭建調試環(huán)境