freeRtos源码分析之移植

1.freeRtos源码分析之移植到stm32F103

1.freeRtos源码获取

​ 1.Gitee 极速下载/freertos

2.freeRtos源码结构

└─FreeRTOS
   ├─Demo		// 各种开发平台的Demo例程
   │  ├─CORTEX_M4F_STM32F407ZG-SK	// STM32F407例程
   │  ├─CORTEX_STM32F103_IAR		// STM32F103 IAR 例程
   │  └─CORTEX_STM32F103_Keil		// STM32F103 Keil例程
   ├─License	// 许可证文件
   │  └─license.txt				// 许可证文件
   └─Source		// 移植所需的源码和头文件等
	  ├─include				// 通用头文件,无编译器区分
	  │  └─xxx.h				// 通用头文件,无编译器区分
	  ├─portable			// 编译器相关文件
	  │  ├─IAR					// IAR编译器
	  │  │  ├─ARM_CM0			// M0内核
	  │  │  ├─ARM_CM3			// M3内核
	  │  │  ├─ARM_CM4F			// M4内核
	  │  │  └─ARM_CM7			// M7内核
      │  │     ├─port.c			// 处理器写的接口文件
	  │  │     └─portmacro.h	// port.c对应的头文件
      │  ├─Keil					// Keil编译器
	  │  │  └─See-also-the-RVDS-directory.txt	// 提示查看RVDS文件夹
	  │  │     └─Nothing to see here.	// txt里面的内容
      │  ├─MemMang				// 内存管理相关
	  │  │  ├─heap_1.c			// 动态内存分配相关函数接口
	  │  │  ├─heap_2.c
	  │  │  ├─heap_3.c
	  │  │  ├─heap_4.c
	  │  │  └─heap_5.c
	  │  └─RVDS					// Keil编译器
	  │     ├─ARM_CM0	
	  │     ├─ARM_CM3	
	  │     ├─ARM_CM4F	
	  │     └─ARM_CM7		  
	  │        ├─port.c			// 处理器写的接口文件
	  │        └─portmacro.h	// port.c对应的头文件
	  ├─croutine.c			 // c协程文件,可以不要
	  ├─event_groups.c		 // 事件组c文件,可以不要
	  ├─list.c				// 核心链表c文件,必须
	  ├─queue.c				// 队列互斥锁信号量c文件,必须
	  ├─tasks.c				// 核心任务创建调度c文件,必须
	  ├─timers.c			// 软件定时器c文件,可以不要
	  └─readme.txt			// readme文件

3.移植到stm32f103上

3.1标准库下移植

第一步找一个能够正常使用的标准库程序,并创建FreeRtos文件夹,名字随便。

在这里插入图片描述
将FreeRtos源码复制到FreeRtos目录下。
在这里插入图片描述
source目录下的所有.c文件,也可以只要list.c queue.c tasks.c

include目录下所有.h文件

porttable目录下只保留MemMang文件夹和RVDS文件夹,RVDS文件夹下只保留ARM_CM3文件夹,因为stm32F103它是M3架构的内核。如果是f4就选CM4F。

将源码目录\Demo\CORTEX_STM32F103_Keil下的FreeRTOSConfig.h文件复制到include目录下。

全部复制完成后目录结构如下图,可以在CMD终端输入tree 文件夹名字 /f指令显示详细结构。
在这里插入图片描述
复制完成后打开Kile工具添加对应的文件。

头文件添加。

在这里插入图片描述
源文件添加
在这里插入图片描述
在这里插入图片描述
这写文件可以随便放到哪,为了结构化,将这些文件进行分组。因为FreeRtos是通过中断进任务切换的在port.c文件中实现了下面这三个中断服务函数。

void xPortPendSVHandler( void );
void xPortSysTickHandler( void );
void vPortSVCHandler( void );

我们需要将原来的stm32f10x_it.c中的下面三个服务函数替换掉。

void SVC_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);

第一种是使用typedef重命名,在FreeRTOSConfig.h中添加下面语句。并删除stm32f10x_it.c中的定义。

#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define xPortSysTickHandler SysTick_Handler

第二种直接将S汇编文件中的,如下所示的三个名称替换掉。
在这里插入图片描述
完后编译出现几个问题,我的freeRtos是10.04版本。

问题

第一个问题提示内存不够
在这里插入图片描述
这个将FreeRTOSConfig.h中的堆栈改小一点解决。

#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 10 * 1024 ) )

