芯源半导体CW32
直播中

hehung

8年用户 659经验值
擅长:嵌入式技术
私信 关注

【CW32饭盒派开发板试用体验】5. 极简方式移植FreeRTOS成功

【CW32饭盒派开发板试用体验】1. 开箱啦

【CW32饭盒派开发板试用体验】2. 使用扩展板串口UART3以及scanf重定向到串口

【CW32饭盒派开发板试用体验】3. 使用BTIM实现任务调度器

【CW32饭盒派开发板试用体验】4. ADC采样摇杆模块X轴和Y轴输出

前言

FreeRTOS作为一款开源的嵌入式实时操作系统,广泛的运用在嵌入式行业,在芯片中集成嵌入式系统也是很有必要的一件事,可以方便的处理各个任务之间的关系,进行精确地时间控制等。本文将讲解如何在CW32F030中集成FreeRTOS OS。

开发环境:

  • 系统:win10
  • IDE:KEIL V5.34
  • 单片机:CW32F030
  • FreeRTOS:KEIL集成包CMSIS-FreeRTOS 10.5.1

前两天也是采用这种使用CMSIS-FreeRTOS的方式移植,但是没成功,是因为在配置的时候选择了使用CMSIS RTOS2,对工程有一定的影响,但是systick进不去,这一次直接选择FreeRTOS,移植成功,而且简洁很多。

1 准备工作

1.1 下载FreeRTOS

KEIL中是集成了FreeRTOS系统的,可以直接在 Pack Installer中安装,如下图,点击 Install即可。这样就不用去freeRTOS官网下载整个freeRTOS包了。简单方便快捷
1685276345031.png

下载过程中可能出现超时的问题,导致下载不成功,因为keil官网从国内访问不是很稳定。
1685276993261.png

出现上述情况,可以直接在keil官网去下载,使用迅雷要快很多,下载好了之后直接双击pack包安装即可。

官方地址:http://www.keil.com/pack/
1685277663285.png

1.2 集成freeRTOS到工程

  1. 下载好freeRTOS的pack包之后,双击安装即可。

  2. 安装完成之后,选择官方工程,在官方提供的工程基础上进行移植,选择了 实验一 流水灯实验

  3. 打开工程,选择 Manage Run-Time Environment,选择 RTOS,配置相关信息,见下图:
    1685717820916.png

  4. 之后会上报如下几个函数的重定义:
    1685282890046.png

  5. interrupts_cw32f030.c文件中将函数实现 SVC_Handler, PendSV_Handler注释掉,在 cw32f030_systick.c中将函数 SysTick_Handler注释掉即可。

  6. 之后编译不会再报错

到此为止表示移植完成了,接下来就是写两个任务测试一下功能是否正常了

2 代码编写

代码如下,创建了两个任务,分别为led1_task和led2_task,分别驱动LED2和LED3闪烁,led1_task的工作周期为500ms,led2_task的工作周期为1000ms。

#include "main.h"

/* FreeRTOS includes. */

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


#define LED1_TASK_PRIO                3                //任务优先级
#define LED1_STK_SIZE                 50          //任务堆栈大小
TaskHandle_t LED1Task_Handler;                //任务句柄
void led1_task(void *pvParameters);        //任务函数

#define LED2_TASK_PRIO		3		//任务优先级
#define LED2_STK_SIZE 		50  	//任务堆栈大小
TaskHandle_t LED2Task_Handler;		//任务句柄
void led2_task(void *pvParameters);	//任务函数


void GPIO_Configuration(void);
void RCC_Configuration(void);

int main()
{
//	uint32_t i;
	RCC_Configuration(); //时钟配置64M
	GPIO_Configuration();//LED初始化

	//创建led1任务
    xTaskCreate((TaskFunction_t )led1_task,            //任务函数
                (const char*    )"led1_task",          //任务名称
                (uint16_t       )LED1_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )LED1_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&LED1Task_Handler);   //任务句柄  
			
    xTaskCreate((TaskFunction_t )led2_task,            //任务函数
                (const char*    )"led2_task",          //任务名称
                (uint16_t       )LED2_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )LED2_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&LED2Task_Handler);   //任务句柄  

	vTaskStartScheduler();          //开启任务调度

	while(1)
	{

	}
}

void led1_task(void *pvParameters)
{
	while(1)
	{
		PA07_TOG();
		vTaskDelay(500);
	}
}

void led2_task(void *pvParameters)
{
	while(1)
	{
		PA08_TOG();
		vTaskDelay(1000);
	}
}


void RCC_Configuration(void)
{
  /* 0. HSI使能并校准 */
  RCC_HSI_Enable(RCC_HSIOSC_DIV6);

  /* 1. 设置HCLK和PCLK的分频系数 */
  RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
  RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
  
  /* 2. 使能PLL,通过PLL倍频到64MHz */
  RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, 8);     // HSI 默认输出频率8MHz
 // RCC_PLL_OUT();  //PC13脚输出PLL时钟
  
  ///< 当使用的时钟源HCLK大于24M,小于等于48MHz:设置FLASH 读等待周期为2 cycle
  ///< 当使用的时钟源HCLK大于48MHz:设置FLASH 读等待周期为3 cycle
  __RCC_FLASH_CLK_ENABLE();
  FLASH_SetLatency(FLASH_Latency_3);   
  
  /* 3. 时钟切换到PLL */
  RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL);
  RCC_SystemCoreClockUpdate(64000000);
}


void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
	__RCC_GPIOB_CLK_ENABLE();
	__RCC_GPIOC_CLK_ENABLE();
	__RCC_GPIOA_CLK_ENABLE();

  GPIO_InitStruct.IT = GPIO_IT_NONE; //LED 
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pins = GPIO_PIN_7|GPIO_PIN_8;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
 
	GPIO_InitStruct.Pins = GPIO_PIN_13;	// LED4
  GPIO_Init(CW_GPIOC, &GPIO_InitStruct);

	GPIO_WritePin(CW_GPIOA,GPIO_PIN_7|GPIO_PIN_8,GPIO_Pin_RESET);   //LED灯拉高
	GPIO_WritePin(CW_GPIOC,GPIO_PIN_13,GPIO_Pin_RESET);
}

3 实验效果

见文末视频,LED2闪烁两次,LED3才会闪烁一次,而且是按照预定时间闪烁,实验成功。

总结

使用KEIL集成的CMSIS-FreeRTOS移植FreeRTOS简直是事半功倍。只需要话费很少的时候就可以完成移植,极大地提高了效率。

后边就可以使用freeRTOS愉快的玩耍了。

更多回帖

发帖
×
20
完善资料,
赚取积分