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.

TMS570LS3137: CAN Only transmits one message. Can't clear the IntPnd flag. Using embOS.

Part Number: TMS570LS3137
Other Parts Discussed in Thread: HALCOGEN

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:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

One possibility is that the way embOS handles interrupts is interfering.

Edit: I added some of the HALCoGen generated code below for reference:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Can someone explain how I am supposed to clear the pending interrupt flag?

    Here's my understanding of how this demo works:

    • Initial CAN peripheral. All the message boxes are disabled
    • Write a message into a message box using IF1
    • Message is sent, and the interrupt flag is set in Message RAM
      • Interrupt is (attempted to be) cleared by writing 0x08 to IF1, with the message object number specified in IF in the Message Number field
    • We can send another message.

    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.

    Fullscreen
    1
    2
    3
    4
    5
    6
    push.w {r0-r3, r12, lr}
    mrs r0, spsr
    push.w {r0}
    rs r0, cpsr
    orr r0, r0, #19
    msr cpsr_c, r0
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    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.