Wake up on CAN receive

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

Wake up on CAN receive

5,468 Views
dastek
Contributor III

Hi,

I have a working CAN interface code and now want the micro to go to sleep when there are no CAN messages on the bus and to wake on reception of a CAN message.

To test this I have a variable I write to with the debug interface to tell it to sleep.  This works as I can see the current supply drop when I activate my sleep.

Then I send some CAN frames and nothing happens.

I have 3 CAN interfaces active although only one will provide the wake up event.  I have code to re-initialise the other CANs inside their Wake interrupts.

This is a sample of my code.  For brevity I show only CAN0 where possible.


    if (Go_to_Sleep == 99)            // Test if I must sleep ?
      {
        CAN0CTL0 |= WUPE;
        CAN1CTL0 |= WUPE;
        CAN4CTL0 |= WUPE;

        CAN0RIER |= WUPIE;
        CAN1RIER |= WUPIE;
        CAN4RIER |= WUPIE;

        CAN0CTL0 |= SLPRQ;            // Request sleep mode
        CAN1CTL0 |= SLPRQ;            // Request sleep mode
        CAN4CTL0 |= SLPRQ;            // Request sleep mode
        while ((CAN0CTL1 & SLPAK) != 0) ;    // Wait for SLPAK to == 1
        while ((CAN1CTL1 & SLPAK) != 0) ;    // Wait for SLPAK to == 1
        while ((CAN4CTL1 & SLPAK) != 0) ;    // Wait for SLPAK to == 1

        _asm ("ANDCC  #$7f");        // Clear S bit
        _asm ("nop");
        _asm ("STOP");            // Enter STOP mode
                                    // Processor will now SLEEP here
                                    // And wakeup here.
      }


ISR                                          // Interrupt on wake
void Isr_CAN0_Wake(void)    // Triggers when the procesor wakes on a Can packet receive
{
    if ((CAN0CTL1 & INITAK) != 0)
      return;            // Not initialised yet

    if (((CAN0CTL0 & SLPRQ) != 0) && ((CAN0CTL1 & SLPAK) == 0))
      return;                  // Not yet in Sleep mode: cannot clear SLPRQ
    else
      {
        DisableInterrupts;              // SEI
        CAN0RIER |= WUPIE;        // clear wakeup interrupt
        CAN1RIER |= WUPIE;
        CAN4RIER |= WUPIE;
        EnableInterrupts;                 // CLI

        CAN0CTL0 &= ~SLPRQ;        // clear SLPRQ
        CAN1CTL0 &= ~SLPRQ;        //
        CAN4CTL0 &= ~SLPRQ;        //
      }
    Go_to_Sleep = 0;        // Clear my Variable
}

void CAN_Init_(void)                        // CAN initialisation called at start up.
{
    CAN0CTL0 |= INITRQ;            // set INITRQ, this will also set INITAK

    while ((CAN0CTL1 & INITAK) != 1) ;    // wait for init mode to occur
    CAN0CTL1 = CTL1;                     // == CANE | BORM
                     
    CAN0BTR0 = BTR0_500;            // == 0xc0
    CAN0BTR1 = BTR1_500;            // == 0x34

    CAN0IDAC = IDAM0;            // Four 16 bit acceptance filters

    CAN0_Dont_care();               // Setup Acceptance registers
    CAN0CTL0 &= ~INITRQ;            // clear INITRQ.  Restart and synchronise

    while ((CAN0CTL1 & INITAK) != 0) ;    // Wait for acknowledge

    CAN0RIER = CSCIE | RSTATE0 | TSTATE0 | OVRIE | RXFIE;    // enable receive interrupt RXFIE
    CAN0RFLG = WUPIF | OVRIF | RXF;                // Reset Error Flags
}

The CAN1 and CAN4 are initialised with the same values.  The Wake is also the same.

My debug interface disconnects when I enter sleep so this is rather difficult to debug.

Can you help?

Regards,

Wade

0 Kudos
Reply
14 Replies

4,421 Views
dastek
Contributor III

Hi,

I am happy to share my test project.  I use Cosmic C compiler for S12X so there are some small differences.

www.dastek.co.za/Wake files.zip

Regards,

Wade

0 Kudos
Reply

4,421 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi,

Why do you clear SLPRQ just before it enters Stop mode?

It should be like this:

CAN0CTL0 |= WUPE;     // Enable Wake Up
CAN1CTL0 |= WUPE;     // WUPE allows restart from Sleep

CAN0RIER |= WUPIE;     // Enable Wake Up Interrupt Enable
CAN1RIER |= WUPIE;

CAN0RFLG |= WUPIF;     // Clear WUP Flag
CAN1RFLG |= WUPIF;

CAN0CTL0 |= SLPRQ;     // Request sleep mode, clock continues to run
CAN1CTL0 |= SLPRQ;     // Request sleep mode

while ((CAN0CTL1 & SLPAK) == 0) ;     // Wait for SLPAK to == 1          
while ((CAN1CTL1 & SLPAK) == 0) ;     // Wait for SLPAK to == 1

_asm ("ANDCC  #$7f");     // Clear S bit.  If not S is Set then STOP is disabled and it does a 2 cycle NOP
_asm ("nop");
_asm ("STOP");          // Enter STOP mode

Regards,

Daniel

0 Kudos
Reply

4,421 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi,

Thanks for the code.

Unfortunately, we don't use Cosmic so I cannot run it as it is and I haven't found the root cause yet.

But I will continue.

Regards,

Daniel

0 Kudos
Reply

