说明:
1,这里所指的嵌入式其实是指嵌入式微控制器MCU,即单片机
2,万事开头难,本文目前提供了WSL工具链的搭建,后面会持续更新
一、启用RTOS集成
在搭建WSL工具链之前,先讲一下集成的RTOS功能,可跳过。
CLion已经集成了有关RTOS的调试功能(不过下面仅以FreeRTOS为例),比如多线程查看、并行堆栈等,想要启用这个功能,只需要在FreeRTOS的配置文件里添加宏定义并创建一个时基用于统计任务计时。
详细信息,请查看官方教程有价值的非捆绑插件 |CLion 文档 (jetbrains.com)
1,启用功能
在设置中找到如下项,勾选即可
2,修改配置文件
在FreeRTOSConfig.h文件中,添加如下定义。官方文档里有更详细的解释
//用于发布时,取消RTOS调试功能,因为该功能会占用CPU资源
//使用宏定义是为了方便统一控制这个RTOS调试功能,记得包含该宏定义的头文件
#if FreeRTOS_DebugMode
#define configRECORD_STACK_HIGH_ADDRESS 1
#define configGENERATE_RUN_TIME_STATS 1
extern volatile uint32_t CPU_RunTime;
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (CPU_RunTime = 0ul)
#define portGET_RUN_TIME_COUNTER_VALUE() CPU_RunTime
#endif
//在合适的地方创建并启用这个宏定义
#define FreeRTOS_DebugMode 1
如果下面宏定义的值为0,那么改为1或其他非零值
#define configUSE_TRACE_FACILITY 1 //改为1即可
#define configMAX_TASK_NAME_LEN (16) //设置为大于零的值,以便正确显示任务名称,一般默认为16不用改
3,创建时基
新建文件CPU_RunTime.h/.cpp (或者.h/.c)
时基频率一般为系统节拍的10到20倍,系统节拍一般默认1000Hz,那么时基频率可设为15000Hz(根据自己需求)。下面选用的是TIM13,你可以换成其他闲置定时器。
#if FreeRTOS_DebugMode
/* 用于统计运行时间 */
volatile uint32_t CPU_RunTime = 0UL;
TIM_HandleTypeDef htim13;
void ConfigureTimerForRunTimeStats()
{
__HAL_RCC_TIM13_CLK_ENABLE();
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim13.Instance = TIM13;//总频84MHz,现为15000Hz
htim13.Init.Prescaler = 55;
htim13.Init.CounterMode = TIM_COUNTERMODE_UP;
htim13.Init.Period = 99;
htim13.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_Base_Init(&htim13);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim13, &sMasterConfig);
HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
HAL_TIM_Base_Start_IT(&htim13);//不要忘记开启中断
}
//由于我是C++环境,所以使用extern "C"包含
extern "C"
{
void TIM8_UP_TIM13_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim13);
}
}
#endif
在中断回调里让计时变量计数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM7)
{
HAL_IncTick();
}
#if FreeRTOS_DebugMode
else if(htim->Instance == TIM13)
{
++CPU_RunTime;
}
#endif
}
一般来说,由于中断回调是固定的放在某个文件中,不在CPU_RunTime.cpp中,所以为了隔离起来,可以直接使用服务例程ISR,不使用HAL里的中断回调函数
extern "C"
{
void TIM8_UP_TIM13_IRQHandler(void)
{
if(__HAL_TIM_GET_IT_SOURCE(&htim13, TIM_IT_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_IT(&htim13, TIM_IT_UPDATE);
++CPU_RunTime;
}
}
}
最后,不要忘记调用void ConfigureTimerForRunTimeStats()函数来完成RTOS调试功能的初始化
接下来就可以在调试时,愉快地使用集成的RTOS功能(就在变量旁边的栏里)
二、WSL工具链及一些工具的使用
先说明一下为什么使用这个,主要是Windows下开发不如linux方便,在linux有很多工具可用,比如分析内存泄露的valgrind,还有仿真模拟用到QEMU等等。而Windows就很苦逼了,啥都没有。
1,配置WSL
配置过程网上有教程,可跟着配置(其实是过程有些复杂,而我又没有记录下来。后面如果有空就补上,见谅见谅)
先提供一些博客参考Clion使用:在windows下结合wsl进行linux开发_clion wsl linux 源码-CSDN博客
用于WSL下的复制粘贴
2,搭建WSL工具链
①下载工具链
首先要下载cmake,gdb之类的,参考下面这篇博客(很重要)【安装配置】安装适用于 Linux 的 Windows 子系统 WSL
然后到官网下载工具链,由于使用的是stm32f407,没有linux操作系统,所以选用的是none类型,即裸机类型
- arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz
下载完成后直接把这个压缩包拖到目录/usr下
然后在WSL命令行里输入下面指令解压,这个位置自己看着移动,我这里为了方便就放在这了
tar -xvf arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz
②添加进环境变量中
图省事,我把解压后的文件夹直接改为了arm-gnu-toolchain
此时输入下面命令,把这个工具链添加进环境变量中
vim /etc/profile
按i在vim界面最下面一行输入下面语句,然后按Esc键,输入:wq保存退出
export PATH=$PATH:/usr/arm-gnu-none/bin
输入下面指令,让配置文件生效
source /etc/profile
③配置工具链
打开CLion并进入设置,找到下面C和C++编译器所在的位置。如果报错没有找到指定编译器,那么可能需要重启。
④改变配置文件
只要把下面工具链换了就行了,gdb先不管它(比较好解决)
⑤修改CMakeLists文件
#下面代码是MinGW工具链下的
#specify cross-compilers and tools
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_AR arm-none-eabi-ar)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_OBJDUMP arm-none-eabi-objdump)
set(SIZE arm-none-eabi-size)
将上面这段配置改为下面这个,不然会报错找不到指定编译器,因为你是在Windows下运行CLion的,那么它会根据Windows下的环境变量去找而非WSL里的
#下面配置是WSL工具链下的
set(toolsPath /usr/arm-gnu-toolchain/bin)
set(CMAKE_C_COMPILER ${toolsPath}/arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER ${toolsPath}/arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER ${toolsPath}/arm-none-eabi-gcc)
set(CMAKE_AR ${toolsPath}/arm-none-eabi-ar)
set(CMAKE_OBJCOPY ${toolsPath}/arm-none-eabi-objcopy)
set(CMAKE_OBJDUMP ${toolsPath}/arm-none-eabi-objdump)
#下面代码是MinGW工具链下的,先注释掉
# specify cross-compilers and tools
#set(CMAKE_C_COMPILER arm-none-eabi-gcc)
#set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
#set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
#set(CMAKE_AR arm-none-eabi-ar)
#set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
#set(CMAKE_OBJDUMP arm-none-eabi-objdump)
#set(SIZE arm-none-eabi-size)
⑥构建
先CMake一下,然后构建,就会有跟之前一样的提示,只不过速度慢了很多很多
3,Valgrind(不可用)
后来才知道,它是被设计成非嵌入式的,即它直接工作于可执行文件上,因此在检查前不需要重新编译、连接和修改你的程序。也就是说如果你感兴趣的话,倒可以试试,只不过得使用CMake程序而非OpenOCD。
有空我会去试一试QEMU并在文章后面更新,这里先起个头
先在WSL里或CLion的终端里使用下面命令更新一下包,如果你初次进来的话
apt update
然后下载valgrind
apt-get install valgrind
再然后在CLion里设置里浏览它的路径,或者填入路径
\\wsl.localhost\Ubuntu-24.04\usr\bin\valgrind