赞
踩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
最近搞电池把GD32E230烧坏了- -整个芯片和LDO都烧坏了- -嘉立创什么时候再免费派券让我白嫖一个开发板?
用KEIL5移植FreeRTOS到STM32F103C8T6上,因为我看网上好多教程都是用CUBE直接生成的,但是好多国产芯片还没有能使用CUBE,虽然也有逃课的办法但是我觉得也不太好用,而且在GITHUB上移植大多数也是需要对文件修改的,所以就当是个学习机会啦。
后续也会写在国产芯片上移植FreeRTOS的办法,一步步来尽量做到通俗易懂。
我这次用的开发板是立创的STM32F103C8T6,这个板子很多人用而且也很便宜(我白嫖到的,谢谢嘉立创)。
但是芯片不是重点,基本上STM下面的芯片都非常兼容FreeRTOS,更简单的办法是用CUBEIDE直接生成工程文件。
这篇日志纯粹是能在其他芯片上也能移植FreeRTOS打基础的。
好啦,闲话不多说,直接开始找资料。
众所周知,FreeRTOS是基于滴答定时器的高级应用,所以滴答定时器尤其重要,在这个实验里我们要实现灯闪烁的效果。
链接: 立创提供的STM32F103资料
链接: FreeRTOS
请在创建FreeRTOS工程模板之前确保你的点灯程序是可以跑起来的。
下面列出来的就是我们需要多加的文件(有些工程是有it.c的,这是一个关于中断的文件。)
下载了FreeRTOS之后,我们需要找到FreeRTOS里面的Source,具体路径为:FreeRTOSv202212.01\FreeRTOSv202212.01\FreeRTOS\Source
把不是.c后缀的文件删掉,再把这个文件夹移植到你的项目工程下,改名成FreeRTOS方便管理。
打开里面的portable文件夹,把除了KEIL,MemMang和RVDS的其他文件都删掉。
然后在KEIL里打开项目,在项目里加入头文件
FreeRTOS\include
FreeRTOS\portable\RVDS\ARM_CM3
module
第一个文件是FreeRTOS依赖的头文件,每个人都一样要加的。
第二个文件的选择是基于你的芯片的ARM架构,数据手册上的第一页就会写,所以移植的时候也要特别注意是不是FreeRTOS写好的架构。有些芯片是不太支持的。(或者说大佬自己改)
FreeRTOS目前支持的架构:
第三个文件是中断函数相关的,大多数工程都会把他们放出来,但是立创这次没有,咱也不敢问,默默补上就行。中断函数非常重要,一定要加到工程里。(虽然里面都是空的,自己补写也是可以的。)
再将对应的文件加入进来,如下:
这里我强烈建议各位去看官网的资料,实际上并没有想象的那么复杂,而且官网讲的非常详细!
链接: FreeRTOSConfig介绍
而且大多数的配置文件只需要修改很少很少地方。下面是我写的,可以复制过去,要改的地方我都写了备注的。
/* * FreeRTOS Kernel V10.2.0 * Copyright (C) 2019 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. */ /* 确保 stdint 只被编译器使用,而不是汇编器使用。 */ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #include <stdint.h> extern uint32_t SystemCoreClock; #endif // FreeRTOS 配置选项 #define configUSE_PREEMPTION 1 // 使用抢占式调度 #define configUSE_IDLE_HOOK 0 // 不使用空闲钩子函数 #define configUSE_TICK_HOOK 0 // 不使用滴答钩子函数 #define configCPU_CLOCK_HZ ( SystemCoreClock ) // 设置 CPU 时钟频率,这里可以根据数据手册写死,也可以像我一样用内核文件定义 #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) // 滴答频率设置为 1000Hz,这个官方示例给的 #define configMAX_PRIORITIES ( 5 ) // 最大优先级数目,根据需要修改 #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 ) // 最小任务堆栈大小,根据需要修改,每个代表4个字节,即:130*4=520个字节 #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8 * 1024 ) ) // 堆大小设置为 8KB,,根据需要修改 #define configMAX_TASK_NAME_LEN ( 16 ) // 任务名字的最大长度 #define configUSE_TRACE_FACILITY 1 // 启用追踪功能 #define configUSE_16_BIT_TICKS 0 // 使用 16 位的滴答计数器或者32位的滴答计时器 #define configIDLE_SHOULD_YIELD 1 // 空闲任务是否应该放弃 CPU,这里必须设置1 #define configUSE_MUTEXES 1 // 启用互斥量 #define configQUEUE_REGISTRY_SIZE 8 // 队列注册表的大小 #define configCHECK_FOR_STACK_OVERFLOW 0 // 不启用堆栈溢出检查 #define configUSE_RECURSIVE_MUTEXES 1 // 启用递归互斥量 #define configUSE_MALLOC_FAILED_HOOK 0 // 不使用内存分配失败钩子函数 #define configUSE_APPLICATION_TASK_TAG 0 // 不使用任务标签 #define configUSE_COUNTING_SEMAPHORES 1 // 启用计数信号量 #define configGENERATE_RUN_TIME_STATS 0 // 不生成运行时统计信息 /* 协程定义 */ #define configUSE_CO_ROUTINES 0 // 不使用协程 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) // 最大协程优先级数 /* 软件定时器定义 */ #define configUSE_TIMERS 1 // 启用软件定时器 #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) // 定时器任务的优先级 #define configTIMER_QUEUE_LENGTH 5 // 定时器队列长度 #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) // 定时器任务堆栈深度 /* 包含 API 函数的设置,根据自己需求启用 */ #define INCLUDE_vTaskPrioritySet 1 // 启用 vTaskPrioritySet 函数 #define INCLUDE_uxTaskPriorityGet 1 // 启用 uxTaskPriorityGet 函数 #define INCLUDE_vTaskDelete 1 // 启用 vTaskDelete 函数 #define INCLUDE_vTaskCleanUpResources 1 // 启用 vTaskCleanUpResources 函数 #define INCLUDE_vTaskSuspend 1 // 启用 vTaskSuspend 函数 #define INCLUDE_vTaskDelayUntil 1 // 启用 vTaskDelayUntil 函数 #define INCLUDE_vTaskDelay 1 // 启用 vTaskDelay 函数 #define INCLUDE_xTaskGetSchedulerState 0 #define INCLUDE_xTaskGetCurrentTaskHandle 1 #define INCLUDE_uxTaskGetStackHighWaterMark 0 #define INCLUDE_uxTaskGetStackHighWaterMark2 0 #define INCLUDE_xTaskGetIdleTaskHandle 0 #define INCLUDE_eTaskGetState 0 #define INCLUDE_xEventGroupSetBitFromISR 0 #define INCLUDE_xTimerPendFunctionCall 0 #define INCLUDE_xTaskAbortDelay 0 #define INCLUDE_xTaskGetHandle 0 #define INCLUDE_xTaskResumeFromISR 0 /* Cortex-M 特定定义 */ #ifdef __NVIC_PRIO_BITS /* 当使用 CMSIS 时,__NVIC_PRIO_BITS 会被指定 */ #define configPRIO_BITS __NVIC_PRIO_BITS #else #define configPRIO_BITS 4 /* 15 个优先级 */ #endif /* 可用于调用 "set priority" 函数的最低中断优先级 */ #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf /* 可由任何中断服务例程使用的最高中断优先级 (较高的优先级具有较低的数值)。不要从比这更高优先级 的中断中调用 FreeRTOS API 函数!*/ #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 /* 内核端口层自身使用的中断优先级。适用于所有 Cortex-M 端口, 不依赖于任何特定的库函数 */ #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY 不能设置为零 !!!! 参见 http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /* 不依赖 assert.h 头文件提供的正常 assert() 语义 */ #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } /* 定义将 FreeRTOS 端口中断处理程序映射到它们的 CMSIS 标准名称 */ #define vPortSVCHandler SVC_Handler #define xPortPendSVHandler PendSV_Handler //#define xPortSysTickHandler SysTick_Handler #endif /* FREERTOS_CONFIG_H */
将配置文件放到Include文件夹即可。
这样FreeRTOS基本上就配置好了,我们先来写一个点灯函数进行测试:
/* **GPIO口初始化 */ void LED_Init() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_SetBits(GPIOC,GPIO_Pin_13); } /* **创建灯闪烁任务 */ void vTaskLED(void *pvParameters) { (void) pvParameters; while(1) { // 切换 LED 状态 GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13))); // 延时 1 秒 vTaskDelay(pdMS_TO_TICKS(1000)); } } int main(void) { // 配置系统时钟 board_init(); // 初始化 LED LED_Init(); // 创建 LED 闪烁任务 xTaskCreate(vTaskLED, "LED Task", configMINIMAL_STACK_SIZE, NULL, 1, NULL); // 启动调度器 vTaskStartScheduler(); // 如果启动调度器失败,将会执行到这里 while(1); }
这个时候编译会出错,提示如下:
这是因为在配置文件中我们对两个函数进行了映射,在中断文件中也有映射。
/* 定义将 FreeRTOS 端口中断处理程序映射到它们的 CMSIS 标准名称 */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
我们不想用原来的,就需要到it.c文件中把这两个函数注释掉。
目前到这里我就没报错问题了,现在将程序烧录到单片机上,现象是:程序烧录之后单片机没有正常亮灯,调试会发现执行到这里就会卡死。
vTaskDelay(pdMS_TO_TICKS(1000));
这还是因为中断的问题,FreeRTOS用了滴答定时器,我们要在滴答定时器中断时调用的函数里调用FreeRTOS的函数。在it.c文件里找到修改就好啦。
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
xPortSysTickHandler();
}
再进行烧录,就能在单片机上看到灯闪烁了。
这个DEMO我其实已经做了两次- -没想到第二次还是花了我两个多小时的时间,虽然里面有一半是因为在写文章。但是还是好累啊- -一定要保存好DEMO不要天天搭建环境啊- -
文件放在这里,需要自提哈。
链接:https://pan.baidu.com/s/1L0MrklDR94agIlbDJnlVqA?pwd=ki9e
提取码:ki9e
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。