KeilMDK环境 stm32f10x快速移值FreeRTOSv9.0

stm32f10x快速移值FreeRTOS

FreeRTOS由于其短小精悍,开源免费被广泛的应用。在使用FreeRTOS之前不可避免的就是移值。在这里分享一个快速简单、亲测可用的freertos移值教程。其他类型的编译器和单片机也可做为参考。

准备工作

在进行FreeRTOS移值之前首先得先拿到FreeRTOS源码,并分析它得目录结构。
源码可以在FreeRTOS官网获得,下载下来为一个可执行文件,双击解压可获得源码。
根目录我们将要使用的是FreeRTOS里的文件,另一个FreeRTOS-Plus不必管它,它包含了FreeRTOS的其他一下可选和扩展功能。
在这里插入图片描述
Demo文件夹包含了官方提供的大量的基于不同硬件和编译器的例程,有很大的参考价值。在移值程序的时候可以用到。
Source里包含了移值所必须的文件如下图:
在这里插入图片描述
红框标出的是操作系统内核正常工作所需要的必要文件。其他的为一些可选功能:事件组,协程,软件定时器等。
include为头文件需要在工程中包含该文件夹
protable文件夹中的文件不是所有是必须的,只需要选择对应处理器和平台的文件夹中的文件使用即可。
在这里插入图片描述
框选出来的为必须选的,MemMang中的heap_x.c是不同的内存管理方案,任意选择一种即可,这里选择heap_4.c,关于他们之间的差异可以自行百度。
由于在Keil文件夹下See-also-the-RVDS-directory.txt文件明确说了去RVDS找,于是乎还需要RVDS文件夹中的 \RVDS\ARM_CM3文件夹中的源代码。

最后需要准备的是例程里的FreeRTOSConfig.h源码,这个头文件已经将大部分配置工作给做好了,大大简化了移值。可以在 \FreeRTOS\Demo\CORTEX_STM32F103_Keil找到。
在这里插入图片描述
到这里需要的文件就准备齐了。将他们复制到已有的工程目录下,然后添加进工程,并包含头文件所在位置。如图所示:
在这里插入图片描述
添加源文件到工程里面。并索引头文件所在位置。
在这里插入图片描述

移值

添加完程序,还需要少量修改。

将一些中断向量交给操作系统内核管理

FreeRTOSConfig.h中添加宏定义:

#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

在这里插入图片描述为了避免重定义,我们将stm32f10x_it.h中的申明给注释掉。
在这里插入图片描述然后进行编译。

测试程序

#include "stm32f10x.h" 
#include "usart.h"
#include "led.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);

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);    			
	uart_init(115200);				
	LED_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();      
}

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();        //进入临界区
    xTaskCreate((TaskFunction_t )led0_task,     	  //创建led0任务
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   

    xTaskCreate((TaskFunction_t )led1_task,     //创建led1任务
                (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();       //推出临界区
}

void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}   

void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

一共创建三个任务,在开始任务中创建了led0闪烁和led1闪烁任务。然后在主函数中创建开始任务,并删除开始任务,最后启动任务调度。

总结

统过宏定义的方法,可以免去在启动文件中进行修改,简单快速。提高开发效率。

发布了18 篇原创文章 · 获赞 92 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_27350133/article/details/89606558