This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I am attempting to use the TMS570 CAN peripheral. I have it configured using the latest version of HALCoGen. I am able to send a single message using canTransmit.
Here is the relevant section of my code:
void can1HighLevelInterrupt(void); void can1LowLevelInterrupt(void); NORETURN static void HPTask(void) { canInit(); OS_ARM_InstallISRHandler(16, can1LowLevelInterrupt); OS_ARM_EnableISR(16); OS_ARM_InstallISRHandler(29, can1HighLevelInterrupt); OS_ARM_EnableISR(29); canEnableErrorNotification(canREG1); canEnableStatusChangeNotification(canREG1); canTransmit(canREG1, canMESSAGE_BOX1, tx_ptr); while (true) { if (tx_done) { canTransmit(canREG1, canMESSAGE_BOX1, tx_ptr); tx_done = false; } OS_TASK_Delay(1000); } } void canErrorNotification(canBASE_t *node, uint32 notification) { } void canStatusChangeNotification(canBASE_t *node, uint32 notification) { } bool if1_busy(void) { return (canREG1->IF1STAT & 0x80) == 0x80; } void canMessageNotification(canBASE_t *node, uint32 messagebox) { /* node 1 - transfer request */ if(node==canREG1) { while (if1_busy()) {} canREG1->IF1NO = messagebox; canREG1->IF1CMD = 0x8; canREG1->IF2CMD = 0x80; while (if1_busy()) {} // Clear the interrupt tx_done=1; /* confirm transfer request */ } /* node 2 - receive complete */ if(node==canREG2) { while(!canIsRxMessageArrived(canREG2, canMESSAGE_BOX1)); canGetData(canREG2, canMESSAGE_BOX1, rx_ptr); /* copy to RAM */ rx_ptr +=8; } /* note: since only message box 1 is used on both nodes we dont check it here.*/ }
One possibility is that the way embOS handles interrupts is interfering.
Edit: I added some of the HALCoGen generated code below for reference:
void canInit(void) { /* USER CODE BEGIN (4) */ /* USER CODE END */ /** @b Initialize @b CAN1: */ /** - Setup control register * - Disable automatic wakeup on bus activity * - Local power down mode disabled * - Disable DMA request lines * - Enable global Interrupt Line 0 and 1 * - Disable debug mode * - Release from software reset * - Enable/Disable parity or ECC * - Enable/Disable auto bus on timer * - Setup message completion before entering debug state * - Setup normal operation mode * - Request write access to the configuration registers * - Setup automatic retransmission of messages * - Disable error interrupts * - Disable status interrupts * - Enter initialization mode */ canREG1->CTL = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)((uint32)0x00000005U << 10U) | (uint32)0x00020043U; /** - Clear all pending error flags and reset current status */ canREG1->ES |= 0xFFFFFFFFU; /** - Assign interrupt level for messages */ canREG1->INTMUXx[0U] = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U; canREG1->INTMUXx[1U] = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U; /** - Setup auto bus on timer period */ canREG1->ABOTR = (uint32)0U; /** - Initialize message 1 * - Wait until IF1 is ready for use * - Set message mask * - Set message control word * - Set message arbitration * - Set IF1 control byte * - Set IF1 message number */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG1->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG1->IF1MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x000007FFU & (uint32)0x1FFFFFFFU) << (uint32)0U); canREG1->IF1ARB = (uint32)0x80000000U | (uint32)0x40000000U | (uint32)0x20000000U | (uint32)((uint32)((uint32)1U & (uint32)0x1FFFFFFFU) << (uint32)0U); canREG1->IF1MCTL = 0x00001000U | (uint32)0x00000800U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)8U; canREG1->IF1CMD = (uint8) 0xF8U; canREG1->IF1NO = 1U; /** - Setup IF1 for data transmission * - Wait until IF1 is ready for use * - Set IF1 control byte */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG1->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG1->IF1CMD = 0x87U; /** - Setup IF2 for reading data * - Wait until IF1 is ready for use * - Set IF1 control byte */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG1->IF2STAT & 0x80U) ==0x80U) { } /* Wait */ canREG1->IF2CMD = 0x17U; /** - Setup bit timing * - Setup baud rate prescaler extension * - Setup TSeg2 * - Setup TSeg1 * - Setup sample jump width * - Setup baud rate prescaler */ canREG1->BTR = (uint32)((uint32)0U << 16U) | (uint32)((uint32)(2U - 1U) << 12U) | (uint32)((uint32)((3U + 2U) - 1U) << 8U) | (uint32)((uint32)(2U - 1U) << 6U) | (uint32)19U; /** - CAN1 Port output values */ canREG1->TIOC = (uint32)((uint32)1U << 18U ) | (uint32)((uint32)0U << 17U ) | (uint32)((uint32)0U << 16U ) | (uint32)((uint32)1U << 3U ) | (uint32)((uint32)1U << 2U ) | (uint32)((uint32)1U << 1U ); canREG1->RIOC = (uint32)((uint32)1U << 18U ) | (uint32)((uint32)0U << 17U ) | (uint32)((uint32)0U << 16U ) | (uint32)((uint32)1U << 3U ) | (uint32)((uint32)0U << 2U ) | (uint32)((uint32)0U <<1U ); /** - Leave configuration and initialization mode */ canREG1->CTL &= ~(uint32)(0x00000041U); /** @b Initialize @b CAN2: */ /** - Setup control register * - Disable automatic wakeup on bus activity * - Local power down mode disabled * - Disable DMA request lines * - Enable global Interrupt Line 0 and 1 * - Disable debug mode * - Release from software reset * - Enable/Disable parity or ECC * - Enable/Disable auto bus on timer * - Setup message completion before entering debug state * - Setup normal operation mode * - Request write access to the configuration registers * - Setup automatic retransmission of messages * - Disable error interrupts * - Disable status interrupts * - Enter initialization mode */ canREG2->CTL = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)((uint32)0x00000005U << 10U) | 0x00020043U; /** - Clear all pending error flags and reset current status */ canREG2->ES |= 0xFFFFFFFFU; /** - Assign interrupt level for messages */ canREG2->INTMUXx[0U] = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U; canREG2->INTMUXx[1U] = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U; /** - Setup auto bus on timer period */ canREG2->ABOTR = (uint32)0U; /** - Setup IF1 for data transmission * - Wait until IF1 is ready for use * - Set IF1 control byte */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG2->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG2->IF1CMD = 0x87U; /** - Setup IF2 for reading data * - Wait until IF1 is ready for use * - Set IF1 control byte */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG2->IF2STAT & 0x80U) ==0x80U) { } /* Wait */ canREG2->IF2CMD = 0x17U; /** - Setup bit timing * - Setup baud rate prescaler extension * - Setup TSeg2 * - Setup TSeg1 * - Setup sample jump width * - Setup baud rate prescaler */ canREG2->BTR = (uint32)((uint32)0U << 16U) | (uint32)((uint32)(2U - 1U) << 12U) | (uint32)((uint32)((3U + 2U) - 1U) << 8U) | (uint32)((uint32)(2U - 1U) << 6U) | (uint32)19U; /** - CAN2 Port output values */ canREG2->TIOC = (uint32)((uint32)1U << 18U ) | (uint32)((uint32)0U << 17U ) | (uint32)((uint32)0U << 16U ) | (uint32)((uint32)1U << 3U ) | (uint32)((uint32)1U << 2U ) | (uint32)((uint32)1U << 1U ); canREG2->RIOC = (uint32)((uint32)1U << 18U ) | (uint32)((uint32)0U << 17U ) | (uint32)((uint32)0U << 16U ) | (uint32)((uint32)1U << 3U ) | (uint32)((uint32)0U << 2U ) | (uint32)((uint32)0U <<1U ); /** - Leave configuration and initialization mode */ canREG2->CTL &= ~(uint32)(0x00000041U); /** @b Initialize @b CAN3: */ /** - Setup control register * - Disable automatic wakeup on bus activity * - Local power down mode disabled * - Disable DMA request lines * - Enable global Interrupt Line 0 and 1 * - Disable debug mode * - Release from software reset * - Enable/Disable parity or ECC * - Enable/Disable auto bus on timer * - Setup message completion before entering debug state * - Setup normal operation mode * - Request write access to the configuration registers * - Setup automatic retransmission of messages * - Disable error interrupts * - Disable status interrupts * - Enter initialization mode */ canREG3->CTL = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)((uint32)0x00000005U << 10U) | 0x00020043U; /** - Clear all pending error flags and reset current status */ canREG3->ES |= 0xFFFFFFFFU; /** - Assign interrupt level for messages */ canREG3->INTMUXx[0U] = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U; canREG3->INTMUXx[1U] = (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U | (uint32)0x00000000U; /** - Setup auto bus on timer period */ canREG3->ABOTR = (uint32)0U; /** - Setup IF1 for data transmission * - Wait until IF1 is ready for use * - Set IF1 control byte */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG3->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG3->IF1CMD = 0x87U; /** - Setup IF2 for reading data * - Wait until IF1 is ready for use * - Set IF1 control byte */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG3->IF2STAT & 0x80U) ==0x80U) { } /* Wait */ canREG3->IF2CMD = 0x17U; /** - Setup bit timing * - Setup baud rate prescaler extension * - Setup TSeg2 * - Setup TSeg1 * - Setup sample jump width * - Setup baud rate prescaler */ canREG3->BTR = (uint32)((uint32)0U << 16U) | (uint32)((uint32)(2U - 1U) << 12U) | (uint32)((uint32)((3U + 2U) - 1U) << 8U) | (uint32)((uint32)(2U - 1U) << 6U) | (uint32)(uint32)19U; /** - CAN3 Port output values */ canREG3->TIOC = (uint32)((uint32)1U << 18U ) | (uint32)((uint32)0U << 17U ) | (uint32)((uint32)0U << 16U ) | (uint32)((uint32)1U << 3U ) | (uint32)((uint32)1U << 2U ) | (uint32)((uint32)1U << 1U ); canREG3->RIOC = (uint32)((uint32)1U << 18U ) | (uint32)((uint32)0U << 17U ) | (uint32)((uint32)0U << 16U ) | (uint32)((uint32)1U << 3U ) | (uint32)((uint32)0U << 2U ) | (uint32)((uint32)0U << 1U ); /** - Leave configuration and initialization mode */ canREG3->CTL &= ~(uint32)(0x00000041U); /** @note This function has to be called before the driver can be used.\n * This function has to be executed in privileged mode.\n */ /* USER CODE BEGIN (5) */ /* USER CODE END */ } /* SourceId : CAN_SourceId_021 */ /* DesignId : CAN_DesignId_019 */ /* Requirements : HL_SR221, HL_SR223 */ void can1LowLevelInterrupt(void) { uint32 messageBox = canREG1->INT >> 16U; /* USER CODE BEGIN (44) */ /* USER CODE END */ /** - Setup IF1 for clear pending interrupt flag */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG1->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG1->IF1CMD = 0x08U; /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */ canREG1->IF1NO = (uint8) messageBox; /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG1->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG1->IF1CMD = 0x87U; canMessageNotification(canREG1, messageBox); /* USER CODE BEGIN (45) */ /* USER CODE END */ } /* SourceId : CAN_SourceId_021 */ /* DesignId : CAN_DesignId_019 */ /* Requirements : HL_SR221, HL_SR223 */ void can1LowLevelInterrupt(void) { uint32 messageBox = canREG1->INT >> 16U; /* USER CODE BEGIN (44) */ /* USER CODE END */ /** - Setup IF1 for clear pending interrupt flag */ /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG1->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG1->IF1CMD = 0x08U; /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */ canREG1->IF1NO = (uint8) messageBox; /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */ while ((canREG1->IF1STAT & 0x80U) ==0x80U) { } /* Wait */ canREG1->IF1CMD = 0x87U; canMessageNotification(canREG1, messageBox); /* USER CODE BEGIN (45) */ /* USER CODE END */ }
Can someone explain how I am supposed to clear the pending interrupt flag?
Here's my understanding of how this demo works:
What appears to be happening, is that a message is sent, but writing 0x8 to IF1 does not clear the interrupt, and it keeps firing, preventing the main code from sending another message.
Part of my things that since I'm using embOS, and all ISRs first pass through an embOS function, that is interfering with correct operation of the HALCoGen supplied interrupt handler. However, I can't think of how this interference might happen.
Hello,
The intPnd bit in the message object is cleared by writing 0x08 to IFxCMD filed of IF command register. This is done in the CAN ISR. You don't need to re-write IFxCMD again in the notification callback function.
Can you receive the message on CAN2 using interrupt? The code for CAN message TX and RX look fine to me.
Hello,
I am receiving the message successfully using a Kvaser USB CAN interface connected to the board.
The problem is the interrupt keeps occurring preventing any other code from running.
I've done some additional research into my code.
the embOS RTOS changes modes from IRQ to SVC mode before calling the ISR.
push.w {r0-r3, r12, lr} mrs r0, spsr push.w {r0} rs r0, cpsr orr r0, r0, #19 msr cpsr_c, r0
Is it possible the CAN registers are not accessible from SVC mode, or the peripheral behaves differently?
I figured out the issue. There are two different ISRs.
I mapped the high level interrupt handler to the low level interrupt.
IRQ #16 needs to map to canHighLevelnterrupt.