|
|
/* FreeRTOS头文件 */
|
|
|
#include "FreeRTOS.h"
|
|
|
#include "task.h"
|
|
|
|
|
|
#include "rgb.h"
|
|
|
#include "usart.h"
|
|
|
|
|
|
/**************************** 任务句柄 ********************************/
|
|
|
/*
|
|
|
* 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄
|
|
|
* 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么
|
|
|
* 这个句柄可以为NULL。
|
|
|
*/
|
|
|
static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */
|
|
|
static TaskHandle_t Test_Task_Handle = NULL;/* LED任务句柄 */
|
|
|
static TaskHandle_t KEY_Task_Handle = NULL;/* KEY任务句柄 */
|
|
|
|
|
|
/********************************** 内核对象句柄 *********************************/
|
|
|
/*
|
|
|
* 信号量,消息队列,事件标志组,软件定时器这些都属于内核的对象,要想使用这些内核
|
|
|
* 对象,必须先创建,创建成功之后会返回一个相应的句柄。实际上就是一个指针,后续我
|
|
|
* 们就可以通过这个句柄操作这些内核对象。
|
|
|
*
|
|
|
* 内核对象说白了就是一种全局的数据结构,通过这些数据结构我们可以实现任务间的通信,
|
|
|
* 任务间的事件同步等各种功能。至于这些功能的实现我们是通过调用这些内核对象的函数
|
|
|
* 来完成的
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
|
|
|
/******************************* 全局变量声明 ************************************/
|
|
|
/*
|
|
|
* 当我们在写应用程序的时候,可能需要用到一些全局变量。
|
|
|
*/
|
|
|
|
|
|
|
|
|
/*
|
|
|
*************************************************************************
|
|
|
* 函数声明
|
|
|
*************************************************************************
|
|
|
*/
|
|
|
static void AppTaskCreate(void);/* 用于创建任务 */
|
|
|
|
|
|
static void Test_Task(void* pvParameters);/* Test_Task任务实现 */
|
|
|
static void KEY_Task(void* pvParameters);/* KEY_Task任务实现 */
|
|
|
|
|
|
static void SystemClock_Config(void)
|
|
|
{
|
|
|
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
|
|
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
|
|
|
|
//配置时钟源HSE/HSI/LSE/LSI
|
|
|
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSI;
|
|
|
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
|
|
|
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
|
|
|
// RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_8MHz; //配置HSI输出时钟为8MHz
|
|
|
//RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_4MHz; //配置HSI输出时钟为4MHz
|
|
|
//RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_16MHz; //配置HSI输出时钟为16MHz
|
|
|
//RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_22p12MHz; //配置HSI输出时钟为22.12MHz
|
|
|
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_24MHz; //配置HSI输出时钟为24MHz
|
|
|
|
|
|
RCC_OscInitStruct.HSEState = RCC_HSE_ON; //开启HSE
|
|
|
RCC_OscInitStruct.HSEFreq = RCC_HSE_16_32MHz; //HSE工作频率范围16M~32M
|
|
|
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
|
|
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
|
|
RCC_OscInitStruct.LSIState = RCC_LSI_ON; //开启LSI
|
|
|
|
|
|
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) //初始化RCC振荡器
|
|
|
{
|
|
|
// Error_Handler();
|
|
|
}
|
|
|
|
|
|
//初始化CPU,AHB,APB总线时钟
|
|
|
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1; //RCC系统时钟类型
|
|
|
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //SYSCLK的源选择为HSE
|
|
|
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; //APH时钟不分频
|
|
|
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; //APB时钟2分频
|
|
|
|
|
|
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) //初始化RCC系统时钟(FLASH_LATENCY_0=24M以下;FLASH_LATENCY_1=48M)
|
|
|
{
|
|
|
// Error_Handler();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief 初始化外设相关
|
|
|
*/
|
|
|
static void BSP_Init(void)
|
|
|
{
|
|
|
/* LED 初始化 */
|
|
|
RGB_Init();
|
|
|
|
|
|
/* 串口初始化 */
|
|
|
USART_Config();
|
|
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
|
* @brief 主函数
|
|
|
* @param 无
|
|
|
* @retval 无
|
|
|
* @note 第一步:开发板硬件初始化
|
|
|
第二步:创建APP应用任务
|
|
|
第三步:启动FreeRTOS,开始多任务调度
|
|
|
****************************************************************/
|
|
|
int main(void)
|
|
|
{
|
|
|
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
|
|
|
SystemClock_Config();
|
|
|
HAL_Init();
|
|
|
/* 开发板硬件初始化 */
|
|
|
BSP_Init();
|
|
|
|
|
|
/* 创建AppTaskCreate任务 */
|
|
|
xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */
|
|
|
(const char* )"AppTaskCreate",/* 任务名字 */
|
|
|
(uint16_t )configMINIMAL_STACK_SIZE, /* 任务栈大小 */
|
|
|
(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(); //进入临界区
|
|
|
|
|
|
/* 创建Test_Task任务 */
|
|
|
xReturn = xTaskCreate((TaskFunction_t )Test_Task, /* 任务入口函数 */
|
|
|
(const char* )"Test_Task",/* 任务名字 */
|
|
|
(uint16_t )configMINIMAL_STACK_SIZE, /* 任务栈大小 */
|
|
|
(void* )NULL, /* 任务入口函数参数 */
|
|
|
(UBaseType_t )2, /* 任务的优先级 */
|
|
|
(TaskHandle_t* )&Test_Task_Handle);/* 任务控制块指针 */
|
|
|
if(pdPASS == xReturn) {
|
|
|
printf("创建Test_Task任务成功!\r\n");
|
|
|
}
|
|
|
/* 创建KEY_Task任务 */
|
|
|
xReturn = xTaskCreate((TaskFunction_t )KEY_Task, /* 任务入口函数 */
|
|
|
(const char* )"KEY_Task",/* 任务名字 */
|
|
|
(uint16_t )configMINIMAL_STACK_SIZE, /* 任务栈大小 */
|
|
|
(void* )NULL,/* 任务入口函数参数 */
|
|
|
(UBaseType_t )3, /* 任务的优先级 */
|
|
|
(TaskHandle_t* )&KEY_Task_Handle);/* 任务控制块指针 */
|
|
|
if(pdPASS == xReturn) {
|
|
|
printf("创建KEY_Task任务成功!\r\n");
|
|
|
}
|
|
|
|
|
|
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
|
|
|
|
|
|
taskEXIT_CRITICAL(); //退出临界区
|
|
|
}
|
|
|
|
|
|
int test = 0;
|
|
|
|
|
|
/**********************************************************************
|
|
|
* @ 函数名 : Test_Task
|
|
|
* @ 功能说明: Test_Task任务主体
|
|
|
* @ 参数 :
|
|
|
* @ 返回值 : 无
|
|
|
********************************************************************/
|
|
|
static void Test_Task(void* parameter)
|
|
|
{
|
|
|
(void)parameter;
|
|
|
while (1) {
|
|
|
test = configCPU_CLOCK_HZ;
|
|
|
HAL_GPIO_WritePin(LED4_GPIO_PORT, LED4_PIN, GPIO_PIN_RESET);
|
|
|
printf("Test_Task Running,LED1_ON\r\n");
|
|
|
vTaskDelay(pdMS_TO_TICKS(500)); /* 延时500个tick */
|
|
|
|
|
|
HAL_GPIO_WritePin(LED4_GPIO_PORT, LED4_PIN, GPIO_PIN_SET);
|
|
|
printf("Test_Task Running,LED1_OFF\r\n");
|
|
|
vTaskDelay(500); /* 延时500个tick */
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
|
* @ 函数名 : Test_Task
|
|
|
* @ 功能说明: Test_Task任务主体
|
|
|
* @ 参数 :
|
|
|
* @ 返回值 : 无
|
|
|
********************************************************************/
|
|
|
static void KEY_Task(void* parameter)
|
|
|
{
|
|
|
(void)parameter;
|
|
|
static uint8_t key_flag = 0;
|
|
|
|
|
|
while (1) {
|
|
|
/* 等待按键按下 */
|
|
|
// if(BSP_PB_GetState(BUTTON_USER))
|
|
|
// {
|
|
|
// vTaskDelay(20);/* 延时20个tick */
|
|
|
// continue;
|
|
|
// }
|
|
|
|
|
|
key_flag = key_flag ? 0 : 1;
|
|
|
|
|
|
// if(key_flag) {
|
|
|
// printf("挂起Test任务!\n");
|
|
|
// vTaskSuspend(Test_Task_Handle);/* 挂起LED任务 */
|
|
|
// printf("挂起Test任务成功!\n");
|
|
|
// }
|
|
|
//
|
|
|
// if(!key_flag) {/* K2 被按下 */
|
|
|
// printf("恢复Test任务!\n");
|
|
|
// vTaskResume(Test_Task_Handle);/* 恢复LED任务! */
|
|
|
// printf("恢复Test任务成功!\n");
|
|
|
// }
|
|
|
|
|
|
vTaskDelay(20);/* 延时20个tick */
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#ifdef USE_FULL_ASSERT
|
|
|
void assert_failed(uint8_t* file, uint32_t line)
|
|
|
{
|
|
|
(void)file;
|
|
|
(void)line;
|
|
|
/* User can add their own implementation here */
|
|
|
while (1) {
|
|
|
/* Infinite loop - you could also log the error or trigger a system reset */
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
/********************************END OF FILE****************************/
|