打印
[CW32F030系列]

立创CW32F030C8T6移植FreeRTOS

[复制链接]
137|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-11-7 10:45 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、下载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

使用特权

评论回复
沙发
OKAKAKO| | 2024-11-13 17:45 | 只看该作者
移植FreeRTOS参考一下

使用特权

评论回复
板凳
星辰大海不退缩| | 2024-11-22 18:04 | 只看该作者
移植学习一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1931

主题

15650

帖子

12

粉丝