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.

AM335x DCAN Receive not working

Other Parts Discussed in Thread: SYSBIOS

Hi,

I am trying the dcanTxRx.c starterware example code on AM335x based Phytech board. I am using CAN232 (from Gridconnect) to send the CAN data frames from AM335x to CAN232 (CAN232 is connected to Serial console  terraterm). The CAN data frame transfer from AM335x to CAN 232 works fine (i'm able to see the packet received in the serial console) where as the CAN Receive from CAN232 to AM335x is not working. I am sending Data packet from Terraterm through CAN232 to AM335x which is not working.

I just connected 2 CAN232 modules and tried to send and Receive CAN frames, and it works fine. This was done to ensure that the CAN232 works fine for send and receive. I'm using the following code for CAN Receive at AM335x (Same code in dcanTxRx.c example).

main code

{

/* Enable the DCAN1 module clock */
DCANModuleClkConfig();

/* Perform the pinmux for DCAN1 */
DCANPinMuxSetUp(0);

/* Initialize the DCAN message RAM */
DCANMsgRAMInit(1);

/* Enable the processor IRQ */
IntMasterIRQEnable();

/* Register the DCAN interrupts */
DCANAintcConfigure();

/* Perform the DCAN configuration */
ConfigureDCAN();

index = CAN_NUM_OF_MSG_OBJS;

while(index--)
{
/* Invalidate all message objects in the message RAM */
CANInValidateMsgObject(SOC_DCAN_1_REGS, index, DCAN_IF2_REG);
}

entry.flag = rxflag;
// entry.id = canId;
entry.id = 0;

  CANMsgObjectConfig(SOC_DCAN_1_REGS, &entry);

CANMsgObjectConfig(SOC_DCAN_1_REGS, &entry);

entry.flag = (CAN_EXT_FRAME | CAN_MSG_DIR_RX | CAN_DATA_FRAME);
entry.id = 0x00;


/*
** Configure a receive message object to accept CAN
** frames with extended ID.
*/
CANMsgObjectConfig(SOC_DCAN_1_REGS, &entry);

/* Start the CAN transfer */
DCANNormalModeSet(SOC_DCAN_1_REGS);

/* Enable the error interrupts */
DCANIntEnable(SOC_DCAN_1_REGS, DCAN_ERROR_INT);

/* Enable the interrupt line 0 of DCAN module */
DCANIntLineEnable(SOC_DCAN_1_REGS, DCAN_INT_LINE0);

while(1);

}

void CANRxObjectConfig(unsigned int baseAdd, can_frame* canPtr)
{
unsigned int idLen;
unsigned int msgIndex;

msgIndex = (CAN_NUM_OF_MSG_OBJS / 2);

idLen = (canPtr->flag & CAN_EXT_FRAME) ? DCAN_29_BIT_ID : DCAN_11_BIT_ID;

/* don't Use Acceptance mask. */

DCANUseAcceptanceMaskControl(baseAdd, DCAN_MASK_IGNORED, DCAN_IF2_REG);
// DCANUseAcceptanceMaskControl(baseAdd, DCAN_MASK_USED, DCAN_IF2_REG);

/* Configure the DCAN mask registers for acceptance filtering. */
// DCANMsgObjectMskConfig(baseAdd, DCAN_IDENTIFIER_MSK(DCAN_ID_MASK,
// DCAN_ID_MSK_11_BIT), DCAN_MSK_MSGDIR_DISABLE,
// DCAN_MSK_EXT_ID_ENABLE, DCAN_IF2_REG);

/* Set the message valid bit */
DCANMsgObjValidate(baseAdd, DCAN_IF2_REG);

/* Set the message id of the frame to be received */
DCANMsgIdSet(baseAdd, canPtr->id, idLen, DCAN_IF2_REG);

/* Set the message object direction as receive */
DCANMsgDirectionSet(baseAdd, DCAN_RX_DIR, DCAN_IF2_REG);

/* Enable the receive interrupt for the message object */

DCANMsgObjIntEnable(baseAdd, DCAN_RECEIVE_INT, DCAN_IF2_REG);

/* Enable the FIFO end of block */
DCANFIFOEndOfBlockControl(baseAdd, DCAN_END_OF_BLOCK_ENABLE, DCAN_IF2_REG);


/* Check for the message valid status for receive objects */
while((DCANMsgValidStatusGet(baseAdd, msgIndex)) &&
(msgIndex <= (CAN_NUM_OF_MSG_OBJS - 1)))
{
msgIndex++;
}

/* Configure the command register */
DCANCommandRegSet(baseAdd, (DCAN_ACCESS_CTL_BITS | DCAN_MSG_WRITE |
DCAN_ACCESS_MSK_BITS | DCAN_ACCESS_ARB_BITS),
msgIndex, DCAN_IF2_REG);
}

The ISR for DCAN Interrupt 0 is as follows.

static void DCANIsr0(void)
{
unsigned int errVal;
unsigned int data[2];
unsigned char *dataPtr;
unsigned int index = 0;
unsigned int msgNum;
if (DCANIntRegStatusGet(SOC_DCAN_1_REGS, 0xFFFF0000))
{
ConsoleUtilsPrintf("**INT1 is getting generated**\n");
}

while(DCANIntRegStatusGet(SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT))
{
if(DCANIntRegStatusGet(SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT) ==
DCAN_ERROR_OCCURED)
{
/* Check the status of DCAN Status and error register */
errVal = DCANErrAndStatusRegInfoGet(SOC_DCAN_1_REGS);

if(errVal & DCAN_MOD_IN_BUS_OFF_STATE)
{
ConsoleUtilsPrintf("**DCAN is in Bus-off state**\n");

/*
** This feature will automatically get the CAN bus to bus-on
** state once the error counters are below the error warning
** limit.
*/
DCANAutoBusOnControl(SOC_DCAN_1_REGS, DCAN_AUTO_BUS_ON_ENABLE);
}

if(errVal & DCAN_ERR_WARN_STATE_RCHD)
{
ConsoleUtilsPrintf("Atleast one of the error counters have");
ConsoleUtilsPrintf(" reached the error warning limit\n");
}
}

if((DCANIntRegStatusGet(SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT) !=
DCAN_NO_INT_PENDING) &&
((DCANIntRegStatusGet(SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT) !=
DCAN_ERROR_OCCURED)))
{
/* Get the number of the message object which caused the interrupt */
msgNum = DCANIntRegStatusGet(SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT);

/* Interrupt handling for transmit objects */
if(msgNum < (CAN_NUM_OF_MSG_OBJS/2))
{
/* Clear the Interrupt pending status */
CANClrIntPndStat(SOC_DCAN_1_REGS, msgNum, DCAN_IF1_REG);

isrTxFlag = 0;

if(value == index3)
{
/* Disable the transmit interrupt of the message object */
CANTxIntDisable(SOC_DCAN_1_REGS, msgNum, DCAN_IF1_REG);

/* Invalidate the transmit message object */
CANInValidateMsgObject(SOC_DCAN_1_REGS, msgNum, DCAN_IF1_REG);
}
}

if((msgNum >= (CAN_NUM_OF_MSG_OBJS/2)) && (msgNum < CAN_NUM_OF_MSG_OBJS))
{
/* Read a received message from message RAM to interface register */
CANReadMsgObjData(SOC_DCAN_1_REGS, msgNum, (unsigned int*) data, DCAN_IF2_REG);

/* Clear the Interrupt pending status */
CANClrIntPndStat(SOC_DCAN_1_REGS, msgNum, DCAN_IF2_REG);

dataPtr = (unsigned char*) data;

ConsoleUtilsPrintf("Data received = ");

index1 = (DCANIFMsgCtlStatusGet(SOC_DCAN_1_REGS, DCAN_IF2_REG) &
DCAN_DAT_LEN_CODE_READ);

/* Print the received data bytes on the UART console */
for(index = 0; index < index1; index++)
{
ConsoleUtilsPrintf("%c", *dataPtr++);
}

ConsoleUtilsPutChar('\r');
ConsoleUtilsPutChar('\n');

isrRxFlag = 0;

if(value == index3)
{
/* Disable the receive interrupt of the message object */
CANRxIntDisable(SOC_DCAN_1_REGS, msgNum, DCAN_IF2_REG);

/* Invalidate the receive message object */
CANInValidateMsgObject(SOC_DCAN_1_REGS, msgNum, DCAN_IF2_REG);
}
}
}
}
}

I'm configuring AM335x for 1Mb/sec and the CANId is set to 1. Please suggest what is the issue here?

Regards,

  • Just a correction canid is set to 0
  • sram said:
    I am trying the dcanTxRx.c starterware example code on AM335x based Phytech board.

    Is this from Starterware 2.00.01.01?

    Which specific pins are you using for DCAN1?  Each DCAN is pinned out to 3 different sets of pins.

    sram said:
    /* Perform the pinmux for DCAN1 */
    DCANPinMuxSetUp(0);

    Are you calling the function from platform/evmAM335x/dcan.c?  That function as it ships in starterware will only configure DCAN0 (regardless of the argument passed).

  • Moving this to the Starterware forum.
  • Thanks brad,

    Please see the answers below.


    Yes, i'm using starterware 02_00_01_01.

    i am using the following pin muxing for DCAN1. I have modified the DCANPinMuxSetUp function to use DCAN1 signals irrespective of the argument passed.

    DCANPinMuxSetUp()
    {
    /* Pin Mux for DCAN0 Tx Pin */
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_UART_CTSN(0)) =
    DCAN_SLEWFAST_RXDISABLED_PULLDWN_PUPDENABLED_MODE2; // This control register is at address 0x44E1-0968 and 0x02 corresponds to dcan1_tx

    /* Pin Mux for DCAN0 Rx Pin */
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_UART_RTSN(0)) =
    DCAN_SLEWFAST_RXENABLED_PULLUP_PUPDENABLED_MODE2; // This control register is at address 0x44E1-0968 and 0x02 corresponds to dcan1_rx
    }

    Secondly, i am able to send CAN packet from AM335x target to CAN232 module and it works fine, which shows that the clk configuration, pin muxing etc are proper. I am facing problem with CAN reception.

    Please suggest.
  • sram said:
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_UART_CTSN(0)) =
    DCAN_SLEWFAST_RXDISABLED_PULLDWN_PUPDENABLED_MODE2; // This control register is at address 0x44E1-0968 and 0x02 corresponds to dcan1_tx

    From the look of this, it appears you have a pull-down on the dcan1_tx signal.  Why is that?  I expected this to either be "no pull" (since it is an output) or perhaps a pull-up to keep it in an unused state during sleep modes, etc.

    Can you please report the run-time values of all of the following registers:

    • 0x44E10900
    • 0x44E10904
    • 0x44E10968
    • 0x44E1096C
    • 0x44E10980
    • 0x44E10984

    sram said:
    Secondly, i am able to send CAN packet from AM335x target to CAN232 module and it works fine, which shows that the clk configuration, pin muxing etc are proper. I am facing problem with CAN reception.

    You've proven the pin muxing is correct for transmit.  There could very well still be an issue with receive.  I want to verify with the above check that you don't have more than 1 pin configured inadvertently as dcan1_rx.

    Can you look at the DCAN TEST register?  The Rx bit shows the status of the receive pin.  Are you able to see high and low levels with that bit?

    What's the value of the RIOC register?

  • Brad:

    From the look of this, it appears you have a pull-down on the dcan1_tx signal.  Why is that?  I expected this to either be "no pull" (since it is an output) or perhaps a pull-up to keep it in an unused state during sleep modes, etc.

     This was pulldown by default in the starterware example Code dcanTxRx.c but when i tried to make it pullup, Can Tx doesn't work and similarly for the Rx pin the default it is configured as pull up and here also the pull down doesn't work.

    Brad:

    Can you please report the run-time values of all of the following registers:

    • 0x44E10900
    • 0x44E10904
    • 0x44E10968
    • 0x44E1096C
    • 0x44E10980
    • 0x44E10984

    Here are the values stored in these registers.

    • 0x44E10900 - 0x00000030
    • 0x44E10904 - 0x00000030
    • 0x44E10968 - 0x00000002
    • 0x44E1096C - 0x00000032
    • 0x44E10980 - 0x00000037
    • 0x44E10984 - 0x00000037

    Brad:

    Can you look at the DCAN TEST register?  The Rx bit shows the status of the receive pin.  Are you able to see high and low levels with that bit?

    The DCAN Test Register Rx Bit toggles for every function execution starting from main.

    RIOC Register has the value 0x00040008

    I have captured all the control registers and DCAN1 Registers during init and runtime and attaching them here for your reference.4857.control_module_after_canclk_config.txt1121.dcan1_rx_config.txt7115.dcan1_rx_runtime.txt

  • Your pin muxing looks correct. Sorry to belabor that, but it was critical to be sure!

    Did you update DCANMsgRAMInit too? The control module dump you sent did not show dcan1_raminit_done=1 (though that might be related to the timing of when you captured it).
  • Did you update DCANMsgRAMInit too? The control module dump you sent did not show dcan1_raminit_done=1 (though that might be related to the timing of when you captured it).

    Yes You are right, the DCAN1 message RAM was not initialized but only the DCAN0 message RAM was initialized.

    I added the code to initialize the DCAN1 message RAM but still having the same problem, when i send some CAN packet the Receive ISR0 is not getting triggered!

    I wonder how the DCAN1 Tx works even if i don't initialize the Message RAM for DCAN1?

  • Sram,

    When you type into the console, do you see the "COM TX Serial Transmit Data" LED blink to indicate that the data has left the CAN232 device(i.e before hitting the AM335x RX)?

    Did this example work on the AM335x GPEVM?

    From reading the posts, you are using DCAN1 correct? Just out of curiosity, I noticed in the Phycore AM335x HW documentation (I assume this is the HW you are using), there are some special notes for DCAN0 on table 31, I guess these aren't applicable to what you are trying (MII modes)?

    http://phytec.com/site/assets/files/1345/phycore-am335x_manual.pdf

    Lali

  • Please see my answers below

    When you type into the console, do you see the "COM TX Serial Transmit Data" LED blink to indicate that the data has left the CAN232 device(i.e before hitting the AM335x RX)?

    The COM RX LED on CAN 232 glows which indicates that the Serial data is received from terraterm. There is one more LED CAN TX which receives the data from Serial Port and sends the data to AM335x. But this LED is not glowing. I checked with 2 CAN 232 modules connected back to back and both TX and RX work fine which indicates that CAN232 is fine. Now only suspect is AM335x CAN RX code as TX works from AM335x to CAN232. I don't suspect any hardware issues.

    Did this example work on the AM335x GPEVM?

    Currently I don't have GPEVM. I am working on Phytech WEGA board. http://www.phytec.in/manuals/HARDWARE-MANUAL-WEGA.pdf

     

    From reading the posts, you are using DCAN1 correct? Just out of curiosity, I noticed in the Phycore AM335x HW documentation (I assume this is the HW you are using), there are some special notes for DCAN0 on table 31, I guess these aren't applicable to what you are trying (MII modes)?

    Yes I am using DCAN1. I'm not using DCAN0 so it doesn't matter. Secondly the CAN Transmission works from AM335x to CAN232 which proves the fact that the hardware configuration is correct.

     

     

     

     

  • sram,

    When you set the TEST bit on the DCAN1_CTL resgister, do you see anything on the DCAN1_TEST (offset 14h) RX bit? This is supporsed to monitor the RX pin value, so at least we can determine if the frames hit the RX pin.

    Are you able to run the dcan_app_loopback example first to ensure that all is well at the SOC loopback before moving to comms with the external hardware?

    I don't think the example supports this, but you can also do an external loopback by setting the EXL in the TEST register to 1 (Pg 4672 of the TRM).

    Also, looking at your register dumps, shouldn't DCAN1_IF2DATA and DCAN1_IF2DATB have some frames in it?
    You are using connector X13 on the Phytech board? Everything's jumpered correctly on JP7 and JP8 (3+4)?

    I don't have access to a Phytech SOM or its schematics, but I believe the SOM has a CAN transceiver also onboard, this won't be a problem when connected to the external CAN-RS232 transceiver on the RX side?


    Lali
  • Lali, Please see my response below:

    When you set the TEST bit on the DCAN1_CTL resgister, do you see anything on the DCAN1_TEST (offset 14h) RX bit? This is supporsed to monitor the RX pin value, so at least we can determine if the frames hit the RX pin.

    sram: I set the TEST bit in DCAN1_CTL register and observed that, the Rx bit is initially 0 and becomes 1 when i TX a CAN packet and also it changes from 0 to 1 when i try to receive the CAN packet.

    Are you able to run the dcan_app_loopback example first to ensure that all is well at the SOC loopback before moving to comms with the external hardware?

    sram: I tried the Loopback Mode (TRM 23.3.8.3.2) and in this mode, i can see the DCAN1_IF1DATA, DCAN1_IF1DATB contents reflected in DCAN1_IF2DATA and DCAN1_IF2DATAB registers. So the "Loopback mode" works fine. But when i tried the "External Loop back mode", the IF1DATA, IF2DATB contents will not get reflected in IF2DATA and IF2DATB registers. Not sure why this didn't work! The external loop back mode sends data through CAN core to TX pin and Back to Rx in CAN core as per TRM so has no external dependency here. I think this should work with having any CAN nodes connected to AM335x. But it is not working. Does this mean that there is some issue in the AM335x CAN port or the Code which configures the CAN port for RX mode?

    From Phytech Board point, i have taken care of the necessary configuration and settings.

    Regards,
  • sram,

    Appreciate the feedback. We are taking a closer look and will get back to you.
    In the meantime, if you have any updates, please post here. Thanks for your patience.

    Lali
  • sram,

    Here's some feedback after some experimenting. I wanted to see if I can get as close as possible to the scenario that you have with the Phytec board, and external CAN converter.

    I wanted to see if the AM335x GPEVM board-board loopback example would work to rule out any problems with the CAN port or the code. Below is a screenshot of the experiment and the console prints. Instructions are located here.


    This is using the DCAN loopback example that is provided in the Industrial SDK Starterware package located at 

    http://downloads.ti.com/sitara_indus/esd/SYSBIOSSDK-IND-SITARA/02_01_00_01/index_FDS.html

    The same .out was used on both sides obviously each side configured differently. The example is located at sysbios_ind_sdk_2.1.0.1\sdk\starterware\examples\dcan\frame_tx_rx.

    I know that you had confirmed earlier that the pinmuxing is all good.
    Did Phytech have any feedback on this issue?

    Lali 

  • Hi Lalindra,

    This was the first example code I looked into but I didn't have TI GPEVM's with me to experiment so we procured the CAN232 converters to check the CAN communication between the Phytech WEGA EVM and the PC HyperTerminal and Vice Versa.

    Regards,

    Seetaram

  • Hi Lalindra,

    The DCAN Receive is still not working. Can you suggest how to make it work in Polling mode that interrupt mode?

    Regards,

    Seetaram

  • Seetaram,

    Did you eventually run this on the AM335x GPEVM to reproduce what I had shown earlier with the example running?

    Are you still trying to get it to work with the Phytec device?

    " Can you suggest how to make it work in Polling mode that interrupt mode?"

    You are trying to get it to work in polling mode?

    Lali