查看: 274|回复: 0

立创CW32F030C8T6移植FreeRTOS

[复制链接]
  • TA的每日心情

    2024-11-15 16:19
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    292

    主题

    26

    回帖

    2978

    积分

    管理员

    积分
    2978
    发表于 2024-11-12 09:37:22 | 显示全部楼层 |阅读模式
    一、下载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

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    友情链接:

    返回顶部 返回列表