FreeRTOS-01移植及任务创建和删除

本文介绍如何将FreeRTOS移植到STM32F207VC单片机上,并通过实例演示了任务创建、删除等基本操作。文中详细展示了代码实现过程,包括配置定时器中断、LED控制等。

根据正点原子FreeRTOS视频整理

单片机:STM32F207VC

FreeRTOS源码版本:v10.0.1

任务创建和删除API函数:

 

 工程列表:

 1. main.c

 1 /**/
 2 #include "main.h"
 3 #include "gpio.h"
 4 #include "delay.h"
 5 #include "sys.h"
 6 
 7 #include "stm32f2xx_gpio.h"
 8 
 9 #include "FreeRTOS.h"
10 #include "task.h"
11 
12 #define START_TASK_PRIO         1     /*任务优先级*/
13 #define START_STK_SIZE          128   /*任务堆栈大小*/
14 TaskHandle_t StartTask_Handle;        /*任务句柄*/
15 void StartTask(void *pvParameters);   /*任务函数*/
16 
17 #define LED1_TASK_PRIO         2
18 #define LED1_STK_SIZE          50
19 TaskHandle_t LED1Task_Handle;
20 void LED1Task(void *pvParameters);
21 
22 #define LED2_TASK_PRIO         3
23 #define LED2_STK_SIZE          50
24 TaskHandle_t LED2Task_Handle;
25 void LED2Task(void *pvParameters);
26 
27 
28 
29 /***** 声明 *****/
30 static void SystemInitial(void);
31 
32 
33 void StartTask(void *pvParameters)
34 {
35   taskENTER_CRITICAL();           /*进入临界区*/
36   
37   xTaskCreate((TaskFunction_t )LED1Task,            /*任务函数*/
38                             (const char *   )"LED1Task",            /*任务名称*/
39                             (uint16_t       )LED1_STK_SIZE,       /*任务堆栈大小*/
40                             (void *         )NULL,                /*传递给任务函数的参数*/
41                             (UBaseType_t    )LED1_TASK_PRIO,      /*任务优先级*/
42                             (TaskHandle_t   )&LED1Task_Handle);   /*任务句柄*/             
43               
44   xTaskCreate((TaskFunction_t )LED2Task,
45                             (const char *   )"LED2Task",        
46                             (uint16_t       )LED2_STK_SIZE,
47                             (void *         )NULL,
48                             (UBaseType_t    )LED2_TASK_PRIO,
49                             (TaskHandle_t   )&LED2Task_Handle);
50 
51   vTaskDelete(StartTask_Handle);    /*删除开始任务*/
52   taskEXIT_CRITICAL();              /*推出临界区*/
53 } 
54 
55 
56 void LED1Task(void *pvParameters)
57 {
58   while (1)
59   {
60     GPIOE->ODR ^= LED_ALARM;
61     vTaskDelay(200);
62 //    DelayNms(2);
63   }
64 } 
65 
66 void LED2Task(void *pvParameters)
67 {
68   while (1)
69   {
70     GPIOE->ODR ^= LED_RUN;
71     vTaskDelay(500);
72   }
73 } 
74 
75 
76 static void SystemInitial(void)
77 {
78   DelayInitial();
79   GPIO_Initial();
80 }
81 
82 int main(void)
83 {
84   SystemInitial();
85  
86   
87   /*创建开始任务*/
88   xTaskCreate((TaskFunction_t )StartTask,           /*任务函数*/
89                             (const char *   )"StartTask",            /*任务名称*/
90                             (uint16_t       )START_STK_SIZE,      /*任务堆栈大小*/
91                             (void *         )NULL,                /*传递给任务函数的参数*/
92                             (UBaseType_t    )START_TASK_PRIO,     /*任务优先级*/
93                             (TaskHandle_t   )&StartTask_Handle);  /*任务句柄*/             
94               
95   /*开启任务调度*/
96   vTaskStartScheduler();
97 }
98 
99 /***************************END OF FILE***************************/
View Code

 2. main.h

 1 /**/
 2 #ifndef __MAIN_H__
 3 #define __MAIN_H__
 4 
 5 
 6 
 7 
 8 #endif    /*__MAIN_H__*/
 9 
10 /***************************END OF FILE***************************/
View Code

3. sys.c

1 /**/
2 #include "sys.h"
3 #include "stdio.h"
4 
5 
6 /***************************END OF FILE***************************/
View Code

4. sys.h

 1 /**/
 2 #ifndef __SYS_H__
 3 #define __SYS_H__
 4 
 5 /*0不支持OS,1支持OS*/
 6 #define SYSTEM_SUPPORT_OS        1        /*定义系统文件夹是否支持OS*/
 7 
 8 #endif    /*__SYS_H__*/
 9 
10 /***************************END OF FILE***************************/
View Code

5. delay.c

 1 /**/
 2 #include "delay.h"
 3 #include "sys.h"
 4 /*如果需要使用OS,则包括下面的头文件即可*/
 5 #if SYSTEM_SUPPORT_OS
 6 #include "FreeRTOS.h"                      
 7 #include "task.h" 
 8 #endif
 9 
10 __IO uint32_t TimingDelay;
11 
12 /***** 声明 *****/
13 extern void xPortSysTickHandler(void);
14 
15 /*systick中断服务函数,使用FreeRTOS时用到*/
16 void SysTick_Handler(void)
17 {    
18     TimingDelayDecrement();
19     
20     if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)   /*系统已运行*/
21     {
22       xPortSysTickHandler();    
23     }
24 }
25 
26 void DelayInitial(void)
27 {
28   /*
29      * SystemCoreClock / 1000      1ms中断一次
30      * SystemCoreClock / 100000    10us中断一次
31      * SystemCoreClock / 1000000   1us中断一次
32      */
33   if (SysTick_Config(SystemCoreClock / 1000))
34   {
35     while (1);
36   }
37   /*关闭systick timer定时器*/
38   /*    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;*/
39 
40   /*使能滴答定时器*/
41   SysTick->CTRL |=   SysTick_CTRL_ENABLE_Msk;  
42 }
43 
44 /*
45  * 本函数在中断函数中调用,滴答定时器中断一次调用一次。
46  */
47 void TimingDelayDecrement(void)
48 {
49     if (TimingDelay != 0x00)
50     {
51         TimingDelay--;
52     }
53 }
54 
55 /*
56  * TimingDelay值在TimingDelayDecrement函数中递减
57  */
58 void DelayNms(uint32_t nTimes)
59 {
60     TimingDelay = nTimes;
61     
62     while (TimingDelay!=0);   //等待计数停止
63 }
64 
65 /***************************END OF FILE***************************/
View Code

6. delay.h

 1 /**/
 2 #ifndef __DELAY_H__
 3 #define __DELAY_H__
 4 
 5 #include "stm32f2xx.h"
 6 
 7 #include <stdint.h>
 8 
 9 extern void DelayInitial(void);
10 extern void TimingDelayDecrement(void);
11 extern void DelayNms(uint32_t nTimes);
12 
13 #endif    /*__DELAY_H__*/
14 /***************************END OF FILE***************************/
View Code

7. gpio.c

 1 /**/
 2 #include "gpio.h"
 3 
 4 /***** 声明 *****/
 5 static void GPIO_LED_Configuration(void);
 6 
 7 
 8 void GPIO_Initial(void)
 9 {
10   GPIO_LED_Configuration();
11 }
12 
13 
14 static void GPIO_LED_Configuration(void)
15 {
16   GPIO_InitTypeDef    GPIO_InitStructure;
17   
18   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
19   
20   GPIO_InitStructure.GPIO_Pin     = LED_POWER | LED_RUN | LED_ALARM;
21   GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
22   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_100MHz;
23   GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
24   GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
25   GPIO_Init(GPIOE, &GPIO_InitStructure);  
26   
27   LED_Power_On();
28   LED_Run_Off();
29   LED_Alarm_Off();
30 }
31 
32 /***************************END OF FILE***************************/
View Code

