在 STM32 上使用 C++ 指南

论坛 期权论坛 期权     
RTThread物联网操作系统   2019-6-16 21:53   926   0
简介

本文描述了如何使用在搭载了 RT-Thread 系统的 STM32 平台上使用 C++,包括 C++ 的配置和应用等。并给出了在意法半导体 STM32F411 nucleo 开发板上验证的代码示例。

[h1][/h1]硬件平台简介
本文基于意法半导体
  1. STM32F411 nucleo
复制代码
开发板,给出了
  1. C++
复制代码
的具体应用示例代码,由于
  1. RT-Thread
复制代码
上层应用
  1. API
复制代码
的通用性,因此这些代码不局限于具体的硬件平台,用户可以轻松将它移植到其它平台上。
  1. STM32F411 nucleo
复制代码
是意法半导体推出的一款基于
  1. ARM Cortex-M4
复制代码
内核的开发板,最高主频为
  1. 100Mhz
复制代码
,该开发板具有丰富的板载资源,可以充分发挥
  1. STM32F411RE
复制代码
的芯片性能。


[h1][/h1][h1]如何在
  1. STM32
复制代码
上使用
  1. C++
复制代码
[/h1]
准备工作

1、下载 RT-Thread 源码
2、下载 ENV 工具
3、进入
  1. rt-thread\bsp\stm32f411-st-nucleo
复制代码
目录,检查 BSP
  1. rtconfig.py
复制代码
文件和
  1. SConstruct
复制代码
文件是否支持
  1. C++
复制代码
配置,如下图所示

检查
  1. rtconfig.py
复制代码
文件中对
  1. C++
复制代码
的支持


检查
  1. SConstruct
复制代码
文件中对
  1. C++
复制代码
的支持


打开
  1. C++
复制代码
支持:
  • 打开
    1. Env
    复制代码
    工具,在
    1. Env
    复制代码
    命令行中输入
    1. menuconfig
    复制代码
    ,进入配置界面,使用
    1. menuconfig
    复制代码
    工具(学习如何使用)配置工程。在
    1. menuconfig
    复制代码
    配置界面依次选择
    1. RT-Thread Components ---> C++ features ---> Support C++ features
    复制代码
    ,如图所示:



编译工程:
  1. scons --target=mdk5
复制代码
1. 生成
  1. mdk5
复制代码
工程,将示例代码附带的
  1. main.cpp
复制代码
替换掉
  1. BSP
复制代码
中的
  1. main.c
复制代码
并重新加入到工程中,如图所示:


  • 编译,下载程序,在终端输入
    1. help
    复制代码
    命令可以看到
    1. test_cpp
    复制代码
    已经添加成功了。



  • 运行
    1. C++
    复制代码
    程序:

在终端输入
  1. test_cpp
复制代码
运行结果如下图所示。



C++ 全局对象构造函数的调用
  1. RT-Thread
复制代码
中对全局对象构造函数的实现中,以
  1. GNUC
复制代码
为例,在
  1. rt-thread\components\cplusplus
复制代码
目录下的
  1. crt_init.c
复制代码
文件中对
  1. C++
复制代码
进行了系统初始化, 在特定的
  1. BSP
复制代码
目录下,连接脚本文件
  1. link.lds
复制代码
  1. C++
复制代码
全局构造函数的代码分配了段,使
  1. C++
复制代码
全局对象构造函数链接后能够存放在指定的段中。如下图所示:

  1. crt_init.c
复制代码
文件完成了
  1. C++
复制代码
系统的初始化工作
  1. C++
复制代码
系统初始化部分:
  1. 1RT_WEAK int cplusplus_system_init(void) 2{ 3    typedef void(*pfunc)(); 4    extern pfunc __ctors_start__[]; 5    extern pfunc __ctors_end__[]; 6    pfunc *p; 7 8    for (p = __ctors_start__; p < __ctors_end__; p++) 9        (*p)();1011    return 0;12}13INIT_COMPONENT_EXPORT(cplusplus_system_init);
复制代码
  1. cplusplus_system_init
复制代码
函数中,将全局对象的构造函数依次链接到了链接脚本文件中为其分配的段中,并且调用了
  1. RT-Thread
复制代码
组件自动初始化的宏
  1. INIT_COMPONENT_EXPORT
复制代码
,所以在链接的时候,
  1. C++
复制代码
全局对象构造函数所产生的目标文件就被链接到了
  1. __ctors_start__
复制代码
  1. __ctors_end__
复制代码
组成的段中。
链接脚本中为
  1. C++
复制代码
全局构造函数分配的段部分:
  1. 1PROVIDE(__ctors_start__ = .);2KEEP (*(SORT(.init_array.*)))3KEEP (*(.init_array))4PROVIDE(__ctors_end__ = .);
复制代码
  1. __ctors_start__
复制代码
分配了
  1. C++
复制代码
全局构造函数段的起始地址,
  1. __ctors_end__
复制代码
分配了
  1. C++
复制代码
全局构造函数段的结束地址,所以全局构造函数在系统初始化的时候,就会被链接到这里分配的段地址中。
[h1]RT-Thread C++ 异常说明[/h1]
同样,在链接脚本文件
  1. link.lds
复制代码
中,也为
  1. C++
复制代码
异常分配了段地址:
  1. 1    __exidx_start = .;2    ARM.exidx :3    {4        *(.ARM.exidx* .gnu.linkonce.armexidx.*)5        _sidata = .;6    } > CODE7    __exidx_end = .;
复制代码
  1. __exidx_start
复制代码
分配了
  1. C++
复制代码
异常的起始地址,
  1. __exidx_end
复制代码
分配了
  1. C++
复制代码
异常的结束地址,当异常产生的时候,就会被分配到指定的段地址中.
这里以一个
  1. C++
复制代码
除零异常的抛出和捕获为例:
  1. 1   #include 2 3    #define MIN_VALUE                 (1e-4)                           4    #define IS_DOUBLE_ZERO(d)         (abs(d) < MIN_VALUE) 5 6    double div_func(double x, double y)                      7    { 8        if (IS_DOUBLE_ZERO(y)) 9        {10            throw y;                                           /* throw exception */11        }1213        return x / y;                                  14    }1516    void throw_exceptions(void *args)17    {18        try                                            19        {20            div_func(6, 3);21            rt_kprintf("there is no err\n");22            div_func(4, 0);                                   /* create exception*/23            rt_kprintf("you can run here?\n");24        }25        catch(double)                                         /* catch exception */     26        {27            rt_kprintf("error of dividing zero\n");28        }29    }3031    MSH_CMD_EXPORT(throw_exceptions, throw cpp exceptions);
复制代码
当除零异常发生的时候
  1. div_func
复制代码
函数会抛出一个异常,在
  1. throw_exceptions
复制代码
函数中会去捕获这个异常。
下载代码,并在终端输入
  1. throw_exceptions
复制代码
运行结果如下图所示。


到这一步为止,如何在搭载了
  1. RT-Thread
复制代码
系统的
  1. STM32
复制代码
平台上如何使用
  1. C++
复制代码
的介绍就结束了。
参考资料
1、ENV 用户手册
https://www.rt-thread.org/document/site/programming-manual/env/env/

2、STM32F411-ST-NUCLEO BSP 源码
https://github.com/RT-Thread/rt-thread/tree/master/bsp/stm32/stm32f411-st-nucleo

(请将以上链接复制至外部浏览器打开)




NOW现在行动!


近期活动

RT-Thread线上活动


1、RT-Thread企业人才服务计划:只要加入该人才计划,即可对接睿赛德科技的人才库,得到人才的推荐和人才评估指导,且每年可以接受一次RT-Thread官方提供的OS专业培训。




企业扫码进入官网



2、欢迎开发者们加入RT-Thread 人才库,我们将会为你个性化推荐来自中国移动、ST、许继、格力、博通集成、富翰微、东软载波、欧瑞博、海康、利尔达、灵动微、Cypress等顶级公司职位,为你创造更好的职业发展空间!




个人可申请加入人才库


#题外话# 喜欢RT-Thread不要忘了在GitHub上留下你的星

哦,你的star对我们来说非常重要!链接地址:https://github.com/RT-Thread/rt-thread






你可以添加微信18917005679为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流

RT-Thread

让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。Apache2.0协议,可免费在商业产品中使用,不需要公布源码,无潜在商业风险。
长按二维码,关注我们

点击“阅读原文”进入RT-Thread官网!
喜欢就点击“在看”
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP