在宏 C 内部或外部定义函数(高中断)

发布于 2024-12-27 13:14:41 字数 5344 浏览 1 评论 0原文

首先,我为我的 PIC 使用 C18 编译器。当我创建像 high_ISR 这样的函数而不进行任何调用时,我的编译器会向其中添加代码,这些代码我只能在反汇编列表视图中看到。这使得我的 high_ISR 函数的周期时间为 160 个周期(但从 C 代码来看它似乎是空的)。

相反,如果我将其定义为宏,则它会清空“秘密”代码。我是否会以某种方式遇到其他函数的问题,导致删除我的编译器秘密放置在那里的代码,它会以其他方式处理这个问题吗?

我的意思是,我希望 ISR 能够更快。 在 ac 文件中编写函数时,有没有办法使 ISR 函数快速运行,我可以以某种方式抑制“秘密代码”吗?

请参阅下面的代码示例:

在 .c 文件中正确创建 high_ISR 函数,但循环时间较长

#pragma interrupt highISR
void highISR(void)
{
    SomeFunction();
}

在我的头文件中创建宏函数(例如 16 个周期的循环时间)

#define FAST_INTERRUPT           \
    void highISR(void)           \
    {                            \
        SomeFunction();          \
    }

只是为了澄清,如果我使用宏,我将其实现为:

#pragma interrupt higISR
    FAST_INTERRUPT

第一个 highISR 声明产生此:

    #pragma interrupt highISR
323: void highISR(void)
 12B12    CFDA     MOVFF 0xfda, 0xfe4
 12B14    FFE4     NOP
 12B16    CFE2     MOVFF 0xfe2, 0xfda
 12B18    FFDA     NOP
 12B1A    CFE9     MOVFF 0xfe9, 0xfe4
 12B1C    FFE4     NOP
 12B1E    CFEA     MOVFF 0xfea, 0xfe4
 12B20    FFE4     NOP
 12B22    CFD9     MOVFF 0xfd9, 0xfe4
 12B24    FFE4     NOP
 12B26    CFDA     MOVFF 0xfda, 0xfe4
 12B28    FFE4     NOP
 12B2A    C1FB     MOVFF 0x1fb, 0xfe4
 12B2C    FFE4     NOP
 12B2E    C1FC     MOVFF 0x1fc, 0xfe4
 12B30    FFE4     NOP
 12B32    C1FD     MOVFF 0x1fd, 0xfe4
 12B34    FFE4     NOP
 12B36    C1FE     MOVFF 0x1fe, 0xfe4
 12B38    FFE4     NOP
 12B3A    CFF6     MOVFF 0xff6, 0xfe4
 12B3C    FFE4     NOP
 12B3E    CFF7     MOVFF 0xff7, 0xfe4
 12B40    FFE4     NOP
 12B42    CFF8     MOVFF 0xff8, 0xfe4
 12B44    FFE4     NOP
 12B46    CFF5     MOVFF 0xff5, 0xfe4
 12B48    FFE4     NOP
 12B4A    CFF3     MOVFF 0xff3, 0xfe4
 12B4C    FFE4     NOP
 12B4E    CFF4     MOVFF 0xff4, 0xfe4
 12B50    FFE4     NOP
 12B52    CFFA     MOVFF 0xffa, 0xfe4
 12B54    FFE4     NOP
 12B56    CFFB     MOVFF 0xffb, 0xfe4
 12B58    FFE4     NOP
 12B5A    EE05     LFSR 0, 0x500
 12B5C    F000     NOP
 12B5E    0E12     MOVLW 0x12
 12B60    04E8     DECF 0xfe8, W, ACCESS
 12B62    E303     BNC 0x12b6a
 12B64    CFEE     MOVFF 0xfee, 0xfe4
 12B66    FFE4     NOP
 12B68    D7FB     BRA 0x12b60
 12B6A    52E6     MOVF 0xfe6, F, ACCESS
