此章介绍c++开发stm32f系列mcu,下一章介绍freeRTOS关于c++的兼容以及如何兼容AC6
目录
堆空间分配
c++启动相较于c语言需要更大的堆栈空间,我们需要修改启动文件中空间的分配。
手动分配
打开启动汇编文件

M3内核的f103系列一般分配堆栈0x400,0x200Byte空间,一般也能运行,但是可能会出现bug,比如不能调试,跳不出SystemInit之类的,建议各分配0x600以上。这里我使用stm32f103RCT6,有48kRAM,就各分配了0x1000也就是4kByte空间。

CubeMX分配空间
使用CubeMX在Projext Manager的Project这一栏分配内存,其原理与上面类似,都是在启动文件中修改内存分配。

c++开发环境
1.首先,取消勾选微库

然后看你是用AC5还是AC6,AC5支持c++03,部分c++11,且不支持string等堆内存使用的类型
AC6引入了大量gcc编译器特性,支持到c++17,new和delete重载重载后支持string等堆内存使用的函数和方法
AC5的话
勾上C99

AC6的话,选择你的c++版本

C++环境兼容
当 C++ 代码调用一个 C 语言编写的函数fun()时:
- C 编译器生成的符号是简单修饰的(如
_fun)。 - 但 C++ 编译器会按照自己的规则去查找
fun()对应的修饰名(如_Z3funv)。 - 由于两者符号不匹配,链接阶段会出现 “未定义的引用” 错误。
重点:直接在头文件中写函数名,c++文件是找不到函数的,我们需要extern "C"来告诉编译器,这是要给c++用的函数(c也能用,相当于增加了兼容性),这样就好了
#ifndef XXX_H
#define XXX_H
/*------------------------------------*/
#ifdef __cplusplus
extern "C"{
#endif
/*----------------------------------*/
|-----------------------|
| |
| |
| 此处声明函数 |
| |
| |
|-----------------------|
/*------------------------------------*/
#ifdef __cplusplus
}
#endif
/*-------------------------------------*/
#endif
到这一步,就可以使用c++了,不过还不能使用string和中断。
c++兼容中断处理
stm32f系列的库做了对c++的兼容处理,但是中断并不在此行列
故而在重写中断函数时如果是在.cpp文件重写,需要使用extern “C”{}修饰,这样,中断也可以正常运行了
extern "C"{
//不管你是IRQHandle()还是Callbac(),包起来就好了
XXX_IRQHandler()
{
....
}
XXX_Callback()
{
...
}
}
C环境下创建c++接口
这里参考了江雨潇潇下的 c++开发keil方案创建一个函数,这个函数中写业务c++代码,在main()中执行它
#ifndef CPPSTART_H
#define CPPSTART_H
#ifdef __cplusplus
extern "C"
{
#endif
void cppstart(void);//把它看作主函数
#ifdef __cplusplus
}
#endif
#endif
实现它,以点灯为例子,在c语言中,我们可以调用符合c语言语法的C++函数,利用这个特性,所有含c++特性的业务代码写在此接口函数中即可。好了,如果你用的是AC5编译器,到这里已经能使用c++03的大部分特性了。
//cppstart.cpp
#include "cppstart.h"
#include "main.h"
#include "gpio.h"
void cppstart()
{
while(1)
{
LL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
HAL_Delay(1000);
}
}
//main.c
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "cppstart.h"
/* USER CODE END Includes */
...
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
cppstart();//在此调用即可
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
....
C++字符特性,重载new delete
c++string类型基于堆分配实现,想要使用此类特性,需要将以下代码加入到cpp项目文件中,随便什么地方,出现一次就行,这样标准模板库和算法库也能使用了
void* operator new(size_t size) {
return pvPortMalloc(size);
}
void operator delete(void* ptr) noexcept {
vPortFree(ptr);
}
void* operator new[](size_t size) {
return pvPortMalloc(size);
}
void operator delete[](void* ptr) noexcept {
vPortFree(ptr);
}
到这里裸机开发对C++的兼容就做好了,如果想了解FreeRTOS对C++的兼容,可以看我的文章
《c++开发stm32f系列 2》。如果这篇文章对你有帮助的话点个赞支持一下把。

757

被折叠的 条评论
为什么被折叠?