4,421 Views
dastek
Contributor III

Update 2 ...

I decided to re-use Ladislav's code from "main.c" from G128-CAN-WakeUpfromSTOPand Sleep-CW51.zip

I used the one in CAN-SleepWakeUp-RxDevice-CW51.

I needed to make some modifications as I use 2 CAN interfaces, I use PLL and I am not using LOOP BACK mode on CAN.

I have an interrupt vector and code for CAN Wake.

Once it goes to STOP, it never wakes up.

Any idea what is needed.

Regards,

Wade

0 Kudos
Reply

4,421 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi Wade,

I really don't know.

Could you attach the project? So we can run it and see what it does.

If you don't want to share your projects publicly, you may create a ticket.

https://community.nxp.com/docs/DOC-329745 

Regards,

Daniel

0 Kudos
Reply

4,421 Views
dastek
Contributor III

Update....

I now get the micro to wake from the WAI for the CAN interrupts, the Timer Input Capture as well as the pin interrupt on Port H 0.  That is with the debug interface connected.

When I disconnect the debug interface, it makes outputs and sees CAN messages at start up.  When my timer runs out and the WAI is active then it will not wake even if all three interrupt sources are going at once.

Any ideas?

Regards,

Wade

0 Kudos
Reply

4,421 Views
dastek
Contributor III

Hi,

I made the problem simpler.  I am using the WAI instruction, no going to SLEEP.

I have the following interrupt sources :
  Interrupt on Timer Input capture 0, 1, 2, 3
  Pin interrupt on Port H 0
  Interrupt on CAN receive on CAN 0 and 1


I use a WAI instruction as follows :

    EnableInterrupts;    // CLI
    for (;;)
      {
        Ulong++;

        while ((CRGFLG & RTIF) == 0)
          {
          }                // Wait for RTIF to set
        CRGFLG = RTIF;        // Clear RTIF flag          

        if (Ulong == 0x200)
          {
            Ulong = 0;
            _asm ("WAI");
          }

        Reset_WatchDog;        //
      }

My Ulong value will increment when I have a timer interrupt going, otherwise Port H and CAN interrupts do not wake the WAI.  ie Ulong is always = 0.

This happens with the debug interface connected and running, but not with it not connected.  Once the WAI is reached it never recovers.  I can monitor the Ulong value changing value.  I also have an external method of seeing that its working.

I had to set the TSWAI flag in TSCR1 to get the Timer input capture to work.
I tried CSWAI flag in CAN0CTL0 and CAN1CTL0 but no different.

I also added CLKSEL |= COPWAI;

Do you have any suggestions?

Regards,

Wade

0 Kudos
Reply

4,421 Views
dastek
Contributor III

Hi,

I restarted on the CAN wake up today.

I assumed that the clocks need to run to wakeup from a CAN receive.  I made CLKSEL.PSTP = 1.

This did not help.  I read that the micro will wakeup to any CAN receive, even if it is not for me, so clocks do not need to run.

I looked at the code supplied and it seems very simple:

  CANCTL0.WUPE = 1

  CANRIER.WUPIE = 1

and then

  wait for CANCTL1.SLPAK = 0

I get my micro to go to sleep, as the current drops and the BDM looses connection.  But I have no joy at waking it.

I then tried to execute the WAI instruction instead of STOP. 

If I keep a Timer Input Capture interrupt event going it does not go to sleep and if I turn off my Timer input capture event, is goes to sleep, but does not wake.

I have checked that the Interrupt vector is in the right place and that the code it jumps to is right and exits with an RTI.

At wake up I do the following:

  CANRIER.WUPIE = 0

I do not see any way to acknowledge the CAN Wake interrupt.  Is this right?

I am sure I only have something small I have wrong, but I do not see it.

Any ideas?

Regards,

Wade Whitehorn

0 Kudos
Reply

4,421 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi,

Have you tried to wake it on a port interrupt to see if the MCU can be woken up.

The MSCAN wakes up on any bus activity and it does not need clock.

And the first message cannot be acknowledged. 

Regards,

Daniel

0 Kudos
Reply

4,421 Views
dastek
Contributor III

Hi,

I have tried a "WAI" instruction instead of "STOP".

The WAI does not wake on an interrupt.

I tried without the debug interface connected, but once in SLEEP it does not wake up.

I think that I am missing something fundamental for wake from sleep.

Regards,

Wade

0 Kudos
Reply

4,421 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi,

Please make sure you don't mask interrupts.

I would try to wake it up from Stop using a simple pin interrupt.

To see if it works.

Regards,

Daniel

0 Kudos
Reply

4,421 Views
lama
NXP TechSupport
NXP TechSupport

Hi,

it is not easy to say what is wrong because I do no see entire project.

If I were you I would check:

1) Whether the wakeup interrupt function is correctly defined

2) Whether "return" function is correctly assembled. it is not clear whether the function is interrupt or it is called from an interrupt function.

It is really hard to say the result if I am not able to see all project dependencies.

However, I have found on my PC an examples where XEP100 - CAN stop mode EVB - CW47.zip wakes up the XEP100 - CAN stop mode - CW47.zip.

best regads,

Ladislav

0 Kudos
Reply

4,421 Views
dastek
Contributor III

Yes MC9s12XEQ384.

Regards,

Wade

0 Kudos
Reply

4,421 Views
lama
NXP TechSupport
NXP TechSupport

Hi,

at the beginning. The MCU is MC9S12......

I suppose some S12XE...but not sure.

Best regards,

Ladislav

0 Kudos
Reply