FreeRTOSConfig.h 配置優化及深入

本篇目標:基於上一篇的移植freertos(stm32f4_freertos)上,修改 FreeRTOSConfig.h 文件的相關配置來優化輔助 FreeRtos 的使用,並且建立一些基本功能(信號量、消息地列等)的簡單應用位於(stm32f4_os_app)工程。

資料準備:


配置優化簡介

之前的移植功能只是將從源文件 demo中拷貝了一份 FreeRTOSConfig.h 做了一些移植修改而已,但是對於文件每個宏的定義,以及配置的修改沒有做過多的深入。

所以這篇中的工程將 FreeRTOSConfig.h 進行了配置的修改與優化,並且註釋了常用的宏定義的用途,詳細的也會在下面進行解析,初步來看下相關的配置。

首先將 FreeRTOSConfig.h 的配置分成幾部分:

  • FreeRTOS 與系統有關的配置
  • FreeRTOS 與功能api相關的配置
  • FreeRTOS 相關鉤子函數的配置
  • FreeRTOS DEBUG調試相關的配置
  • FreeRTOS 與系統優先級相關的配置
  • FreeRTOS 應用自定義配置

配置優化解析

  • FreeRTOS 與系統有關的配置:

    /* RTOS CONFIG(配置) */
    
    /* 系統調度器配置 :搶佔式調度爲1,時間片調度爲0 */
    #define configUSE_PREEMPTION            1
    
    /* 移植系統(stm32)配置的時鐘主頻,stm32主頻最高爲 168MHz */
    #define configCPU_CLOCK_HZ              ( SystemCoreClock )
    
    /* Freertos 每 1/1000 s產生一次systick,來維持實時性調度 */
    #define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
    
    /* Freertos 配置的最大優先級,配置32以內的值 */
    #define configMAX_PRIORITIES            ( 10 )
    
    /* 空閒任務棧大小 */
    #define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 130 )
    
    /* 整個 Freertos 內存堆的大小 */
    #define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 75 * 1024 ) )
    
    /* 任務名稱最大長度 */
    #define configMAX_TASK_NAME_LEN         ( 10 )
    
    /* 系統數據類型長度定義,stm32爲32位,16位機開啓該宏 */
    #define configUSE_16_BIT_TICKS          0
    
    /* 調度與空閒任務優先級相同的任務 */
    #define configIDLE_SHOULD_YIELD         0
    
  • FreeRTOS 與功能api相關的配置:

    /* RTOS API(資源使能與裁剪) */
    
    /* 與互斥鎖相關 */
    #define configUSE_MUTEXES               1       //使能互斥鎖
    #define configUSE_RECURSIVE_MUTEXES     1       //使能遞歸互斥鎖
    #define configUSE_TASK_NOTIFICATIONS    1       //使能任務間通知
    #define configUSE_COUNTING_SEMAPHORES   1       //使能計數信號量
    #define configUSE_QUEUE_SETS            1       //使能消息集
    #define configQUEUE_REGISTRY_SIZE       8       //設置隊列註冊的個數
    
    #define configUSE_TIMERS                1       //使能定時器
    #if configUSE_TIMERS
        #define configTIMER_TASK_PRIORITY           ( 2 )
        #define configTIMER_QUEUE_LENGTH            10
        #define configTIMER_TASK_STACK_DEPTH        ( configMINIMAL_STACK_SIZE * 2 )
        #define configUSE_DAEMON_TASK_STARTUP_HOOK  0
    #endif
    
    /* Set the following definitions to 1 to include the API function, or zero
    to exclude the API function. (使能任務相關api) */
    #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_xTaskGetIdleTaskHandle          0
    #define INCLUDE_xTaskGetCurrentTaskHandle       1
    #define INCLUDE_uxTaskGetStackHighWaterMark     1
    #define INCLUDE_xTaskGetSchedulerState          1
    
  • FreeRTOS 相關鉤子函數的配置,需要定義鉤子函數,鉤子函數定義放在了工程 stm_config.c 中:

    #define configUSE_IDLE_HOOK             1
    /* 空閒任務鉤子函數使能,需要定義下列函數,此函數在空閒函數 prvIdleTask 中調用 */
    void vApplicationIdleHook( void )
    {
        //log_d("%s", __FUNCTION__);
    }
    
    /* 空閒任務低功耗函數使能,stm32 已經在 port.c 中定義了 vPortSuppressTicksAndSleep 函數,在空閒函數 prvIdleTask 中調用 */
    #define configUSE_TICKLESS_IDLE         0       //
    
    
    #define configUSE_TICK_HOOK             0
    /* tick鉤子函數使能,需要定義下列函數,此函數在systick中斷函數中由 xTaskIncrementTick 調用 */
    void vApplicationTickHook( void )
    {
        //printf("%s\r\n", __FUNCTION__);
    }
    
    
    #define configUSE_MALLOC_FAILED_HOOK    1
    /* 內存申請失敗鉤子函數使能,需要定義下列函數,此函數在內存申請函數pvPortMalloc中調用 */
    void vApplicationMallocFailedHook( void )
    {
        log_d("%s", __FUNCTION__);
        log_e("os malloc fail");
    }
    
    
    #define configCHECK_FOR_STACK_OVERFLOW  2
    /* 任務棧溢出檢測鉤子函數使能,需要定義下列函數,此函數在PendSV函數中由 vTaskSwitchContext調用。
     * 任務堆棧檢測有兩種方式,發生異常則會調用鉤子函數:
     * 方式1爲檢查當前任務棧指針是否在任務棧的合法空間內。
     * 方式2爲在任務棧最後區域填入0xa5a5a5a5的數據,每次調度的時候檢查數據是否有改動。
     */
    void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
    {
        log_d("%s", __FUNCTION__);
        log_e("task Overflow : %s [%p]", pcTaskName, xTask);
    }
    
    
    #define configSUPPORT_STATIC_ALLOCATION 0
    /* 靜態任務創建函數使能,需要定義下列官方示例函數,使能後可以使用 xTaskCreateStatic 函數 */
    /* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
    implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
    used by the Idle task. */
    void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
                                        StackType_t **ppxIdleTaskStackBuffer,
                                        uint32_t *pulIdleTaskStackSize )
    {
        /* If the buffers to be provided to the Idle task are declared inside this
        function then they must be declared static - otherwise they will be allocated on
        the stack and so not exists after this function exits. */
        static StaticTask_t xIdleTaskTCB;
        static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
    
        /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
        state will be stored. */
        *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
    
        /* Pass out the array that will be used as the Idle task's stack. */
        *ppxIdleTaskStackBuffer = uxIdleTaskStack;
    
        /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
        Note that, as the array is necessarily of type StackType_t,
        configMINIMAL_STACK_SIZE is specified in words, not bytes. */
        *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
    }
    /*-----------------------------------------------------------*/
    
    /* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
    application must provide an implementation of vApplicationGetTimerTaskMemory()
    to provide the memory that is used by the Timer service task. */
    void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
                                         StackType_t **ppxTimerTaskStackBuffer,
                                         uint32_t *pulTimerTaskStackSize )
    {
        /* If the buffers to be provided to the Timer task are declared inside this
        function then they must be declared static - otherwise they will be allocated on
        the stack and so not exists after this function exits. */
        static StaticTask_t xTimerTaskTCB;
        static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
    
        /* Pass out a pointer to the StaticTask_t structure in which the Timer
        task's state will be stored. */
        *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
    
        /* Pass out the array that will be used as the Timer task's stack. */
        *ppxTimerTaskStackBuffer = uxTimerTaskStack;
    
        /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
        Note that, as the array is necessarily of type StackType_t,
        configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
        *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
    }
    
  • FreeRTOS DEBUG調試相關的配置,函數實現在工程 stm_config.c 中:

    /* 使能以下兩個宏,既可以使用任務可視化追蹤,可以調用 vTaskList 打印任務信息 */
    #define configUSE_TRACE_FACILITY                1
    #define configUSE_STATS_FORMATTING_FUNCTIONS    1
    
    /* 使能下面的宏,將可以調用 vTaskGetRunTimeStats 查看任務佔用情況
     * rtos_sys_timer_init 爲定時器初始化,定義一個10倍tick(100Hz)以上的速率來計算任務佔用率
     * rtos_sys_cnt_get 爲獲取按上述速率增加的計數值
     */
    #define configGENERATE_RUN_TIME_STATS   1
    #if (defined configGENERATE_RUN_TIME_STATS) && (configGENERATE_RUN_TIME_STATS == 1)
    #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()  rtos_sys_timer_init()
    #define portGET_RUN_TIME_COUNTER_VALUE()          rtos_sys_cnt_get()
    #endif
    
    /* Normal assert() semantics without relying on the provision of an assert.h
        header file. (斷言) */
    #include "elog.h"
    #define OS_ASSERT(x)       log_e(x)
    #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); OS_ASSERT("os err"); for( ;; ); }
    
  • FreeRTOS 與系統優先級相關的配置:

    /* stm32與os相關中斷優先級的配置,由stm32手冊以及頭文件可知支持優先級爲4bit,所以下面配置爲4,並且系統初始化的時候需要設置中斷分組配置:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); */
    #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    5
    
    /* 以上兩個爲RTOS配置的優先級區間,從最大到最小,所以注意所有需要在中斷裏調用RTOS的api的時候,
     * 這個中斷的優先級一定要在上面這個區間內,否則就會出現斷言錯誤,系統也無法正常調度。
     * --------------------------------------------------------------------
     * 下面兩個優先級爲轉換後的優先級數據,因爲上面的4bit優先級佔據寄存器的高4位,
     * 所以下面需要進行移位轉換
     */
    
    /* 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) )
    
  • FreeRTOS 應用自定義配置:

    /* 定義常用的優先級,進行應用應用,避免應用編程出現直接的數值 */
    #define RTOS_PRIORITY_HIGHEST       (configMAX_PRIORITIES-1)
    #define RTOS_PRIORITY_LEVEL_1ST     (configMAX_PRIORITIES-2)
    #define RTOS_PRIORITY_LEVEL_2ST     (configMAX_PRIORITIES-3)
    #define RTOS_PRIORITY_LEVEL_3ST     (configMAX_PRIORITIES-4)
    #define RTOS_PRIORITY_LEVEL_4ST     (configMAX_PRIORITIES-5)
    #define RTOS_PRIORITY_LEVEL_5ST     (configMAX_PRIORITIES-6)
    

也貼一下修改後所有的 FreeRTOSConfig.h 以及移植適配的 stm_config.c 文件:

/*
 * FreeRTOS Kernel V10.3.1
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 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

#ifndef USE_OS
#define USE_OS
#endif

/* RTOS CONFIG(配置) */
#define configUSE_PREEMPTION            1       //搶佔式調度:1 | 時間片調度:0
#define configCPU_CLOCK_HZ              ( SystemCoreClock )          //移植系統運行主頻
#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )      //RTOS運行tick時鐘
#define configMAX_PRIORITIES            ( 10 )                       //RTOS最大優先級
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 130 )   //RTOS任務最小棧大小
#define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 75 * 1024 ) ) //RTOS內存堆大小
#define configMAX_TASK_NAME_LEN         ( 10 )                       //任務名稱最大長度
#define configUSE_16_BIT_TICKS          0       //數據類型長度定義,32位爲0,16位或8位開啓
#define configIDLE_SHOULD_YIELD         0       //使能與空閒任務優先級相同的任務


/* RTOS API(資源使能與裁剪) */
#define configUSE_MUTEXES               1       //使能互斥鎖
#define configUSE_RECURSIVE_MUTEXES     1       //使能遞歸互斥鎖
#define configUSE_TASK_NOTIFICATIONS    1       //使能任務間通知
#define configUSE_COUNTING_SEMAPHORES   1       //使能計數信號量
#define configUSE_QUEUE_SETS            1       //使能隊列集
#define configQUEUE_REGISTRY_SIZE       8       //設置隊列註冊的個數

#define configUSE_TIMERS                1       //使能定時器
#if configUSE_TIMERS
    #define configTIMER_TASK_PRIORITY           ( 2 )
    #define configTIMER_QUEUE_LENGTH            10
    #define configTIMER_TASK_STACK_DEPTH        ( configMINIMAL_STACK_SIZE * 2 )
    #define configUSE_DAEMON_TASK_STARTUP_HOOK  0
#endif

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. (使能任務相關api) */
#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_xTaskGetIdleTaskHandle          0
#define INCLUDE_xTaskGetCurrentTaskHandle       1
#define INCLUDE_uxTaskGetStackHighWaterMark     1
#define INCLUDE_xTaskGetSchedulerState          1


/* RTOS HOOK(功能鉤子函數) */
#ifdef OS_HOOK
    #define configUSE_IDLE_HOOK             1       //空閒任務鉤子函數
    #define configUSE_TICKLESS_IDLE         0       //空閒任務低功耗功能使能
    #define configUSE_TICK_HOOK             0       //tick時鐘鉤子函數
    #define configUSE_MALLOC_FAILED_HOOK    1       //內存申請失敗的鉤子函數
    #define configCHECK_FOR_STACK_OVERFLOW  2       //任務棧溢出檢測
    #define configSUPPORT_STATIC_ALLOCATION 0       //額外靜態任務創建,需添加額外函數
#else
    #define configUSE_IDLE_HOOK             0       //空閒函數鉤子函數
    #define configUSE_TICK_HOOK             0       //tick時鐘鉤子函數
#endif