第二个问题提示
在这里插入图片描述
这个将FreeRTOS.h中内容修改为

#ifndef INCLUDE_xTaskGetCurrentTaskHandle
    #define INCLUDE_xTaskGetCurrentTaskHandle    1
#endif
或者直接在头文件定义
#define INCLUDE_xTaskGetCurrentTaskHandle    1

修改完成后编译通过。

创建任务测试

添加头文件

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

创建任务函数

static void vLedTask( void *pvParameters )
{
	
			for(;;)
			{	
				LED_BLUE_TOGGLE;
				vTaskDelay(50);
			}
						
}
static void vprintfTask( void *pvParameters )
{
			for(;;)
			{
					printf("test is .....\n");
					vTaskDelay(100);
			}	
}

启动调度

xTaskCreate( vLedTask, "LED", 128, NULL, 2, NULL );
xTaskCreate( vprintfTask, "printf", 128, NULL, 1, NULL );
vTaskStartScheduler();

注意任务函数内一定要有死循环。

main.c内容如下

#include <stm32f10x.h>            // 头文件引用(标准库); 内核、芯片外设....;(stm32f10x.conf.h, 对标准库头文件进行调用)     
#include "stm32f10x_conf.h"       // 头文件引用(标准库); 内核、芯片外设....;(stm32f10x.conf.h, 对标准库头文件进行调用) 
#include "system_f103.h"
#include "stdio.h"                // C标准库文件,用于调用printf, sprintf等常用函数
#include "bsp_led.h"              // LED指示灯
#include "bsp_key.h"              // 按键
#include "bsp_usart.h"            // USART1、2、3,UART4、5
#include "bsp_W25Q128.h"    
#include "string.h"

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

#define mainCHECK_TASK_STACK_SIZE			( 128 )
#define mainCHECK_TASK_PRIORITY				( tskIDLE_PRIORITY+1 )

extern const unsigned char gImage_red[];                       // 声明外部变量:图片缓存数组,位于外部文件font.h中
extern const unsigned char gImage_g[];
extern const unsigned char gImage_b[];
extern const unsigned char gImage_y[];
unsigned char* cmd;

int i = 0;
static void delay_ms(uint32_t ms)                             // 定义一个ms延时函数,减少移植时对外部文件依赖;
{
    ms = ms * 10286;                                          // 注意:打勾 "Options --> C/C++ ---> One ELF Section per Function选项"
    for (uint32_t i = 0; i < ms; i++);                        // 72MHz系统时钟下,大约多少个空循环耗时1ms
}
static void vLedTask( void *pvParameters )
{
	
			for(;;)
			{	
				LED_BLUE_TOGGLE;
				vTaskDelay(50);
			}
						
}

static void vprintfTask( void *pvParameters )
{
			for(;;)
			{
					printf("test is .....\n");
					vTaskDelay(100);
			}	
}

// 主函数
int main(void)
{
		SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);           // 中断分组,组2:抢占级0~3,子优先级0~3 ; 全局只设置一次,尽量放在显眼的地方
    System_SwdMode();                                         // 设置芯片调试方式(SWD); 关闭JTAG只保留SWD; 目的:释放PB3、PB4、PA15,只需PA13、PA14

    USART1_Init(115200);                                      // 串口1初始化; 用于与串口软件通信,方便代码调试; USART1(115200-N-8-1), 且工程已把printf重定向至USART1输出

    Led_Init();                                               // LED 初始化
                                              // 点亮蓝灯

    W25Q128_Init();                                           // 设备W25Q128初始化:引脚配置,SPI配置,测试连接, 测试是否存在字库

   // LCD_Init();                                               // 显示屏初始化: 引脚配置,SPI配置,LCD参数配置

		
		xTaskCreate( vLedTask, "LED", 128, NULL, 2, NULL );
	     xTaskCreate( vprintfTask, "printf", 128, NULL, 1, NULL );
		vTaskStartScheduler(); //启动任务调度器
		
		return 0;

}
// 注意:每一个代码文件,末尾保留一空行,否则编译会产生警告

3.2HAL库下移植

​ 和标准库的移植过程一样,也可以通过STM32CubeMX直接生成,但st对freeRtos进行和简单封装,调用的还是原来的函数,个人感觉没必要,直接用原来的API就好。HAL库只是方便STM32CubeMX生成和标准库没有太大差别只是换了个名字。

3.3 现象

板上led灯以一定间隔闪烁,同时串口打印字符串。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值