Low Power modes in MM9Z1638

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

Low Power modes in MM9Z1638

1,407 Views
vardhan
Contributor I

I am working with CAN transmission on MM9Z1_638 with demo board RD9Z1_638_4Li Rev 1.2, We establish CAN communication between MM9Z1_638 and MICROCHIP CAN analyzer with demo code (RD9Z1_638_12VLA_CAN_demo). My aim is to work low power modes with CAN protocol, in this process i am setting MSCAN is in Sleep Mode and MCU in stop mode and according to the datasheet to wake the MCU from stop mode using PTB4 ( For Wake-up  i am setting of the NWUE bit in the GPIO_IN4 register and with the Wake-up Enable Bit (WUPTB4) and the port configuration bit (PTWU) set) But i am unable wake the MCU.

Please help me to sort of this problem and I am attaching my code here


// --------------------------------------------------------------------
#include "drv638.h" // driver for MM9Z1-638
#include "nvm.h" // nvm driver
#include <stdio.h> // sprintf
#include "main.h"
#include "soc.h"
#include "rd9z1_638_12vc.h"
#include "ntc.h"
#include "service.h"
#include "usercan.h"
#include "msCANdrv.h"

// For CAN bit Timing see AN1798.pdf

extern u8 wak_int;
// --------------------------------------------------------------------
// This demo software is provided "AS-IS".
// For documentation please see the folder \docu\documentation.html
// --------------------------------------------------------------------
//---------------------------------------------------------------------
/*! \brief Structure for Clock configuration for CAN demo

- use external oscillator (16.000MHz) as reference clock (divide by 16)
- target VCO clock: 50.000MHz
- target core clock: 50.000MHz
- target bus clock : 25.000MHz
- target D2D clock : 25.000MHz
*/
TYPE_CPMU_CONF const ClockConf = {
ClockSrc_EXT,
VCO_RANGE,
SYNR(CLOCK_VCO, CLOCK_REF),
REFCLK_FREQ_1_2_MHZ_RANGE, // Ref is IRC = 1.000MHz
// REFDIV(4), // Refdivider div = 4 (4MHz quarz)
REFDIV(16), // Refdivider div = 16 (16MHz quarz)
POSTDIV(CLOCK_VCO, CLOCK_BUS),
PLL_FREQ_MOD_0_PERCENT,
PCRPRE(CLOCK_D2D), // PCR prescaler
D2DDIV(CLOCK_BUS, CLOCK_D2D)
};
// --------------------------------------------------------------------
//! \brief TSENSE list of channels to convert...
TYPE_TSENSE_LIST const tList[] = {
// ch , avg
CH_TSENSE_ITS , 1, 6, //!< measure internal chip temperature
TSENSE_EXT , 1, 6 //!< measure external temperature sensor (NTC)
};
const u8 tListEntries = sizeof(tList)/sizeof(TYPE_TSENSE_LIST); //!< number of entries in the list above
static u16 tValues[sizeof(tList)/sizeof(TYPE_TSENSE_LIST)]; //!< RAM buffer for the TSENSE module
// --------------------------------------------------------------------
//! \brief VSENSE list of channels to convert...
TYPE_VSENSE_LIST const vList[] = {
// ch , avg , latency
CH_VSENSE2 , 100, 12,
};
const u8 vListEntries = sizeof(vList)/sizeof(TYPE_VSENSE_LIST); //!< number of entries in the list above
static u16 vValues[sizeof(vList)/sizeof(TYPE_VSENSE_LIST)]; //!< RAM buffer for the VSENSE module

// --------------------------------------------------------------------
//! \brief CSENSE list of channels to convert...
TYPE_CSENSE_LIST const cList[] = {
// ch , avg , latency
CH_CSENSE , 100 , 0
};
const u8 cListEntries = sizeof(cList)/sizeof(TYPE_CSENSE_LIST); //!< number of entries in the list above
static s32 cValues[sizeof(cList)/sizeof(TYPE_CSENSE_LIST)]; //!< RAM buffer for the TSENSE module
/*
// --------------------------------------------------------------------
// PTA0 is connected to MC33901 STB pin
#define STANDBYMODE (1)
#define NORMALMODE (0)
#define CAN_STDBY(v) {DDRA_DDRA0 = 1; PTA_PTA0 = (v);}
*/

// --------------------------------------------------------------------
// PTA6 is connected to MC33901 STB pin
#define STANDBYMODE (1)
#define NORMALMODE (0)
#define CAN_STDBY(v) {DDRA_DDRA6 = 1; PTA_PTA6 = (v);}

// ---------------------------------------------------------------------
// private prototypes
void GPIOInit(void);
void LTCInit(void);
void asciitohexa(char* input, char* output); // Change by baji

// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
void main(void) {
u16 TSensor[tListEntries];
u16 VSensor[vListEntries];
s32 CSensor[cListEntries];

TYPE_CAN_IBS_Data CAN_IBS_Data;
TYPE_CAN_IBS_Data_Ext CAN_IBS_Data_Ext;

u8 rec_data[9]={0},trans_arr[8],rec_flag;

TYPE_CAN_IBS_CONTROL CAN_IBS_Control;
MSCAN_TYPE_ERROR_CODE err_status; //To store the return value of the driver APIs.
MSCAN_TYPE_STATUS mbStat;
u8 CAN_status[3]; //CAN_status to store channel status,byte 0 store CANCTL0, byte 1 store CANCTL1, byte 2 store CANRFLG

u8 u8ModeTimer;
u32 u32Temp;
static TYPE_BATTERY Battery;
s16 s16Vdrop;
u8 u8WakeUpReason;
u8 u8ChipTemp;
u16 u16Result;
Bool WriteSystemCalibrationValues = FALSE; // do not change !!!


SYS_Init();
CPMUInit(&ClockConf);
D2DInit((TYPE_D2DCLKDIV) ClockConf.D2dDiv);
XirqEnable(); // enable XIRQ -> isrD2DErr() "write-once"
if (B_PCR_CTL_OPM & 2) { // Check if Wake Up from Sleep mode (see page RM3.0 110 Intermediate Mode)
u32Temp = B_ACQ_AHC;
B_PCR_CTL = OPM_SET_NORMAL; // set normal mode
while (!(B_PCR_SRH_WLPMF )) DO_NOTHING; // Wait for Clock Domain Change \! /todo where is this described?
}else{
if(!B_PCR_SR_HWRF) {
PCRReset(); // generate a HWR reset to ensure analog die is in defined state! E.g. debugging might cause strange effects in case bits are set from before //
}
}

B_WD_CTL = WD_OFF;
u8WakeUpReason = 0;

// evaluate wakeup reason
if(B_PCR_SR_WULINF) { // wakeup caused by LIN
u8WakeUpReason = 1;
}

if(B_PCR_SR_WUAHTHF) {
u8WakeUpReason = 2;
}

if(B_PCR_SR_WUCALF) {
u8WakeUpReason = 3;
}
if(B_PCR_SR_WUCTHF) { // current threshold
u8WakeUpReason = 4;
}

if(B_PCR_SR_WULTCF) {
u8WakeUpReason = 5;
}

B_PCR_SRH = 0xFF; // clear all flags

PCRInit(ClockConf.PCRprescaler);
SYSStartupTrimming();

//! \brief Set a breakpoint to this line and change the variable WriteSystemCalibrationValues to TRUE in the debugger to write values \ref CalibWrite
if(WriteSystemCalibrationValues) { // hook to manually write system calibration values to eeprom during sw development
CalibWriteManual();
}

if(CalibRead()==FALSE) { // reads system calibration data from EEPROM (if avaliable). needs to be before ADCInit()
CalibDefault(); // otherwise use default values
}

VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();

GPIOInit();
LTCInit();

CAN_STDBY(NORMALMODE);
// IBS control frame
CAN_IBS_Control.u8Len = 2;

err_status = Init_CAN(CAN0, FAST); //Initialization msCAN channel 0, FAST means the reset won't wait until current transmit completed
do{
err_status = Check_CAN_Status(CAN0, CAN_status);
}while ((CAN_status[0] & SYNCH) == 0); //Wait for msCAN channel 0 synchronized to CAN Bus
err_status = Config_CAN_MB(CAN0, CANBUF1, TXDF, CAN_MO1); //configure the msCAN channel 0, buffer 1 to be TXDF mode (transmit dataframe) -> message object 1,see details in "MSCANID.h"
err_status = Config_CAN_MB(CAN0, CANBUF2, TXDF, CAN_MO2); //configure the msCAN channel 0, buffer 2 to be TXDF mode (transmit dataframe) -> message object 2
err_status = Config_CAN_MB(CAN0, CANBUF3, RXDF, CAN_MO3); //configure the msCAN channel 0, buffer 3 to be RXDF mode (receive dataframe) -> message object 3

Battery.tMode = BM_PARKING; // used to get an initial OCV based SoC
SoCInit();
RTIInit();
RTIEnable();
IrqEnable();
u8ModeTimer = 50; // timed mode change from parking -> driving (5*100ms)

for EVER {

switch(Battery.tMode) {
case BM_PARKING:
case BM_DRIVING:
// ----- measurements, voltage, current and temp ------
if(TsenseGetValue(CH_TSENSE_ITS, &TSensor[0])) { // request data
u8ChipTemp = (u8)(TSensor[0]/TSENSE_ITS_INVRES+K2C+40); // scale to deg C with offset 40
}

if(TsenseGetValue(TSENSE_EXT, &TSensor[1])) {
Battery.u16TempK = NTCRaw2Kelvin(NTCconvert, TSensor[1]);
}
if(CsenseGetValue(CH_CSENSE, &CSensor[0])) {
Battery.s32mAFilt = CSensor[0];
}
if(VsenseGetValue(CH_VSENSE2, &VSensor[0])) { // if 0 channel is converted then

#if (ISENSE_GND_REF==ISENSEL)
// ISENSEL is GND reference
s16Vdrop = (s16)(Battery.s32mAFilt/G_SHUNT); // calculated shunt drop voltage
Battery.u16mV = (VSensor[0]>>1) - s16Vdrop; // scale to mV and correct shunt drop voltage
#endif

#if (ISENSE_GND_REF==ISENSEH)
// ISENSEH is GND reference
Battery.u16mV = VSensor[0]>>1; // scale to mV and no correction
#endif
}
if(RTIEvery100ms()) {
SoCUpdate(&Battery);
TsenseHandler(); // temperature needs to be done polling (V,I interrupt driven)
if(u8ModeTimer>0) { // timed mode change from parking -> driving (5*100ms)
u8ModeTimer--;
}else{
Battery.tMode = BM_DRIVING;
}
CAN_IBS_Data.FrameLen = 8;
CAN_IBS_Data.BatVolt = u16Swap(Battery.u16mV); // scale to mV
CAN_IBS_Data.BatCurr = u32Swap(Battery.s32mAFilt);
CAN_IBS_Data.BatTemp = (u8)(Battery.u16TempK+K2C+40);
CAN_IBS_Data.BatMode = Battery.tMode;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
}
if(RTIEvery1000ms()) {
CAN_IBS_Data_Ext.FrameLen = 6;
CAN_IBS_Data_Ext.ChipTemp = u8ChipTemp;
CAN_IBS_Data_Ext.SOC = Battery.u8SoC;
CAN_IBS_Data_Ext.Coulomb = u32Swap(Battery.u32CoulombCnt);
err_status = Load_CAN_MB(CAN0, CANBUF2, CAN_IBS_Data_Ext.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF2);
}
break;

case BM_CALIBRATION:

ServiceApp();
break;
default:
break;
}

// read message object .....
(void) Check_CAN_MB_Status(CAN0, CANBUF3, &mbStat);
if((mbStat.Status == NEWDATA) || (mbStat.Status == OVERRUN)) { //Wait for the Receive ISR to finish and change the buffer status, NEWDATA indicates that the buffer has receive a new data

if(wak_int == 10){
wak_int=1;
}
err_status = Read_CAN_MB_Data(CAN0, CANBUF3, CAN_IBS_Control.byte);//Copy the received data in msCAN channel 0 buffer 2 to data_rec;
CAN_IBS_Control.u16Var = u16Swap(CAN_IBS_Control.u16Var);
//Clear buffer_status[0]
//err_status = Read_CAN_MB_Data(CAN0, CANBUF3, rec_data);
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Control.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
mbStat.Status = NODATA;

if(CAN_IBS_Control.u16Var&0x8000) { // Goto Sleep Request
// goto sleep
err_status = Sleep_CAN(CAN0, CMPTX); // request CAN channel 0 go to sleep with completing transmission scheduled
do {
err_status = Check_CAN_Status(CAN0,CAN_status); // read the channel 0 status
}while (!(CAN_status[1]&SLPAK)); // wait till SLPAK bit set

B_PCR_WUEH_WUPTB4 = 1; // enable PTB4 wakeup
ADCDisable();
TsenseDisable();
B_GPIO_VSENSE = 0;

CAN_STDBY(STANDBYMODE);
PTA_PTA1 = 0;
PCREnterStopMode();

// .....zzzzzzzzzzz (stop mode)
// after wakeup the code continues to run here....
// but first the D2D Interrupt service routine will be run
B_WD_CTL = WD_OFF;
B_PCR_CTL = OPM_SET_NORMAL; /* set normal mode*/ // bb
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
CAN_STDBY(NORMALMODE);
}

if(CAN_IBS_Control.u16Var&0x1000) { // Goto Calib mode
Battery.tMode = BM_CALIBRATION;

CAN_IBS_Data.BatMode = Battery.tMode;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);

err_status = Config_CAN_MB (CAN0, 8, RXDF, 8);
err_status = Config_CAN_MB (CAN0, 9, TXDF, 9);
}
if(CAN_IBS_Control.u16Var&0x2000) { // Goto normal mode
Battery.tMode = BM_DRIVING;
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
}
}
} // for EVER
}
// ---------------------------------------------------------------------
/*! \brief Init GPIO

<b>Configuration used for the RD9Z1_638_12VLA_CAN_Demo:</b>

| Pin | Enabled | Direction | Routing | used for |
|:----------:|:--------:|:---------:|:-------:|------------------------------------|
| PTB0 | - | - | | analog input |
| PTB1 | disabled | n.a. | | not used |
| PTB2 | disabled | n.a. | | not used |
| PTB3 | disabled | n.a. | | not used |
| PTB4 | enabled | input | PTWU | CAN PHY wake up input |
| PTB5/GNDSW | - | - | - | GND switch for TSENSE_EXT |

*/
void GPIOInit(void) {

B_GPIO_CTL = GPIO_CTL_PTB1_DISABLE | GPIO_CTL_PTB1_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB2_DISABLE | GPIO_CTL_PTB2_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB3_DISABLE | GPIO_CTL_PTB3_INPUT;

B_GPIO_PUC_PDE4 = 1; // enable pull down (missing on KT9Z1638EVM)
B_GPIO_CTL = GPIO_CTL_PTB4_ENABLE; // PTB4 is used for CAN Wakeup
B_GPIO_IN4 = IN4_PTWU|IN4_NWUE; // enable WU in low power mode, negative edge
}

