Other Parts Discussed in Thread: C2000WARE, SYSCONFIG
Tool/software:
Hi
In my project, I am utilizing two CPUs where CPU1 sends commands to CPU2 via Inter-Processor Communication (IPC). Upon receiving a command from CPU1, CPU2 transmits the CAN data stored in its buffer. CPU2 receives CAN data from an external source. However, I am encountering an issue: when I start or run the code, CPU2 gets stuck during CAN initialization. Upon debugging, the code halts at the can_initialization_RAM
section.
I have configured the IPC communication between CPU1 and CPU2 as per the guidelines provided in the C2000 Multicore Development User Guide. Specifically, I have ensured that CPU1 writes data to the CPU1_TO_CPU2 MSGRAM, and CPU2 reads from this location.
below code for CPU1
.............................................................................
/
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "ipc.h"
#include "memcfg.h"
//
// Defines
//
#define IPC_CMD_READ_CAN 0x1002
#define CPU1_TO_CPU2_FLAG IPC_FLAG0
#define CPU2_TO_CPU1_FLAG IPC_FLAG1
#define SYNC_FLAG IPC_FLAG31
#define CAN_DATA_SIZE 8
#pragma DATA_SECTION(canData, "MSGRAM_CPU2_TO_CPU1")
volatile uint32_t canData[CAN_DATA_SIZE];
//
// Function to Blink LED
//
void blinkLED()
{
GPIO_togglePin(DEVICE_GPIO_PIN_LED1);
DEVICE_DELAY_US(500000);
GPIO_togglePin(DEVICE_GPIO_PIN_LED1);
}
//
// Main Function
//
void main(void)
{
// Initialize device and peripherals
Device_init();
// MemCfg_initSections(MEMCFG_SECT_MSGRAM_CPU2_TO_CPU1);
//MemCfg_initSections(MEMCFG_SECT_MSGRAM_CPU2_TO_CPU1);
Interrupt_initModule();
Interrupt_initVectorTable();
Board_init();
// Configure LED pin
GPIO_setPinConfig(DEVICE_GPIO_PIN_LED1);
GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
GPIO_setMasterCore(DEVICE_GPIO_PIN_LED1, GPIO_CORE_CPU1);
// Initialize IPC and synchronize with CPU2
IPC_clearFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG_ALL);
IPC_sync(IPC_CPU1_L_CPU2_R, SYNC_FLAG);
EINT; // Enable global interrupts
ERTM;
// while(1)
// {
// // Request CAN data from CPU2
// IPC_sendCommand(IPC_CPU1_L_CPU2_R, CPU1_TO_CPU2_FLAG, IPC_ADDR_CORRECTION_ENABLE,
// IPC_CMD_READ_CAN, 0, 0);
//
// // Wait for CPU2 response before accessing data
// IPC_waitForAck(IPC_CPU1_L_CPU2_R, CPU2_TO_CPU1_FLAG);
//
// // Blink LED immediately when data is received
// blinkLED();
//
// DEVICE_DELAY_US(1000000);
// }
while(1)
{
// Request CAN data from CPU2
IPC_sendCommand(IPC_CPU1_L_CPU2_R, CPU1_TO_CPU2_FLAG, IPC_ADDR_CORRECTION_ENABLE,
IPC_CMD_READ_CAN, 0, 0);
// Wait for CPU2 response before accessing data
IPC_waitForAck(IPC_CPU1_L_CPU2_R, CPU2_TO_CPU1_FLAG);
// Check received data
uint8_t i;
bool valid = true;
for(i = 0; i < CAN_DATA_SIZE; i++)
{
if(canData[i] == 0)
{
valid = false;
break;
}
}
if(valid)
{
blinkLED();
}
DEVICE_DELAY_US(1000000);
}
}
below code for CPU2
............................................................................
//
// Included Files
//
#include "device.h"
#include "can.h"
#include "interrupt.h"
#include "sysctl.h"
#include "board.h"
#include "ipc.h"
//
// Defines
//
#define IPC_CMD_READ_CAN 0x1002
#define IPC_CMD_RESP 0x2002
#define CPU1_TO_CPU2_FLAG IPC_FLAG0
#define CPU2_TO_CPU1_FLAG IPC_FLAG1
#define SYNC_FLAG IPC_FLAG31
#define TX_MSG_OBJ_ID 1
#define RX_MSG_OBJ_ID 1
#define MSG_DATA_LENGTH 8
//#pragma DATA_SECTION(rxMsgData, "MSGRAM_CPU1_TO_CPU2")
//volatile uint16_t rxMsgData[MSG_DATA_LENGTH] = {0};
#pragma DATA_SECTION(rxMsgData, "GSRAM");
volatile uint16_t rxMsgData[MSG_DATA_LENGTH] = {0};
//
// Function Prototypes
//
__interrupt void IPC_ISR0(void);
__interrupt void canbISR(void);
//
// Main Function
//
void main(void)
{
// Initialize Device & GPIOs
Device_init();
// MemCfg_initSections(MSGRAM_CPU1_TO_CPU2);
Device_initGPIO();
// Configure CANB for RX
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);
// Initialize CANB Module
CAN_initModule(CANB_BASE);
CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 500000, 20);
// Enable CANB interrupts
CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0 | CAN_INT_ERROR | CAN_INT_STATUS);
// Initialize Interrupt System
Interrupt_initModule();
Interrupt_register(INT_CANB0, &canbISR);
Interrupt_enable(INT_CANB0);
// Setup RX Message Object
CAN_setupMessageObject(CANB_BASE, RX_MSG_OBJ_ID, 0x1, CAN_MSG_FRAME_STD,
CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
CAN_startModule(CANB_BASE);
// IPC Initialization
IPC_clearFlagLtoR(IPC_CPU2_L_CPU1_R, IPC_FLAG_ALL);
IPC_sync(IPC_CPU2_L_CPU1_R, SYNC_FLAG);
// Register IPC Interrupt
Interrupt_register(INT_IPC_0, IPC_ISR0);
Interrupt_enable(INT_IPC_0);
// Enable Global Interrupts
EINT;
ERTM;
while (1);
}
//
// CANB Interrupt Service Routine (ISR)
//
__interrupt void canbISR(void)
{
uint32_t status = CAN_getInterruptCause(CANB_BASE);
if (status == RX_MSG_OBJ_ID)
{
// Read received CAN data
CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID,(uint16_t*)rxMsgData);
}
CAN_clearGlobalInterruptStatus(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
//
// IPC Interrupt Service Routine (Handles CPU1 -> CPU2 Command)
//
__interrupt void IPC_ISR0(void)
{
uint32_t command;
// Read IPC command from CPU1
IPC_readCommand(IPC_CPU2_L_CPU1_R, CPU1_TO_CPU2_FLAG, IPC_ADDR_CORRECTION_ENABLE,
&command, NULL, NULL);
if (command == IPC_CMD_READ_CAN)
{
uint8_t i;
// Send stored CAN data to CPU1 via IPC
for(i = 0; i < MSG_DATA_LENGTH; i++)
{
IPC_sendCommand(IPC_CPU2_L_CPU1_R, CPU2_TO_CPU1_FLAG, IPC_ADDR_CORRECTION_ENABLE,
IPC_CMD_RESP, rxMsgData[i], i);
}
// Wait for CPU1 to acknowledge reception
IPC_waitForAck(IPC_CPU2_L_CPU1_R, CPU2_TO_CPU1_FLAG);
}
IPC_ackFlagRtoL(IPC_CPU2_L_CPU1_R, CPU1_TO_CPU2_FLAG);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}