Dear Expert
The MCU I am using is s32k116, because I want to do bus-off fast recovery/slow recovery, so I need to turn off the bus-off auto recovery.
My CAN module settings are as follows:
void CAN0_init(void)
{
uint8_t databyte;
/* Enable clock for PORTE */
PCC->PCCn[PCC_PORTE_INDEX] |= PCC_PCCn_CGC_MASK;
#if 0 //Pinchi 20181213 change to 116 SBC board
// for V04 of hardware board
/* Port B0: MUX = ALT5, CAN0_RX */
PORTB->PCR[0U] |= PORT_PCR_MUX(5U);
/* Port B1: MUX = ALT5, CAN0_TX */
PORTB->PCR[1U] |= PORT_PCR_MUX(5U);
#else
// for V05 of hardware board
/* Port E4: MUX = ALT5, CAN0_RX */
PORTE->PCR[4U] |= PORT_PCR_MUX(5U);
/* Port E5: MUX = ALT5, CAN0_TX */
PORTE->PCR[5U] |= PORT_PCR_MUX(5U);
#endif
/* CGC=1: enable clock to FlexCAN0 */
PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK;
/* To access the memory mapped registers */
/* Enter disable mode (hard reset). */
if(((CAN0->MCR & CAN_MCR_MDIS_MASK) >> CAN_MCR_MDIS_SHIFT) == 0U)
{
/* Clock disable (module) */
CAN0->MCR = (uint32_t)((CAN0->MCR & ~CAN_MCR_MDIS_MASK) | CAN_MCR_MDIS(1U));
/* Wait until disable mode acknowledged */
while (((CAN0->MCR & CAN_MCR_LPMACK_MASK) >> CAN_MCR_LPMACK_SHIFT) == 0U) {}
}
/* Select a source clock for the FlexCAN engine */
CAN0->CTRL1 = (uint32_t)((CAN0->CTRL1 & ~CAN_CTRL1_CLKSRC_MASK) | CAN_CTRL1_CLKSRC(0U));
/* Enter the freeze mode */
CAN0->MCR &= ~CAN_MCR_MDIS_MASK;
CAN0->MCR = (CAN0->MCR & ~CAN_MCR_FRZ_MASK) | CAN_MCR_FRZ(1U);
CAN0->MCR = (CAN0->MCR & ~CAN_MCR_HALT_MASK) | CAN_MCR_HALT(1U);
/* Wait for entering the freeze mode */
while (!((CAN0->MCR & CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT)) {}
/* Reset the FLEXCAN */
CAN0->MCR = (uint32_t)((CAN0->MCR & ~CAN_MCR_SOFTRST_MASK) | CAN_MCR_SOFTRST(1U));
/* Wait for reset cycle to complete */
while (((CAN0->MCR & CAN_MCR_SOFTRST_MASK) >> CAN_MCR_SOFTRST_SHIFT) != 0U) {}
/* Clear MB region */
for (databyte = 0U; databyte < 128U; databyte++)
{
CAN0->RAMn[databyte] = 0U;
}
/* Clear RXIMR region */
for (databyte = 0U; databyte < 32U; databyte++)
{
CAN0->RXIMR[databyte] = 0U;
}
/* Disable all MB interrupts */
CAN0->IMASK1 = 0U;
/* Clear all MB interrupt flags */
CAN0->IFLAG1 = (uint32_t)CAN_IMASK1_BUF31TO0M_MASK;
/* Disable can fd */
CAN0->MCR = (uint32_t)((CAN0->MCR & ~CAN_MCR_FDEN_MASK) | CAN_MCR_FDEN(0UL));
/* Enable the use of extended bit time definitions */
CAN0->CBT = (uint32_t)(CAN0->CBT | CAN_CBT_BTF(0UL));
/* Disable the Stuff Bit Count */
#if (0)
CAN0->CTRL2 = (uint32_t)((CAN0->CTRL2 & ~CAN_CTRL2_ISOCANFDEN_MASK) | CAN_CTRL2_ISOCANFDEN(0UL));
#else
//CAN0->CTRL2 = (uint32_t)(0x40000000U) ;
CAN0->CTRL2 = (uint32_t)(0) ;
#endif // #if (0)
/* enabling warning enable interrupt for tx and rx passive errors*/
CAN0->MCR = (uint32_t)(CAN0->MCR | CAN_MCR_WRNEN(1U));
CAN0->CTRL1 = (uint32_t)(CAN0->CTRL1 | CAN_CTRL1_RWRNMSK(1U) | CAN_CTRL1_TWRNMSK(1U));
/* Set operation mode as normal */
CAN0->MCR = (uint32_t)((CAN0->MCR & ~CAN_MCR_SUPV_MASK) | CAN_MCR_SUPV(0U));
CAN0->CTRL1 = (uint32_t)((CAN0->CTRL1 & ~CAN_CTRL1_LOM_MASK) | CAN_CTRL1_LOM(0U));
CAN0->CTRL1 = (uint32_t)((CAN0->CTRL1 & ~CAN_CTRL1_LPB_MASK) | CAN_CTRL1_LPB(0U));
/* Set the maximum number of MBs*/
CAN0->MCR = (uint32_t)((CAN0->MCR & ~CAN_MCR_MAXMB_MASK) | \
((CANT_MAXMB_CNT << CAN_MCR_MAXMB_SHIFT) & CAN_MCR_MAXMB_MASK));
/* Sets the FlexCAN time segments for setting up bit rate */
CAN0->CTRL1 = (uint32_t)(((CAN0->CTRL1) & ~((CAN_CTRL1_PROPSEG_MASK | CAN_CTRL1_PSEG2_MASK |
CAN_CTRL1_PSEG1_MASK | CAN_CTRL1_PRESDIV_MASK) |
CAN_CTRL1_RJW_MASK)));
//sample rate 75%
CAN0->CTRL1 = (uint32_t)(((CAN0->CTRL1) | (CAN_CTRL1_PROPSEG(6U) | //7U
CAN_CTRL1_PSEG2(3U) | //1U
CAN_CTRL1_PSEG1(3U) | // 4U
CAN_CTRL1_PRESDIV(PRESDIV) |
CAN_CTRL1_RJW(4U)))); //1U
/* Sets the CAN error and busoff error interrupts masks */
CAN0->CTRL1 = (uint32_t)((CAN0->CTRL1)&~((CAN_CTRL1_ERRMSK_MASK )|(CAN_CTRL1_BOFFMSK_MASK)));
CAN0->CTRL1 = (uint32_t)((CAN0->CTRL1)|(CAN_CTRL1_ERRMSK(1)|(CAN_CTRL1_BOFFMSK(1))));
/* Disable auto recovery*/
CAN0->CTRL1 |=(uint32_t)((CAN_CTRL1_BOFFREC_MASK));
CAN0->CTRL1 |=(uint32_t)CAN_CTRL1_BOFFREC(1);
CAN0->CTRL2 |= CAN_CTRL2_BOFFDONEMSK(1);
/* Sets the individual masking for each MB */
CAN0->MCR=(uint32_t)((CAN0->MCR & ~CAN_MCR_IRMQ_MASK)|(CAN_MCR_IRMQ(1U)));
/* Sets the self reception disable */
CAN0->MCR=(uint32_t)((CAN0->MCR & ~CAN_MCR_SRXDIS_MASK)|(CAN_MCR_SRXDIS(1U)));
/* Configure Rx Id filtering */
Enable_ID_filter();
/* Configure Rx msg objects*/
CAN0_ConfRxMsgObj();
/* Configure Tx msg objects*/
CAN0_ConfTxMsgObj();
/* Exit freeze mode */
CAN0->MCR = (uint32_t)((CAN0->MCR & ~CAN_MCR_HALT_MASK) | CAN_MCR_HALT(0U));
CAN0->MCR = (uint32_t)((CAN0->MCR & ~CAN_MCR_FRZ_MASK) | CAN_MCR_FRZ(0U));
/* Wait till exit freeze mode */
while (((CAN0->MCR & CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT) != 0U) {}
/* Enable receive buffer interrupts */
Clr_Pending_IRQ(CAN0_ORed_0_31_MB_IRQn);
Enable_IRQ(CAN0_ORed_0_31_MB_IRQn);
Set_IRQ_Priority(CAN0_ORed_0_31_MB_IRQn,IRQ_PRIORITY);
/* Enable error interrupt */
Clr_Pending_IRQ(CAN0_ORed_Err_Wakeup_IRQn);
Enable_IRQ(CAN0_ORed_Err_Wakeup_IRQn);
Set_IRQ_Priority(CAN0_ORed_Err_Wakeup_IRQn,IRQ_PRIORITY);
}
I set the CAN0->CTRL1 |=(uint32_t)CAN_CTRL1_BOFFREC(1);
However, I found that the setting has no effect, the following picture shows the can tx signal I measured with an oscilloscope. You can see that it still sends out the signal at 3.6ms at the bus off status.
This problem has been bothering me for a long time, please help me to solve this problem.
Thanks.
BT
please have a try below sentence.
CAN0->CTRL1 |= 0x40;
and then check if the rigister CRTL1->BOFFREC is set or not.
Hi @Senlent
The register date from bit 15~0 are "1100 1100 0100 0110" (0xCC, 0x46).
It means the rigister CRTL1->BOFFREC is set to 1.
Could you please tell me, when a bus off occurs, are there any other register settings that need to be done in the handler?
Thanks.
BT
we have some demo about bus-off test.
You can check whether BOFFREC is 1 in the debugging interface.
When you turn off auto bus-off recovery, you need to manually recover the CAN module after a bus-off event occurs. This is the only difference.