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.

[参考译文] TM4C1294KCPDT:FPU float 指令

Guru**** 2558250 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/784249/tm4c1294kcpdt-fpu-float-directive

器件型号:TM4C1294KCPDT

数据表指出 、默认情况下禁用 FPU、并需要以下代码来启用 FPU 指令。 为了执行 float 指令语法、当(float)指令看起来调用 eabi.lib 的一部分时、CCS 编译器如何以及为什么不抛出异常?  遇到编译的 float 指令并且 CCS 调试在 float 变量中显示浮点十进制时、运行时应用程序如何不会对 MCU 产生故障?

3.1.5.7启用 FPU
FPU 复位时被禁用。 必须先启用它、然后才能使用任何浮点指令。 处理器必须处于特权模式才能读取和写入协处理器访问控制(CPAC)寄存器。 下面的示例代码序列在特权和用户模式下启用 FPU。

;CPACR 位于地址0xE000ED88
LDR.W R0,=0xE000ED88
;读取 CPACR
LDR R1,[R0]
;设置位20-23以启用 CP10和 CP11协处理器
ORR R1、R1、#(0xF <<20)
;将修改后的值写回 CPACR
STR R1,[R0]; 等待存储完成
DSB
;现在已启用 FPU
ISB 

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

    您好 BP101:

     编译器不知道您是否启用了 FPU、或者处理器是否具有内置 FPU。 在编译器设置中、您可能已指定 FPv4SPD16支持 FPU、因此编译器将使用 FPU 生成代码。 在 boot.asm 代码中、硬件 FPU 在应用程序运行前被启用。 请参阅 boot.asm 的以下片段。

    .if __TI_ARM_V7M__|__TI_ARM_V6M0__
    thumbfunc _c_int00
    其他
    .armfunc _c_int00
    .endif


    ;在不同 ABI 中容纳不同的低名称

    .if __TI_EABI_ASSEMBLER
    .asg _system_pre_init、pre_init_rtn
    .asg __TI_auto_init、Auto_init_RTN
    .asg _args_main、args_main_RTN
    .asg 退出、EXIT_RTN
    .asg main_func_sp、main_FUNC_SP
    .else;COFF TI ARM9 ABI
    .asg __system_pre_init、pre_init_rtn
    .asg __TI_auto_init、auto_init_RTN;注意不使用 COFF 前缀
    .asg __args_main、args_main_RTN
    .asg _exit、exit_rtn
    .asg _main_func_sp、main_FUNC_SP
    .endif

    如果.TMS470_16BIS


    ;* 16位状态引导例程*

    .if __TI_ARM_V7M__|__TI_ARM_V6M0__
    Thumb
    其他
    ARM
    .endif

    .global __stack
    ;*********
    ;*定义用户模式堆栈(默认大小为512)
    ;*********
    _stack:.usect ".stack"、0、4

    全局_c_int00

    ;*********
    ;*函数 DEF:_c_int00
    ;*********
    c_int00:.asmfunc stack_usage (0)

    if!__TI_ARM_V7M__&!__TI_ARM_V6M0__
    .if __TI_NENEL_support__|__TI_VFP_support__
    ;*--------------------------------------------------
    ;*设置对协处理器的特权和用户模式访问
    ;* 10和11,需要启用 NED/VFP
    ;*协处理器访问控制寄存器
    ;*位[23:22]- CP11、[21:20]- CP10
    ;*设置为0b11以启用用户和 PRIV 模式访问
    ;*--------------------------------------------------
    MRC P15、#0x0、r0、c1、c0、#2
    MOV R3、#0xf00000
    ORR r0、r0、r3
    MCR P15、#0x0、r0、c1、c0、#2

    ;*--------------------------------------------------
    ;将 EN 位置位,FPEXC[30]以启用 NEON 和 VFP
    ;*--------------------------------------------------
    MOV r0、#0x40000000
    FMXR FPEXC、r0
    endif;__TI_NENEL_support__|__TI_VFP_support__

    ;------------------------------------------------
    ;*设置为用户模式
    ;*--------------------------------------------------
    R0夫人、CPSR
    BIC r0、r0、#0x1F;清除模式
    ORR r0、r0、#0x10;设置用户模式
    MSR CPSR_CF、r0

    ;*--------------------------------------------------
    ;*更改为16位状态
    ;*--------------------------------------------------
    添加 r0、pc、#1
    BX r0

    Thumb
    其他;!_TI_ARM_V7M 和!_TI_ARM_V6M0
    .if __TI_TMS470_V7M4__和__TI_VFP_support__
    Thumb
    ;*--------------------------------------------------
    ;*设置对协处理器10和11的完全访问,
    ;*对于 FP 是必需的。 协处理器访问控制寄存器
    ;*位[23:22]- CP11、[21:20]- CP10
    ;*设置为0b11以启用完全访问
    ;*--------------------------------------------------
    cpacr .set 0xE000ED88;CAPCR 地址
    MOVW R1、#cpacr 和0xFFFF
    MOVT R1、#cpacr >> 16.
    LDR r0、[ R1 ]
    MOV R3、#0xf0
    ORR r0、r0、r3、LSL #16
    STR r0、[ R1 ]
    Thumb
    endif;__TI_TMS470_V7M4__和__TI_VFP_support__
    endif;!__TI_ARM_V7M &!__TI_ARM_V6M0__

    ;*--------------------------------------------------
    ;*初始化用户模式堆栈
    ;*--------------------------------------------------
    .if __TI_deve_embedded_constants
    Thumb
    MOVW r0、__stack
    MOVT r0、__堆栈
    MOV sp、r0
    MOVW r0、__STACK_SIZE
    MOVT r0、__STACK_SIZE
    Thumb
    否则;__TI_evee_embedded_constants
    LDR r0、c_stack
    MOV sp、r0
    LDR r0、c_stack_size
    endif;__TI_evee_embedded_constants
    添加 sp、r0

    ;*------------------------------------------------
    ;*如果是 EABI,则将堆栈对齐到64位。
    ;*------------------------------------------------
    .if __TI_EABI_ASSEMBLER
    MOV r7、sp
    MOV r0、#0x07
    bics r7、r0;清除高3位以进行64位对齐。
    MOV sp、r7
    .endif

    ;*------------------------------------------------
    ;*保存当前堆栈指针以进行 SDP 分析
    ;*------------------------------------------------
    .if __TI_deve_embedded_constants
    Thumb
    MOVW r0、MAIN_FUNC_SP
    MOVT r0、MAIN_FUNC_SP
    Thumb
    其他
    LDR r0、c_mf_sp
    .endif
    MOV r7、sp
    STR r7、[r0]

    ;*--------------------------------------------------
    ;*调用__mpu_init 挂钩函数。
    ;*--------------------------------------------------
    BL _MPU_init

    ;*--------------------------------------------------
    ;*在时执行所有必需的初始化
    ;*_system_pre_init()返回非零:
    ;*-处理 BINIT 表
    ;*-执行 C 自动初始化
    ;*-调用全局构造函数
    ;*--------------------------------------------------
    BL pre_init_rtn
    CMP R0、#0
    BEQ BYPASS_auto_init
    BL AUTO_INIT_RTN
    BYPASS_auto_init:

    ;*--------------------------------------------------
    ;*调用应用程序
    ;*--------------------------------------------------
    BL args_main_RTN

    ;*--------------------------------------------------
    ;*如果应用程序没有调用 exit,则调用 exit (1)
    ;*--------------------------------------------------
    MOV r0、#1
    BL exit_RTN

    ;*--------------------------------------------------
    ;*完成,循环永远
    ;*--------------------------------------------------
    L1:B L1
    endasmfunc

    else;!.tms470_16BIS


    ;* 32位状态引导例程*

    .global __stack
    ;*********
    ;*定义用户模式堆栈(默认大小为512)
    ;*********
    _stack:.usect ".stack"、0、4

    全局_c_int00
    ;*********
    ;*函数 DEF:_c_int00
    ;*********
    c_int00:.asmfunc stack_usage (0)

    .if __TI_NENEL_support__|__TI_VFP_support__
    ;*--------------------------------------------------
    ;*设置对协处理器的特权和用户模式访问
    ;* 10和11,需要启用 NED/VFP
    ;*协处理器访问控制寄存器
    ;*位[23:22]- CP11、[21:20]- CP10
    ;*设置为0b11以启用用户和 PRIV 模式访问
    ;*--------------------------------------------------
    MRC P15、#0x0、r0、c1、c0、#2
    MOV R3、#0xf00000
    ORR r0、r0、r3
    MCR P15、#0x0、r0、c1、c0、#2

    ;*--------------------------------------------------
    ;将 EN 位置位,FPEXC[30]以启用 NEON 和 VFP
    ;*--------------------------------------------------
    MOV r0、#0x40000000
    FMXR FPEXC、r0
    .endif

    ;*--------------------------------------------------
    ;*设置为用户模式
    ;*--------------------------------------------------
    R0夫人、CPSR
    BIC r0、r0、#0x1F;清除模式
    ORR r0、r0、#0x10;设置用户模式
    MSR CPSR_CF、r0

    ;*--------------------------------------------------
    ;*初始化用户模式堆栈
    ;*--------------------------------------------------
    .if __TI_deve_embedded_constants
    MOVW sp、__STACK
    MOVT sp、__STACK
    MOVW r0、__STACK_SIZE
    MOVT r0、__STACK_SIZE
    其他
    LDR sp、c_stack
    LDR r0、c_stack_size
    .endif
    添加 sp、sp、r0

    ;*------------------------------------------------
    ;*如果是 EABI,则将堆栈对齐到64位。
    ;*------------------------------------------------
    .if __TI_EABI_ASSEMBLER
    BIC sp、sp、#0x07;清除高3位以进行64位对齐。
    .endif

    ;*------------------------------------------------
    ;*保存当前堆栈指针以进行 SDP 分析
    ;*------------------------------------------------
    .if __TI_deve_embedded_constants
    MOVW r0、MAIN_FUNC_SP
    MOVT r0、MAIN_FUNC_SP
    其他
    LDR r0、c_mf_sp
    .endif
    str sp、[r0]

    ;*--------------------------------------------------
    ;*调用__mpu_init 挂钩函数。
    ;*--------------------------------------------------
    BL _MPU_init

    ;*--------------------------------------------------
    ;*在时执行所有必需的初始化
    ;*_system_pre_init()返回非零:
    ;*-处理 BINIT 表
    ;*-执行 C 自动初始化
    ;*-调用全局构造函数
    ;*--------------------------------------------------
    BL pre_init_rtn
    CMP R0、#0
    BEQ BYPASS_auto_init
    BL AUTO_INIT_RTN
    BYPASS_auto_init:

    ;*--------------------------------------------------
    ;*调用应用程序
    ;*--------------------------------------------------
    BL args_main_RTN

    ;*--------------------------------------------------
    ;*如果应用程序没有调用 exit,则调用 exit (1)
    ;*--------------------------------------------------
    MOV R0、#1
    BL exit_RTN

    ;*--------------------------------------------------
    ;*完成,循环永远
    ;*--------------------------------------------------
    L1:B L1
    endasmfunc

    endif;!.tms470_16BIS

    ;*********
    ;*此模块使用的常量
    ;*********
    if!_TI_Avee_embedded_constants
    c_stack .long __stack
    c_stack_size .long __stack_size
    c_mf_sp .long main_FUNC_SP
    .endif

    .if __TI_EABI_ASSEMBLER
    .data
    对齐4.
    stkchk_called:
    .field 0.32.
    其他
    .sect ".cinit"
    对齐4.
    .field 4、32
    .field _stkchk_called + 0、32
    .field 0.32.

    .bss _stkchk_called、4、4
    .symdepend ".cinit"、".bss"
    .symdepend ".cinit"、".text"
    .symdepend ".bss"、".text"
    .endif

    ;'********
    ;*未定义的引用*
    ;'********
    全局_stkchk_called
    .global __stack_size
    全局 pre_init_rtn
    全局 AUTO_INIT_RTN
    全局 args_main_RTN
    全局 main_FUNC_SP
    全局 EXIT_RTN
    .global __MPU_init

    .end

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

    为上面的脚本创建(startup_ccs.s)[LDR.W]生成非法操作数错误。

    ;
    ;
    ;;;;;将汇编器置于正确的配置中。
    ;
    ;;
    经验
    
    ;/
    ;;* FPU 在复位时被禁用。 在使用任何浮点指令之前启用它。
    ;;*处理器必须处于特权模式才能读取和写入协处理器访问
    ;;*控制(CPAC)寄存器。
    ; /.thumbfunc
    
    EnableFPU
    EnableFPU:.asmfunc
    ; CPACR 位于地址0xE000ED88
    LDR.W R0、0xE000ED88
    ;读取 CPACR
    LDR R1、[R0]
    ;设置位20-23以启用 CP10和 CP11协处理器
    ORR R1、R1、#(0xF << 20)
    ;将修改后的值写回 CPACR
    STR R1、[R0]
    ;等待存储完成
    DSB
    ;重置管道现在启用 FPU
    isb
    .endasmfunc 

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

    为什么不只使用 LDR 而不是 LDR.W?

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

    是为项目启用了 FPv4SPD16支持。 将检查编译日志以查看是否调用了(boot.asm)。 在调试会话期间调用该函数会加载到项目文件视图窗格中。 想知道为什么数据表汇编器中的脚本在编译期间拒绝接受 LDR.W?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 BP101:
    LDR.W 应该强制它是一个32位 Thumb-2指令。 但是、我建议您将您的问题发布到 TI 编译器论坛、为什么不采用 LDR.W、因为这更多是工具问题、而不是 MCU 硬件问题。 同时、请使用 LDR。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    对于 R0 =意外操作数或不=的非法操作数、编译器仍然显示非法操作数错误(LDR)

    您是否想知道数据表第146页的代码中是否有拼写错误?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    据我所知、TI 汇编器中的字面量池不再支持=。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Charles、

    很棒的侦探工作!

     M4v7引用中没有列出此类 Thumb 指令。 但是、如果在编译器高级选项下启用 ASM 列表输出、 则 会编译 float 指令数学(V~~~)。 编译 日志中未生成 boot.asm。 看似 boot.asm FP 部分用于 调试仿真器、以便在"Variables"视图窗格中显示小数点。

    ;*------------------------------------------------------------ *
    .dwpsn文件"./adc_ctrl.c"、行638、列13、is_stmt、ISA 1.
    MOV A1、#0 ;[DPU_3_PIPE]|638|
    VMOV S0、V3 ;[DPU_LIN_BIPE]|638|
    MOVT A1、#17792 ;[DPU_3_PIPE]|638|
    VMOV S1、A1 ;[DPU_LIN_BIPE]|638|
    MOV v4、#0 ;[DPU_3_PIPE]|638|
    VCVT.F32.U32 S0、S0 ;[DPU_LIN_BIPE]|638|
    MOVW A1、#5770 ;[DPU_3_PIPE]|638|
    MOVT A1、#15182 ;[DPU_3_PIPE]|638|
    VMOV S2、A1 ;[DPU_LIN_BIPE]|638|
    MOVT V4、#17327 ;[DPU_3_PIPE]|638|
    VMUL.F32 S0、S1、S0 ;[DPU_LIN_BIPE]|638|
    VMOV S1、V4 ;[DPU_LIN_BIPE]|638|
    VMUL.F32 S0、S2、S0 ;[DPU_LIN_BIPE]|638|
    VCVT.U32.F32 S0、S0 ;[DPU_LIN_BIPE]|638|
    VMOV A1、S0 ;[DPU_LIN_PIPE]|638|
    .dwpsn文件"../adc_ctrl.c",行641,列13,is_stmt,ISA 1.
    MOV LR、#0 ;[DPU_3_PIPE]|641|
    .dwpsn文件"../adc_ctrl.c",第638行,第13列,is_stmt,ISA 1.
    VMOV S0、A1 ;[DPU_LIN_PIPE]|638|
    .dwpsn文件"../adc_ctrl.c",行641,列13,is_stmt,ISA 1.
    STRH LR、[A4、#0] ;[DPU_3_PIPE]|641|
    .dwpsn文件"../adc_ctrl.c",第638行,第13列,is_stmt,ISA 1.
    VCVT.F32.U32 S0、S0 ;[DPU_LIN_PIPE]|638|
    .dwpsn文件"../adc_ctrl.c",第635行,第13列,is_stmt,ISA 1.
    STRH V3、[A2、#0] ;[DPU_3_PIPE]|635|
    .dwpsn文件"../adc_ctrl.c",第638行,第13列,is_stmt,ISA 1.
    VSUB.F32 S1、S0、S1 ;[DPU_LIN_PIPE]|638|
    .dwpsn文件"../adc_ctrl.c",行641,列13,is_stmt,ISA 1.
    B ||$C$L13|| ;[DPU_3_PIPE]|641|
    ;分支发生{||$C$L13||} ;[]|641|
    ;*------------------------------------------------------- 

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

    您好、Charles、

    有一种更简单的方法  可以通过 Tivaware 调用来启用 FPU。 尽管 CCS 已编译并输出 FPU 汇编器结果、但我们似乎仍需要在 MCU 中启用 FPU。 当 FPU 尚未启用时、CPU 可能会忽略应用程序中的 float 指令?

    /*启用 NVIC 浮点单元,FPU */
    MAP_FPUEnable();
    
    /*浮点状态不会保存在中断条目上*/
    MAP_FULazyStackingEnable();