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.

DCAN update DLC of a message

Other Parts Discussed in Thread: HALCOGEN

In my program i want to send multiple messages though 1 Mailbox, But i can't seem to change the message DLC, i can change it in the CAN init, where HalCoGen generated the messageboxes and writes the DLC in the IF1MCTL register. But i need to change it runtime when i send multiple messages.

I want to change the DLC inside the canTransmit function generated by Halcogen.

I saw another post about this, here they suggested the TRM chapters: "Reconfiguration of Message Objects for the Transmission of Frames"and "Changing a Transmit Object" but that doesn't seem to help me. i don't quite get the sentence: "The Data Length Code of a message object must be defined to the same value as in the corresponding objects with the same identifier at other nodes" either in Table 27-2. Message Object Field Descriptions the part about "DLC[3:0]"

am i missing something when i try this modified "canTransmit()" function: 

uint32 canTransmit(canBASE_t *node, uint32 messageBox, const uint8 * data, const uint8 dlc)
{
uint32 i;
uint32 success = 0U;
uint32 regIndex = (messageBox - 1U) >> 5U;
uint32 bitIndex = 1U << ((messageBox - 1U) & 0x1FU);

/** - Check for pending message:
* - pending message, return 0
* - no pending message, start new transmission
*/
if ((node->TXRQx[regIndex] & bitIndex) != 0U)
{
success = 0U;
}
else
{
/******* MY ADDED CODE *****/////////
node->IF1CMD = 0x90U;
/* set message length */
node->IF1MCTL = (uint32)((uint32)(node->IF1MCTL & 0xFFFFFFF0) | ((uint32)0x0000000FU & (uint32)dlc));
/******* MY ADDED CODE END*****/////////
/** - Wait until IF1 is ready for use */
while ((node->IF1STAT & 0x80U) ==0x80U)
{
node->IF1CMD = 0x87U;
/** - Copy TX data into IF1 */
for (i = 0U; i < dlc; i++)
{
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
node->IF1DATx[i] = *data;
data++;
#else
node->IF1DATx[s_canByteOrder[i]] = *data;
data++;
#endif
}
/** - Copy TX data into message box */
node->IF1NO = (uint8) messageBox;
success = 1U;
}
/** @note The function canInit has to be called before this function can be used.\n
* The user is responsible to initialize the message box.
*/
return success;
}

What am i doing wrong? this just produces messages with a length of 8 (DLC has been set to 8 in canInit)

  • The message  "The Data Length Code of a message object must be defined to the same value as in the corresponding objects with the same identifier at other nodes" means don't use the same message ID with different DLC. (This is what I think you want to do.) I think the issue is that some CAN devices may not handle receiving a message with a different DLC than it is expecting for that message ID. I don't think our DCAN module cares, it writes the DLC value received into the received message object.

  • If you still want to send CAN messages with the same ID, but different data lengths, the simplest way is to use 9 transmit mail boxes, each one defined with the same ID, but a different DLC.
  • Finally, if you don't have enough mailboxes to have one for each different DLC, then you can modify your mailbox. I suggest you not modify the existing HALCoGen functions, or at least don't modify then except between the lines "/* USER CODE BEGIN (x) */" and "/* USER CODE END */". That way you can go back into HALCoGen and make modifications without overwriting your changes.

    The code you suggested will not work for several reasons. First you write to the IF1 registers before you check to see if IF1 is still busy. Second you read from the IF1MCTL register assuming it still contains the value you used the last time this mailbox was initialized. Remember the IF1 and IF2 registers are just a big write buffer so that all of the bits of a message mailbox are written into the real mailbox concurrently. Third, you don't, write the IF1NO after the write to IF1MCTL. Your information is not transferred to the mailbox. Then the HALCoGen write to IF1CMD overwrites what you wrote.
  • In my program the messages with the same ID will always have the same DLC, but i want to send all my extended messages with Mailbox 1 and all my standard messages through Mailbox 2. So would it be possible to just keep these Mailboxes and update the DLC? before i call this function i always call canUpdateID, so the ID of the messagebox is updated to the message i want to send.

    I tried a lot of different appreaches when deugging, the one i showed you was the last one i tried, when i take in your advice on that, should look like this (ignoring the fact i write outside of usercode blocks):

    uint32 canTransmit(canBASE_t *node, uint32 messageBox, const uint8 * data, const uint8 dlc)
    {
    uint32 i;
    uint32 success = 0U;
    uint32 regIndex = (messageBox - 1U) >> 5U;
    uint32 bitIndex = 1U << ((messageBox - 1U) & 0x1FU);

    /* USER CODE BEGIN (7) */
    /* USER CODE END */


    /** - Check for pending message:
    * - pending message, return 0
    * - no pending message, start new transmission
    */
    if ((node->TXRQx[regIndex] & bitIndex) != 0U)
    {
    success = 0U;
    }

    else
    {
    while ((node->IF1STAT & 0x80U) ==0x80U)
    {
    } /* Wait */

    node->IF1CMD = 0x90U;
    /* set message length */
    node->IF1MCTL = (uint32)((uint32)(node->IF1MCTL & 0xFFFFFFF0) | ((uint32)0x0000000FU & (uint32)dlc));
    node->IF1NO = (uint8) messageBox;

    /** - Wait until IF1 is ready for use */
    /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */
    while ((node->IF1STAT & 0x80U) ==0x80U)
    {
    } /* Wait */

    /** - Configure IF1 for
    * - Message direction - Write
    * - Data Update
    * - Start Transmission
    */
    node->IF1CMD = 0x87U;
    /** - Copy TX data into IF1 */
    for (i = 0U; i < dlc; i++)
    {
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
    node->IF1DATx[i] = *data;
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
    /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
    data++;
    #else
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
    node->IF1DATx[s_canByteOrder[i]] = *data;
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are only allowed in this driver" */
    /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
    data++;
    #endif
    }

    /** - Copy TX data into message box */
    /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
    node->IF1NO = (uint8) messageBox;

    success = 1U;
    }
    /** @note The function canInit has to be called before this function can be used.\n
    * The user is responsible to initialize the message box.
    */

    /* USER CODE BEGIN (8) */
    /* USER CODE END */

    return success;
    }

     But this ends up sending 1 message. with the RIGHT DLC, so i actually get a message with a DLC of 3 instead of 8. but then i just get 1 message and then it stops sending, i don't get more messages.

    Opposed to removing the lines: 

    while ((node->IF1STAT & 0x80U) ==0x80U)
    {
    } /* Wait */

    node->IF1CMD = 0x90U;
    /* set message length */
    node->IF1MCTL = (uint32)((uint32)(node->IF1MCTL & 0xFFFFFFF0) | ((uint32)0x0000000FU & (uint32)dlc));
    node->IF1NO = (uint8) messageBox;

    will result in the origional code with which it keeps sending messages every 200 ms like i want

  • Bob Crosby said:
     Second you read from the IF1MCTL register assuming it still contains the value you used the last time this mailbox was initialized. Remember the IF1 and IF2 registers are just a big write buffer so that all of the bits of a message mailbox are written into the real mailbox concurrently. 

    I didn't quite see what you meant with that, i wanted to retain the bits already set, i see now, when i just set the other bits to what i want them to be it does work and it keeps on sending (i asume that happens because of the TxIE that is now set and we send on interrupt basis) 

    "node->IF1MCTL = ((uint32)0x0000000FU & (uint32)dlc) | (uint32)((uint32)1U << 11)| (uint32)((uint32)1U << 7);"

    so not reading the IFx register is indeed a very good idea.1

    Thanks for your help!