324:                    {
325:                        SomeFunction();
 12B6C    EC48     CALL 0x14090, 0
 12B6E    F0A0     NOP
327:                    }
 12B70    52E5     MOVF 0xfe5, F, ACCESS
 12B72    EE05     LFSR 0, 0x511
 12B74    F011     NOP
 12B76    0E12     MOVLW 0x12
 12B78    04E8     DECF 0xfe8, W, ACCESS
 12B7A    E303     BNC 0x12b82
 12B7C    CFE5     MOVFF 0xfe5, 0xfed
 12B7E    FFED     NOP
 12B80    D7FB     BRA 0x12b78
 12B82    CFE5     MOVFF 0xfe5, 0xffb
 12B84    FFFB     NOP
 12B86    CFE5     MOVFF 0xfe5, 0xffa
 12B88    FFFA     NOP
 12B8A    CFE5     MOVFF 0xfe5, 0xff4
 12B8C    FFF4     NOP
 12B8E    CFE5     MOVFF 0xfe5, 0xff3
 12B90    FFF3     NOP
 12B92    CFE5     MOVFF 0xfe5, 0xff5
 12B94    FFF5     NOP
 12B96    CFE5     MOVFF 0xfe5, 0xff8
 12B98    FFF8     NOP
 12B9A    CFE5     MOVFF 0xfe5, 0xff7
 12B9C    FFF7     NOP
 12B9E    CFE5     MOVFF 0xfe5, 0xff6
 12BA0    FFF6     NOP
 12BA2    CFE5     MOVFF 0xfe5, 0x1fe
 12BA4    F1FE     NOP
 12BA6    CFE5     MOVFF 0xfe5, 0x1fd
 12BA8    F1FD     NOP
 12BAA    CFE5     MOVFF 0xfe5, 0x1fc
 12BAC    F1FC     NOP
 12BAE    CFE5     MOVFF 0xfe5, 0x1fb
 12BB0    F1FB     NOP
 12BB2    CFE5     MOVFF 0xfe5, 0xfda
 12BB4    FFDA     NOP
 12BB6    CFE5     MOVFF 0xfe5, 0xfd9
 12BB8    FFD9     NOP
 12BBA    CFE5     MOVFF 0xfe5, 0xfea
 12BBC    FFEA     NOP
 12BBE    CFE5     MOVFF 0xfe5, 0xfe9
 12BC0    FFE9     NOP
 12BC2    CFE5     MOVFF 0xfe5, 0xfda
 12BC4    FFDA     NOP
 12BC6    0011     RETFIE 0x1

第二个函数仅产生此 ->

322:      #pragma interrupt highISR
323:          FAST_INTERRUPT
 13742    CFDA     MOVFF 0xfda, 0xfe4
 13744    FFE4     NOP
 13746    CFE2     MOVFF 0xfe2, 0xfda
 13748    FFDA     NOP
 1374A    52E6     MOVF 0xfe6, F, ACCESS
 1374C    0105     MOVLB 0x5
 1374E    5140     MOVF 0x40, W, BANKED
 13750    1A77     XORWF 0xf77, F, ACCESS
 13752    96A4     BCF 0xfa4, 0x3, ACCESS
 13754    2877     INCF 0xf77, W, ACCESS
 13756    6078     CPFSLT 0xf78, ACCESS
 13758    86A4     BSF 0xfa4, 0x3, ACCESS
 1375A    7E8B     BTG 0xf8b, 0x7, ACCESS
 1375C    0011     RETFIE 0x1
 1375E    52E5     MOVF 0xfe5, F, ACCESS
 13760    CFE5     MOVFF 0xfe5, 0xfda
 13762    FFDA     NOP
 13764    0011     RETFIE 0x1

进一步澄清只是为了表明它们本身的函数是相同的: 对于第一个例行程序->

void SomeFunction(void)
{
    if(PIR3bits.TMR4IF)
    {
        PIR3bits.TMR4IF = 0; 

        PR4 ^= _SoftPWM_Toggle;

        _asm
            INCF PR4,0,ACCESS 
            CPFSLT TMR4,ACCESS 
        _endasm

            PIR3bits.TMR4IF = 1; 

        SOFT_PWM_PIN ^= 1;
    }
}

标头中的第二个作为宏 ->

#define FAST_INTERRUPT \
    void highISR(void) \
    { \
        PR4 ^= _SoftPWM_Toggle; \
        \
        PIR3bits.TMR4IF = 0; \
        \
        _asm \
            INCF PR4,0,ACCESS \
            CPFSLT TMR4,ACCESS \
        _endasm \
        \
            PIR3bits.TMR4IF = 1; \
        \
        SOFT_PWM_PIN ^= 1; \
        \
        _asm \
            RETFIE 1 \
        _endasm \
    }

For starter, Im using the C18 compiler for my PIC. When I create the function like high_ISR without any calls in it, my compiler adds code to it, code I can only see in a Disassembly listing view. This makeing my high_ISR function have a cycle time of say 160 cycles (but it appears to be empty looking at the C code).

Instead if I define it as a macro, I will have it empty of "secret" code. Will I somehow have a problem with other functions cause removing code that my compiler secretly puts there, will it cope with that in other ways?

I mean, I want the ISRs to be fast.
Is there a way to make the ISR function fast when writing the function in a c file, could I somehow supress the "secret code".

See code examples below:

Proper creation of my high_ISR function in a .c file but with a long cycle time

#pragma interrupt highISR
void highISR(void)
{
    SomeFunction();
}

Macro created function for instance in my header file (say cycle time of 16 cycles)

#define FAST_INTERRUPT           \
    void highISR(void)           \
    {                            \
        SomeFunction();          \
    }

Just for clarification, If I use the macro, I implement it as:

#pragma interrupt higISR
    FAST_INTERRUPT

The First highISR declaration produces this:

    #pragma interrupt highISR
323: void highISR(void)
 12B12    CFDA     MOVFF 0xfda, 0xfe4
 12B14    FFE4     NOP
 12B16    CFE2     MOVFF 0xfe2, 0xfda
 12B18    FFDA     NOP
 12B1A    CFE9     MOVFF 0xfe9, 0xfe4
 12B1C    FFE4     NOP
 12B1E    CFEA     MOVFF 0xfea, 0xfe4
 12B20    FFE4     NOP
 12B22    CFD9     MOVFF 0xfd9, 0xfe4
 12B24    FFE4     NOP
 12B26    CFDA     MOVFF 0xfda, 0xfe4
 12B28    FFE4     NOP
 12B2A    C1FB     MOVFF 0x1fb, 0xfe4
 12B2C    FFE4     NOP
 12B2E    C1FC     MOVFF 0x1fc, 0xfe4
 12B30    FFE4     NOP
 12B32    C1FD     MOVFF 0x1fd, 0xfe4
 12B34    FFE4     NOP
 12B36    C1FE     MOVFF 0x1fe, 0xfe4
 12B38    FFE4     NOP
 12B3A    CFF6     MOVFF 0xff6, 0xfe4
 12B3C    FFE4     NOP
 12B3E    CFF7     MOVFF 0xff7, 0xfe4
 12B40    FFE4     NOP
 12B42    CFF8     MOVFF 0xff8, 0xfe4
 12B44    FFE4     NOP
 12B46    CFF5     MOVFF 0xff5, 0xfe4
 12B48    FFE4     NOP
 12B4A    CFF3     MOVFF 0xff3, 0xfe4
 12B4C    FFE4     NOP
 12B4E    CFF4     MOVFF 0xff4, 0xfe4
 12B50    FFE4     NOP
 12B52    CFFA     MOVFF 0xffa, 0xfe4
 12B54    FFE4     NOP
 12B56    CFFB     MOVFF 0xffb, 0xfe4
 12B58    FFE4     NOP
 12B5A    EE05     LFSR 0, 0x500
 12B5C    F000     NOP
 12B5E    0E12     MOVLW 0x12
 12B60    04E8     DECF 0xfe8, W, ACCESS
 12B62    E303     BNC 0x12b6a
 12B64    CFEE     MOVFF 0xfee, 0xfe4
 12B66    FFE4     NOP
 12B68    D7FB     BRA 0x12b60
 12B6A    52E6     MOVF 0xfe6, F, ACCESS
324:                    {
325:                        SomeFunction();
 12B6C    EC48     CALL 0x14090, 0
 12B6E    F0A0     NOP
327:                    }
 12B70    52E5     MOVF 0xfe5, F, ACCESS
 12B72    EE05     LFSR 0, 0x511
 12B74    F011     NOP
 12B76    0E12     MOVLW 0x12
 12B78    04E8     DECF 0xfe8, W, ACCESS
 12B7A    E303     BNC 0x12b82
 12B7C    CFE5     MOVFF 0xfe5, 0xfed
 12B7E    FFED     NOP
 12B80    D7FB     BRA 0x12b78
 12B82    CFE5     MOVFF 0xfe5, 0xffb
 12B84    FFFB     NOP
 12B86    CFE5     MOVFF 0xfe5, 0xffa
 12B88    FFFA     NOP
 12B8A    CFE5     MOVFF 0xfe5, 0xff4
 12B8C    FFF4     NOP
 12B8E    CFE5     MOVFF 0xfe5, 0xff3
 12B90    FFF3     NOP
 12B92    CFE5     MOVFF 0xfe5, 0xff5
 12B94    FFF5     NOP
 12B96    CFE5     MOVFF 0xfe5, 0xff8
 12B98    FFF8     NOP
 12B9A    CFE5     MOVFF 0xfe5, 0xff7
 12B9C    FFF7     NOP
 12B9E    CFE5     MOVFF 0xfe5, 0xff6
 12BA0    FFF6     NOP
 12BA2    CFE5     MOVFF 0xfe5, 0x1fe
 12BA4    F1FE     NOP
 12BA6    CFE5     MOVFF 0xfe5, 0x1fd
 12BA8    F1FD     NOP
 12BAA    CFE5     MOVFF 0xfe5, 0x1fc
 12BAC    F1FC     NOP
 12BAE    CFE5     MOVFF 0xfe5, 0x1fb
 12BB0    F1FB     NOP
 12BB2    CFE5     MOVFF 0xfe5, 0xfda
 12BB4    FFDA     NOP
 12BB6    CFE5     MOVFF 0xfe5, 0xfd9
 12BB8    FFD9     NOP
 12BBA    CFE5     MOVFF 0xfe5, 0xfea
 12BBC    FFEA     NOP
 12BBE    CFE5     MOVFF 0xfe5, 0xfe9
 12BC0    FFE9     NOP
 12BC2    CFE5     MOVFF 0xfe5, 0xfda
 12BC4    FFDA     NOP
 12BC6    0011     RETFIE 0x1

