freeRTos菜鸟入门

裸机开发最后的救赎

目录


1 开篇

又滚回windows了,真香


2 一个最简单的工程

2.1 你需要 STM32CubeMX 这个神器

为了操作方便–我买了一个 stm32nucleo-f103

2.2 通过Board Selector 新建一个工程

有这个小板子的好处是可以通过用它的模版工程

2.2.1 找到对应工程

5681bae09b5a4cff87e9b5003efa46f2.png

2.2.2 设置系统时钟

这里我习惯(其实也没有习惯–菜鸟哪有习惯)把系统时钟设置到最高

d2f5f18589044cd3a364cef73e68ede1.png

2.2.3 找到 FREETROS 激活它

455e48fec02f4d56a29461333c8ba866.png

2.2.4 更换系统的时钟源

fbd592406aec40b593f0bd7749b1d0c6.png


3 进入任务

到此,生成 keil5 工程,测试一下能不能编译下载

3.1 新建一个任务

新建一个任务 myTask_LED 在这里,我调整了 defaultTaskPriority 级别

32f130e909434cbca8c91c9ff13d9607.png

在板子上有个灯

Func_LED 中添加对 LED的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @brief Function implementing the myTask_LED thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Func_LED */
void Func_LED(void const * argument)
{
/* USER CODE BEGIN Func_LED */
/* Infinite loop */
for(;;)
{
//osDelay(50);
vTaskDelay(100);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
//osDelay(50);
vTaskDelay(100);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
}
/* USER CODE END Func_LED */
}

3.2.1 覆盖串口输出函数

由于 printf 最终是调用 fputc 输出数据,fputc是一个弱引用(weak)函数,覆写即可重定向printf

1
2
3
4
int fputc(int ch, FILE *f) {
HAL_USART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

3.2.2 串口输出测试

1
2
/* Infinite loop */
printf("UART Transmit\r\n");

到这步正常输出了

4 添加一个串口服务

4.1 打开串口的接收中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 这里只有一位数据做缓存
// 这里大量发送数据会有丢数据,这个没找到问题再哪里
uint8_t aRxBuffer;

// 在 main 配置完成后添加
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END 2 */

// 在下面添加数据处理函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) {
HAL_UART_Transmit(&huart2, (uint8_t *)&aRxBuffer, 1,0xFFFF);
HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
}
}

这样串口算是工作起来了

5 任务的挂起和恢复

到这里算是要精细话的操作 freertos 了,这边就比较的陌生。

找到一个资料,FreeRTOS任务状态信息查询

为什么要找它,我在这会先依靠cubeMX来管理任务,但控制任务需要任务句柄,但是在现在的代码中,两个任务句柄的是类似匿名的,我的思路是先尝试把句柄查出来

上面画掉的部分是不需要的,为什么,这就要来读一读,直接生成的代码

1
2
3
4
5
6
7
8
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

/* definition and creation of myTask_LED */
osThreadDef(myTask_LED, Func_LED, osPriorityHigh, 0, 128);
myTask_LEDHandle = osThreadCreate(osThread(myTask_LED), NULL);

我被教程给带偏了,一心想着,为什么没有配置 任务句柄,人家是在create的时候返回的。

1
2
3
4
// 默认任务的句柄
defaultTaskHandle
// LED 任务的句柄
myTask_LEDHandle

我觉得,我需要看看别人是怎么写得

下一页吧