// ---------------------------------------------------------------------
/*! \brief
*
*/
void LTCInit(void) {

B_LTC_CTL = B_LTC_CTL_LTCEM_MASK | B_LTC_CTL_LTCE_MASK; // LTC enable, no interrupt
}

// --------------------------------------------------------------------
// --------------------------------------------------------------------
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0wkup void isrCANWakeup(void) {

CAN_Wakeup(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0err void isrCANErr(void) {

CAN_ERR(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0tx void isrCANTx(void) {

CAN_Transmit(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0rx void isrCANRx(void) {

CAN_Receive(CAN0);
}

 

0 Kudos
6 Replies

1,389 Views
Q_man
NXP Employee
NXP Employee

Hi Vardhan,

seems you are doing things correct. The NXP provided SW should also work on the RD9Z1_638_4Li as you have correctly configured the PTA6 for the CAN standby.

I suggest the check the following items:

  1. is CAN communication working (I assume yes)?
  2. when you send a Goto to Sleep CAN frame and stop CAN communication, is the MM9Z1_638 in STOP mode? E.g. monitor the Supply current? If possible you can also monitor VDDH which is 0V in low power modes and 2.5V during normal mode.
  3. when you attempt to wakeup via CAN what happens?
    • does the supply current change (which value?, please also provide the active current and current in Sleep as well)
    • can you probe the PTB4 pin and check if there is a falling edge?

W.

 

 

0 Kudos

1,381 Views
vardhan
Contributor I

Thank you Q_man,

1. I check CAN communication between RD9Z1_638_4Li  board and CAN BUS analyzer(Microchip) and it is working.

2. According to the datasheet during stop mode(one of the low power mode) the MCU VDDH is 0v & VDDX is 5.0v but i observed these levels VDDH is in 2.5v and VDDX is in 5.0v after MCU entered into STOP mode by using function PCREnterStopMode();

3. I probe on PTB4 pin and it is falling edge transition.

Can you please help me to sort of this issue and here i am attaching Stopmode function

void PCREnterStopMode(void) {

IrqDisable();
B_INT_MSK = 0xFF3F; // disable all Analog Interrupts
B_ACQ_SRH = 0xFF; // Clear pending Flags
B_INT_MSK = 0xFF00; // enable all Analog Interrupts

B_PCR_SR = 0xFFFF; // Clear Flags
B_PCR_CTL = OPM_SET_STOP; // Goto Stop Mode
StopEnable();
StopEnter();
}

0 Kudos

1,363 Views
Q_man
NXP Employee
NXP Employee

It seems to be similar issue than Baji - could you please check the proposed test there (with MC33879_En()).

Thx

W.

0 Kudos

1,337 Views
Q_man
NXP Employee
NXP Employee

Hi Vardhan,

what is the status on this issue?

One other potential problem could be a connected Debugger. It's not possible to enter STOP mode on the uC with the debugger connected! So please try without debugger!

W.

0 Kudos

1,330 Views
Q_man
NXP Employee
NXP Employee

Hi,

I just tried it with the RD9Z1_638-4Li board and its works Sleep (=STOP) and Wakeup.

Trace Sleep -> WakeupTrace Sleep -> Wakeup

You can see the Goto To Sleep -> PTA7 = low and VDDH = 0V and wakeup via CAN PTA7 = high and VHHD = 2.5V.

Debugger was disconnected!

0 Kudos

1,400 Views
baji
Contributor I

I am also facing the same issue while worling on low power modes. please help us for understanding wake up mechanism on PTB4 and give some example code for understanding the wakeup mechanisms 

0 Kudos