The Second Function only produce this ->

322:      #pragma interrupt highISR
323:          FAST_INTERRUPT
 13742    CFDA     MOVFF 0xfda, 0xfe4
 13744    FFE4     NOP
 13746    CFE2     MOVFF 0xfe2, 0xfda
 13748    FFDA     NOP
 1374A    52E6     MOVF 0xfe6, F, ACCESS
 1374C    0105     MOVLB 0x5
 1374E    5140     MOVF 0x40, W, BANKED
 13750    1A77     XORWF 0xf77, F, ACCESS
 13752    96A4     BCF 0xfa4, 0x3, ACCESS
 13754    2877     INCF 0xf77, W, ACCESS
 13756    6078     CPFSLT 0xf78, ACCESS
 13758    86A4     BSF 0xfa4, 0x3, ACCESS
 1375A    7E8B     BTG 0xf8b, 0x7, ACCESS
 1375C    0011     RETFIE 0x1
 1375E    52E5     MOVF 0xfe5, F, ACCESS
 13760    CFE5     MOVFF 0xfe5, 0xfda
 13762    FFDA     NOP
 13764    0011     RETFIE 0x1

Further more clarification just to show that the functions them self is written the same:
For the first rutine ->

void SomeFunction(void)
{
    if(PIR3bits.TMR4IF)
    {
        PIR3bits.TMR4IF = 0; 

        PR4 ^= _SoftPWM_Toggle;

        _asm
            INCF PR4,0,ACCESS 
            CPFSLT TMR4,ACCESS 
        _endasm

            PIR3bits.TMR4IF = 1; 

        SOFT_PWM_PIN ^= 1;
    }
}

The Second one in header as a macro ->

#define FAST_INTERRUPT \
    void highISR(void) \
    { \
        PR4 ^= _SoftPWM_Toggle; \
        \
        PIR3bits.TMR4IF = 0; \
        \
        _asm \
            INCF PR4,0,ACCESS \
            CPFSLT TMR4,ACCESS \
        _endasm \
        \
            PIR3bits.TMR4IF = 1; \
        \
        SOFT_PWM_PIN ^= 1; \
        \
        _asm \
            RETFIE 1 \
        _endasm \
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我是有多爱你 2025-01-03 13:14:41

我不认为它在你的运行时是垃圾。请记住,中断可能发生在主线代码中的任何位置。当您从中断返回时,您希望代码能够恢复到其停止时的相同状态。编译器添加的是在 ISR 开始时保存该状态的代码,然后在中断结束时恢复该状态。如果它不这样做,并且您修改了主线代码正在使用的 ISR 中的寄存器或内存位置,那么当 ISR 返回时,代码很可能不会按预期执行。通过消除编译器生成的代码,您已将保存并恢复主线代码状态的责任移交给 ISR。如果你能保证你会没事(一个空的 ISR 就是一个例子,它永远不会改变状态)。如果不能,当您从 ISR 返回主线代码时,将会发生奇怪的代码执行。如果您使用的是高级编译语言,则很难知道它在幕后使用的是什么,因此让编译器为您生成状态保存代码 ISR 比您自己尝试更安全。

我建议您查看 MPLAB® C18 C 编译器用户指南文档。 #pragma interupt 指令还有其他参数,允许您在某种程度上自定义保存哪些状态信息。

I don't think its garbage in your runtime. Remember that an interrupt can occur anywhere in your main line code. When you return from the interrupt, you would expect your code to pick up in the same state where it left off. What the compiler is adding is code to save that state at the start of the ISR and then restore the state at the end of the interrupt. If it does not do that, and you modify a register or memory location in the ISR that the main line code was using, then odds are good that the code is not going to execute as exepected when the ISR returns. By elminating the compiler generated code, you have turned over the resposibility to your ISR to save, and then restore, the state of the mainline code. If you can gurantee that you will be ok (an empty ISR would be an example, it never changes the sate). If you can not, weird code execution is going to happen when you return to the main line code from the ISR. If you are using a high level compiled language, its hard to know what it is using under the covers, so having the compiler generate the state saving code for you ISR is safer than trying to do it on your own.

I suggest you take a look in the MPLAB® C18 C Compiler User’s Guide docs. There are aditional parameters to the #pragma interupt directive that allow you to somewhat customize what state information gets saved.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文