KDS V1.1 Cpu_INT_Hard_FaultInterrupt on atof() using MK22FN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

KDS V1.1 Cpu_INT_Hard_FaultInterrupt on atof() using MK22FN

Jump to solution
1,532 Views
randylee
Contributor V

so I've ported a project off CW10.5 onto KDS V1.1 and got it to compile.  Debugging is another thing.

 

The following code is exploding on a hard fault interrupt:

 

double test = atof("1.2345");

 

if I do this:

double test = 54.321;

test = atof("12.345");

 

it explodes in the atof call inside something called _strtod_r()... test is showing actually as 54.321 (or close to it) indicating that there is some actual floating point going on.

 

When it explodes in this routine it appears to be on

 

vpush {d8}

 

I'm missing some sort of setting on this project now?  Is this library a bit wonky?  does this thing not understand floating point?  Is there some setting in the CPU that PE is missing that tells this it actually should use floating point hardware?

 

Target processor settings appear reasonable:

14237_14237.pngpastedImage_0.png

Labels (1)
0 Kudos
1 Solution
1,047 Views
BlackNight
NXP Employee
NXP Employee

Randy,

in my code snippets the store is missing. So here is it again:

void vPortEnableVFP(void) {

  /* The FPU enable bits are in the CPACR. */

  __asm volatile (

    "  ldr.w r0, =0xE000ED88  \n" /* CAPCR, 0xE000ED88 */

    "  ldr r1, [r0]           \n" /* read CAPR */

    "  orr r1, r1, #(0xf<<20) \n" /* Enable CP10 and CP11 coprocessors */

    "  str r1,[r0] \n" /* store to new value back */

    : /* no output */

    : /* no input */

    : "r0","r1" /* clobber */

  );

}

Erich

View solution in original post

0 Kudos
11 Replies
1,047 Views
BlackNight
NXP Employee
NXP Employee

Hi Randy,

I quickly tried your code, but I cannot see a hard fault on my end.

Just to be sure:

I assume you have

#include <stdlib.h>

before using atof()?

The other thing: could it be that you have a stack overflow? Can you check your linker file that you have say 0x800 allocated both for heap and stack?

HEAP_SIZE  = DEFINED(__heap_size__)  ? __heap_size__  : 0x0000800;

STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0000800;

Erich

0 Kudos
1,047 Views
randylee
Contributor V

I created a blank project for the correct chip (K22FN1M0VLK12) and used pretty much default settings for this but with a couple small modifications to get the hardware context closer to right. very simple 2 lines in main to check this and yes, it goes "pow" as soon as it hits an FP instruction.

I've attached the project here (very small)

0 Kudos
1,047 Views
randylee
Contributor V

Hmmm... this tells me that there is a setting somewhere in the basic project that's different

I did set the stack up and the heap up with no difference.. I expected that as this portion would use no heap but anything is possible.  I found this bug deep in the code under a lot of stack and so moved it way up front where no stack would be used with it exploding in exactly the same spot.

on CW10.5 I see that it's explicitly linking in some FPU things in whereas this does not.  It is possible that is now all hidden under the covers.

It's almost like this CPU is being setup to turn off the FPU or something really odd like that.  The particular instruction involved is very particular to FPUs.  Could it be that this is the wrong library for this part?

0 Kudos
1,047 Views
BlackNight
NXP Employee
NXP Employee

Hi Randy,

yes, the libraries are different in KDS. Are you using newlib or newlib-nano?

For my tests I created a project with the wizard and used the default (newlib-nano).

But if you have ported a project, you might be still linking against the CW libraries?

Maybe this is the issue?

Erich

0 Kudos
1,047 Views
randylee
Contributor V

Sorry to take so long getting back. Unwinding the stack and got a time slice for this particular issue.

I have found that the conversion tools don't work for me at all so what I did was to create the project with the right CPU in KDS then export PE from CW10.5 and import them here and then add the source files.  A little editing and things fell into place.

the link line goes: -T "C:\D\LC\Cyclops.kiln\Helmet.kiln\L22Helm.KDS/Project_Settings/Linker_Files/ProcessorExpert.ld" -Xlinker --gc-sections -L"C:\D\LC\Cyclops.kiln\Helmet.kiln\L22Helm.KDS/Project_Settings/Linker_Files" -Wl,-Map,"K22Helm.map" -nanolibc

This thing is on a K22FN1M0 so this thing is supposed to have floating point instructions in it.  Blowing up on running those is strange unless you can turn off the FPU and this isn't turning it on correctly.

0 Kudos
1,047 Views
BlackNight
NXP Employee
NXP Employee

Floating point unit/instructions are disabled at reset:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/BEHBJHIG.html

So you have to enable it somehow (e.g. in the startup code). Below is an example how I do it with GNU gcc:

void vPortEnableVFP(void) {

  /* The FPU enable bits are in the CPACR. */

  __asm volatile (

    "  ldr.w r0, =0xE000ED88  \n" /* CAPCR, 0xE000ED88 */

    "  ldr r1, [r0]           \n" /* read CAPR */

    /* Enable CP10 and CP11 coprocessors, then save back. */

    "  orr r1, r1, #(0xf<<20) \n" /* wait for store to complete */

    : /* no output */

    : /* no input */

    : "r0","r1" /* clobber */

  );

}

0 Kudos
1,047 Views
randylee
Contributor V

Gave it a try both after PE initialization (adding it to the init code) and much later after my app has control.  Neither of them exploded there but the FPU code still explodes in either case.  Which is odd.  Maybe I have to be able to run this much sooner than after PE initialization?

Let's for the sake of argument say this is what it is.  I don't have the problem on CW 10.5 which tells me that there is maybe a bug in the PE that comes with this that doesn't enable it?

0 Kudos
1,048 Views
BlackNight
NXP Employee
NXP Employee

Randy,

in my code snippets the store is missing. So here is it again:

void vPortEnableVFP(void) {

  /* The FPU enable bits are in the CPACR. */

  __asm volatile (

    "  ldr.w r0, =0xE000ED88  \n" /* CAPCR, 0xE000ED88 */

    "  ldr r1, [r0]           \n" /* read CAPR */

    "  orr r1, r1, #(0xf<<20) \n" /* Enable CP10 and CP11 coprocessors */

    "  str r1,[r0] \n" /* store to new value back */

    : /* no output */

    : /* no input */

    : "r0","r1" /* clobber */

  );

}

Erich

0 Kudos
1,047 Views
randylee
Contributor V

OK, that got it.  I still think this is some sort of bug in KDS -- generates FPU instructions correctly but doesn't turn it on in the startup file.  Odd.

well, that clears up that problem anyway.  On to the next one!

thanx

0 Kudos
1,047 Views
BlackNight
NXP Employee
NXP Employee

Yes, it is a bug. I already logged a ticket about this. Thanks for bringing this one up.

0 Kudos
1,047 Views
randylee
Contributor V

in CW 10.5 there is a file __arm_start.c that does the startup code. In it there is the sequence (slightly edited)

...

zero_fill_bss();
if (__S_romp != 0L)
            _copy_rom_sections_to_ram();
__fp_init();

__call_static_initializers();

__init_user();

exit(main(0, argv));

Now in KDS 1.1 there is a file called startup.c that does

zero_fill_bss();

// SUPPORT_ROM_TO_RAM
__copy_rom_sections_to_ram();

// initializations before main, user specific
__init_user();

main(0, argv);
No mention of fp init at all.  Which is sort of what we expect here, I guess.  So KDS doesn't know about FP processors?

Same deal, BTW for KDS 1.1.1

0 Kudos