STM32标准库部署和FreeRTOS移植指南(适用各类开发板)

FreeRTOS的移植

  • 一、准备
  • 1.下载源文件
  • 2. 文件内容
  • 2.1 include文件
  • 2.2 portable文件
  • 二、STM32工程部署
  • 1. 标准库
  • 1.1 下载标准库
  • 1.2 标准库简介
  • 内核文件
  • 库文件
  • 配置文件和中断函数文件
  • 2. keil设置
  • 2.1 为什么要添加STM32F10X_HD,USE_STDPERIPH_DRIVER宏定义
  • 2.1.1 USE_STDPERIPH_DRIVER
  • 2.1.1 STM32F10X_HD
  • 三、移植FreeRTOS到工程
  • 1. 复制文件
  • 2. 在keil工程中添加FreeRTOS内容
  • 3. 修改FreeRTOSConfig.h文件
  • 4. 修改stm32f10x_it.c文件
  • 四、编写程序
  • 一、准备

    1.下载源文件

    FreeRTOS Real Time Kernel Files
    下载V9.0.0下的FreeRTOSv9.0.0.zip
    文件下载
    下载完成解压后
    文件解压

    2. 文件内容

    双击打开FreeRTOS文件夹,这就是FreeRTOS V9.0.0的源文件了
    Source文件夹

    2.1 include文件

    在include文件夹中是一些头文件,这是需要移植到嵌入式平台的部分
    头文件夹

    2.2 portable文件

    这个文件夹下需要关注的是移植哪种编译环境的文件和管理内存的文件
    在本次的学习中使用的是keil环境,“See-also-the-RVDS-directory”其主要参照是在RVDS文件夹中的ARM系列CM3
    portable文件夹
    RVDS文件夹

    二、STM32工程部署

    在keil中创建一个STM32的工程首先开始部署STM32的标准库环境。

    1. 标准库

    1.1 下载标准库

    STM32F10x标准外设库
    可以选择注册一个stm32的账号来下载该固件库
    下载并解压后得到如下
    STM32F1标准库

    1.2 标准库简介

    在上图中需要的标准库内容只在Libraries文件夹中,为了方便管理将该文件夹分类

    内核文件

    内核文件在Libraries\CMSIS\CM3\CoreSupport
    内核文件
    将这两个文件复制到刚刚创建的keil工程下的CORE文件夹(自己创建的文件夹)下
    CORE文件夹1
    并且内核文件只是一些对动作的具体描述,比如数据的压栈等等,但这并不能使单片机真正运行起来,还需要单片机的启动程序,这个启动程序也是内核的一部分
    在Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm下选择合适的启动文件也放入到CORE中
    启动文件
    复制合适的启动文件
    CORE文件夹2

    库文件

    Libraries\STM32F10x_StdPeriph_Driver
    库文件
    在工程下新建一个STM32_Libraries文件夹将ku文件全部存入
    STM32_Libraries文件夹

    配置文件和中断函数文件

    是在例程中,打开任意例程就可以找到这两个文件(外加一个头文件)
    Project\STM32F10x_StdPeriph_Examples\ADC\ADC1_DMA
     配置文件和中断函数文件
    系统文件

    将他们复制到STM32_Config中
    并且在Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x找到系统文件也一并存入STM32_Config中
    STM32_Config

    说明:system_stm32f10x.c .h是系统的初始化程序包括系统的基础时钟初始化

    至此STM32的标准库部署基本完成 下面是对keil工程的设置和文件的添加了

    2. keil设置

    向keil中添加文件夹及添加文件,文件夹按照创建的文件夹名创建文件夹
    文件设置1
    文件设置2
    文件设置3
    文件设置4
    最重要的是要在编译器中添加宏定义,要让编译器明确单片机容量类型STM32F10X_HD,USE_STDPERIPH_DRIVER
    并且将头文件地址加入到头文件地址框中

    2.1 为什么要添加STM32F10X_HD,USE_STDPERIPH_DRIVER宏定义

    2.1.1 USE_STDPERIPH_DRIVER

    在main函数中需要在开头包含stm32f10x.h这个文件
    main
    在该文件中搜索USE_STDPERIPH_DRIVER宏,可以发现这个宏是决定是否要包含stm32f10x_conf.h这个头文件的一个标识
    stm32宏
    而打开stm32f10x_conf.h这个文件可以发现,在这个文件里面包含了所有的标准库的头文件,这也是为什么在main.c中只引入了一个stm32f10x.h文件的原因
    头文件

    2.1.1 STM32F10X_HD

    同理也在stm32f10x.h这个文件中搜索STM32F10X_HD宏,可以看到有对中断的描述,也有对内核链接外设的描述
    中断

    三、移植FreeRTOS到工程

    1. 复制文件

    在工程下新建一个文件夹叫FreeRTOS
    将FreeRTOS的源文件FreeRTOSv9.0.0\FreeRTOS\Source下的内容复制到FreeRTOS中

    打开portable文件夹删除我们不需要的内容

    打开FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_STM32F103_Keil文件

    将这个文件复制到工程文件夹中的FreeRTOS/include文件夹下

    2. 在keil工程中添加FreeRTOS内容

    在keil中新建两个文件夹FreeRTOS_CORE和FreeRTOS_PORT,并在这两个文件夹下添加文件


    接下来将头文件地址加入到keil的头文件寻址框中

    3. 修改FreeRTOSConfig.h文件

    在FreeRTOSConfig.h中添加如下内容
    #define xPortPendSVHandler PendSV_Handler
    #define xPortSysTickHandler SysTick_Handler
    #define vPortSVCHandler SVC_Handler

    4. 修改stm32f10x_it.c文件

    将以下三个函数注释

    至此FreeRTOS的移植和STM32标准库的部署基本完工

    四、编写程序

    #include "stm32f10x.h"
    #include "FreeRTOS.h"
    #include "task.h"
    
    //任务优先级
    #define START_TASK_PRIO		1
    //任务堆栈大小	
    #define START_STK_SIZE 		128  
    //任务句柄
    TaskHandle_t StartTask_Handler;
    //任务函数
    void start_task(void *pvParameters);
    
    //任务优先级
    #define LED0_TASK_PRIO		2
    //任务堆栈大小	
    #define LED0_STK_SIZE 		50  
    //任务句柄
    TaskHandle_t LED0Task_Handler;
    //任务函数
    void led0_task(void *pvParameters);
    
    //任务优先级
    #define LED1_TASK_PRIO		3
    //任务堆栈大小	
    #define LED1_STK_SIZE 		50  
    //任务句柄
    TaskHandle_t LED1Task_Handler;
    //任务函数
    void led1_task(void *pvParameters);
    
    
     
     void GPIO_INIT()
     {
    	 
    		GPIO_InitTypeDef  GPIO_InitStructure;
     	
    		 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PB,PE端口时钟
    			
    		 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PB.5 端口配置
    		 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    		 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    		 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.5
    		 GPIO_SetBits(GPIOB,GPIO_Pin_5);						 //PB.5 输出高
    
    		 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	    		 //LED1-->PE.5 端口配置, 推挽输出
    		 GPIO_Init(GPIOE, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
    		 GPIO_SetBits(GPIOE,GPIO_Pin_5); 						 //PE.5 输出高 
     }
     
     void start_task(void *pvParameters)
    {
    	 taskENTER_CRITICAL();           //进入临界区
        //创建LED0任务
        xTaskCreate((TaskFunction_t )led0_task,     	
                    (const char*    )"led0_task",   	
                    (uint16_t       )LED0_STK_SIZE, 
                    (void*          )NULL,				
                    (UBaseType_t    )LED0_TASK_PRIO,	
                    (TaskHandle_t*  )&LED0Task_Handler); 
        //创建LED1任务
        xTaskCreate((TaskFunction_t )led1_task,     
                    (const char*    )"led1_task",   
                    (uint16_t       )LED1_STK_SIZE, 
                    (void*          )NULL,
                    (UBaseType_t    )LED1_TASK_PRIO,
                    (TaskHandle_t*  )&LED1Task_Handler);         
        vTaskDelete(StartTask_Handler); //删除开始任务
        taskEXIT_CRITICAL();            //退出临界区
    }
    //LED0 任务函数
    void led0_task(void *pvParameters)
    {
     while(1)
     {
    	  GPIO_SetBits(GPIOE,GPIO_Pin_5);
    	  vTaskDelay(500);
    	  GPIO_ResetBits(GPIOB,GPIO_Pin_5);
    	  vTaskDelay(500);
     }
    }
    //LED1 任务函数
    void led1_task(void *pvParameters)
    {
    	while(1)
    	{
     		GPIO_ResetBits(GPIOE,GPIO_Pin_5);
    		vTaskDelay(300);
    		GPIO_SetBits(GPIOB,GPIO_Pin_5);	
    		vTaskDelay(300);
    	}
    }
     int main(void)
     {	
    	 
    	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4 
    	 GPIO_INIT();
    	 
    	 //创建开始任务
        xTaskCreate((TaskFunction_t )start_task,            //任务函数
                    (const char*    )"start_task",          //任务名称
                    (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                    (void*          )NULL,                  //传递给任务函数的参数
                    (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                    (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
        vTaskStartScheduler();          //开启任务调度
    		 	  
    }
    
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32标准库部署和FreeRTOS移植指南(适用各类开发板)

    发表评论