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.

Undefined Instruction (Floating point operation)

Other Parts Discussed in Thread: HALCOGEN

Hi,

Stumbled on a ARM exception... When attempting to cast a short (16-byte integer) to a float, like so:

short aShort = 12;

float aFloat = (float) aShort;

On the second line, we get a "Undefined Instruction"... But we've checked the settings for the project, and the instructions given to the compiler, and floating point support should be enabled!

Here is a screenshot of the settings used:

Any idea why we can't cast to a float?

Edit : It's currently happening using the Hercules Development Kit

  • The error message you cite, 'Undefined instruction' is weird.  But I would say that you cannot declare a global variable with a non-constant value.  When I do this:

    short a=12;
    float x = (float)a;
    void main(void)
    {
    }

    I get an "expression must have a constant value" error for the float x line.  Makes sense, since the initialization table for globals (.cinit section) has to have constants in it.

    Initialize your global in your own code instead:

    short a=12;
    float x;
    void main(void)
    {
         x = (float)a;
    }

     

    Regards,

    David

     

  • My "example" was just to illustrate what I was trying to do... It's all inside a function... Actually, the "short" variable is a value read from a peripheral (I2C in this instance). However, I need to cast this value in float in order to do some mathematical operaions on it with precision.

    Basically, As soon as I try to cast an integer type into a float, I get a CPU Interruption... Not a compiler message or error... The CPU halts... As if, once compiled, the code was trying to use a CPU instruction that didn't exists on the ARM, when attempting a cast! As if the code wasn't crossed-compiled with the correct instruction set, or the ARM had floating point instructions disabled!

    I hope I've better explained what we're observing!

  • As added information...

    Wer're based on Micrium uC/OS-III code for our software....

    As soon as we attempt a cast, we get stuck there, highlighted in yellow:

    /*
    *********************************************************************************************************
    * ARM INTERRUPT/EXCEPTION HANDLER
    *
    * Description : Handle ARM exceptions.
    *
    * Argument(s) : src_id ARM exception source identifier:
    *
    * OS_CPU_ARM_EXCEPT_RESET 0x00
    * OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01
    * OS_CPU_ARM_EXCEPT_SWI 0x02
    * OS_CPU_ARM_EXCEPT_ABORT_PREFETCH 0x03
    * OS_CPU_ARM_EXCEPT_ABORT_DATA 0x04
    * OS_CPU_ARM_EXCEPT_RSVD 0x05
    * OS_CPU_ARM_EXCEPT_IRQ 0x06
    * OS_CPU_ARM_EXCEPT_FIQ 0x07
    *
    * Return(s) : none.
    *
    * Caller(s) : OS_CPU_ARM_ExceptHndlr(), which is declared in os_cpu_a.s.
    *
    * Note(s) : (1) Only OS_CPU_ARM_EXCEPT_FIQ and OS_CPU_ARM_EXCEPT_IRQ exceptions handler are implemented.
    * For the rest of the exception a infinite loop is implemented for debuging pruposes. This behavior
    * should be replaced with another behavior (reboot, etc).
    *********************************************************************************************************
    */

    void OS_CPU_IntHandler (CPU_INT32U src_id)
    {
    switch (src_id) {
    case OS_CPU_ARM_EXCEPT_IRQ:
    case OS_CPU_ARM_EXCEPT_FIQ:
    CSP_IntHandlerSrc((CSP_DEV_NBR)src_id);
    break;

    default:
    case OS_CPU_ARM_EXCEPT_RST:
    case OS_CPU_ARM_EXCEPT_UND:
    case OS_CPU_ARM_EXCEPT_SWI:
    case OS_CPU_ARM_EXCEPT_ABORT_DATA:
    case OS_CPU_ARM_EXCEPT_ABORT_PREFETCH:
    case OS_CPU_ARM_EXCEPT_RSVD:
    OS_CSP_BSP_ExceptHandler((CPU_INT08U)src_id);
    break;
    }
    }

    /*
    *********************************************************************************************************
    * OS_CSP_BSP_ExceptHandler()
    *
    * Description : Handles ARM exceptions.
    *
    * Argument(s) : Exception type.
    *
    * CPU_ARM_EXCEPT_RST Reset exception.
    * CPU_ARM_EXCEPT_UND Undefined instruction.
    * CPU_ARM_EXCEPT_SWI Software interrupt.
    * CPU_ARM_EXCEPT_ABORT_PREFETCH Prefetch Abort.
    * CPU_ARM_EXCEPT_ABORT_DATA Data Abort.
    *
    * Return(s) : none.
    *
    * Caller(s) : OS_CPU_IntHandler().
    *
    * Note(s) : (1) This exception handler is implemented with an infinite loop for
    * debugging porpuses only.
    *********************************************************************************************************
    */

    void OS_CSP_BSP_ExceptHandler (CPU_INT08U except_type)
    {
    switch (except_type) {
    case CPU_ARM_EXCEPT_RST:
    case CPU_ARM_EXCEPT_UND:
    case CPU_ARM_EXCEPT_SWI:
    case CPU_ARM_EXCEPT_ABORT_PREFETCH:
    case CPU_ARM_EXCEPT_ABORT_DATA:
    while (DEF_TRUE) {
    ;
    }
    }
    }

  • Jeremie,

    Well, we know you can typecast an integer as a float in C, so this is not the problem.

    A thought.  The FPU (floating-pt. unit) in the R4 must be enabled.  Maybe your OS is not doing this?  Check the FPEXC register (see the ARM Cortex R4 Technical Reference Manual on ARMs website).  I'm looking at document DDI0363G_cortex_r4_r1p4_trm, and on page 11-8 it says about the EN bit in this register: "Clearing EN disables VFP functionality, causing instructions apart from privileged system register generate an Undefined Instruction exception." Sound like maybe this is what you are experiencing?

    Regards,

    David

  • Hi Jeremie, This might be something basic to check. You have followed the sequence to enable the FPU on the CPU right? The option only adds the library for this purpose.

  • Found out what was wrong...

    In fact, it was disabled in my code... I'm missing a #define 

    __TI_VFPV3D16_SUPPORT__

    Is it a #define that CCS would be giving to the compiler normally, is there a setting for it? Or should I be setting it myself, manually in the project's properties?

    I've figured out what was wrong, thanks to a little more perusing in the code, and this post : http://e2e.ti.com/support/microcontrollers/hercules/f/766/p/196850/702303.aspx

    I'm very confident this is my problem... The question now, is how should this #define be made... Is it already in CCS, or do I have to do it manually?

  • Jeremie,

    It sounds like this is a #define needed by your OS.  The OS probably doesn't enable the FPU unless this constant is defined.  CCS does not define this constant as far as I can tell.

    You can also stick the define in the project options under Build->ARM_Compiler->Advanced_Options->Predefined_Symbols.  Then you don't need to include it in every file.  Of course, you can always put it in a top-level include file.

    - David

  • Alright... I was guessing, because of it's name, that it might be a setting in CCS that would produce this #define

    Even more so, because micrium's own #defines are always prefixed with "OS_" And they have their own #define for VFP, wich is set inside a #if #else block, guarded by that infamous __TI_VFPV3D16_SUPPORT__ I was talking about

    This looked like a TI #define to me   ;)

    #if ((defined(__TI_VFP_SUPPORT__ ) && (__TI_VFP_SUPPORT__ == 1)) || \
    (defined(__TI_VFPV3_SUPPORT__ ) && (__TI_VFPV3_SUPPORT__ == 1)) || \
    (defined(__TI_VFPV3D16_SUPPORT__) && (__TI_VFPV3D16_SUPPORT__ == 1)))
    #define OS_CPU_ARM_FP_EN                DEF_ENABLED
    #else
    #define OS_CPU_ARM_FP_EN                DEF_DISABLED
    #endif

    Anyway, I'll set it manually... I'll try it out tomorrow, and get back here to "Answer" this thread when I've confirmed it's all working!

  • When looking at document SPNA106, there's something that changed

    I found two versions of this document

    SPNA106 (from september 2011) : http://www.eetindia.co.in/STATIC/PDF/201112/EEIOL_2011DEC07_CTRL_EMS_AN_01.pdf

    SPAN106A (from january 2012) : http://www.ti.com/lit/an/spna106a/spna106a.pdf

    The older version has the same code I have (files sys_core.h and sys_core.asm)... The new version doesn't have the __TI_VFPV3D16_SUPPORT__ anymore...

    It must have something to do with the other difference I've noted... the switch between the nowGen tool and the HALCoGen tool...

  • I don't know what's changed... the compiler should be defining some constants that aren't...

    I found tow constants that should have been defined, and weren't :

    1. __TI_VFPV3D16_SUPPORT__
    2. _big_endian_ or _little_endian_
    For the second one, it fell between the cracks, since the behavior was the same when not defined as the _big_endian_ constant. I event tried setting the option for little endian, and it didn't defined that one either! Something's really wrong!
    Once #define'd manually, it all works out!
    P.S. Also had to activate an option on the specific tasks in the OS that need FPU enabled!
    Problem solved!