Low current mode and float calculation errors

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

Low current mode and float calculation errors

1,668 Views
thomasjohansen
Contributor I

Dear NXP Community

I use the low current mode of the LPC824 in my application. But it seems that doing this, makes calculation with double faulty...

I call a function that has a formula with 8-9 coefs (double) with an input value (Double). The function also return double. With some values, the result is alternating each time i call the function. With other values it is ok. Also the calculated values can be a bit of the correct ones.

When I disabling the low current mode there are no problems.

// Low power mode

cmdData[0] = 12;
cmdData[1] = PWR_LOW_CURRENT;
cmdData[2] = 12;
__disable_irq();
LPC_ROM_API->pPWRD->set_power(cmdData, &response);
__enable_irq();

My question is. How can the low current mode has impact on the calculation of float/double and have this strange behavior?

I'm pretty sure the early prototypes we did not behave like this.

I have attached a small project demonstrating this behaviour. It is for KEIL MDK v5 and the source code below

Test with low current mode:

LoopFunction Input dResult
127.78121.105545438064
227.78121.105545438064
327.78121.105545438064
427.81251.106883269864
527.81251.106883269864
627.81251.106883270273

The result for loop 4, 5 and 6 the resulting value is alternating (loop 4 and 6) and the value itself is a bit off.

Loop 1-3 is correct.

Removing the low power mode, no result is alternating and the value itself is spot on

Maybe this behaviour is expected using low current mode?

Best regards 

Thomas Johansen

Source code

double dCalcResult = 0.0;

#define cjT0t 2.5000000E+1
#define cjV0t 9.9198279E-01
#define cjP1t 4.0716564E-02
#define cjP2t 7.1170297E-04
#define cjP3t 6.8782631E-07
#define cjP4t 4.3295061E-11
#define cjq1t 1.6458102E-02
#define cjq2t 0.0000000E+00


double T0[4] = {0, 0, 0, cjT0t};
double V0[4] = {0, 0, 0, cjV0t};
double P1[4] = {0, 0, 0, cjP1t};
double P2[4] = {0, 0, 0, cjP2t};
double P3[4] = {0, 0, 0, cjP3t};
double P4[4] = {0, 0, 0, cjP4t};
double q1[4] = {0, 0, 0, cjq1t};
double q2[4] = {0, 0, 0, cjq2t};
double q3[4] = {0, 0, 0, cjq2t};


double dResult = 0.0;

/* Systick interrupt rate */
#define TICKRATE_HZ (100) /* 10 ticks per second */

double Calculations(double dTemp, int paramIndex)
{

    dResult = V0[paramIndex] + ( (dTemp-T0[paramIndex])*(P1[paramIndex]+(dTemp-T0[paramIndex])*(P2[paramIndex]+(dTemp-T0[paramIndex])*(P3[paramIndex]+P4[paramIndex]*(dTemp-T0[paramIndex]))))/( 1+(dTemp-T0[paramIndex])*(q1[paramIndex]+q2[paramIndex]*(dTemp-T0[paramIndex]))));
   return dResult;
}

double fCJTemps[] = {27.7812, 27.7812, 27.7812, 27.8125, 27.8125, 27.8125};
int nCount = 6;
int nIndex = 0;

int main(void)
{
   // uint8_t data[4] = {0xff};
   uint32_t cmdData[3];
   uint32_t response;

   // Generic Initialization
   SystemCoreClockUpdate();

   cmdData[0] = 12;
   cmdData[1] = PWR_LOW_CURRENT;
   cmdData[2] = 12;
   __disable_irq();
   LPC_ROM_API->pPWRD->set_power(cmdData, &response);
   __enable_irq();

   while(1)
   {
      if(nIndex >= nCount)
      {
          nIndex = 0;
       }
        dCalcResult = Calculations(fCJTemps[nIndex], 3);
        nIndex++;
    }
}

Labels (1)
Tags (2)
0 Kudos
Reply
7 Replies

1,397 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Thomas Johansen,
I'd like to share my testing result.
Demo: periph_flashiap demo from LPCOpen library.
Board: LPCXpress824 MAX board

I've ported your code in the periph_flashiap demo which is from LPCOpen library, then run this demo on the LPCXpresso824 board, as the Fig 1 shows, it works well.
I've attached the code, please check it.

pastedImage_1.png

Fig 1


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

1,396 Views
thomasjohansen
Contributor I

Hi TIC, 

Thanks for your efforts. 

I have not tried you sample from LPC Open because I have KEIL MDK.

I have just run my test code again and this is my result:

test.png

As you can see the values at index 3, 4 and 5 are different and off the correct value.

Could there be some batch difference with the LPC824? Compiler environment?

Thomas

0 Kudos
Reply

1,396 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Thomas Johansen,
It encountered some error when compiling your demo code, so I've ported the code to the periph_blinky project in the LPCOpen library and it works well, I've also attached the code, please check it.

#include "board.h"
#include <stdio.h>

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

#define TICKRATE_HZ (10)     /* 10 ticks per second */

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/
uint8_t flash_number=0;
/*****************************************************************************
 * Public functions
 ****************************************************************************/
double dCalcResult[6];

