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:
Loop | Function Input | dResult |
---|---|---|
1 | 27.7812 | 1.105545438064 |
2 | 27.7812 | 1.105545438064 |
3 | 27.7812 | 1.105545438064 |
4 | 27.8125 | 1.106883269864 |
5 | 27.8125 | 1.106883269864 |
6 | 27.8125 | 1.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++;
}
}
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.
Fig 1
Have a great day,
TIC
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
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:
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
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++;
}
}
Fig 1
Have a great day,
TIC
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
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
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
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!
-----------------------------------------------------------------------------------------------------------------------
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:
Correct clock param:
Thomas
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!
-----------------------------------------------------------------------------------------------------------------------