This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] ARM-CGT-CLANG-1_1.3.0-BETA.1在调用其他函数的中断函数中保存寄存器

Guru**** 2535150 points
Other Parts Discussed in Thread: RM48L952, HALCOGEN

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/1001592/arm-cgt-clang-1_1-3-0-beta-1-saving-registers-in-interrupt-functions-which-call-other-functions

主题中讨论的其他器件:RM48L952HALCOGEN

附加的项目是一个基于 HALCoGen 的项目、用于 RM48L952、它使用 RTI 中断。 源代码由 HALCoGen 创建、指定"TI 工具"、有两种构建配置:

a.使用 TI ARM v20.2.5的 Debug_TI_ARM_CGT

b.使用 TI ARM Clang v1.3.0的 Debug_TI_clang

添加  Debug_TI_clang 编译配置后、对源代码和链接器命令文件进行了一些调整、以允许编译和运行这两种编译器、 将修改保留在 HALCoGen //用户代码中*/块中,以便在使用 HALCoGen 重新生成驱动程序代码时保留修改。

source/RTI.c 源文件包含以下 HALCoGen 创建的 rtiCompare0Interrupt()中断处理程序,该处理程序调用用户提供的处理程序:

/* USER CODE BEGIN (73) */
/* Work-around for TI ARM CLANG not understanding CODE_STATE and INTERRUPT pragmas */
void rtiCompare0Interrupt(void) __attribute__((target("arm"))) __attribute__((interrupt("IRQ")));
/* USER CODE END */

/** @fn void rtiCompare0Interrupt(void)
*   @brief RTI1 Compare 0 Interrupt Handler
*
*   RTI1 Compare 0 interrupt handler 
*
*/
#pragma CODE_STATE(rtiCompare0Interrupt, 32)
#pragma INTERRUPT(rtiCompare0Interrupt, IRQ)

/* SourceId : RTI_SourceId_022 */
/* DesignId : RTI_DesignId_022 */
/* Requirements : HL_SR95 */
void rtiCompare0Interrupt(void)
{
/* USER CODE BEGIN (74) */
/* USER CODE END */

    rtiREG1->INTFLAG = 1U;
    rtiNotification(rtiNOTIFICATION_COMPARE0);

/* USER CODE BEGIN (75) */
/* USER CODE END */
}

 TI arm v20.2.5编译器为 rtiCompare0Interrupt()生成以下内容,保留浮点寄存器,这大概是因为 TI arm v20.2.5不知道被调用函数是否可以使用浮点寄存器:

