国民技术G45X系列移植FreeRtos一共分为四步: 1.下载FreeRtos源码 2.添加FreeRtos源码到原有的工程文件 3.添加修改FreeRTOSConfig.h文件、n32g45x_it.h文件 4.修改Delay.c文件
一、下载FreeRtos源码 官网: http://www.freertos.org/ 代码托管网站: https://sourceforge.net/projects/freertos/files/FreeRTOS/ Github https://github.com/FreeRTOS 这里使用的版本是V202012.00 使用的平台是N32G455RE 以国民技术SDK中的LedBlink工程为模板
二、添加FreeRtos源码到原有工程文件 在KEIL工程中新建分组FreeRTOS_CODE添加如下文件: 在KEIL工程中新建分组FreeRTOS_PORTABLE添加如下文件: 在KEIL工程中添加对应头文件路径:
三、添加并修改FreeRtosConfig.h、n32g45x_it.h文件 1.此时编译应该会报错:“error: #5: cannot open source input file “FreeRTOSConfig.h”: No such file or directory” FreeRTOSConfig.h 是FreeRTOS 的配置文件,一般的操作系统都有裁剪、配置功能,而这些裁剪及配置都是通过一个文件来完成的,基本都是通过宏定义来完成对系统的配置和裁剪。 从freertos源码的DEMO中M4F工程中直接拷贝过来。
2.编译报错:“Error: L6200E: Symbol SVC_Handler multiply defined (by port.o and n32g45x_it.o).” SVC_Handler重复定义。删除n32g45x_it.c中的SVC_Handler。
3.编译报错:“Error: L6406E: No space in execution regions with .ANY selector matching heap_4.o(.bss).” RAM溢出的报错,所以需要根据自身实际情况修改。修改FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE参数
4.编译报错: FreeRTOSConfig.h 中开启了这些钩子函数,但是却没有定义导致的。在 FreeRTOSConfig.h 中关闭这些钩子函数即可,即将相应的宏定义改为 0。
四、修改Delay.c文件 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 90 91 92 93 94 95 96 97 98 #include "NZ_Delay.h" #include "FreeRTOS.h" #include "task.h" extern void xPortSysTickHandler (void ) ;void SysTick_Handler (void ) { if (xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); } } static u32 fac_us = 0 ; static u32 fac_ms = 0 ; void NZ_Delay_init (void ) { u32 reload; SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); fac_us = (SystemCoreClock / (1000000 )); reload = (SystemCoreClock / 1000000 ); reload *= (1000000 / configTICK_RATE_HZ); fac_ms = (1000 / configTICK_RATE_HZ); SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; SysTick->LOAD=reload; SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; } void NZ_Delay_us (u32 nus) { u32 ticks; u32 told,tnow,tcnt = 0 ; u32 reload = SysTick->LOAD; ticks = nus*fac_us; told = SysTick->VAL; while (1 ) { tnow = SysTick->VAL; if (tnow != told) { if (tnow<told) tcnt += told-tnow; else tcnt += reload-tnow+told; told = tnow; if (tcnt >= ticks) break ; } }; } void NZ_Delay_ms (u32 nms) { if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { if (nms >= fac_ms) { vTaskDelay(nms / fac_ms); } nms %= fac_ms; } NZ_Delay_us((u32)(nms*1000 )); } void NZ_Delay_xms (u32 nms) { u32 i; for (i=0 ;i<nms;i++) NZ_Delay_us(1000 ); }
编译报错:“Error: L6200E: Symbol SysTick_Handler multiply defined (by nz_delay.o and n32g45x_it.o).” SysTick_Handler重复定义。删除n32g45X_it.c中的SysTick_Handler。
到这里算是已经移稙完成。 下面做简单的验证。 在main.c函数添加如下代码:
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 #include "main.h" #include "NZ_Delay.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 FLOAT_TASK_PRIO 4 #define FLOAT_STK_SIZE 128 TaskHandle_t FLOATTask_Handler; void float_task (void *pvParameters) ;int main (void ) { GPIO_InitType GPIO_InitStructure; RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); GPIO_InitStructure.Pin = GPIO_PIN_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); 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, (const char * )"led0_task" , (uint16_t )LED0_STK_SIZE, (void * )NULL , (UBaseType_t )LED0_TASK_PRIO, (TaskHandle_t* )&LED0Task_Handler); vTaskDelete(StartTask_Handler); taskEXIT_CRITICAL(); } void led0_task (void *pvParameters) { while (1 ) { GPIOA->POD ^= GPIO_PIN_8; vTaskDelay(1000 ); } }
现象为PA8的LED灯闪烁。