/* RTOS TASK DEBUG(任務資源調試) */
#if (defined OS_DEBUG) && (OS_DEBUG == 1)
    #define configUSE_TRACE_FACILITY                1       //使能任務可視化追蹤
    #define configUSE_STATS_FORMATTING_FUNCTIONS    1

    #define configGENERATE_RUN_TIME_STATS   1               //使能任務狀態統計函數-計算任務佔用率
    #if (defined configGENERATE_RUN_TIME_STATS) && (configGENERATE_RUN_TIME_STATS == 1)
        #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()  rtos_sys_timer_init()
        #define portGET_RUN_TIME_COUNTER_VALUE()          rtos_sys_cnt_get()
    #endif

    /* Normal assert() semantics without relying on the provision of an assert.h
    header file. (斷言) */
    #include "elog.h"
    #define OS_ASSERT(x)       log_e(x)
    #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); OS_ASSERT("os err"); for( ;; ); }
#endif

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES                        0
#define configMAX_CO_ROUTINE_PRIORITIES              ( 2 )

/* Cortex-M specific definitions. (stm32與os相關中斷優先級的配置) */
#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    5

/* 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) )


/* 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


/* others */


/* user config code (用戶自定義配置) */
#if (configMAX_PRIORITIES > 6)
    #define RTOS_PRIORITY_HIGHEST       (configMAX_PRIORITIES-1)
    #define RTOS_PRIORITY_LEVEL_1ST     (configMAX_PRIORITIES-2)
    #define RTOS_PRIORITY_LEVEL_2ST     (configMAX_PRIORITIES-3)
    #define RTOS_PRIORITY_LEVEL_3ST     (configMAX_PRIORITIES-4)
    #define RTOS_PRIORITY_LEVEL_4ST     (configMAX_PRIORITIES-5)
    #define RTOS_PRIORITY_LEVEL_5ST     (configMAX_PRIORITIES-6)
#endif


#endif /* FREERTOS_CONFIG_H */


/**
  *****************************************************************************
  * @file    : stm_config.c
  * @author  : Tuu
  * @version : 1.0.0
  * @date    : 2020-04-01
  * @brief   : stm32f407 freertos config file
  ******************************************************************************
  * @lasteditors  : Tuu
  * @lasteditTime : 2020-06-02
  ******************************************************************************
  * @atten   : Copyright (C) by Tuu Inc
  *
  *****************************************************************************
  */

/* Includes -------------------------------------------------------------------*/
#include "config.h"

#include "FreeRTOS.h"
#include "task.h"


/* Defines --------------------------------------------------------------------*/


/* Variables ------------------------------------------------------------------*/
static TaskHandle_t xTask_creat;

/* Functions ------------------------------------------------------------------*/
extern void user_main(void *p);

/**
  * @note   This function is used to creat app task and delect self.
  * @brief  None
  * @param  *p
  * @retval None
  */
static void creat_task(void *p)
{
    log_d("%s", __FUNCTION__);

    /* creat app task in this 在這裏創建應用任務 */
    taskENTER_CRITICAL();

    user_main(NULL);

    taskEXIT_CRITICAL();
    /* creat app task in this 在這裏創建應用任務 */

#if 0
    int cnt = 0;

    /* delay task 延時退出,並刪除本任務 */
    while(1){
        log_d("this is creat task:idle-%d", cnt++);
        vTaskDelay(1000);

        if (cnt >= 10){
            break;
        }
    }
#endif

    log_d("delete creat task");

    vTaskDelete(xTask_creat);
}

/**
  * @note   This function is used to creat app task and delect self.
  * @brief  None
  * @param  *p
  * @retval None
  */
int rtos_init(void)
{
    /* stm32 NVIC config */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

    BaseType_t xReturn = pdPASS;

    log_i("Freertos v10.3.1 start ");

    /* first creat task in this 創建rtos第一個任務,用於創建其他任務 */
    xReturn = xTaskCreate(  (TaskFunction_t )creat_task,
                            (const char *   )"creat_task",
                            (unsigned short )1024,
                            (void *         )NULL,
                            (UBaseType_t    )1,
                            (TaskHandle_t * )&xTask_creat);

    if (pdPASS != xReturn){
        return -1;
    }

    /* start task 開啓任務調度 */
    vTaskStartScheduler();

    return xReturn;
}

/* systick */
#if 1
void SysTick_Handler(void)
{
    extern void xPortSysTickHandler( void );
    /* USER CODE END SysTick_IRQn 0 */
    #if (INCLUDE_xTaskGetSchedulerState == 1 )
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
    {
    #endif /* INCLUDE_xTaskGetSchedulerState */
        xPortSysTickHandler();
    #if (INCLUDE_xTaskGetSchedulerState == 1 )
    }
    #endif /* INCLUDE_xTaskGetSchedulerState */
}
#endif

#if (defined OS_DEBUG) && (OS_DEBUG == 1)

#if (defined configGENERATE_RUN_TIME_STATS) && (configGENERATE_RUN_TIME_STATS == 1)
#define USE_IRQ_TICK_CNT    0
#if USE_IRQ_TICK_CNT
static uint32_t rtos_run_time_cnt = 0;

/**
  * @note   TIM2_IRQHandler
  * @brief  None
  * @param  None
  * @retval None
  */
void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){
        rtos_run_time_cnt++;

        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    }
}
#endif

/**
  * @note   rtos_sys_timer_init
  * @brief  None
  * @param  None
  * @retval None
  */
void rtos_sys_timer_init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

#if !USE_IRQ_TICK_CNT
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Prescaler = 16800-1;
    TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
#else
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Prescaler = 168-1;
    TIM_TimeBaseStructure.TIM_Period = 100;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    rtos_run_time_cnt = 0;
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
#endif

    TIM_Cmd(TIM2, ENABLE);
}

/**
  * @note   rtos_sys_cnt_get
  * @brief  None
  * @param  None
  * @retval None
  */
uint32_t rtos_sys_cnt_get(void)
{
#if USE_IRQ_TICK_CNT
    return rtos_run_time_cnt;
#else
    return TIM_GetCounter(TIM2);
#endif
}
#endif

#endif

/* config function */
#ifdef OS_HOOK

#if (defined configUSE_IDLE_HOOK) && (configUSE_IDLE_HOOK == 1)
void vApplicationIdleHook( void )
{
    //log_d("%s", __FUNCTION__);
}
#endif

#if (defined configUSE_TICK_HOOK) && (configUSE_TICK_HOOK == 1)
void vApplicationTickHook( void )
{
    //printf("%s\r\n", __FUNCTION__);
}
#endif

#if (defined configUSE_MALLOC_FAILED_HOOK) && (configUSE_MALLOC_FAILED_HOOK == 1)
void vApplicationMallocFailedHook( void )
{
    log_d("%s", __FUNCTION__);
    log_e("os malloc fail");
}
#endif

#if (defined configCHECK_FOR_STACK_OVERFLOW) && (configCHECK_FOR_STACK_OVERFLOW >= 1)
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
    log_d("%s", __FUNCTION__);
    log_e("task Overflow : %s [%p]", pcTaskName, xTask);
}
#endif

#if (defined configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
                                    StackType_t **ppxIdleTaskStackBuffer,
                                    uint32_t *pulIdleTaskStackSize )
{
    /* If the buffers to be provided to the Idle task are declared inside this
    function then they must be declared static - otherwise they will be allocated on
    the stack and so not exists after this function exits. */
    static StaticTask_t xIdleTaskTCB;
    static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];

    /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
    state will be stored. */
    *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;

    /* Pass out the array that will be used as the Idle task's stack. */
    *ppxIdleTaskStackBuffer = uxIdleTaskStack;

    /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
    Note that, as the array is necessarily of type StackType_t,
    configMINIMAL_STACK_SIZE is specified in words, not bytes. */
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*-----------------------------------------------------------*/

/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
                                     StackType_t **ppxTimerTaskStackBuffer,
                                     uint32_t *pulTimerTaskStackSize )
{
    /* If the buffers to be provided to the Timer task are declared inside this
    function then they must be declared static - otherwise they will be allocated on
    the stack and so not exists after this function exits. */
    static StaticTask_t xTimerTaskTCB;
    static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];

    /* Pass out a pointer to the StaticTask_t structure in which the Timer
    task's state will be stored. */
    *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;

    /* Pass out the array that will be used as the Timer task's stack. */
    *ppxTimerTaskStackBuffer = uxTimerTaskStack;

    /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
    Note that, as the array is necessarily of type StackType_t,
    configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#endif

#endif


/************************ (C) COPYRIGHT Tuu ********END OF FILE****************/



功能簡單應用

在 stm32f4_os_app 工程中,建立了有關任務、信號量、消息隊列、互斥鎖、定時器、事件通知的簡單應用。工程及運行情況如下:
在這裏插入圖片描述
在這裏插入圖片描述


小結

這次只是介紹了常用的一些系統配置,這樣就可以初步得知道Freertos各方面的功能,也方便以後實際使用。一般大家都喜歡由淺入深,這也是便於理解的方式,先知道功能與使用方法,用於正常開發,再在其他的時間深入功能具體實現的方式。工程也包括了經常會用到的基本功能,可以通過開關宏定義來試着嘗試一下。


如有其它問題可以問我哦~

Tuu

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章