865       {
          rtiCompare0Interrupt():
08001660:   E92D500F            push       {r0, r1, r2, r3, r12, r14}
08001664:   EEF8CA10            vmrs       r12, fpexc
08001668:   E92D1000            stmdb      r13!, {r12}
0800166c:   EEF1CA10            vmrs       r12, fpscr
08001670:   E92D1000            stmdb      r13!, {r12}
08001674:   ED2D0B10            vpush      {d0, d1, d2, d3, d4, d5, d6, d7}
869           rtiREG1->INTFLAG = 1U;
08001678:   E30FCC88            movw       r12, #0xfc88
0800167c:   E34FCFFF            movt       r12, #0xffff
08001680:   E3A00001            mov        r0, #1
08001684:   E58C0000            str        r0, [r12]
870           rtiNotification(rtiNOTIFICATION_COMPARE0);
08001688:   EBFFFF9C            bl         rtiNotification
0800168c:   ECBD0B10            vpop       {d0, d1, d2, d3, d4, d5, d6, d7}
08001690:   E8BD1000            ldm        r13!, {r12}
08001694:   EEE1CA10            vmsr       fpscr, r12
08001698:   E8BD1000            ldm        r13!, {r12}
0800169c:   EEE8CA10            vmsr       fpexc, r12
080016a0:   E8BD500F            pop        {r0, r1, r2, r3, r12, r14}
080016a4:   E25EF004            subs       pc, r14, #4

而 TI ARM Clang v1.3.0编译器为 不保留浮点寄存器的 rtiCompare0Interr()生成以下代码:

865       {
          rtiCompare0Interrupt():
08001630:   E92D5C0F            push       {r0, r1, r2, r3, r10, r11, r12, r14}
08001634:   E28DB014            add        r11, r13, #0x14
08001638:   E7C2D01F            bfc        r13, #0, #3
0800163c:   E30FEC88            movw       r14, #0xfc88
08001640:   E3A00001            mov        r0, #1
08001644:   E34FEFFF            movt       r14, #0xffff
869           rtiREG1->INTFLAG = 1U;
08001648:   E58E0000            str        r0, [r14]
870           rtiNotification(rtiNOTIFICATION_COMPARE0);
0800164c:   E3A00001            mov        r0, #1
08001650:   EBFFFFAA            bl         rtiNotification
874       }
08001654:   E24BD014            sub        r13, r11, #0x14
08001658:   E8BD5C0F            pop        {r0, r1, r2, r3, r10, r11, r12, r14}
0800165c:   E25EF004            subs       pc, r14, #4

 TI ARM Clang v1.3.0编译器为  rtiCompare0Interr()对 rtiNotification()的调用生成了"无中断属性的函数调用可能是 clobber interree 的 VFP 寄存器"警告:

Building file: "../source/rti.c"
Invoking: Arm Compiler
"C:/ti/ccs1030/ccs/tools/compiler/ti-cgt-armllvm_1.3.0-beta.1/bin/tiarmclang.exe" -c -march=armv7r -mcpu=cortex-r4 -mfloat-abi=hard -mfpu=vfpv3-d16 -mlittle-endian -marm -O2 -I"C:/Users/mr_halfword/E2E_example_projects/RM48L952_rtiblinky" -I"C:/Users/mr_halfword/E2E_example_projects/RM48L952_rtiblinky/include" -I"C:/ti/ccs1030/ccs/tools/compiler/ti-cgt-armllvm_1.3.0-beta.1/include" -D_INLINE -gdwarf-3 -Werror=ti-intrinsics -fno-short-wchar -fcommon -ffunction-sections -MMD -MP -MF"source/rti.d_raw" -MT"source/rti.o" -std=gnu90  -o"source/rti.o" "../source/rti.c"
In file included from ../source/rti.c:54:
In file included from C:/Users/mr_halfword/E2E_example_projects/RM48L952_rtiblinky/include\rti.h:53:
In file included from C:/Users/mr_halfword/E2E_example_projects/RM48L952_rtiblinky/include/reg_rti.h:52:
C:/Users/mr_halfword/E2E_example_projects/RM48L952_rtiblinky/include/sys_common.h:95:9: warning: __little_endian__ is a legacy TI macro that is not defined in clang compilers and will evaluate to 0, use '!defined(__ARM_BIG_ENDIAN)' instead [-Wti-macros]
#ifndef __little_endian__
        ^
../source/rti.c:858:9: warning: pragma CODE_STATE is a legacy TI pragma and not supported in clang compilers. use '__attribute__((target("code_state")))' instead [-Wti-pragmas]
#pragma CODE_STATE(rtiCompare0Interrupt, 32)
        ^
../source/rti.c:859:9: warning: pragma INTERRUPT is a legacy TI pragma and not supported in clang compilers. use '__attribute__((interrupt("int_kind")))' instead [-Wti-pragmas]
#pragma INTERRUPT(rtiCompare0Interrupt, IRQ)
        ^
../source/rti.c:870:5: warning: call to function without interrupt attribute could clobber interruptee's VFP registers [-Wextra]
    rtiNotification(rtiNOTIFICATION_COMPARE0);
    ^
4 warnings generated.
Finished building: "../source/rti.c"

该警告建议为安全起见,应 将名为 rtiNotification()的函数标记为中断函数。 但是、在尝试使用 include/rti.h 中的以下内容时、程序不再正常运行:

/* USER CODE BEGIN (6) */
void rtiNotification(uint32 notification) __attribute((interrupt));
/* USER CODE END */

原因是为 函数指定了中断属性:

[引用]为 Arm Cortex-R 处理器进行编译时、编译器将生成代码以保留通用寄存器、并生成一系列指令以影响处理器的适当异常返回[/引用]

发生这种情况时 ,rtiCompare0Interr()和 rtiNotification()都被标记为中断函数:

a. rtiCompare0Interrupt() 是从 IRQ 中调用的。

b. rtiCompare0Interr()被称为 rtiNotification()。

c.当 rtiNotification()尝试返回时,由于已被标记为中断,编译器生成的结束尝试执行异常返回时,重新输入函数,然后处理器将其全部时间都用在 rtiNotification()函数中。

对于 TI ARM Clang v1.3.0编译器、当调用具有未知副作用的函数时、调用其他函数以保留 VFP 寄存器的中断处理程序的正确方法是什么?

从 ARM 上的中断调用非中断函数时、我发现警告 、这似乎是 在 LLVM 中添加了"调用不带中断属性的函数可能是 clobber interree 的 VFP 寄存器"警告时、 但是 、如果中断函数调用其他函数、获得与 TI ARM v20.2.5相同的行为并保留 VFP 寄存器(出于安全考虑)的正确方法是什么?

此外、 "call to function without interrupt attribute can clobber interruptee 的 VFP 寄存器"的文本会引起一些误解、因为向被调用函数添加中断属性会破坏代码。

e2e.ti.com/.../6470.RM48L952_5F00_rtiblinky.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    有关 pragma 和属性的 tiarmclang 文档中 ,它声明...

     tiarmclang 编译器不会生成代码以在标有 中断 属性的函数中保留 FPU 寄存器。 如果在中断范围内需要浮点运算、则必须手动保留 FPU 寄存器。

    谢谢、此致、

    乔治