c++开发stm32f系列 1

此章介绍c++开发stm32f系列mcu,下一章介绍freeRTOS关于c++的兼容以及如何兼容AC6

目录

堆空间分配

手动分配

CubeMX分配空间

c++开发环境

C++环境兼容

c++兼容中断处理

C环境下创建c++接口

C++字符特性,重载new   delete


堆空间分配

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》。如果这篇文章对你有帮助的话点个赞支持一下把。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值