一、下载FreeRTOS源码
首先从代码托管网站上https://sourceforge.net/projects/freertos/files/FreeRTOS/下载最新的FreeRTOS,下载的是v10.4.1版本。
下载解压后的是这些东西。
其中FreeRTOS是需要移植的操作系统。而FreeRTOS-Plus内我感觉是些附加的其他库,而且大部分好像是收费的,所以我们仅需要用到FreeRTOS这个文件夹即可。
二、移植FreeRTOS
首先需要找一套可以用来移植的源码,我从立创开发板https://wiki.lckfb.com/zh-hans/dwx-cw32f030c8t6/。这个网页的百度云盘中找到一份空白工程模板下载后。
这就是代码的文件夹了。
在其中创建一个FreeRTOS的文件夹,用于存放移植的代码。
并且在其中创建三个文件夹。
分别用来移植以下代码。
将Source目录下的代码复制到src中,include也直接复制即可,注意portable仅需要MemMang文件夹和RVDS的ARM_CM0(因为CW32F030C8T6是M0的内核)。
另外复制一份Demo中的FreeRTOSConfig并存入APP文件夹内,我复制的是stm32f103的。
后续我们就可以打开keil,将代码路径等存储进去了。
另外需要配置xPortSysTickHandler这个函数,具体位置如下。
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
#if (INCLUDE_xTaskGetSchedulerState == 1 )
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
#endif /* INCLUDE_xTaskGetSchedulerState */
xPortSysTickHandler();
#if (INCLUDE_xTaskGetSchedulerState == 1 )
}
#endif /* INCLUDE_xTaskGetSchedulerState */
}
然后从野火那里抄点main函数代码即可。
#include "board.h"
#include "stdio.h"
#include "bsp_uart.h"
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
/**************************** 任务句柄 ********************************/
/*
* 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄
* 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么
* 这个句柄可以为NULL。
*/
/* 创建任务句柄 */
static TaskHandle_t AppTaskCreate_Handle = NULL;
/* LED1任务句柄 */
static TaskHandle_t LED1_Task_Handle = NULL;
/* LED2任务句柄 */
static TaskHandle_t LED2_Task_Handle = NULL;
/*
*************************************************************************
* 函数声明
*************************************************************************
*/
static void AppTaskCreate(void);/* 用于创建任务 */
static void LED1_Task(void* pvParameters);/* LED1_Task任务实现 */
static void LED2_Task(void* pvParameters);/* LED2_Task任务实现 */
static void BSP_Init(void);/* 用于初始化板载相关资源 */
int32_t main(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
BSP_Init();
printf("你好!\r\n");
/* 创建AppTaskCreate任务 */
xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */
(const char* )"AppTaskCreate",/* 任务名字 */
(uint16_t )64, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )1, /* 任务的优先级 */
(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */
/* 启动任务调度 */
if(pdPASS == xReturn)
vTaskStartScheduler(); /* 启动任务,开启调度 */
else
return -1;
while(1); /* 正常不会执行到这里 */
}
/***********************************************************************
* @ 函数名 : AppTaskCreate
* @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
* @ 参数 : 无
* @ 返回值 : 无
**********************************************************************/
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
taskENTER_CRITICAL(); //进入临界区
/* 创建LED_Task任务 */
xReturn = xTaskCreate((TaskFunction_t )LED1_Task, /* 任务入口函数 */
(const char* )"LED1_Task",/* 任务名字 */
(uint16_t )64, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )2, /* 任务的优先级 */
(TaskHandle_t* )&LED1_Task_Handle);/* 任务控制块指针 */
if(pdPASS == xReturn)
printf("创建LED1_Task任务成功!\r\n");
/* 创建LED_Task任务 */
xReturn = xTaskCreate((TaskFunction_t )LED2_Task, /* 任务入口函数 */
(const char* )"LED2_Task",/* 任务名字 */
(uint16_t )64, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )3, /* 任务的优先级 */
(TaskHandle_t* )&LED2_Task_Handle);/* 任务控制块指针 */
if(pdPASS == xReturn)
printf("创建LED2_Task任务成功!\r\n");
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
taskEXIT_CRITICAL(); //退出临界区
}
/**********************************************************************
* @ 函数名 : LED_Task
* @ 功能说明: LED_Task任务主体
* @ 参数 :
* @ 返回值 : 无
********************************************************************/
static void LED1_Task(void* parameter)
{
while (1)
{
// 高电平
GPIO_WritePin(CW_GPIOC, GPIO_PIN_13, GPIO_Pin_SET);
vTaskDelay(500); /* 延时500个tick */
printf("LED1_Task Running,LED1_ON\r\n");
// 低电平
GPIO_WritePin(CW_GPIOC, GPIO_PIN_13, GPIO_Pin_RESET);
vTaskDelay(500); /* 延时500个tick */
printf("LED1_Task Running,LED1_OFF\r\n");
}
}
/**********************************************************************
* @ 函数名 : LED_Task
* @ 功能说明: LED_Task任务主体
* @ 参数 :
* @ 返回值 : 无
********************************************************************/
static void LED2_Task(void* parameter)
{
while (1)
{
GPIO_WritePin(CW_GPIOC, GPIO_PIN_14, GPIO_Pin_SET);
vTaskDelay(500); /* 延时500个tick */
printf("LED2_Task Running,LED2_ON\r\n");
GPIO_WritePin(CW_GPIOC, GPIO_PIN_14, GPIO_Pin_RESET);
vTaskDelay(500); /* 延时500个tick */
printf("LED2_Task Running,LED2_OFF\r\n");
}
}
static void BSP_Init(void)
{
board_init(); // 开发板初始化
uart1_init(115200); // 串口1波特率115200
GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化结构体
__RCC_GPIOC_CLK_ENABLE(); // 使能GPIO时钟
GPIO_InitStruct.Pins = GPIO_PIN_13|GPIO_PIN_14; // GPIO引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 输出速度高
GPIO_Init(CW_GPIOC, &GPIO_InitStruct); // 初始化
}
三、解决问题
在移植的过程中遇到数个问题,解决方法如下。
问题1:直接移植报错
.\OBJ\LED.axf: Error: L6218E: Undefined symbol xTaskGetCurrentTaskHandle (referred from stream_buffer.o).
问题主要在于xTaskGetCurrentTaskHandle 这个函数有个宏,把他打开就行。
问题2:主频问题
直接复制过来之后stm32f103的主频其实是72M,所以我们需要改成CW32的64M。
问题3:RAM报错
Error: L6406E: No space in execution regions with .ANY selector matching queue.o(.bss). 这个报错是因为移植的stm32f103它的RAM比CW32大的多,从其手册可知RAM是8KB。
故需要将HEAP_SIZE改小,我改成了5*1024。
问题4:上电卡死在初始化任务上
首先结论是我没有在FreeRTOSConfig中配置下面这个东西。
最开始没配置会卡死在startup中的PendSV这个中断函数上,我加上上面的代码就好了,应该是会用到这两个中断。
四、现象展示及代码
最终结果如下,LED灯闪烁就不展示了,因为其实也就一个灯在闪而已。
大概就是这些了,后续打算继续利用cw32做一些东西,也会发在CSDN上,可以私聊我一起学习共同进步。
代码链接如下:
通过百度网盘分享的文件:cw32移植freertos.rar
链接:https://pan.baidu.com/s/1AUHh22onuiauFJv6K06S5g?pwd=87w7
提取码:87w7
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/huayidw/article/details/141167770
|