【STM32】CubeMX + CLion + FreeRTOS移植过程问题记录

news2024/11/28 23:52:02

文章目录

  • 一、portable 文件选择
  • 二、自定义文件添加
  • 三、ST-Link v2 烧录问题
  • 四、STM32F407工程中程序无法启动调度器


前言

本文依照稚晖君分享的配置CLion用于STM32开发【优雅の嵌入式开发】,尝试配置STM32CubeMX + CLion开发环境,并在此基础上移植FreeRTOS工程。记录一些Bug和经验,与诸君共勉。

  • STM32型号:STM32F103C8T6、STM32F407ZGT6
  • FreeRTOS版本:V202212.01
  • Keil 5-MDK版本:5.40.0.3
  • CLion版本:2024.1
  • FreeRTOS移植工程类型:标准库(仅STM32F1)、HAL库(F1、F4)
  • 烧录工具:ST-Link V2(U盘版本)、ST-Link/V2(正点原子授权版)

一、portable 文件选择

如果您和我一样,之前(习惯)使用Keil进行STM32开发FreeRTOS,突然转到CLion开发环境,这时就需要更改选择的 portable 文件的路径。由于要使用MinGW编译环境编译C/C++代码,并且CLion使用CMake组织工程编译方式,所以 portable 文件需要选择 FreeRTOS → \rightarrow Source → \rightarrow portable → \rightarrow ARM_CM3 中的port.hportmacro.h文件。内存管理文件的路径不需要更改,同样选择MemMang中的heap_4.c文件加入工程即可。
在这里插入图片描述

二、自定义文件添加

CLion开发环境使用CMakeLists.txt构建和组织工程,这时如果需要添加include path和BSP包,就需要部分修改CubeMX自动生成的CMakeLists.txt。(每次在CubeMX中点击GENERATE CODE后都会覆盖之前修改的CMakeLists.txt,所以修改CubeMX配置后需要手动修改CMakeLists.txt,之后重置缓存并重新加载项目
在这里插入图片描述
如果添加了自定义的头文件和源文件,请修改CMakeLists.txt中的include_directoriesfile配置:
在这里插入图片描述
如果需要在CLion中创建C源文件或者头文件,注意不要在创建时将其添加到CMake目标,如果添加会破坏上图中黄色框标出部分,可能会导致编译报错。注意取消勾选“添加到目标”,如下图所示:
在这里插入图片描述

三、ST-Link v2 烧录问题

使用OpenOCD烧录STM32程序需要一个配置文件.cfg。在这个配置文件中,定义了烧录方式,烧录速度等信息。笔者开发STM32F103C8T6使用的ST-Link v2是江科大套件中的U盘型:
在这里插入图片描述
OpenOCD配置如下图所示:
在这里插入图片描述
如果需要修改配置设置,可以这样快速打开配置:
在这里插入图片描述

  • stlink.cfg
# 这里的stlink.cfg是OpenOCD官方编写的,适用于STLINK的V2、V2-1、V2-2版本
source [find interface/stlink.cfg]

transport select hla_swd
# 下载速度 10000kHz,即10MHz
adapter speed 10000

# 内存大小
# STM32F103C8T6为 RAM20KB, FLASH 64KB
set WORKAREASIZE 0x5000
set FLASH_SIZE 0x10000

# chip name
set CHIPNAME STM32F103C8T6

# CPUTAPID 应该是 0x1ba01477,如果烧录失败使用 0x2ba01477(芯片版权问题)
set CPUTAPID 0x2ba01477
source [find target/stm32f1x.cfg]
# 删掉这一行,否则无法复位开发板
# reset_config srst_only

奇怪的是,博主使用上面的配置文件无法使芯片进入Debug状态,或者说进入Debug状态后程序无法暂停。如果点击暂停后会报错:
在这里插入图片描述
报错信息:

Open On-Chip Debugger 0.12.0 (2023-10-02) [https://github.com/sysprogs/openocd]
Licensed under GNU GPL v2
libusb1 09e75e98b4d9ea7909e8837b7a3f00dda4589dc3
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results mi
ght differ compared to plain JTAG/SWD
Info : clock speed 1000 kHz
Info : STLINK V2J45S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.234574
Info : [stm32f1x.cpu] Cortex-M3 r2p0 processor detected
Info : [stm32f1x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
[stm32f1x.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080004c8 msp: 0x20005000
(((READY)))
Info : tcl server disabled
Info : Listening on port 4444 for telnet connections
Info : accepting 'gdb' connection on tcp/3333
Info : device id = 0x10010414
Info : flash size = 256 KiB
Warn : Prefer GDB command "target extended-remote :3333" instead of "target remo
te :3333"
调试器已连接至 tcp:localhost:3333
The target is not running when halt was requested, stopping GDB.
Info : The target is not running when halt was requested, stopping GDB.
Error: [stm32f1x.cpu] not halted (gdb fileio)


提示芯片无法进入暂停状态。初步排查错误后估计是OpenOCD或者CLion的设置问题,因为在Keil中对相同的芯片和开发板进行Debug调试没有出现问题。对具体无法调试的原因进行排查,先后排除了cfg文件的设置、GDB的选择存在问题,依然无法调试(希望不是盗版芯片问题)。在网上没有找到更多信息,好在不是什么致命问题,如有知道原因的朋友欢迎在评论区指出,不胜感激!

四、STM32F407工程中程序无法启动调度器

笔者在创建STM32F407ZGT6的CLion工程的过程中遇到一个相当奇怪的问题。通过网上的各种资料、官方手册,甚至CubeMX中的配置页面都可以得到一个结论:STM32中决定中断优先级的寄存器位数为4位。Cortex-M内核最多提供8位,但是不同的单片机厂商使用不同的位数。例如STM32使用高4位,所以最多有16级可分组的优先级(优先级值0到15);MSP432系列中使用3位,所以最多有8级可分组的优先级(优先级值0到7,该信息出自文章CORTEX-M4F基本知识)。

在配置过程中,笔者使用的FreeRTOSconfig.h文件如下所示。该文件修改自官方提供的Demo工程CORTEX_M4F_STM32F407ZG-SK。

/*
 * FreeRTOS V202212.01
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * https://www.FreeRTOS.org
 * https://github.com/FreeRTOS
 *
 */


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html
 *----------------------------------------------------------*/

/* Ensure stdint is only used by the compiler, and not the assembler. */
// #ifdef __ICCARM__
// 	#include <stdint.h>
// 	extern uint32_t SystemCoreClock;
// #endif

#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h>
	extern uint32_t SystemCoreClock;
#endif

#define configUSE_PREEMPTION			1
#define configUSE_IDLE_HOOK				0
#define configUSE_TICK_HOOK				0
#define configCPU_CLOCK_HZ				( SystemCoreClock )
#define configTICK_RATE_HZ				( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES			( 5 )
#define configMINIMAL_STACK_SIZE		( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE			( ( size_t ) ( 75 * 1024 ) )
#define configMAX_TASK_NAME_LEN			( 10 )
#define configUSE_TRACE_FACILITY		1
#define configUSE_16_BIT_TICKS			0
#define configIDLE_SHOULD_YIELD			1
#define configUSE_MUTEXES				1
#define configQUEUE_REGISTRY_SIZE		8
#define configCHECK_FOR_STACK_OVERFLOW	0
#define configUSE_RECURSIVE_MUTEXES		1
#define configUSE_MALLOC_FAILED_HOOK	0
#define configUSE_APPLICATION_TASK_TAG	0
#define configUSE_COUNTING_SEMAPHORES	1
#define configGENERATE_RUN_TIME_STATS	0


/* Software timer definitions. */
#define configUSE_TIMERS				1
#define configTIMER_TASK_PRIORITY		( 2 )
#define configTIMER_QUEUE_LENGTH		10
#define configTIMER_TASK_STACK_DEPTH	( configMINIMAL_STACK_SIZE * 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet		1
#define INCLUDE_uxTaskPriorityGet		1
#define INCLUDE_vTaskDelete				1
#define INCLUDE_vTaskCleanUpResources	1
#define INCLUDE_vTaskSuspend			1
#define INCLUDE_vTaskDelayUntil			1
#define INCLUDE_vTaskDelay				1

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
	/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
	#define configPRIO_BITS       		__NVIC_PRIO_BITS
#else
	#define configPRIO_BITS       		4        /* 15 priority levels */
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0xf

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */


乍一看没什么问题,甚至网络上其他关于STM32F407的FreeRTOS移植教程都使用这个文件作为基准修改。主要修改的点在于SystemCoreClock的声明、钩子函数的使能等。但是当笔者使用修改后的该文件作为FreeRTOS配置文件加入工程后,添加两个任务,让LED0和LED1分别以1s和0.5s闪烁,编译通过,烧录却没有现象。为什么呢?通过Debug调试,发现函数卡死在port.c的下面的程序语句中:
在这里插入图片描述

#ifdef configPRIO_BITS
{
     /* Check the FreeRTOS configuration that defines the number of
      * priority bits matches the number of priority bits actually queried
      * from the hardware. */
     configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
 }
 #endif

笔者移植时采用的port.c文件是FreeRTOS → \rightarrow Source → \rightarrow portable → \rightarrow GCC → \rightarrow ARM_CM4F 中的文件,按理说在CLion这种基于GCC编译器的开发环境中不应该有问题。仔细阅读代码和Debug信息,发现是该程序段上方的检查中断优先级寄存器的可用位出了问题:
在这里插入图片描述
0xFF赋值给0xe000e400地址的寄存器,此时寄存器内的值居然不是255,而是224?见鬼了。冷静下来思考一下,224说明此时寄存器的值为0b11100000,查阅资料后发现该地址的寄存器就是内核的其中一个中断优先级寄存器NVIC_IPR0,所以博主猜测该芯片使用3位表示中断优先级。但是笔者搜遍资料,STM32全系列都采用高4位表示中断优先级。莫非是又遇到了假芯片,这次碰到的甚至是假内核?
在这里插入图片描述

抱着试一试的态度,将FreeRTOSconfig.h中关于中断优先级表示的宏定义改为3:

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
	/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
	#define configPRIO_BITS       		__NVIC_PRIO_BITS
#else
	#define configPRIO_BITS       		3        /* 8 priority levels */
#endif

编译同样不会报错,通过Debug和烧录,任务函数正常执行,说明程序可以正常启动调度器了。

在FreeRTOS官网的文章可以找到这样的描述:

在这里插入图片描述

简单分析一下,FreeRTOS源码中断言函数的作用就是检查当前工程配置的中断优先级位数和实际硬件中是否匹配,既然将configPRIO_BITS改为3程序可以正常运行,说明笔者使用的芯片中确实使用3位作为中断优先级寄存器。Cortex-M系列内核最多可以支持寄存器的八位表示中断优先级,但是市面上常见的单片机使用3位或者4位。既然STM32都采用4位(并且通过CubeMX配置可以发现STM32F407ZGT6确实也使用4位作为中断优先级),只能说明该芯片有可能不是真正的STM32,而是“Chinese Fake Chips”。

回首以往,在之前的学习过程中好像确实遇到过中断函数嵌套无法正常运行的情况。难道问题就出现在这里?答案就不得而知了。笔者手中也没有多余的同款芯片和开发板来进行进一步验证,所以求证之路只能到此为止。好在这一点问题并不影响学习FreeRTOS,只是这一次Debug的结论可能是单片机芯片可能是假的,格外令人气愤,遂记录在此,望后来者可少花时间,继续向前。


持续更新完善中……


  原创笔记,码字不易,欢迎点赞,收藏~ 如有谬误敬请在评论区不吝告知,感激不尽!博主将持续更新有关嵌入式开发、FPGA方面的学习笔记。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2034597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用Emgucv绘制条形码边框16(C#)

EmguCV环境配置&#xff1a; ​​​​​​Emgu CV4图像处理之环境搭建1(C#)_emgucv 4.7-CSDN博客 本文测试环境&#xff1a; win10 64位 vistual studio 2019 Emgu CV 4.6.0 环境配置准备&#xff1a; 1 新增控制台项目&#xff0c;.net framework为4.7.2 2 把win-x…

minikube 实践练习

前言 我这里就简单跟着官方教程做了下练习 参考文档&#xff1a;https://v1-27.docs.kubernetes.io/zh-cn/docs/tutorials/hello-minikube/ 这里最重要的是&#xff0c;你需要提前配置好你的网络。 这个我教不了&#xff0c;之前发了篇帖子vmware实现科学上网审核不通过&…

ElasticSearch 全文检索相关性 算分

文章目录 相关性相关性Relevance相关性算法TF-IDFBM25 通过Explain查看TF-IDFboosting query 多字段查询 相关性dis_max query最佳字段查询multi_match querybest_fields最佳匹配字段most_fields 多数字段搜索cross_fields跨字段搜索 相关性 相关性Relevance 搜索的相关性算分…

Ubuntu 通过 docker 安装 Nginx 镜像 + 创建并运行 nginx01 容器

一、安装 nginx:精简版镜像 1. 查找有什么类型的 nginx 镜像 yammiemy-pc >/home/yammie $ docker search nginx 2. 下载精简版 nginx 镜像 yammiemy-pc >/opt $ docker pull nginx:alpine alpine: Pulling from library/nginx 46b060cc2620: Already exists 21af147…

【深度学习|目标跟踪】快速入门卡尔曼滤波!

卡尔曼滤波详解 申明一、什么是卡尔曼滤波1.1 卡尔曼滤波的使用场景1.2 卡尔曼滤波的定义 二、卡尔曼滤波公式详解&#xff08;无推导&#xff09;三、卡尔曼滤波的简单应用 申明 本博客参考了b站up主“华南小虎队”的卡尔曼滤波教学视频以及Lauszus Kristian Sloth Lauszus的卡…

联想Thinkpad驱动安装下载(官网的驱动下载)

联想Thinkpad驱动安装官网下载地址&#xff1a; 联想驱动管理_ThinkPad服务网站-联想服务 联想驱动管理 帮助您更快速准确的定位驱动 自动下载安装,安装驱动不求人 软件版本&#xff1a;V2.9.0719.1104 | 大小&#xff1a;5.7M最后更新&#xff1a;2021-07-21支持系统&#…

41.【C语言之外】聊聊Cheat Engine官方教程步骤6的思考

0.看前须知 有一定指针概念的基础 推荐阅读前几篇博文&#xff1a; 19.【C语言】指针&#xff08;重难点&#xff09;&#xff08;A&#xff09; 37.【C语言】指针&#xff08;重难点&#xff09;&#xff08;B&#xff09; 38.【C语言】指针&#xff08;重难点&#xff09…

oracle的exp.exe、imp.exe在哪下载?

需要oracle账号 地址&#xff1a; Instant Client for Microsoft Windows (x64) 64-bit 下载这个工具包

开发一个能打造虚拟带货直播间的工具!

在当今数字化时代&#xff0c;直播带货已成为电商领域的一股强劲力量&#xff0c;其直观、互动性强的特点极大地提升了消费者的购物体验。 然而&#xff0c;随着技术的不断进步&#xff0c;传统直播带货模式正逐步向更加智能化、虚拟化的方向演进&#xff0c;本文将深入探讨如…

智慧景区系统开发功能定制

智慧景区系统开发功能定制是一项综合性服务&#xff0c;它涉及到利用云计算、物联网、AI监控等先进技术&#xff0c;通过互联网和移动互联网&#xff0c;实现景区智慧化管理和服务提升。 以下是智慧景区系统开发中应考虑的关键功能点&#xff1a; 游客服务平台&#xff1a;包…

23款奔驰E350eL升级原厂香氛负离子系统,保持一股高级的香味

相信大家都知道&#xff0c;奔驰自从研发出香氛负离子系统后&#xff0c;一直都受广大奔驰车主的追捧&#xff0c;香氛负离子不仅可以散发出清香淡雅的香气外&#xff0c;还可以对车内的空气进行过滤&#xff0c;使车内的有害气味通过负离子进行过滤&#xff0c;达到车内保持清…

“AI能不能代替某某职业”,到底谁在破防?

前几天&#xff0c;公司在午间分享时谈到一个有趣的辩题&#xff1a;“AI能不能代替产品经理”&#xff0c;不仅双方辩手打了个你来我往&#xff0c;就连下面的吃瓜群众也进入红温状态。 “AI能不能代替xx”已经成为一个普遍的话题&#xff0c;在某乎上随手一刷就是不同的职业…

Linux 利用 ftrace 分析内核调用

目录 一、概述二、ftrace 的使用1、常用信息2、指定 ftrace 跟踪器3、设置要跟踪的函数4、ftrace 的开关5、function 跟踪程序6、function_graph 跟踪程序7、函数过滤器8、跟踪事件 三、trace-cmd 的使用1、常见命令2、常用选项2.1 列出可用的追踪器2.2 跟踪特定进程的函数调用…

如何用剪映自动批量生成左右分屏的视频?

做tiktok中视频计划的朋友&#xff0c;应该都知道一种批量做号的模式&#xff0c;就是找一些热门视频作为左边主机视频&#xff0c;右边则放上一些减压类视频以保存画面的原创度&#xff0c;像下面这种。 这种视频是如何批量用剪映生成的呢&#xff1f; 一、准备好素材 下载好…

数据结构——栈的讲解(超详细)

前言&#xff1a; 小编已经在前面讲完了链表和顺序表的内容&#xff0c;下面我们继续乘胜追击&#xff0c;开始另一个数据结构&#xff1a;栈的详解&#xff0c;下面跟上小编的脚步&#xff0c;开启今天的学习之路&#xff01; 目录 1.栈的概念和结构 1.1.栈的概念 1.2.栈的结构…

redis面试(十五)公平锁队列重排

队列重拍 先说一下当前的加锁状态 anyLock由客户端A持有队列中是客户端B、客户端C并且客户端B现在是排在头部 那么队列重拍就是队列中某个客户端长时间没有重新申请加锁&#xff0c;没有刷新分数&#xff0c;就会被队列中挤掉。 假设这个长时间没有加锁的客户端是B。 总结 …

C++ CMake FFmpeg配置

SDK下载 github 环境变量配置 cmake_modules/FindFFmpeg.cmake # This module defines the following variables: # # FFmpeg_FOUND - All required components and the core library were found # FFmpeg_INCLUDE_DIRS - Combined list of all components includ…

Dijkstra单源最短路径算法学习有感

认识Dijkstra 艾兹格维布迪克斯特拉&#xff08;Edsger Wybe Dijkstra&#xff0c;/ˈdaɪkstrə/ DYKE-strə&#xff1b;荷兰语&#xff1a;[ˈɛtsxər ˈʋibə ˈdɛikstra] 1930年5月11日-2002年8月6日&#xff09;是一位荷兰计算机科学家、程序员、软件工程师、系统科学…

(回溯) LeetCode 46. 全排列

原题链接 一. 题目描述 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a;…

零基础学习Redis(1) -- Redis简介

Redis是一个在内存中存储数据的一个中间组件&#xff0c;可用作数据库或数据缓存&#xff0c;通常在分布式系统中使用 &#xff08;不了解分布式&#xff1f; 点击传送&#xff09; 1. Redis特性 在内存中存储数据&#xff0c;通过键值对的方法存储key为string&#xff0c;v…