how to not acknolwdge CAN messages

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
LaMe_4502671
Level 1
Level 1

How do I make a CAN basic mailbox that does not acknowledge messages? I want to set it up so that a few message IDs are acknowledged and the rest are still processed, but silently. I thought I could do this by setting up full mailboxes for the few IDs I'm supposed to be acking and one basic one to process the rest.

So far I've set up a CAN component with a basic mailbox and a ReceiveMsg_Callback() that does not call CAN_RX_ACK_MESSAGE. I don't see any APIs for explicitly not acking. After doing this, an oscilloscope shows that the tx pin is still going low during the ack window for every frame. I'd expect it to do nothing.

0 Likes
1 Solution
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi ​,

pastedImage_9.png

If the Full Custom internal ISR is unchecked, the component generates complete ISR code for each of the interrupts that you enable in the component. With the default ISR code for Message received interrupt, CAN_MsgRXIsr() in CAN_INT.c is called. This in turn calls CAN_ReceiveMsg(uint8 rxMailbox) . This function does the following

1. Interrupt is cleared

2. Message is acked

void CAN_ReceiveMsg(uint8 rxMailbox)

{

    #if (CY_PSOC3 || CY_PSOC5)

        if ((CAN_RX[rxMailbox].rxcmd.byte[0u] & CAN_RX_ACK_MSG) != 0u)

    #else  /* CY_PSOC4 */

        if ((CAN_RX_CMD_REG(rxMailbox) & CAN_RX_ACK_MSG) != 0u)

    #endif /* CY_PSOC3 || CY_PSOC5 */

        {

            /* `#START MESSAGE_BASIC_RECEIVED` */

            /* `#END` */

            #ifdef CAN_RECEIVE_MSG_CALLBACK

                CAN_ReceiveMsg_Callback();

            #endif /* CAN_RECEIVE_MSG_CALLBACK */

            #if (CY_PSOC3 || CY_PSOC5)

                CAN_RX[rxMailbox].rxcmd.byte[0u] |= CAN_RX_ACK_MSG;

            #else  /* CY_PSOC4 */

                CAN_RX_CMD_REG(rxMailbox) |= CAN_RX_ACK_MSG;

            #endif /* CY_PSOC3 || CY_PSOC5 */

        }

}

ReceiveMsg_Callback() is called from this function and hence ACK can not be avoided if you use default ISR.

You need to create a custom ISR for what you want to achieve. To do so,

1. Under Interrupt tab check the Full custom internal ISR and message received checkbox.

pastedImage_0.png

2. Configure a Basic message box and enable IRQ.

pastedImage_2.png

3. Set up a custom ISR using CyIntSetVector()

/* Set CAN interrupt handler to local routine */

    CyIntSetVector(CAN_ISR_NUMBER, ISR_CAN);

4. CAN_ISR

CY_ISR(ISR_CAN)

{

    /* Clear Receive Message flag */

    CAN_INT_SR_REG.byte[1u] = CAN_RX_MESSAGE_MASK;

    /* Set the isrFlag */

    isrFlag = 1u;   

    /* Acknowledges receipt of new message */

    CAN_RX_ACK_MESSAGE(CAN_RX_MAILBOX_0); // Do not call this if you do not want to ACK

}

But please note that this option requires to you to completely write the ISR for all the events. You can use CAN_ISR.c for reference.

Regards,

Bragadeesh

Regards,
Bragadeesh

View solution in original post

0 Likes
1 Reply
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi ​,

pastedImage_9.png

If the Full Custom internal ISR is unchecked, the component generates complete ISR code for each of the interrupts that you enable in the component. With the default ISR code for Message received interrupt, CAN_MsgRXIsr() in CAN_INT.c is called. This in turn calls CAN_ReceiveMsg(uint8 rxMailbox) . This function does the following

1. Interrupt is cleared

2. Message is acked

void CAN_ReceiveMsg(uint8 rxMailbox)

{

    #if (CY_PSOC3 || CY_PSOC5)

        if ((CAN_RX[rxMailbox].rxcmd.byte[0u] & CAN_RX_ACK_MSG) != 0u)

    #else  /* CY_PSOC4 */

        if ((CAN_RX_CMD_REG(rxMailbox) & CAN_RX_ACK_MSG) != 0u)

    #endif /* CY_PSOC3 || CY_PSOC5 */

        {

            /* `#START MESSAGE_BASIC_RECEIVED` */

            /* `#END` */

            #ifdef CAN_RECEIVE_MSG_CALLBACK

                CAN_ReceiveMsg_Callback();

            #endif /* CAN_RECEIVE_MSG_CALLBACK */

            #if (CY_PSOC3 || CY_PSOC5)

                CAN_RX[rxMailbox].rxcmd.byte[0u] |= CAN_RX_ACK_MSG;

            #else  /* CY_PSOC4 */

                CAN_RX_CMD_REG(rxMailbox) |= CAN_RX_ACK_MSG;

            #endif /* CY_PSOC3 || CY_PSOC5 */

        }

}

ReceiveMsg_Callback() is called from this function and hence ACK can not be avoided if you use default ISR.

You need to create a custom ISR for what you want to achieve. To do so,

1. Under Interrupt tab check the Full custom internal ISR and message received checkbox.

pastedImage_0.png

2. Configure a Basic message box and enable IRQ.

pastedImage_2.png

3. Set up a custom ISR using CyIntSetVector()

/* Set CAN interrupt handler to local routine */

    CyIntSetVector(CAN_ISR_NUMBER, ISR_CAN);

4. CAN_ISR

CY_ISR(ISR_CAN)

{

    /* Clear Receive Message flag */

    CAN_INT_SR_REG.byte[1u] = CAN_RX_MESSAGE_MASK;

    /* Set the isrFlag */

    isrFlag = 1u;   

    /* Acknowledges receipt of new message */

    CAN_RX_ACK_MESSAGE(CAN_RX_MAILBOX_0); // Do not call this if you do not want to ACK

}

But please note that this option requires to you to completely write the ISR for all the events. You can use CAN_ISR.c for reference.

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes