打印

用C++开发STM32,解决了中断向量问题

[复制链接]
12117|41
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
McuPlayer|  楼主 | 2013-7-8 01:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近喜欢上了C++开发STM32,C++语法上基本是C的扩展,所以习惯用C的人所有的知识和代码可以继续发挥作用。
另外,C++的OO编程,代码架构更接近人的思考模式,即使我们不需要OO编程,代码的可维护性也好了很多。

但若要完全C++开发,遇到的问题是中断向量的问题,用C来包装一个C++ 函数的方式可以解决,但似乎有些不爽。
中断向量,就是函数入口地址,这个C++的静态函数可以对应起来。

我们可以从map文件中,把中断向量的一个个的C++函数的入口地址符号找到,写入startup文件中。
但C++的symbol不像C语言那么简洁了,而且可能随着源代码的编辑而改变,包括函数的顺序,函数的返回值,函数的参数等。
_ZN10CInterrupt15TIM3_IRQHandlerEv 看看这个符号,是不是很别扭,C语言的Symbol就一个TIM3_IRQHandler,跟函数名完全相同。

这时候,我们应该尽量不要在汇编程序中写向量表,而是到C++文件中写向量表了。

沙发
McuPlayer|  楼主 | 2013-7-8 01:29 | 只看该作者
这是修改的的startup.s文件
-----------------------------华丽丽的分界线---------------------------------------------------

Stack_Size      EQU     0x00000800

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp
__initial_sp_ex

Heap_Size       EQU     0x00000400

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit


                EXPORT  __initial_sp_ex
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
__Vectors            EQU        0x08006000
__Vectors_End        EQU        0x08006040
__Vectors_Size        EQU        0x40


                PRESERVE8
                THUMB

                AREA    |.text|, CODE, READONLY

; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
     IMPORT  __main
     IMPORT  SystemInit
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP


;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
                 IF      :DEF:__MICROLIB           
               
                 EXPORT  __initial_sp
                 EXPORT  __heap_base
                 EXPORT  __heap_limit
               
                 ELSE
               
                 IMPORT  __use_two_region_memory
                 EXPORT  __user_initial_stackheap
                 
__user_initial_stackheap

                 LDR     R0, =  Heap_Mem
                 LDR     R1, =(Stack_Mem + Stack_Size)
                 LDR     R2, = (Heap_Mem +  Heap_Size)
                 LDR     R3, = Stack_Mem
                 BX      LR

                 ALIGN

                 ENDIF

                 END

使用特权

评论回复
板凳
McuPlayer|  楼主 | 2013-7-8 01:32 | 只看该作者
这个是Interrupt.hpp文件,可根据需要增添,可以把所有的ISR函数都挂上去,也可以只写自己需要的

class CInterrupt
{
public:
        static void USB_LP_CAN1_RX0_IRQHandler();
        static void TIM3_IRQHandler();
};

使用特权

评论回复
地板
McuPlayer|  楼主 | 2013-7-8 01:35 | 只看该作者
这个是Interrupt.cpp文件,包括2个成员函数的实现
------------------------------------------------------------------------------
void CInterrupt::USB_LP_CAN1_RX0_IRQHandler()
{
        if(!g_bInterruptPause)        AndyUSB.USB_Istr();
}
void CInterrupt::TIM3_IRQHandler()
{
        if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
        {
                TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
               
                g_nNowTime++;
               
//                if(0==(g_nNowTime%2))
                {
                        AndyHW.HwCallBackKeyScan();
                }
                AndyHW.HwCallBackOverCurrent();
                AndyOS.sysCallBackTimer10ms();   //10mS
        }
}

使用特权

评论回复
5
McuPlayer|  楼主 | 2013-7-8 01:42 | 只看该作者
下面的这个部分,可以写在Interrupt.cpp文件中,也可单独写一个CPP文件。
-----------------------------------------------------------------------------------------------------------------------------


#ifdef __cplusplus
extern "C" {
#endif

void __initial_sp_ex(void);
void Reset_Handler(void);

#ifdef __cplusplus
}
#endif

void Default_Handler(void);

typedef void(* const ISR_t)(void);

ISR_t IsrVector[] __attribute__ ((section("RESET"))) =
{
                __initial_sp_ex,
                Reset_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                0,
                0,
                0,
                0,
                Default_Handler,
                Default_Handler,
                0,
                Default_Handler,
                Default_Handler,


                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                CInterrupt::USB_LP_CAN1_RX0_IRQHandler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                CInterrupt::TIM3_IRQHandler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler,
                Default_Handler
};

void Default_Handler(void)
{
    while (1);
}


使用特权

评论回复
6
McuPlayer|  楼主 | 2013-7-8 01:47 | 只看该作者
不过有些遗憾的是,STM32的FwLib没有C++版本的,不过C++和C混合使用,没问题的
ST提供的h文件中全加入了兼容C和C++的宏处理
#ifdef __cplusplus
extern "C" {
#endif

当转到C++后,就可以使用虚函数来代替一部分函数指针,可读性更好。
MDK中RVDS编译器,对C++的优化很好,没用到的成员函数会被优化掉,所以如果做平台一定记得对相关的成员函数禁止优化,使用--keep选项

OK,享受C++之旅吧

使用特权

评论回复
7
wangkuo0203| | 2013-7-8 10:52 | 只看该作者
太牛了:handshake

使用特权

评论回复
8
qrshi| | 2013-7-8 12:01 | 只看该作者
mark,有用。

使用特权

评论回复
9
PowerAnts| | 2013-7-8 12:56 | 只看该作者
马屁哥V5, 不过我承认我看不懂

使用特权

评论回复
10
限量_个性。| | 2013-7-8 13:10 | 只看该作者
厉害啊  好好学习 ~

使用特权

评论回复
11
McuPlayer|  楼主 | 2013-7-8 13:41 | 只看该作者
C++不会太臃肿,如果仅仅是使用static成员函数和static成员变量,来实现函数的分门别类管理,有些类似于namespace,那么代码基本和纯C是相当的。
但即使代码会变胖,我仍然使用了C++的一些扩展特性,比如虚函数,多态函数,继承类,代码效率差个10来个点换来的是代码架构的直观化,还有代码的可重用性。
比如一个class你想扩展他的功能,不是直接改代码,而是从他继承一个类,然后增加函数,或者覆盖函数,而不破坏基类代码的完整性,这是开发者多么期待的事啊。

使用特权

评论回复
12
EAMCU| | 2013-7-8 13:48 | 只看该作者
我是用C结构体+指针 模拟C++

使用特权

评论回复
13
McuPlayer|  楼主 | 2013-7-8 13:58 | 只看该作者
不错,我这次全改成C++就是为了处理这个问题
用C的结构体,里面有很多函数指针的那种,我全用class来替代,代码效率会提高。
另外,用虚函数来替代结构体中的函数指针,你不用担心函数指针为空的现象了,因为纯虚函数实现之前,编译器是不允许你实例化的。

使用特权

评论回复
14
reille| | 2013-7-8 14:23 | 只看该作者
嘿嘿,如果在eCos上,那可是小KS了!

使用特权

评论回复
15
youlongltm| | 2013-7-8 20:35 | 只看该作者
NA,NC之间

使用特权

评论回复
16
qq2941070113| | 2013-7-8 20:53 | 只看该作者
顶楼主

使用特权

评论回复
17
dong_abc| | 2013-7-8 21:14 | 只看该作者
楼主能否将你的工程文件共享一下呢? 只要中断向量相关的@@@

使用特权

评论回复
评论
兰小方 2018-3-14 18:35 回复TA
楼主给你没有 求分享 
18
icecut| | 2013-7-8 21:21 | 只看该作者
c++因为不是全功能版本,最后我还是放弃了

使用特权

评论回复
19
呆板书生| | 2013-7-8 21:48 | 只看该作者
观望中

使用特权

评论回复
20
dirtwillfly| | 2013-7-8 21:59 | 只看该作者
收藏。关注中断部分是怎么处理的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:善待今天就是对未来最好的策划。 博客:http://www.mcuplayer.com

338

主题

7307

帖子

26

粉丝