• FreeRTOS移植以及任务


    FreeRTOS移植
    1.在sys.h中需要把SYSTEM_SUPPORT_OS 改为 1,支持我们使用 FreeRTOS

    //0,不支持 os
    //1,支持 os
    #define SYSTEM_SUPPORT_OS 1 //定义系统文件夹是否支持 OS
    
    • 1
    • 2
    • 3

    2.出现报错
    …\SYSTEM\usart\usart.c(6): error: #5: cannot open source input file “includes.h”: No such file or directory
    即需要修改usart.c 文件:

    
    ```c
    默认是添加的 UCOS 中的 includes.h 头文件,修改以后如下:
    //如果使用 os,则包括下面的头文件即可.
    #if SYSTEM_SUPPORT_OS
    #include "FreeRTOS.h" //os 使用
    #endif
    ``
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.delay.c函数需要大改

    FreeRTOS 的系统时钟是由滴答定时器提供的,需要根据FreeRTOS的系统节拍来初始化滴答定时器,delay_init()就是来完成这个功能的。
    FreeRTOS 的系统时钟节拍由宏 configTICK_RATE_HZ 来设置,这个值我们可以自由设置,但是一旦设置好以后我们就要根据这个值来初始化滴答定时器,其实就是设置滴答定时器的中断周期。在基础例程中滴答定时器的时钟频率设置的是 AHB 的 1/8,这里为了兼容 FreeRTOS 将滴答定时器的时钟频率改为了 AHB,也就是 72MHz!这一点一定要注意!
    完整delay.c文件

    #include "delay.h"
    // 	 
    //如果需要使用OS,则包括下面的头文件即可.
    #if SYSTEM_SUPPORT_OS
    #include "FreeRTOS.h"					//ucos 使用	  
    #include "task.h"  //文件在FreeRTOS\include
    #endif
    
    
    static u8  fac_us=0;							//us延时倍乘数			   
    static u16 fac_ms=0;							//ms延时倍乘数,在ucos下,代表每个节拍的ms数
    
    extern void xPortSysTickHandler(void);
     //systick中断服务函数,使用ucos时用到
    void SysTick_Handler(void)
        {
            if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
            {
                xPortSysTickHandler();
            }
        }
    
    //初始化延迟函数
    //SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
    //这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
    //SYSCLK:系统时钟频率
    void delay_init()
    {
    	u32 reload;
    	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟  HCLK
    	fac_us=SystemCoreClock/1000000;				//不论是否使用OS,fac_us都需要使用
    	reload=SystemCoreClock/1000000;				//每秒钟的计数次数 单位为M  
    	reload*=1000000/configTICK_RATE_HZ;			//根据configTICK_RATE_HZ设定溢出时间
    												//reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右	
    	fac_ms=1000/configTICK_RATE_HZ;				//代表OS可以延时的最少单位	   
    
    	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
    	SysTick->LOAD=reload; 						//每1/configTICK_RATE_HZ秒中断一次	
    	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK    
    }
    
    //延时nus
    //nus:要延时的us数.	
    //nus:0~204522252(最大值即2^32/fac_us@fac_us=168)	    								   
    void delay_us(u32 nus)
    {		
    	u32 ticks;
    	u32 told,tnow,tcnt=0;
    	u32 reload=SysTick->LOAD;				//LOAD的值	    	 
    	ticks=nus*fac_us; 						//需要的节拍数 
    	told=SysTick->VAL;        				//刚进入时的计数器值
    	while(1)
    	{
    		tnow=SysTick->VAL;	
    		if(tnow!=told)
    		{	    
    			if(tnow<told)tcnt+=told-tnow;	//这里注意一下SYSTICK是一个递减的计数器就可以了.
    			else tcnt+=reload-tnow+told;	    
    			told=tnow;
    			if(tcnt>=ticks)break;			//时间超过/等于要延迟的时间,则退出.
    		}  
    	};										    
    }  
    //延时nms
    //nms:要延时的ms数
    //nms:0~65535
    void delay_ms(u32 nms)
    {	
    	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    	{		
    		if(nms>=fac_ms)						//延时的时间大于OS的最少时间周期 
    		{ 
       			vTaskDelay(nms/fac_ms);	 		//FreeRTOS延时
    		}
    		nms%=fac_ms;						//OS已经无法提供这么小的延时了,采用普通方式延时    
    	}
    	delay_us((u32)(nms*1000));				//普通方式延时
    }
    
    ## FreeRTOS任务
    
    //延时nms,不会引起任务调度
    //nms:要延时的ms数
    void delay_xms(u32 nms)
    {
    	u32 i;
    	for(i=0;i<nms;i++) delay_us(1000);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    任务句柄: * TaskHandle_t

    struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */
    typedef struct tskTaskControlBlock * TaskHandle_t;
    
    • 1
    • 2

    最终要溯源到 tskTaskControlBlock, tskTaskControlBlock是一个任务句柄结构体,在tasks.c文件中

    ypedef struct tskTaskControlBlock       /* The old naming convention is used to prevent breaking kernel aware debuggers. */
    {
        volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
    
        #if ( portUSING_MPU_WRAPPERS == 1 )
            xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
        #endif
    
        ListItem_t xStateListItem;                  /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
        ListItem_t xEventListItem;                  /*< Used to reference a task from an event list. */
        UBaseType_t uxPriority;                     /*< The priority of the task.  0 is the lowest priority. */
        StackType_t * pxStack;                      /*< Points to the start of the stack. */
        char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
    
        #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
            StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */
        #endif
    
        #if ( portCRITICAL_NESTING_IN_TCB == 1 )
            UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
        #endif
    
        #if ( configUSE_TRACE_FACILITY == 1 )
            UBaseType_t uxTCBNumber;  /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
            UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
        #endif
    
        #if ( configUSE_MUTEXES == 1 )
            UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
            UBaseType_t uxMutexesHeld;
        #endif
    
        #if ( configUSE_APPLICATION_TASK_TAG == 1 )
            TaskHookFunction_t pxTaskTag;
        #endif
    
        #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
            void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
        #endif
    
        #if ( configGENERATE_RUN_TIME_STATS == 1 )
            configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
        #endif
    
        #if ( configUSE_NEWLIB_REENTRANT == 1 )
    
            /* Allocate a Newlib reent structure that is specific to this task.
             * Note Newlib support has been included by popular demand, but is not
             * used by the FreeRTOS maintainers themselves.  FreeRTOS is not
             * responsible for resulting newlib operation.  User must be familiar with
             * newlib and must provide system-wide implementations of the necessary
             * stubs. Be warned that (at the time of writing) the current newlib design
             * implements a system-wide malloc() that must be provided with locks.
             *
             * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
             * for additional information. */
            struct  _reent xNewLib_reent;
        #endif
    
        #if ( configUSE_TASK_NOTIFICATIONS == 1 )
            volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
            volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
        #endif
    
        /* See the comments in FreeRTOS.h with the definition of
         * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
        #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
            uint8_t ucStaticallyAllocated;                     /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
        #endif
    
        #if ( INCLUDE_xTaskAbortDelay == 1 )
            uint8_t ucDelayAborted;
        #endif
    
        #if ( configUSE_POSIX_ERRNO == 1 )
            int iTaskErrno;
        #endif
    } tskTCB;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    xTaskCreate()函数的参数:

    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                                const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                const configSTACK_DEPTH_TYPE usStackDepth,
                                void * const pvParameters,
                                UBaseType_t uxPriority,
                                TaskHandle_t * const pxCreatedTask )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    5个实用的WhatsApp 群发消息模板推荐!
    Redis夺命十二问,差点没抗住
    JS执行机制--同步与异步
    Centos 7 安装 Docker Enginee
    十四天学会C++之第四天(面向对象编程基础)
    Mysql通过show查看资源性能状态——筑梦之路
    Apache Commons LevenshteinDistance莱文斯坦(相似度)算法
    如何正则匹配乱码?
    开源ChatGPT要来了;软件2.0智能革命;GLM、Diffusion模型大加速
    【java学习—九】面向对象内容总结(8)
  • 原文地址:https://blog.csdn.net/qq_44757503/article/details/133973171