#define cjT0t 2.5000000E+1
#define cjV0t 9.9198279E-01
#define cjP1t 4.0716564E-02
#define cjP2t 7.1170297E-04
#define cjP3t 6.8782631E-07
#define cjP4t 4.3295061E-11
#define cjq1t 1.6458102E-02
#define cjq2t 0.0000000E+00


double T0[4] = {0, 0, 0, cjT0t};
double V0[4] = {0, 0, 0, cjV0t};
double P1[4] = {0, 0, 0, cjP1t};
double P2[4] = {0, 0, 0, cjP2t};
double P3[4] = {0, 0, 0, cjP3t};
double P4[4] = {0, 0, 0, cjP4t};
double q1[4] = {0, 0, 0, cjq1t};
double q2[4] = {0, 0, 0, cjq2t};
double q3[4] = {0, 0, 0, cjq2t};


double dResult = 0.0;

double Calculations(double dTemp, int  paramIndex)
{

     dResult = V0[paramIndex] + ( (dTemp-T0[paramIndex])*(P1[paramIndex]+(dTemp-T0[paramIndex])*(P2[paramIndex]+(dTemp-T0[paramIndex])*(P3[paramIndex]+P4[paramIndex]*(dTemp-T0[paramIndex]))))/( 1+(dTemp-T0[paramIndex])*(q1[paramIndex]+q2[paramIndex]*(dTemp-T0[paramIndex]))));
     return dResult;
}


double fCJTemps[] = {27.7812, 27.7812, 27.7812, 27.8125, 27.8125, 27.8125};
int nCount = 6;
int nIndex = 0;


/**
 * @brief     Handle interrupt from SysTick timer
 * @return     Nothing
 */
void SysTick_Handler(void)
{
     Board_LED_Toggle(0);
        flash_number++;
}

/**
 * @brief     main routine for blinky example
 * @return     Function should not exit.
 */
int main(void)
{
     
     uint32_t command[5], result[5];
     uint8_t ret_code;
     
     SystemCoreClockUpdate();
     Board_Init();

     //Board_LED_Set(0, false);

     /* Enable SysTick Timer */
     //SysTick_Config(SystemCoreClock / TICKRATE_HZ);
     
          /* Disable interrupt mode so it doesn't fire during FLASH updates */
     __disable_irq();
     
     
          command[0] = 24;
     command[1] = PWR_LOW_CURRENT;
     command[2] = 24;
     LPC_ROM_API->pPWRD->set_power(command, result);

     ret_code= (uint8_t)result[0];
     if (ret_code != IAP_CMD_SUCCESS) {
          Board_LED_Toggle(0);
          }
     /* Re-enable interrupt mode */
     __enable_irq();
     

     /* Loop forever */
     while (1) {
          
//          if(flash_number == 200)
//          {
//            __disable_irq();
//            Chip_IAP_ReinvokeISP();
//          }
          //__WFI();
                         
     if(nIndex >= nCount)
          {
               nIndex = 0;
          }

          dCalcResult[nIndex] = Calculations(fCJTemps[nIndex], 3);
          nIndex++;     
                         
     }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

pastedImage_1.png

Fig 1


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

1,396 Views
thomasjohansen
Contributor I

Dear TIC, 

I have tried few things here.

I tried the Example_UART0_Terminal sample from the LPC824_Example_Code_Bundle_KEil_r1.0.

Also here there is a bit problem running the code. But It seems to have something todo with the PLL (MSEL value)

I change the MSEL value from 1 to zero, it seems to be ok. When I change it back to 1 it start calculating wrong

msel.png

Could it be something wrong with the PLL setting that could lead to this behavior?

I also tried the the  periph_blinky from the LPCOpen library(It also has KEIL project in the bundle).

As you also see, there are no problems there. But that also run with completely different PLL settings.!!

Thomas 

0 Kudos
Reply

1,396 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Thomas Johansen,
Thanks for your reply.
I suspect that calling set_power incorrectly cause this issue because I found that it would get this wrong calculating result when setting the inconsistent clock frequency to param0 and param2 during calling set_power.
So I'd highly recommend you to add a checking mechanism in your code as I did, please give a try.

     /* Disable interrupt mode so it doesn't fire during FLASH updates */
     __disable_irq();
     
     
          command[0] = 24;
     command[1] = PWR_LOW_CURRENT;
     command[2] = 24;
     LPC_ROM_API->pPWRD->set_power(command, result);

     ret_code= (uint8_t)result[0];
     if (ret_code != IAP_CMD_SUCCESS) {
          Board_LED_Toggle(0);
          }
     /* Re-enable interrupt mode */
     __enable_irq();‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

1,397 Views
thomasjohansen
Contributor I

Hi TIC, 

Yes, you where right. Is is the use of inconsistent clock frequency in the set_power mode.

But the bad part is, that doing a error check to not catch it. The result is always IAP_CMD_SUCCES

Please these two pictures. The first is with wrong clock in the params (12 instead of 24).

The calculations here are wrong, but the result from the set_power is still 0 (IAP_CMD_SUCCES)

In the other picture the correct value of 24 is used. Here the calculation are fine, but the result from set_power is still IAP_CMD_SUCCES

So it can't be detected??

Wrong clock params:

wrong clk.png

Correct clock param:

correct clk.png

Thomas

0 Kudos
Reply

1,397 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Thomas Johansen,
Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
I'd like to replicate this phenomenon at first, and I will respond to you later.
Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply