TI E2E™ 设计支持论坛将于 5 月 30 日至 6 月 1 日进行维护。如果您在此期间需要技术支持,请联系 TI 的客户支持中心寻求帮助。

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**** 2048030 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()中断处理程序,该处理程序调用用户提供的处理程序:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 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 */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

Fullscreen
1
2
3
/* USER CODE BEGIN (6) */
void rtiNotification(uint32 notification) __attribute((interrupt));
/* USER CODE END */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

[引用]为 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 寄存器。

    谢谢、此致、

    乔治