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.
Tool/software:
Hello,
I am working with two LP-MSPM0G3507 boards and two CAN transceivers (ISO1044DEVM), studying the MCAN protocol using examples from the MSPM0 SDK (examples > nortos > driverlib > mcan_multi_message_rx, examples > nortos > driverlib > mcan_multi_message_tx).
I successfully transmitted and received MCAN messages between the two boards using these examples.
After that, I set up one LP-MSPM0G3507 to continuously send MCAN messages, while the other LP-MSPM0G3507 was programmed to both send and receive MCAN messages. Specifically, I aimed to create a project where MCAN messages would be transmitted via MCAN interrupts, and also triggered using a switch on the LP-MSPM0G3507 board.
Initially, the LP-MSPM0G3507 receiving and transmitting MCAN messages worked fine and could successfully receive messages from the other board. However, once I attempted to send a message from the same board using the switch, the MCAN message reception stopped working.
Upon debugging, I found that after sending the MCAN message using the switch, the MCAN0_INST_IRQHandler
stopped being called, and the DL_MCAN_getOpMode(MCAN0_INST)
function no longer returned DL_MCAN_OPERATION_MODE_NORMAL.
I have looked into the MCAN message transmission and reception logic from the example (examples > nortos > msp_subsystems > can_to_i2c_target_bridge) and understand the basic mechanism. However, I am still unsure why the interrupts on the LP-MSPM0G3507 stop triggering when I attempt to transmit a CAN message while it is already receiving messages via MCAN interrupts.
Could you please provide some guidance or suggestions?
The source code for the LP-MSPM0G3507 handling CAN transmission and reception is included below.
- main source code
/* * Copyright (c) 2021, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "ti_msp_dl_config.h" #include <stdio.h> #define LED_STATUS_ON ((uint8_t) 0x00) #define LED_STATUS_OFF ((uint8_t) 0x01) #define ID_MODE_STANDARD (0x0U) #define ID_MODE_EXTENDED (0x1U) volatile uint32_t gInterruptLine1Status; volatile bool gServiceInt; static void processRxMsg(DL_MCAN_RxBufElement *rxMsg); DL_MCAN_TxBufElement txMsg1; int main(void) { DL_MCAN_RxBufElement rxMsg; DL_MCAN_RxFIFOStatus rxFS; /* Identifier Value. */ txMsg1.id = ((uint32_t)(0x3)) << 18U; /* Transmit data frame. */ txMsg1.rtr = 0U; /* 11-bit standard identifier. */ txMsg1.xtd = 0U; /* ESI bit in CAN FD format depends only on error passive flag. */ txMsg1.esi = 0U; /* Transmitting 4 bytes. */ txMsg1.dlc = 1U; /* CAN FD frames transmitted with bit rate switching. */ txMsg1.brs = 1U; /* Frame transmitted in CAN FD format. */ txMsg1.fdf = 1U; /* Store Tx events. */ txMsg1.efc = 1U; /* Message Marker. */ txMsg1.mm = 0xAAU; /* Data bytes. */ txMsg1.data[0] = LED_STATUS_ON; SYSCFG_DL_init(); gServiceInt = false; gInterruptLine1Status = 0; // enable switch NVIC_EnableIRQ(GPIO_SWITCHES_INT_IRQN); NVIC_EnableIRQ(MCAN0_INST_INT_IRQN); while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(MCAN0_INST)) ; while (1) { /* * Wait for flag interrupt to be triggered and flag to check received * message is set to true. */ while (false == gServiceInt) { __WFE(); } gServiceInt = false; rxFS.fillLvl = 0; if ((gInterruptLine1Status & MCAN_IR_RF0N_MASK) == MCAN_IR_RF0N_MASK) { rxFS.num = DL_MCAN_RX_FIFO_NUM_0; while ((rxFS.fillLvl) == 0) { DL_MCAN_getRxFIFOStatus(MCAN0_INST, &rxFS); } DL_MCAN_readMsgRam( MCAN0_INST, DL_MCAN_MEM_TYPE_FIFO, 0U, rxFS.num, &rxMsg); DL_MCAN_writeRxFIFOAck(MCAN0_INST, rxFS.num, rxFS.getIdx); processRxMsg(&rxMsg); gInterruptLine1Status &= ~(MCAN_IR_RF0N_MASK); } } } void processRxMsg(DL_MCAN_RxBufElement *rxMsg) { uint32_t idMode; uint32_t id; idMode = rxMsg->xtd; if (ID_MODE_EXTENDED == idMode) { id = rxMsg->id; } else { /* Assuming package is using 11-bit standard ID. * When package uses standard id, ID is stored in ID[28:18]*/ id = ((rxMsg->id & (uint32_t) 0x1FFC0000) >> (uint32_t) 18); } /* switch (id) { case 0x3: if (rxMsg->data[0] == LED_STATUS_ON) { DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN); } else { DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN); } break; case 0x4: if (rxMsg->data[0] == LED_STATUS_ON) { DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_2_PIN); } else { DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_2_PIN); } break; default: break; } */ } void MCAN0_INST_IRQHandler(void) { switch (DL_MCAN_getPendingInterrupt(MCAN0_INST)) { case DL_MCAN_IIDX_LINE1: /* Check MCAN interrupts fired during TX/RX of CAN package */ gInterruptLine1Status |= DL_MCAN_getIntrStatus(MCAN0_INST); DL_MCAN_clearIntrStatus(MCAN0_INST, gInterruptLine1Status, DL_MCAN_INTR_SRC_MCAN_LINE_1); gServiceInt = true; break; default: break; } } void GROUP1_IRQHandler(void) { switch (DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1)) { case GPIO_SWITCHES_INT_IIDX: switch (DL_GPIO_getPendingInterrupt(GPIO_SWITCHES_PORT)) { case DL_GPIO_IIDX_DIO21: /* Write Tx Message to the Message RAM. */ DL_MCAN_writeMsgRam(MCAN0_INST, DL_MCAN_MEM_TYPE_BUF, 1U, &txMsg1); /* Add request for transmission. */ DL_MCAN_TXBufAddReq(MCAN0_INST, 1U); break; default: break; } break; default: break; } }
- ti_msp_dl_config.c
/* * Copyright (c) 2023, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * ============ ti_msp_dl_config.c ============= * Configured MSPM0 DriverLib module definitions * * DO NOT EDIT - This file is generated for the MSPM0G350X * by the SysConfig tool. */ #include "ti_msp_dl_config.h" /* * ======== SYSCFG_DL_init ======== * Perform any initialization needed before using any board APIs */ SYSCONFIG_WEAK void SYSCFG_DL_init(void) { SYSCFG_DL_initPower(); SYSCFG_DL_GPIO_init(); /* Module-Specific Initializations*/ SYSCFG_DL_SYSCTL_init(); SYSCFG_DL_MCAN0_init(); SYSCFG_DL_SYSCTL_CLK_init(); } SYSCONFIG_WEAK void SYSCFG_DL_initPower(void) { DL_GPIO_reset(GPIOA); DL_GPIO_reset(GPIOB); DL_MCAN_reset(MCAN0_INST); DL_GPIO_enablePower(GPIOA); DL_GPIO_enablePower(GPIOB); DL_MCAN_enablePower(MCAN0_INST); delay_cycles(POWER_STARTUP_DELAY); } SYSCONFIG_WEAK void SYSCFG_DL_GPIO_init(void) { DL_GPIO_initPeripheralAnalogFunction(GPIO_HFXIN_IOMUX); DL_GPIO_initPeripheralAnalogFunction(GPIO_HFXOUT_IOMUX); DL_GPIO_initDigitalInputFeatures(GPIO_SWITCHES_USER_SWITCH_1_IOMUX, DL_GPIO_INVERSION_DISABLE, DL_GPIO_RESISTOR_PULL_UP, DL_GPIO_HYSTERESIS_DISABLE, DL_GPIO_WAKEUP_DISABLE); DL_GPIO_initDigitalOutput(GPIO_LEDS_USER_LED_1_IOMUX); DL_GPIO_initDigitalOutput(GPIO_LEDS_USER_LED_2_IOMUX); DL_GPIO_initDigitalOutput(GPIO_LEDS_PIN_2_IOMUX); DL_GPIO_clearPins(GPIOB, GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_LED_2_PIN | GPIO_LEDS_PIN_2_PIN); DL_GPIO_enableOutput(GPIOB, GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_LED_2_PIN | GPIO_LEDS_PIN_2_PIN); DL_GPIO_setUpperPinsPolarity(GPIOB, DL_GPIO_PIN_21_EDGE_FALL); DL_GPIO_clearInterruptStatus(GPIOB, GPIO_SWITCHES_USER_SWITCH_1_PIN); DL_GPIO_enableInterrupt(GPIOB, GPIO_SWITCHES_USER_SWITCH_1_PIN); DL_GPIO_initPeripheralOutputFunction( GPIO_MCAN0_IOMUX_CAN_TX, GPIO_MCAN0_IOMUX_CAN_TX_FUNC); DL_GPIO_initPeripheralInputFunction( GPIO_MCAN0_IOMUX_CAN_RX, GPIO_MCAN0_IOMUX_CAN_RX_FUNC); } SYSCONFIG_WEAK void SYSCFG_DL_SYSCTL_init(void) { //Low Power Mode is configured to be SLEEP0 DL_SYSCTL_setBORThreshold(DL_SYSCTL_BOR_THRESHOLD_LEVEL_0); DL_SYSCTL_setSYSOSCFreq(DL_SYSCTL_SYSOSC_FREQ_BASE); /* Set default configuration */ DL_SYSCTL_disableHFXT(); DL_SYSCTL_disableSYSPLL(); DL_SYSCTL_setHFCLKSourceHFXTParams(DL_SYSCTL_HFXT_RANGE_32_48_MHZ,10, true); } SYSCONFIG_WEAK void SYSCFG_DL_SYSCTL_CLK_init(void) { while ((DL_SYSCTL_getClockStatus() & (DL_SYSCTL_CLK_STATUS_HFCLK_GOOD | DL_SYSCTL_CLK_STATUS_LFOSC_GOOD)) != (DL_SYSCTL_CLK_STATUS_HFCLK_GOOD | DL_SYSCTL_CLK_STATUS_LFOSC_GOOD)) { /* Ensure that clocks are in default POR configuration before initialization. * Additionally once LFXT is enabled, the internal LFOSC is disabled, and cannot * be re-enabled other than by executing a BOOTRST. */ ; } } static const DL_MCAN_ClockConfig gMCAN0ClockConf = { .clockSel = DL_MCAN_FCLK_HFCLK, .divider = DL_MCAN_FCLK_DIV_1, }; static const DL_MCAN_InitParams gMCAN0InitParams= { /* Initialize MCAN Init parameters. */ .fdMode = true, .brsEnable = true, .txpEnable = false, .efbi = false, .pxhddisable = false, .darEnable = false, .wkupReqEnable = true, .autoWkupEnable = true, .emulationEnable = true, .tdcEnable = true, .wdcPreload = 255, /* Transmitter Delay Compensation parameters. */ .tdcConfig.tdcf = 10, .tdcConfig.tdco = 6, }; static const DL_MCAN_ConfigParams gMCAN0ConfigParams={ /* Initialize MCAN Config parameters. */ .monEnable = false, .asmEnable = false, .tsPrescalar = 15, .tsSelect = 0, .timeoutSelect = DL_MCAN_TIMEOUT_SELECT_CONT, .timeoutPreload = 65535, .timeoutCntEnable = false, .filterConfig.rrfs = true, .filterConfig.rrfe = true, .filterConfig.anfe = 1, .filterConfig.anfs = 1, }; static const DL_MCAN_MsgRAMConfigParams gMCAN0MsgRAMConfigParams ={ /* Standard ID Filter List Start Address. */ .flssa = MCAN0_INST_MCAN_STD_ID_FILT_START_ADDR, /* List Size: Standard ID. */ .lss = MCAN0_INST_MCAN_STD_ID_FILTER_NUM, /* Extended ID Filter List Start Address. */ .flesa = MCAN0_INST_MCAN_EXT_ID_FILT_START_ADDR, /* List Size: Extended ID. */ .lse = MCAN0_INST_MCAN_EXT_ID_FILTER_NUM, /* Tx Buffers Start Address. */ .txStartAddr = MCAN0_INST_MCAN_TX_BUFF_START_ADDR, /* Number of Dedicated Transmit Buffers. */ .txBufNum = MCAN0_INST_MCAN_TX_BUFF_SIZE, .txFIFOSize = 5, /* Tx Buffer Element Size. */ .txBufMode = 0, .txBufElemSize = DL_MCAN_ELEM_SIZE_64BYTES, /* Tx Event FIFO Start Address. */ .txEventFIFOStartAddr = MCAN0_INST_MCAN_TX_EVENT_START_ADDR, /* Event FIFO Size. */ .txEventFIFOSize = MCAN0_INST_MCAN_TX_EVENT_SIZE, /* Level for Tx Event FIFO watermark interrupt. */ .txEventFIFOWaterMark = 0, /* Rx FIFO0 Start Address. */ .rxFIFO0startAddr = MCAN0_INST_MCAN_FIFO_0_START_ADDR, /* Number of Rx FIFO elements. */ .rxFIFO0size = MCAN0_INST_MCAN_FIFO_0_NUM, /* Rx FIFO0 Watermark. */ .rxFIFO0waterMark = 0, .rxFIFO0OpMode = 0, /* Rx FIFO1 Start Address. */ .rxFIFO1startAddr = MCAN0_INST_MCAN_FIFO_1_START_ADDR, /* Number of Rx FIFO elements. */ .rxFIFO1size = MCAN0_INST_MCAN_FIFO_1_NUM, /* Level for Rx FIFO 1 watermark interrupt. */ .rxFIFO1waterMark = 3, /* FIFO blocking mode. */ .rxFIFO1OpMode = 0, /* Rx Buffer Start Address. */ .rxBufStartAddr = MCAN0_INST_MCAN_RX_BUFF_START_ADDR, /* Rx Buffer Element Size. */ .rxBufElemSize = DL_MCAN_ELEM_SIZE_8BYTES, /* Rx FIFO0 Element Size. */ .rxFIFO0ElemSize = DL_MCAN_ELEM_SIZE_8BYTES, /* Rx FIFO1 Element Size. */ .rxFIFO1ElemSize = DL_MCAN_ELEM_SIZE_8BYTES, }; static const DL_MCAN_StdMsgIDFilterElement gMCAN0StdFiltelem = { .sfec = 0x1, .sft = 0x0, .sfid1 = 0, .sfid2 = 4, }; static const DL_MCAN_BitTimingParams gMCAN0BitTimes = { /* Arbitration Baud Rate Pre-scaler. */ .nomRatePrescalar = 0, /* Arbitration Time segment before sample point. */ .nomTimeSeg1 = 126, /* Arbitration Time segment after sample point. */ .nomTimeSeg2 = 31, /* Arbitration (Re)Synchronization Jump Width Range. */ .nomSynchJumpWidth = 31, /* Data Baud Rate Pre-scaler. */ .dataRatePrescalar = 0, /* Data Time segment before sample point. */ .dataTimeSeg1 = 14, /* Data Time segment after sample point. */ .dataTimeSeg2 = 3, /* Data (Re)Synchronization Jump Width. */ .dataSynchJumpWidth = 3, }; SYSCONFIG_WEAK void SYSCFG_DL_MCAN0_init(void) { DL_MCAN_RevisionId revid_MCAN0; DL_MCAN_enableModuleClock(MCAN0_INST); DL_MCAN_setClockConfig(MCAN0_INST, (DL_MCAN_ClockConfig *) &gMCAN0ClockConf); /* Get MCANSS Revision ID. */ DL_MCAN_getRevisionId(MCAN0_INST, &revid_MCAN0); /* Wait for Memory initialization to be completed. */ while(false == DL_MCAN_isMemInitDone(MCAN0_INST)); /* Put MCAN in SW initialization mode. */ DL_MCAN_setOpMode(MCAN0_INST, DL_MCAN_OPERATION_MODE_SW_INIT); /* Wait till MCAN is not initialized. */ while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(MCAN0_INST)); /* Initialize MCAN module. */ DL_MCAN_init(MCAN0_INST, (DL_MCAN_InitParams *) &gMCAN0InitParams); /* Configure MCAN module. */ DL_MCAN_config(MCAN0_INST, (DL_MCAN_ConfigParams*) &gMCAN0ConfigParams); /* Configure Bit timings. */ DL_MCAN_setBitTime(MCAN0_INST, (DL_MCAN_BitTimingParams*) &gMCAN0BitTimes); /* Configure Message RAM Sections */ DL_MCAN_msgRAMConfig(MCAN0_INST, (DL_MCAN_MsgRAMConfigParams*) &gMCAN0MsgRAMConfigParams); /* Configure Standard ID filter element */ DL_MCAN_addStdMsgIDFilter(MCAN0_INST, 0U, (DL_MCAN_StdMsgIDFilterElement *) &gMCAN0StdFiltelem); /* Set Extended ID Mask. */ DL_MCAN_setExtIDAndMask(MCAN0_INST, MCAN0_INST_MCAN_EXT_ID_AND_MASK ); /* Loopback mode */ /* Take MCAN out of the SW initialization mode */ DL_MCAN_setOpMode(MCAN0_INST, DL_MCAN_OPERATION_MODE_NORMAL); while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(MCAN0_INST)); /* Enable MCAN mopdule Interrupts */ DL_MCAN_enableIntr(MCAN0_INST, MCAN0_INST_MCAN_INTERRUPTS, 1U); DL_MCAN_selectIntrLine(MCAN0_INST, DL_MCAN_INTR_MASK_ALL, DL_MCAN_INTR_LINE_NUM_1); DL_MCAN_enableIntrLine(MCAN0_INST, DL_MCAN_INTR_LINE_NUM_1, 1U); /* Enable MSPM0 MCAN interrupt */ DL_MCAN_clearInterruptStatus(MCAN0_INST,(DL_MCAN_MSP_INTERRUPT_LINE1)); DL_MCAN_enableInterrupt(MCAN0_INST,(DL_MCAN_MSP_INTERRUPT_LINE1)); }
Lastly, here are the details of my development environment:
- Development environment: CCS 12.8.1
- MSPM0 SDK version: 2.02.00.05
Thank you for your help!