KeilMDK環境 stm32f10x快速移值FreeRTOS
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閃爍任務。然後在主函數中創建開始任務,並刪除開始任務,最後啓動任務調度。
總結
統過宏定義的方法,可以免去在啓動文件中進行修改,簡單快速。提高開發效率。