8. gpio.h

 1 /**/
 2 #ifndef __GPIO_H__
 3 #define __GPIO_H__
 4 
 5 #include "stm32f2xx_gpio.h"
 6 
 7 #define LED_POWER         GPIO_Pin_2    /*PE2*/
 8 #define LED_RUN           GPIO_Pin_3    /*PE3*/
 9 #define LED_ALARM         GPIO_Pin_4    /*PE4*/
10 
11 #define LED_Power_On()    GPIO_ResetBits(GPIOE, LED_POWER)
12 #define LED_Power_Off()   GPIO_SetBits(GPIOE, LED_POWER)
13 #define LED_Run_On()      GPIO_ResetBits(GPIOE, LED_RUN)
14 #define LED_Run_Off()     GPIO_SetBits(GPIOE, LED_RUN)
15 #define LED_Alarm_On()    GPIO_ResetBits(GPIOE, LED_ALARM)
16 #define LED_Alarm_Off()   GPIO_SetBits(GPIOE, LED_ALARM)
17 
18 
19 extern void GPIO_Initial(void);
20 
21 #endif  /*__GPIO_H__*/
22 /***************************END OF FILE***************************/
View Code

9. 移植过程及问题解决

1. 新建基础例程。
2. 在工程目录中添加FreeRTOS源码。
3. 在MDK中增加FreeRTOS_CODE和FreeRTOS_POARTABLE组,并添加对应文件。
   并包含相应头文件路径。
   编译报错:打不开FreeRTOSConfig.h文件。
   解决办法:在FreeRTOS源码的例程中,复制一个到FreeRTOS\include文件夹下。
   问题:下载程序后,灯不闪烁。
   解决1:选择Use MicroLIB后,重新编译。
   解决2:新建一个文件(如:sys.c),添加以下内容,添加到工程并编译--正点原子的解决方法。
          #include "stdio.h"

          #pragma import(__use_no_semihosting)             
          //标准库需要的支持函数                 
          struct __FILE 
          { 
            int handle; 

          }; 

          FILE __stdout;       
          //定义_sys_exit()以避免使用半主机模式    
          void _sys_exit(int x) 
          { 
            x = x; 
          } 
          //重定义fputc函数 
          int fputc(int ch, FILE *f)
          {      
            // while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
             // USART1->DR = (u8) ch;      
            return ch;
          }
4. 新建sys.h文件,添加以下内容:
    /*0不支持OS,1支持OS*/
    #define SYSTEM_SUPPORT_OS		1		/*定义系统文件夹是否支持OS*/
5. 在delay.c文件中,增加或修改以下内容:
    #include "sys.h"
    /*如果需要使用OS,则包括下面的头文件即可*/
    #if SYSTEM_SUPPORT_OS
    #include "FreeRTOS.h"					  
    #include "task.h" 
    #endif

    /***** 声明 *****/
    extern void xPortSysTickHandler(void);

    /*systick中断服务函数,使用FreeRTOS时用到*/
    void SysTick_Handler(void)
    {	
        TimingDelayDecrement();
        
        if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)   /*系统已运行*/
        {
          xPortSysTickHandler();	
        }
    }
6. main.c函数中新建任务。
7. 具体程序参考上面的内容。

  

  

 

转载于:https://www.cnblogs.com/seifguo/p/9208621.html

