Page 1 of 1

CAN wake up mechanism

Posted: 26 Apr 2017, 22:34
by Magomedimin
Hello

I make a board with CAN transceiver TJA1040. It has STB pin - standby mode control input.
I tried to use CAN wake up function, but it didn't work. Value in Wake-up Status Register is not change.
Please help, i don't know where the problem


/******************************************************************************
* @file main.c
* @version V1.00
* $Revision: 6 $
* $Date: 14/10/06 11:25a $
* @brief Demonstrate CAN bus transmit and receive a message with normal
* mode by connecting CAN 0 and CAN1 to the same CAN bus
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "NUC472_442.h"


#define PLLCON_SETTING SYSCLK_PLLCON_50MHz_XTAL
#define PLL_CLOCK 48000000

extern char GetChar(void);

/*---------------------------------------------------------------------------------------------------------*/
/* Global variables */
/*---------------------------------------------------------------------------------------------------------*/
STR_CANMSG_T rrMsg;

void CAN_ShowMsg(STR_CANMSG_T* Msg);

/*---------------------------------------------------------------------------------------------------------*/
/* ISR to handle CAN interrupt event */
/*---------------------------------------------------------------------------------------------------------*/
void CAN_MsgInterrupt(CAN_T *tCAN, uint32_t u32IIDR)
{
if(u32IIDR==1) {
printf("Msg-0 INT and Callback\n");
CAN_Receive(tCAN, 7,&rrMsg);
CAN_ShowMsg(&rrMsg);
}
if(u32IIDR==5+1) {
printf("Msg-5 INT and Callback \n");
CAN_Receive(tCAN, 10,&rrMsg);
CAN_ShowMsg(&rrMsg);
}
if(u32IIDR==31+1) {
printf("Msg-31 INT and Callback \n");
CAN_Receive(tCAN, 31,&rrMsg);
CAN_ShowMsg(&rrMsg);
}
}


/**
* @brief CAN0_IRQ Handler.
* @param None.
* @return None.
*/
void CAN0_IRQHandler(void)
{
uint32_t u8IIDRstatus;

u8IIDRstatus = CAN0->IIDR;

if(u8IIDRstatus == 0x00008000) { /* Check Status Interrupt Flag (Error status Int and Status change Int) */
/**************************/
/* Status Change interrupt*/
/**************************/
if(CAN0->STATUS & CAN_STATUS_RXOK_Msk) {
CAN0->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/

printf("RX OK INT\n") ;
}

if(CAN0->STATUS & CAN_STATUS_TXOK_Msk) {
CAN0->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/

printf("TX OK INT\n") ;
}

/**************************/
/* Error Status interrupt */
/**************************/
if(CAN0->STATUS & CAN_STATUS_EWARN_Msk) {
printf("EWARN INT\n") ;
}

if(CAN0->STATUS & CAN_STATUS_BOFF_Msk) {
printf("BOFF INT\n") ;
}
} else if (u8IIDRstatus!=0) {
printf("=> Interrupt Pointer = %d\n",CAN0->IIDR -1);

CAN_MsgInterrupt(CAN0, u8IIDRstatus);

CAN_CLR_INT_PENDING_BIT(CAN0, ((CAN0->IIDR) -1)); /* Clear Interrupt Pending */

} else if(CAN0->WU_STATUS == 1) {
printf("Wake up\n");

CAN0->WU_STATUS = 0; /* Write '0' to clear */
}

}



void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();

// TODO: Configure system clock

CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;

CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);

// HCLK select external 4~24 MHz high speed crystal clock
CLK->CLKSEL0 &= ~CLK_CLKSEL0_HCLKSEL_Msk;
CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_HXT;

//uart clock source select external 4~24 MHz high speed crystal clock
//CLK->CLKSEL1 &= ~CLK_CLKSEL1_UARTSEL_Msk;
//CLK->CLKSEL1 |= (0x0 << CLK_CLKSEL1_UARTSEL_Pos);

// Enable IP clock
CLK->APBCLK0 |= CLK_APBCLK0_TMR0CKEN_Msk;
CLK->APBCLK0 |= CLK_APBCLK0_UART0CKEN_Msk; // UART0 Clock Enable
//CLK->APBCLK0 |= CLK_APBCLK0_UART3CKEN_Msk; // UART3 Clock Enable

/* Select IP clock source */
CLK->CLKSEL1 &= ~CLK_CLKSEL1_UARTSEL_Msk;
CLK->CLKSEL1 |= (0x0 << CLK_CLKSEL1_UARTSEL_Pos);// Clock source from external 12 MHz or 32 KHz crystal clock

// Enable UART3 pin function (H11 & H12)
//SYS->GPH_MFPH = (SYS->GPH_MFPH & ~(SYS_GPH_MFPH_PH11MFP_Msk | SYS_GPH_MFPH_PH12MFP_Msk)) | 0x00011000;
/* Set PG multi-function pins for UART0 RXD, TXD */
SYS->GPA_MFPH &= ~(SYS_GPA_MFPH_PA13MFP_Msk | SYS_GPA_MFPH_PA14MFP_Msk);
SYS->GPA_MFPH |= (SYS_GPA_MFPH_PA13MFP_UART0_RXD | SYS_GPA_MFPH_PA14MFP_UART0_TXD);

// Enable CAN0 pin function (B12 & B13)
SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) | (0x33 << SYS_GPB_MFPH_PB12MFP_Pos);

// Enable CAN0 pin function (A0 & A1)
SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA0MFP_Msk | SYS_GPA_MFPL_PA1MFP_Msk);
SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA0MFP_CAN1_RXD | SYS_GPA_MFPL_PA6MFP_CAN1_TXD);

/* Lock protected registers */
SYS_LockReg();

}

void UART4_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
UART_Open(UART0, 115200);
}



/**
* @brief Init CAN driver
*/

void CAN_Init(CAN_T *tCAN)
{
if(tCAN == CAN0) {
// Enable IP clock
CLK->APBCLK0 |= CLK_APBCLK0_CAN0CKEN_Msk;

// Reset CAN0
SYS->IPRST1 |= SYS_IPRST1_CAN0RST_Msk;
SYS->IPRST1 &= ~SYS_IPRST1_CAN0RST_Msk;
} else if(tCAN == CAN0) {
// Enable IP clock
CLK->APBCLK0 |= CLK_APBCLK0_CAN1CKEN_Msk;

// Reset CAN1
SYS->IPRST1 |= SYS_IPRST1_CAN1RST_Msk;
SYS->IPRST1 &= ~SYS_IPRST1_CAN1RST_Msk;
}
}

/**
* @brief Disable CAN
* @details Reset and clear all CAN control and disable CAN IP
*/

void CAN_STOP(CAN_T *tCAN)
{
if(tCAN == CAN0) {
/* Disable CAN0 Clock and Reset it */
SYS->IPRST1 |= SYS_IPRST1_CAN0RST_Msk;
SYS->IPRST1 &= ~SYS_IPRST1_CAN0RST_Msk;
CLK->APBCLK0 &= ~CLK_APBCLK0_CAN0CKEN_Msk;
} else if(tCAN == CAN1) {
/* Disable CAN0 Clock and Reset it */
SYS->IPRST1 |= SYS_IPRST1_CAN1RST_Msk;
SYS->IPRST1 &= ~SYS_IPRST1_CAN1RST_Msk;
CLK->APBCLK0 &= ~CLK_APBCLK0_CAN1CKEN_Msk;
}
}

/*----------------------------------------------------------------------------*/
/* Some description about how to create test environment */
/*----------------------------------------------------------------------------*/
void Note_Configure()
{
printf("\n\n");
printf("+------------------------------------------------------------------------+\n");
printf("| About CAN sample code configure |\n");
printf("+------------------------------------------------------------------------+\n");
printf("| The sample code provide a simple sample code for you study CAN |\n");
printf("| Before execute it, please check description as below |\n");
printf("| |\n");
printf("| 1.CAN0 and CAN1 connect to the same CAN BUS |\n");
printf("| 2.Using UART0 as print message port(Both of NUC472/442 module boards)|\n");
printf("| |\n");
printf("| |--------| |-----------| CANBUS |-----------| |--------| |\n");
printf("| | |------>| |<------->| |<------| | |\n");
printf("| | |CAN0_TX| CAN0 | CAN1_H | CAN1 |CAN1_TX| | |\n");
printf("| | NUC472 | |Transceiver| |Transceiver| | NUC472 | |\n");
printf("| | NUC442 |<------| |<------->| |------>| NUC442 | |\n");
printf("| | |CAN0_RX| | CAN1_L | |CAN1_RX| | |\n");
printf("| |--------| |-----------| |-----------| |--------| |\n");
printf("| | | |\n");
printf("| | | |\n");
printf("| V V |\n");
printf("| UART0 UART0 |\n");
printf("|(print message) (print message)|\n");
printf("+------------------------------------------------------------------------+\n");
}

/*----------------------------------------------------------------------------*/
/* Test Function */
/*----------------------------------------------------------------------------*/
void CAN_ShowMsg(STR_CANMSG_T* Msg)
{
uint8_t i;
printf("Read ID=%8X, Type=%s, DLC=%d,Data=",Msg->Id,Msg->IdType?"EXT":"STD",Msg->DLC);
for(i=0; i<Msg->DLC; i++)
printf("%02X,",Msg->Data);
printf("\n\n");
}

/*----------------------------------------------------------------------------*/
/* Send Tx Msg by Normal Mode Function (With Message RAM) */
/*----------------------------------------------------------------------------*/
void Test_NormalMode_Tx(CAN_T *tCAN)
{
STR_CANMSG_T tMsg;
uint32_t i;

/* Send a 11-bits message */
tMsg.FrameType= DATA_FRAME;
tMsg.IdType = CAN_STD_ID;
tMsg.Id = 0x7FF;
tMsg.DLC = 2;
tMsg.Data[0] = 7;
tMsg.Data[1] = 0xFF;

if(CAN_Transmit(tCAN, MSG(0),&tMsg) == FALSE) { // Configure Msg RAM and send the Msg in the RAM
printf("Set Tx Msg Object failed\n");
return;
}

printf("MSG(0).Send STD_ID:0x7FF, Data[07,FF]done\n");

/* Send a 29-bits message */
tMsg.FrameType= DATA_FRAME;
tMsg.IdType = CAN_EXT_ID;
tMsg.Id = 0x12345;
tMsg.DLC = 3;
tMsg.Data[0] = 1;
tMsg.Data[1] = 0x23;
tMsg.Data[2] = 0x45;

if(CAN_Transmit(tCAN, MSG(1),&tMsg) == FALSE) {
printf("Set Tx Msg Object failed\n");
return;
}

printf("MSG(1).Send EXT:0x12345 ,Data[01,23,45]done\n");

/* Send a data message */
tMsg.FrameType= DATA_FRAME;
tMsg.IdType = CAN_EXT_ID;
tMsg.Id = 0x7FF05;
tMsg.DLC = 4;
tMsg.Data[0] = 0xA1;
tMsg.Data[1] = 0xB2;
tMsg.Data[2] = 0xC3;
tMsg.Data[3] = 0xD4;

if(CAN_Transmit(tCAN, MSG(3),&tMsg) == FALSE) {
printf("Set Tx Msg Object failed\n");
return;
}

printf("MSG(3).Send EXT:0x7FF01 ,Data[A1,B2,C3,D4]done\n");

for(i=0; i < 10000; i++);

printf("Trasmit Done!\nCheck the receive host received data\n\n");

}

/*----------------------------------------------------------------------------*/
/* Receive Rx Msg by Normal Mode Function (With Message RAM) */
/*----------------------------------------------------------------------------*/
void Test_NormalMode_SetRxMsg(CAN_T *tCAN)
{
if(CAN_SetRxMsg(tCAN, MSG(7),CAN_STD_ID, 0x7FF) == FALSE) {
printf("Set Rx Msg Object failed\n");
return;
}

if(CAN_SetRxMsg(tCAN, MSG(10),CAN_EXT_ID, 0x12345) == FALSE) {
printf("Set Rx Msg Object failed\n");
return;
}

if(CAN_SetRxMsg(tCAN, MSG(31),CAN_EXT_ID, 0x7FF05) == FALSE) {
printf("Set Rx Msg Object failed\n");
return;
}

}

void Test_NormalMode_WaitRxMsg(CAN_T *tCAN)
{
STR_CANMSG_T rMsg[5];
/*Choose one mode to test*/
#if 0
/* Polling Mode */
while(1) {
while(tCAN->IIDR ==0); /* Wait IDR is changed */
//while(CAN_Receive(CAN0, 0, &rMsg[0]) == FALSE);
printf("IDR = %x\n",tCAN->IIDR);
CAN_Receive(tCAN, tCAN->IIDR -1, &rrMsg);
CAN_ShowMsg(&rrMsg);
}
#else
/* INT Mode */
CAN_EnableInt(tCAN, CAN_CON_IE_Msk);
CAN_EnableInt(tCAN, CAN_CON_SIE_Msk);
CAN_EnableInt(tCAN, CAN_CON_EIE_Msk);
NVIC_SetPriority(CAN0_IRQn, (1<<__NVIC_PRIO_BITS) - 2);
NVIC_EnableIRQ(CAN0_IRQn);
printf("Wait Msg\n");
printf("Enter any key to exit\n");
//GetChar();
#endif
}

int main()
{
SYS_Init();

GPIO_SetMode(PB, BIT5, GPIO_MODE_OUTPUT);
GPIO_SetMode(PA, BIT7, GPIO_MODE_OUTPUT);

PA7 = 0;
PB5 = 0;

UART4_Init();

/* Select CAN Multi-Function */
CAN_Init(CAN0);
CAN_Init(CAN1);

// Note_Configure();

CAN_Open(CAN0, 500000, CAN_NORMAL_MODE);
CAN_Open(CAN1, 500000, CAN_NORMAL_MODE);
CAN0->MVLD1 &= CAN_IF_ARB2_MSGVAL_Msk;
printf("\n");
printf("+------------------------------------------------------------------ +\n");
printf("| Nuvoton CAN BUS DRIVER DEMO |\n");
printf("+-------------------------------------------------------------------+\n");
printf("| Transmit/Receive a message by normal mode |\n");
printf("+-------------------------------------------------------------------+\n");

printf("Press any key to continue ...\n\n");
//GetChar();

Test_NormalMode_SetRxMsg(CAN0);

Test_NormalMode_Tx(CAN0);
//CAN_CLR_INT_PENDING_BIT(CAN0,0);
Test_NormalMode_WaitRxMsg(CAN0);
CAN_ENABLE_WAKEUP(CAN0);
PA7 = 1;
PB5 = 1;

while(1) ;

}

/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/

Re: CAN wake up mechanism

Posted: 28 Apr 2017, 09:46
by Dylan Hsieh
It seems that you miss some instrument which let NUC442/NUC472 enter into power-saving mode.

Re: CAN wake up mechanism

Posted: 02 May 2017, 18:21
by Magomedimin
Mmm... I thought that "Wake up" function is necessary for power management of CAN adapters.
Thank you for help.