目錄
1.? 獲取裸機工程模版
2.??下載 FreeRTOS V9.0.0 源碼
3.? FreeRTOS文件夾內容簡介
3.1? FreeRTOS文件夾
3.1.1? Demo文件夾
3.1.2??License 文件夾
3.1.3??Source 文件夾
3.2? FreeRTOS-Plus 文件夾
4.? 往裸機工程添加 FreeRTOS 源碼
5.??拷貝 FreeRTOSConfig.h 文件到 user 文件夾
6.??添加 FreeRTOS 源碼到工程組文件夾
6.1??新建 FreeRTOS/src 和 FreeRTOS/port 組
6.2??指定 FreeRTOS 頭文件的路徑
7.??修改 FreeRTOSConfig.h
8.? 修改 stm32f10x_it.c
1.? 獲取裸機工程模版
? ? ? ? 這里我使用的是STM32F103ZET6的開發板,找了一個點亮LED的工程模版進行更改,自己隨便找一個模版都行,沒必要一定一樣:
STM32f103ZET6移植工程模版資源-CSDN文庫
2.??下載 FreeRTOS V9.0.0 源碼
????????在移植之前,我們首先要獲取到 FreeRTOS 的官方的源碼包。這里我們提供兩個下載鏈接:
官網鏈接:www.freertos.org
代碼托管網站:sourceforge.net
????????打開網站鏈接之后,我們選擇 FreeRTOS 的最新版本 V9.0.0(2016 年),盡管現在 FreeRTOS 的版本已經更新到 V10.0.1 了,但是我們還是選擇 V9.0.0,因為內核很穩定,并且網上資料很多,因為 V10.0.0 版本之后是亞馬遜收購了 FreeRTOS 之后才出來的版本,主要添加了一些云端組件:
????????點擊 V9.0.0 會跳轉到版本目錄。這里有 zip 和 exe 格式的壓縮包,其實都是 FreeRTOS 的源碼,只是壓縮的格式不一樣,所以大小也不一樣,我們這里選擇 zip 的下載,點擊了就會出現下載的鏈接,下載完成解壓后就可以得到我們想要的 FreeRTOS V9.0.0 版本的源碼了:
有時候網站打不開,所以附帶一個百度網盤的鏈接:
鏈接: https://pan.baidu.com/s/1G4ezuX0Thwy-kUarMqYYFg?pwd=svii
提取碼: svii?
需要注意一點,該文件可能路徑過長電腦自帶的解壓文件可能無法解壓,試驗過360解壓的軟件能解壓,如果是在無法解壓,后續也會附上配置好的文件。
3.? FreeRTOS文件夾內容簡介
3.1? FreeRTOS文件夾
????????FreeRTOS 包含 Demo 例程和內核源碼(比較重要,我們就需要提取該目錄下的大部分文件):
????????FreeRTOS 文件夾下的 Source 文件夾里面包含的是 FreeRTOS 內核的源代碼,我們移植 FreeRTOS 的時候就需要這部分源代碼;FreeRTOS 文件夾下的Demo 文件夾里面包含了FreeRTOS 官方為各個單片機移植好的工程代碼,FreeRTOS 為了推廣自己,會給各種半導體廠商的評估板寫好完整的工程程序,這些程序就放在 Demo 這個目錄下,這部分 Demo 非常有參考價值。我們把 FreeRTOS 到 STM32 的時候,FreeRTOSConfig.h 這個頭文件就是從這里拷貝過來的。
3.1.1? Demo文件夾
????????這個目錄下內容就是 Deme 例程,我們可以直接打開里面的工程文件,各種開發平臺的完整 Demo,開發者可以方便的以此搭建出自己的項目,甚至直接使用。FreeRTOS 當然也為 ST 寫了很多 Demo,其中就有 F1、F4、F7 等工程,這樣子對我們學習 FreeRTOS 是非常方便的,當遇到不懂的直接就可以參考官方的 Demo:
3.1.2??License 文件夾
????????這里面只有一個許可文件“license.txt”,用 FreeRTOS 做產品的話就需要看看這個文件,但是我們是學習 FreeRTOS,所以暫時不需要理會這個文件。
3.1.3??Source 文件夾
????????這里我們再重點分析下 FreeRTOS/ Source 文件夾下的文件,其中include文件和下圖框柱的文件包含的是FreeRTOS 的通用的頭文件和 C 文件這兩部分的文件試用于各種編譯器和處理器,是通用的。
? ? ? ? 而需要移植的頭文件和 C文件放在portblle 這個文件夾:
????????我們打開 portblle 這個文件夾,可以看到里面很多與編譯器相關的文件夾,在不同的編譯器中使用不同的支持文件:
????????KEIL 就是我們就是我們使用的編譯器,當年打開 KEIL 文件夾的時候,你會看到一句話“See-also-the-RVDS-directory.txt”,其實 KEIL里面的內容跟 RVDS 里面的內容一樣,所以,我們只需要編號RVDS 文件夾里面的內容即可。而編號MemMang 文件夾下存放的是跟內存管理相關的。
????????打開 RVDS 文件夾,下面包含了各種處理器相關的文件夾,從文件夾的名字我們就非常熟悉了,我們學習的 STM32 有 M0、M3、M4 等各種系列,FreeRTOS 是一個軟件,單片機是一個硬件,FreeRTOS 要想運行在一個單片機上面,它們就必須關聯在一起,那么怎么關聯?還是得通過寫代碼來關聯,這部分關聯的文件叫接口文件,通常由匯編和 C 聯合編寫。這些接口文件都是跟硬件密切相關的,不同的硬件接口文件是不一樣的,但都大同小異。編寫這些接口文件的過程我們就叫移植,移植的過程通常由 FreeRTOS 和 mcu 原廠的人來負責,移植好的這些接口文件就放在 RVDS 這個文件夾的目錄下:
????????MemMang 文件夾下存放的是跟內存管理相關的,總共有五個 heap 文件以及一個 readme 說明文件,這五個 heap 文件在移植的時候必須使用一個,因為 FreeRTOS 在創建內核對象的時候使用的是動態分配內存,而這些動態內存分配的函數則在這幾個文件里面實現,不同的分配算法會導致不同的效率與結果,后面在內存管理中我們會講解每個文件的區別,由于現在是初學,所以我們選用 heap4.c 即可:
3.2? FreeRTOS-Plus 文件夾
????????FreeRTOS-Plus 文件夾里面包含的是第三方的產品,一般我們不需要使用,FreeRTOSPlus 的預配置演示項目組件(組件大多數都要收費),大多數演示項目都是在 Windows 環境中運行的,使用 FreeRTOS windows 模擬器,所以暫時不需要關注這個文件夾。
4.? 往裸機工程添加 FreeRTOS 源碼
????????首先在我們的STM32 裸機工程模板根目錄下新建一個文件夾,命名 為“FreeRTOS”,并且在 FreeRTOS 文件夾下新建兩個空文件夾,分別命名為“src”與“port”,src 文件夾用于保存 FreeRTOS 中的核心源文件,也就是我們常說的‘.c 文件’,port 文件夾用于保存內存管理以及處理器架構相關代碼,這些代碼FreeRTOS 官方已經提供給我們的,直接使用即可,在前面已經說了,FreeRTOS是軟件,我們的開發版是硬件,軟硬件必須有橋梁來連接,這些與處理器架構相關的代碼,可以稱之為 RTOS 硬件接口層,它們位于 FreeRTOS/Source/Portable 文件夾下。
????????打開 FreeRTOS V9.0.0 源碼,在“FreeRTOSv9.0.0\FreeRTOS\Source”目錄下找到所有的‘.c 文件’:
????????打開 FreeRTOS V9.0.0 源碼,在“FreeRTOSv9.0.0\FreeRTOS\Source\portable”目錄下找到“MemMang”文件夾與“RVDS”文件夾,將它們拷貝到我們新建的 port 文件夾中,具體見:
????????打開 FreeRTOS V9.0.0 源碼,在“FreeRTOSv9.0.0\ FreeRTOS\Source”目錄下找到“include”文件夾,它是我們需要用到 FreeRTOS 的一些頭文件,將它直接拷貝到我們新建的 FreeRTOS 文件夾中,完成這一步之后就可以看到我們新建的 FreeRTOS 文件夾已經有 3 個文件夾,這 3個文件夾就包含 FreeRTOS 的核心文件,至此,FreeRTOS 的源碼就提取完成:
5.??拷貝 FreeRTOSConfig.h 文件到 user 文件夾
????????FreeRTOSConfig.h 文件是 FreeRTOS 的工程配置文件,因為 FreeRTOS 是可以裁剪的實時操作內核,應用于不同的處理器平臺,用戶可以通過修改這個 FreeRTOS 內核的配置頭文件來裁剪 FreeRTOS 的功能,所以我們把它拷貝一份放在 user 這個文件夾下面。
????????打開 FreeRTOSv9.0.0 源碼,在“FreeRTOSv9.0.0\FreeRTOS\Demo”文件夾下面找到“ CORTEX_STM32F103_Keil ” 這個文件夾 ,雙擊打開 , 在其根目錄下找到這個“FreeRTOSConfig.h”文件,然后拷貝到我們工程的 user 文件夾下即可,等下我們需要對這個文件進行修改。user 文件夾,見名知義我們就可以知道里面存放的文件都是用戶自己編寫的。
6.??添加 FreeRTOS 源碼到工程組文件夾
????????在上一步我們只是將 FreeRTOS 的源碼放到了本地工程目錄下,還沒有添加到開發環境里面的組文件夾里面,FreeRTOS 也就沒有移植到我們的工程中去。
6.1??新建 FreeRTOS/src 和 FreeRTOS/port 組
????????接下來我們在開發環境里面新建 FreeRTOS/src 和 FreeRTOS/port 兩個組文件夾:
????????其中FreeRTOS/src 用于存放 src 文件夾的內容:
????????FreeRTOS/port 用于存放 port\MemMang 文件夾與 port\RVDS\ARM_CM3文件夾的內容:
? ? ? ? 添加完成如下:
? ? ? ? 再將FreeRTOSConfig.h文件,放到user文件夾下:
6.2??指定 FreeRTOS 頭文件的路徑
????????FreeRTOS 的源碼已經添加到開發環境的組文件夾下面,編譯的時候需要為這些源文件指定頭文件的路徑,不然編譯會報錯。FreeRTOS 的源碼里面只有 FreeRTOS\include 和 FreeRTOS\port\RVDS\ARM_CM3這兩個文件夾下面有頭文件,只需要將這兩個頭文件的路徑在開發環境里面指定即可。同時我們還將 FreeRTOSConfig.h 這個頭文件拷貝到了工程根目錄下的 user 文件夾下,所以 user 的路徑也要加到開發環境里面:
7.??修改 FreeRTOSConfig.h
????????FreeRTOSConfig.h 是直接從 demo 文件夾下面拷貝過來的,該頭文件對裁剪整個 FreeRTOS 所需的功能的宏均做了定義,有些宏定義被使能,有些宏定義被失能,一開始我們只需要配置最簡單的功能即可。要想隨心所欲的配置 FreeRTOS 的功能,我們必須對這些宏定義的功能有所掌握,下面我們先簡單的介紹下這些宏定義的含義,然后再對這些宏定義進行修改。
/*FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.All rights reservedVISIT 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 underthe terms of the GNU General Public License (version 2) as published by theFree 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 ANYWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. Full license text is available on the followinglink: 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 readingthe FAQ page "My application does not run, what could be wrong?". Have youdefined configASSERT()?http://www.FreeRTOS.org/support - In return for receiving this top qualityembedded software for free we request you assist our global community byparticipating in the support forum.http://www.FreeRTOS.org/training - Investing in training allows your team tobe as productive as possible as early as possible. Now you can receiveFreeRTOS training directly from Richard Barry, CEO of Real Time EngineersLtd, 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 DOScompatible 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 HighIntegrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOSlicenses offer ticketed support, indemnification and commercial middleware.http://www.SafeRTOS.com - High Integrity Systems also provide a safetyengineered and independently SIL3 certified version for use in safety andmission critical applications that require provable dependability.*/#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H#include "stm32f10x.h"
#include "Usart.h"//針對不同的編譯器調用不同的stdint.h文件
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)#include <stdint.h>extern uint32_t SystemCoreClock;
#endif//斷言
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)/************************************************************************* FreeRTOS基礎配置配置選項 *********************************************************************/
/* 置1:RTOS使用搶占式調度器;置0:RTOS使用協作式調度器(時間片)* * 注:在多任務管理機制上,操作系統可以分為搶占式和協作式兩種。* 協作式操作系統是任務主動釋放CPU后,切換到下一個任務。* 任務切換的時機完全取決于正在運行的任務。*/
#define configUSE_PREEMPTION 1//1使能時間片調度(默認式使能的)
#define configUSE_TIME_SLICING 1 /* 某些運行FreeRTOS的硬件有兩種方法選擇下一個要執行的任務:* 通用方法和特定于硬件的方法(以下簡稱“特殊方法”)。* * 通用方法:* 1.configUSE_PORT_OPTIMISED_TASK_SELECTION 為 0 或者硬件不支持這種特殊方法。* 2.可以用于所有FreeRTOS支持的硬件* 3.完全用C實現,效率略低于特殊方法。* 4.不強制要求限制最大可用優先級數目* 特殊方法:* 1.必須將configUSE_PORT_OPTIMISED_TASK_SELECTION設置為1。* 2.依賴一個或多個特定架構的匯編指令(一般是類似計算前導零[CLZ]指令)。* 3.比通用方法更高效* 4.一般強制限定最大可用優先級數目為32* 一般是硬件計算前導零指令,如果所使用的,MCU沒有這些硬件指令的話此宏應該設置為0!*/
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 /* 置1:使能低功耗tickless模式;置0:保持系統節拍(tick)中斷一直運行* 假設開啟低功耗的話可能會導致下載出現問題,因為程序在睡眠中,可用以下辦法解決* * 下載方法:* 1.將開發版正常連接好* 2.按住復位按鍵,點擊下載瞬間松開復位按鍵* * 1.通過跳線帽將 BOOT 0 接高電平(3.3V)* 2.重新上電,下載* * 1.使用FlyMcu擦除一下芯片,然后進行下載* STMISP -> 清除芯片(z)*/
#define configUSE_TICKLESS_IDLE 0 /** 寫入實際的CPU內核時鐘頻率,也就是CPU指令執行頻率,通常稱為Fclk* Fclk為供給CPU內核的時鐘信號,我們所說的cpu主頻為 XX MHz,* 就是指的這個時鐘信號,相應的,1/Fclk即為cpu時鐘周期;*/
#define configCPU_CLOCK_HZ (SystemCoreClock)//RTOS系統節拍中斷的頻率。即一秒中斷的次數,每次中斷RTOS都會進行任務調度
#define configTICK_RATE_HZ (( TickType_t )1000)//可使用的最大優先級
#define configMAX_PRIORITIES (32)//空閑任務使用的堆棧大小
#define configMINIMAL_STACK_SIZE ((unsigned short)128)//任務名字字符串長度
#define configMAX_TASK_NAME_LEN (16)//系統節拍計數器變量數據類型,1表示為16位無符號整形,0表示為32位無符號整形
#define configUSE_16_BIT_TICKS 0 //空閑任務放棄CPU使用權給其他同優先級的用戶任務
#define configIDLE_SHOULD_YIELD 1 //啟用隊列
#define configUSE_QUEUE_SETS 0 //開啟任務通知功能,默認開啟
#define configUSE_TASK_NOTIFICATIONS 1 //使用互斥信號量
#define configUSE_MUTEXES 0 //使用遞歸互斥信號量
#define configUSE_RECURSIVE_MUTEXES 0 //為1時使用計數信號量
#define configUSE_COUNTING_SEMAPHORES 0/* 設置可以注冊的信號量和消息隊列個數 */
#define configQUEUE_REGISTRY_SIZE 10 #define configUSE_APPLICATION_TASK_TAG 0 /*****************************************************************FreeRTOS與內存申請有關配置選項
*****************************************************************/
//支持動態內存申請
#define configSUPPORT_DYNAMIC_ALLOCATION 1
//支持靜態內存
#define configSUPPORT_STATIC_ALLOCATION 0
//系統所有總的堆大小
#define configTOTAL_HEAP_SIZE ((size_t)(36*1024)) /***************************************************************FreeRTOS與鉤子函數有關的配置選項
**************************************************************/
/* 置1:使用空閑鉤子(Idle Hook類似于回調函數);置0:忽略空閑鉤子* * 空閑任務鉤子是一個函數,這個函數由用戶來實現,* FreeRTOS規定了函數的名字和參數:void vApplicationIdleHook(void ),* 這個函數在每個空閑任務周期都會被調用* 對于已經刪除的RTOS任務,空閑任務可以釋放分配給它們的堆棧內存。* 因此必須保證空閑任務可以被CPU執行* 使用空閑鉤子函數設置CPU進入省電模式是很常見的* 不可以調用會引起空閑任務阻塞的API函數*/
#define configUSE_IDLE_HOOK 0 /* 置1:使用時間片鉤子(Tick Hook);置0:忽略時間片鉤子* * * 時間片鉤子是一個函數,這個函數由用戶來實現,* FreeRTOS規定了函數的名字和參數:void vApplicationTickHook(void )* 時間片中斷可以周期性的調用* 函數必須非常短小,不能大量使用堆棧,* 不能調用以”FromISR" 或 "FROM_ISR”結尾的API函數*//*xTaskIncrementTick函數是在xPortSysTickHandler中斷函數中被調用的。因此,vApplicationTickHook()函數執行的時間必須很短才行*/
#define configUSE_TICK_HOOK 0 //使用內存申請失敗鉤子函數
#define configUSE_MALLOC_FAILED_HOOK 0 /** 大于0時啟用堆棧溢出檢測功能,如果使用此功能 * 用戶必須提供一個棧溢出鉤子函數,如果使用的話* 此值可以為1或者2,因為有兩種棧溢出檢測方法 */
#define configCHECK_FOR_STACK_OVERFLOW 0 /********************************************************************FreeRTOS與運行時間和任務狀態收集有關的配置選項
**********************************************************************/
//啟用運行時間統計功能
#define configGENERATE_RUN_TIME_STATS 0 //啟用可視化跟蹤調試
#define configUSE_TRACE_FACILITY 0
/* 與宏configUSE_TRACE_FACILITY同時為1時會編譯下面3個函數* prvWriteNameToBuffer()* vTaskList(),* vTaskGetRunTimeStats()
*/
#define configUSE_STATS_FORMATTING_FUNCTIONS 1 /********************************************************************FreeRTOS與協程有關的配置選項
*********************************************************************/
//啟用協程,啟用協程以后必須添加文件croutine.c
#define configUSE_CO_ROUTINES 0
//協程的有效優先級數目
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) /***********************************************************************FreeRTOS與軟件定時器有關的配置選項
**********************************************************************///啟用軟件定時器
#define configUSE_TIMERS 0
//軟件定時器優先級
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1)
//軟件定時器隊列長度
#define configTIMER_QUEUE_LENGTH 10
//軟件定時器任務堆棧大小
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) /************************************************************FreeRTOS可選函數配置選項
************************************************************/
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 0
//#define INCLUDE_xTaskGetCurrentTaskHandle 1
//#define INCLUDE_uxTaskGetStackHighWaterMark 0
//#define INCLUDE_xTaskGetIdleTaskHandle 0/******************************************************************FreeRTOS與中斷有關的配置選項
******************************************************************/
#ifdef __NVIC_PRIO_BITS#define configPRIO_BITS __NVIC_PRIO_BITS
#else#define configPRIO_BITS 4
#endif
//中斷最低優先級
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //系統可管理的最高中斷優先級
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /* 240 */#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )/****************************************************************FreeRTOS與中斷服務函數有關的配置選項
****************************************************************/
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler/* 以下為使用Percepio Tracealyzer需要的東西,不需要時將 configUSE_TRACE_FACILITY 定義為 0 */
#if ( configUSE_TRACE_FACILITY == 1 )
#include "trcRecorder.h"
#define INCLUDE_xTaskGetCurrentTaskHandle 1 // 啟用一個可選函數(該函數被 Trace源碼使用,默認該值為0 表示不用)
#endif#endif /* FREERTOS_CONFIG_H */
部分代碼解析:
//針對不同的編譯器調用不同的stdint.h文件
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)#include <stdint.h>extern uint32_t SystemCoreClock;
#endif
針對不同的編譯器調用不同的 stdint.h 文件,在 MDK 中,我們默認的是__CC_ARM。
//斷言
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)
????????在使用 C 語言編寫工程代碼時,我們總會對某種假設條件進行檢查,斷言就是用于在代碼中捕捉這些假設,可以將斷言看作是異常處理的一種高級形式。斷言表示為一些布爾表達式,程序員相信在程序中的某個特定表達式值為真。可以在任何時候啟用和禁用斷言驗證,因此可以在測試時啟用斷言,而在發布時禁用斷言。同樣,程序投入運行后,最終用戶在遇到問題時可以重新啟用斷言。它可以快速發現并定位軟件問題,同時對系統錯誤進行自動報警。斷言可以對在系統中隱藏很深,用其它手段極難發現的問題可以用斷言來進行定位,從而縮短軟件問題定位時間,提高系統的可測性。實際應用時,可根據具體情況靈活地設計斷言。這里只是使用宏定義實現了斷言的功能,斷言作用很大,特別是在調試的時候,而 FreeRTOS 中使用了很多斷言接口 configASSERT,所以我們需要實現斷言,把錯誤信息打印出來從而在調試中快速定位,打印信息的內容是xxx 文件 xxx 行(__FILE__,__LINE__)。
? ? ? ? 簡單來說就是查找報錯,打印錯誤。
#define configUSE_PREEMPTION 1
????????置1:RTOS使用搶占式調度器;置0:RTOS使用協作式調度器(時間片)
????????搶占式調度:在這種調度方式中,系統總是選擇優先級最高的任務進行調度,并且 一旦高優先級的任務準備就緒之后,它就會馬上被調度而不等待低優先級的任務主動放棄 CPU,高優先級的任務搶占了低優先級任務的 CPU 使用權,這就是搶占,在實習操作系統中,這樣子的方式往往是最適用的。
????????協作式調度:則是由任務主動放棄CPU,然后才進行任務調度。
#define configUSE_TIME_SLICING 1
????????使能時間片調度(默認式使能的)。當優先級相同的時候,就會采用時間片調度,這意味著 RTOS 調度器總是運行處于最高優先級的就緒任務,在每個FreeRTOS 系統節拍中斷時在相同優先級的多個任務間進行任務切換。如果宏configUSE_TIME_SLICING 設置為 0,FreeRTOS 調度器仍然總是運行處于最高優先級的就緒任務,但是當 RTOS 系統節拍中斷發生時,相同優先級的多個任務之間不再進行任務切換,而是在執行完高優先級的任務之后才進行任務切換。一般來說,FreeRTOS 默認支持 32 個優先級,很少情況會把 32 個優先級全用完,所以,官方建議采用搶占式調度。
8.? 修改 stm32f10x_it.c
? ? ? ? 首先我們先導入串口文件,我們這里使用野火的串口文件,它的一個宏定義感覺非常方便,別的也可以,進行導入:
? ? ? ? 運行后會發現這兩個報錯:
? ? ? ? 因為SysTick 中斷服務函數是一個非常重要的函數,FreeRTOS 所有跟時間相關的事情都在里面處理,SysTick 就是 FreeRTOS 的一個心跳時鐘,驅動著 FreeRTOS 的運行,就像人的心跳一樣,假如沒有心跳,我們就相當于“死了”,同樣的,FreeRTOS 沒有了心跳,那么它就會卡死在某個地方,不能進行任務調度,不能運行任何的東西,因此我們需要實現一個 FreeRTOS 的心跳時鐘,FreeRTOS 幫我們實現了 SysTick 的啟動的配置:在 port.c 文件中已經實現 vPortSetupTimerInterrupt()函數,并且 FreeRTOS 通用的 SysTick 中斷服務函數也實現了:在 port.c 文件中已經實現 xPortSysTickHandler()函數,所以移植的時候只需要我們在 stm32f10x_it.c 文件中實現我們對應(STM32)平臺上的 SysTick_Handler()函數即可。FreeRTOS 為開發者考慮得特別多,PendSV_Handler()與 SVC_Handler()這兩個很重要的函數都幫我們實現了,在 port.c 文件中已經實現 xPortPendSVHandler()與 vPortSVCHandler()函數,防止我們自己實現不了,那么在 stm32f10x_it.c 中就需要我們注釋掉PendSV_Handler()與 SVC_Handler()這兩個函數了:
/********************************************************************************* @file Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c * @author MCD Application Team* @version V3.5.0* @date 08-April-2011* @brief Main Interrupt Service Routines.* This file provides template for all exceptions handler and * peripherals interrupt service routine.******************************************************************************* @attention** THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.** <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>*******************************************************************************//* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "FreeRTOS.h"
#include "task.h"
/** @addtogroup STM32F10x_StdPeriph_Template* @{*//* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*//******************************************************************************/
/* Cortex-M3 Processor Exceptions Handlers */
/******************************************************************************//*** @brief This function handles NMI exception.* @param None* @retval None*/
void NMI_Handler(void)
{
}/*** @brief This function handles Hard Fault exception.* @param None* @retval None*/
void HardFault_Handler(void)
{/* Go to infinite loop when Hard Fault exception occurs */while (1){}
}/*** @brief This function handles Memory Manage exception.* @param None* @retval None*/
void MemManage_Handler(void)
{/* Go to infinite loop when Memory Manage exception occurs */while (1){}
}/*** @brief This function handles Bus Fault exception.* @param None* @retval None*/
void BusFault_Handler(void)
{/* Go to infinite loop when Bus Fault exception occurs */while (1){}
}/*** @brief This function handles Usage Fault exception.* @param None* @retval None*/
void UsageFault_Handler(void)
{/* Go to infinite loop when Usage Fault exception occurs */while (1){}
}/*** @brief This function handles SVCall exception.* @param None* @retval None*/
//void SVC_Handler(void)
//{
//}/*** @brief This function handles Debug Monitor exception.* @param None* @retval None*/
void DebugMon_Handler(void)
{
}/*** @brief This function handles PendSVC exception.* @param None* @retval None*/
//void PendSV_Handler(void)
//{
//}/*** @brief This function handles SysTick Handler.* @param None* @retval None*/
extern void xPortSysTickHandler(void);
//systick中斷服務函數
void SysTick_Handler(void)
{ #if (INCLUDE_xTaskGetSchedulerState == 1 )if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED){#endif /* INCLUDE_xTaskGetSchedulerState */ xPortSysTickHandler();#if (INCLUDE_xTaskGetSchedulerState == 1 )}#endif /* INCLUDE_xTaskGetSchedulerState */
}/******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32f10x_xx.s). */
/******************************************************************************//*** @brief This function handles PPP interrupt request.* @param None* @retval None*/
/*void PPP_IRQHandler(void)
{
}*//*** @}*/ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
? ? ? ? 這時候在運行報錯解決了。
工程模版:
STM32F103ZET6的FreeRTOS工程移植模版資源-CSDN文庫
FreeRTOS實時操作系統_時光の塵的博客-CSDN博客