查看文章 STM32 keil mdk启动代码发分析_转2010年01月29日 星期五 13:50 ;// Stack Configuration ;// Stack Size (in Bytes) ;// Stack_Size EQU 0x00000200 ;//定义堆栈大小 AREA STACK, NOINIT, READWRITE, ALIGN=3 ;//定义一个数据段 按8字节对齐 ;AREA 伪指令用于定义一个代码段或数据段 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0 Stack_Mem SPACE Stack_Size ;//保留Stack_Size大小的堆栈空间 分 配连续 Stack_Size 字节的存储单元并初始化为 0 __initial_sp ;//标号,代表堆栈顶部地址,后面有用 ;// Heap Configuration ;// Heap Size (in Bytes) ;// Heap_Size EQU 0x00000020 ;//定义堆空间大小 AREA HEAP, NOINIT, READWRITE, ALIGN=3 ;//定义一个数据段,8字节对齐 __heap_base Heap_Mem SPACE Heap_Size ;//保留Heap_Size的堆空间 __heap_limit ;//标号,代表堆末尾地址,后面有用 PRESERVE8 ;//指示编译器8字节对齐 THUMB ;//指示编译器为THUMB指令 ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY ;//定义只读数据段,其实放在CODE区,位于0地址 EXTERN NMIException EXTERN HardFaultException EXTERN MemManageException EXTERN BusFaultException EXTERN UsageFaultException EXTERN SVCHandler EXTERN DebugMonitor EXTERN PendSVC EXTERN SysTickHandler ;//声明这些符号在外部定义,同C ;//在××it.c中实现这些函数 ,中断就能自动调用了 EXPORT __Vectors EXPORT __initial_sp ;EXPORT:在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用;IMPORT:伪指令用于通知编译器要使用的标号在其他的源文件中定义, ;但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中 __Vectors DCD __initial_sp ; Top of Stack //Cotex-M 要求此处为堆栈顶部地址 DCD Reset_Handler ; Reset Handler DCD NMIException ; NMI Handler DCD HardFaultException ; Hard Fault Handler DCD MemManageException ; MPU Fault Handler DCD BusFaultException ; Bus Fault Handler DCD UsageFaultException ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVCHandler ; SVCall Handler DCD DebugMonitor ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSVC ; PendSV Handler DCD SysTickHandler ; SysTick Handler //一大堆的异常处理函数地址 ; External Interrupts EXTERN WWDG_IRQHandler EXTERN PVD_IRQHandler EXTERN TAMPER_IRQHandler EXTERN RTC_IRQHandler EXTERN FLASH_IRQHandler EXTERN RCC_IRQHandler EXTERN EXTI0_IRQHandler EXTERN EXTI1_IRQHandler EXTERN EXTI2_IRQHandler EXTERN EXTI3_IRQHandler EXTERN EXTI4_IRQHandler EXTERN DMAChannel1_IRQHandler EXTERN DMAChannel2_IRQHandler EXTERN DMAChannel3_IRQHandler EXTERN DMAChannel4_IRQHandler EXTERN DMAChannel5_IRQHandler EXTERN DMAChannel6_IRQHandler EXTERN DMAChannel7_IRQHandler EXTERN ADC_IRQHandler EXTERN USB_HP_CAN_TX_IRQHandler EXTERN USB_LP_CAN_RX0_IRQHandler EXTERN CAN_RX1_IRQHandler EXTERN CAN_SCE_IRQHandler EXTERN EXTI9_5_IRQHandler EXTERN TIM1_BRK_IRQHandler EXTERN TIM1_UP_IRQHandler EXTERN TIM1_TRG_COM_IRQHandler EXTERN TIM1_CC_IRQHandler EXTERN TIM2_IRQHandler EXTERN TIM3_IRQHandler EXTERN TIM4_IRQHandler EXTERN I2C1_EV_IRQHandler EXTERN I2C1_ER_IRQHandler EXTERN I2C2_EV_IRQHandler EXTERN I2C2_ER_IRQHandler EXTERN SPI1_IRQHandler EXTERN SPI2_IRQHandler EXTERN USART1_IRQHandler EXTERN USART2_IRQHandler EXTERN USART3_IRQHandler EXTERN EXTI15_10_IRQHandler EXTERN RTCAlarm_IRQHandler EXTERN USBWakeUp_IRQHandler ;//同上, DCD WWDG_IRQHandler ; Window Watchdog DCD PVD_IRQHandler ; PVD through EXTI Line detect DCD TAMPER_IRQHandler ; Tamper DCD RTC_IRQHandler ; RTC DCD FLASH_IRQHandler ; Flash DCD RCC_IRQHandler ; RCC DCD EXTI0_IRQHandler ; EXTI Line 0 DCD EXTI1_IRQHandler ; EXTI Line 1 DCD EXTI2_IRQHandler ; EXTI Line 2 DCD EXTI3_IRQHandler ; EXTI Line 3 DCD EXTI4_IRQHandler ; EXTI Line 4 DCD DMAChannel1_IRQHandler ; DMA Channel 1 DCD DMAChannel2_IRQHandler ; DMA Channel 2 DCD DMAChannel3_IRQHandler ; DMA Channel 3 DCD DMAChannel4_IRQHandler ; DMA Channel 4 DCD DMAChannel5_IRQHandler ; DMA Channel 5 DCD DMAChannel6_IRQHandler ; DMA Channel 6 DCD DMAChannel7_IRQHandler ; DMA Channel 7 DCD ADC_IRQHandler ; ADC DCD USB_HP_CAN_TX_IRQHandler ; USB High Priority or CAN TX DCD USB_LP_CAN_RX0_IRQHandler ; USB Low Priority or CAN RX0 DCD CAN_RX1_IRQHandler ; CAN RX1 DCD CAN_SCE_IRQHandler ; CAN SCE DCD EXTI9_5_IRQHandler ; EXTI Line 9..5 DCD TIM1_BRK_IRQHandler ; TIM1 Break DCD TIM1_UP_IRQHandler ; TIM1 Update DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare DCD TIM2_IRQHandler ; TIM2 DCD TIM3_IRQHandler ; TIM3 DCD TIM4_IRQHandler ; TIM4 DCD I2C1_EV_IRQHandler ; I2C1 Event DCD I2C1_ER_IRQHandler ; I2C1 Error DCD I2C2_EV_IRQHandler ; I2C2 Event DCD I2C2_ER_IRQHandler ; I2C2 Error DCD SPI1_IRQHandler ; SPI1 DCD SPI2_IRQHandler ; SPI2 DCD USART1_IRQHandler ; USART1 DCD USART2_IRQHandler ; USART2 DCD USART3_IRQHandler ; USART3 DCD EXTI15_10_IRQHandler ; EXTI Line 15..10 DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend ;//同上 AREA |.text|, CODE, READONLY ;//定义代码段 ; Reset Handler Reset_Handler PROC ;过程的开始 ;//Rset_Handler的实现 利用PROC、ENDP这一对伪指令把程序段分为若干个过程,使程序的结构加清晰 EXPORT Reset_Handler [WEAK] ;//在外部没有定义该符号时导出该符号,见HELP中[WEAK] IMPORT __main ;//导入符号,__main为 运行时库提供的函数;完成堆栈,堆的初始话 LDR R0, =__main ;//等工作,会调用下面定义的__user_initial_stackheap; BX R0 ;//跳到__main,进入C的世界 ENDP ;过程的结束 ALIGN ; User Initial Stack & Heap IF :DEF:__MICROLIB ;//如果使用micro lib,micro lib 描述见armlib.chm EXPORT __heap_base EXPORT __heap_limit ;//只导出几个定义 ELSE ;//如果使用默认C运行时库 IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap ;//则进行堆栈堆的赋值,在__main函数执行过程中调用。 LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR ALIGN ENDIF END ;//OK ,完了 http://blog.youkuaiyun.com/chehlcy/archive/2010/01/09/5164472.aspx http://files.ourdev.cn/bbs_upload134190/files_11/ourdev_495775.txt ====================================================================== Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main LDR R0, =__main BX R0 ENDP 这段代码什么意思。 有2个地方不理解 一:PROC ENDP 二: [WEAK] 什么意思 ------------------------------------------------------------------------------- 一:PROC为子程序开始,ENDP为子程序结束 二:[weak]的意思就是弱。 怎么弱呢?如果你在其他地方写一个同名函数,比如Reset_handler, 你写的这个函数就可以取代它这个函数了。 语法格式: EXPORT 标号 {[WEAK]} EXPORT 伪指令用于在程序中声明一个全局的标号,该标号可在其他的文件中引用。 EXPORT可用 GLOBAL 代替。标号在程序中区分大小写, [WEAK] 选项声明其他的同名标号优先于该标号被引用。 使用示例: AREA Init , CODE , READONLY EXPORT Stest ;声明一个可全局引用的标号Stest…… END
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值