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.

TDA3MV: Task blocked after receiving CAN messages with different ID

Part Number: TDA3MV


Hello

I have already asked similar question in that thread:

No one have replied me yet, so I decided to re-ask it and explain my problem more clearly, because last time I maybe explained it too hard to understand. I want to remind whats going on. We are using vision sdk on tda3mv to receive and send CAN messages in the task which is running on ipu1.1 core while vision sdk  use-cases running on ipu1.0 core.

I reduced my code down to a couple of  functions. The CanRx purpose is to receive CAN messages and sendTest purpose is to transmit them back. This functions using a cicle buffer where they put and get CAN messages, and I believe it is pretty safe:

typedef struct UDSmsg_t
{
    uint8_t data[8];
    uint8_t len;
    uint32_t id;
} UDSmsg;

#define MSG_COUNT 200

UDSmsg UdsQueueMsg[MSG_COUNT];
UDSmsg* FirstUdsMsg;
UDSmsg* LastUdsMsg;

void sendTest()
{
    Task_sleep(0);
    if (LastUdsMsg != FirstUdsMsg)
    {
        memcpy(&circle_data[0], &FirstUdsMsg->data[0], FirstUdsMsg->len);
        circle_len = (uint32_t)FirstUdsMsg->len;
        canSend(&circle_data[0], circle_len);
        if (FirstUdsMsg + 1 > &UdsQueueMsg[MSG_COUNT]) FirstUdsMsg = &UdsQueueMsg[0];
        else FirstUdsMsg++;
    }
}

void CanRx(UInt32 id, char* data, int len)
{
    if (id == 0x7D4)
    {
        if ((LastUdsMsg + 1 > &UdsQueueMsg[MSG_COUNT]) && (FirstUdsMsg != &UdsQueueMsg[0]))
        {
            memcpy(&LastUdsMsg->data[0], data, len);
            LastUdsMsg->len = len;
            LastUdsMsg->id = id;
            LastUdsMsg = &UdsQueueMsg[0];
        }
        else if (LastUdsMsg + 1 != FirstUdsMsg)
        {
            memcpy(&LastUdsMsg->data[0], data, len);
            LastUdsMsg->len = len;
            LastUdsMsg->id = id;
            LastUdsMsg++;
        }
    }
}

void UDS_Task(UArg arg0, UArg arg1)
{
    FirstUdsMsg = &UdsQueueMsg[0];
    LastUdsMsg = &UdsQueueMsg[0];
    System_dcanStart(CanRx);
    Task_sleep(100);
    while (1)
    {
        sendTest();
    }
}

Task creation happens in the initialization of ipy1.1 core in app_init_ipu1_1.c and that how does it look like:

Task_Handle UDStask;
Task_Params UDSparams;
Error_Block eb;

#pragma DATA_ALIGN(gSwUserBuffer, 32);
uint8_t gSwUserBuffer[10 * 1024];

Error_init(&eb);
Task_Params_init(&UDSparams);
UDSparams.stackSize = 10 * 1024;
UDSparams.priority = 4U;
UDSparams.affinity = 0x1;
UDSparams.stack = &gSwUserBuffer[0];
UDStask = Task_create(UDS_Task, &UDSparams, &eb);

The problem is: when we send messages with only one ID, its OK,regardless how many type of messages we are sending and how hight their rate is, but if we start to send two messages with one ID and one with some other ID, tda stops to respond. I checked it in separate task with Task_state, and it returns UDStask mode is BLOCKED after that happens. I want to understand why does this task set to blocked state and how can I unblock the task if I don't know what is blocking it?

Best regards, D.K. Tovmachenko.

  • Hi,

    Dmitriy Tovmacenko said:
    when we send messages with only one ID, its OK,regardless how many type of messages we are sending and how hight their rate is, but if we start to send two messages with one ID and one with some other ID, tda stops to respond.

    When you say you are able to send only one ID, is it a specific ID? Or any ID but consistent for a particular run of the application?

    CAN would do an acceptance filtering on the RX side. Any message coming on to the bus will be filtered first, are you configuring the filters to receive you messages?

    I would start debugging from the configuration and then go on to look at what happens if a message fails the acceptance filtering.

    Regards,

    Karan

  • Hello, Karan

    We modified Vision SDK project to make it receive several IDs, and I added several specific IDs for our devices. So when I receive ID from my ID list it is accepted and processed, and the result of that action is sendTest() function which is transmitting the result of processing. I can send different messages with only one ID with a very hight rate, like 6 messages per ms, and that is OK. Of course I lose some of those messages because of CAN and buffer limitations, but task never bloks or terminates. But when I add one message with some other ID somewhere between those messages (it could be ID which is included to the ID list or some random ID), task changes its state to BLOCKED, and I dont really understand why, and how to change it back to READY.

    I beleive Vision SDK have its own Queue which is receiving all messages and after that filters them and if message accepted invokes Swi which is calling for a CanRx, so I do receive all messages, even those which is not included to my list, and task blocks somewhere between this queue and CanRx.  The only way I see is to exit the task, terminate it and create it again, but this is not really good to processes I need to support.

    Best regards, D.K. Tovmachenko

  • As you can see, before I send 0C1 ID there is both Rx and Tx messages, but after that there is no more Rx messages, so TDA do not answer. Below You can see what happens with the task which is responcible for answering.

    I have one task which is sending CAN messages and additional task for monitoring state of the first task. Before 45.47 s first task changes between READY and BLOCKED state because sometimes task 2 takes control, but when I send 0C1 Id at 45.47 s task 1 blockes and never return to READY state again. ID 0C1 is in my list, but I do not process it, just receive and drop.

  • Apparently, something is going on in Utils_dcanWrite() function, namely something is going on with mutex in that function according to output of Vps_printf() placed there.

  • Hi

    It seems I'm stucking in vision sdk in Utils_dcanWrite() function. Inside that function we call Utils_dcanWaitForIfReg twice, and at the second time I stuck in while cicle in that function. That while check DCANIsIfRegBusy. There is its description:

    /**
     * \brief     This API checks for whether DCAN IF Register is busy or not
     *
     * \param     baseAddr       Base Address of the DCAN module register
     * \param     ifRegNum       DCAN interface register number
     *                           For valid values refer enum #dcanIfRegNum_t
     *
     * \return     TRUE when DCAN IF Register is busy else FALSE when DCAN IF
     *             Register is not busy
     */
    uint32_t DCANIsIfRegBusy(uint32_t baseAddr, uint32_t ifRegNum);

    So I think somehow DCAN IF Register always busy because of some reason I can't figure out.

    Regards, D.K. Tovmachenko.

  • Hi Dmitriy,

    When your application is stuck inside 'Utils_dcanWrite()' function, can you please send me the DCAN register dump? Addresses are as follows depending on which DCAN module you are using:

    1. DCAN1: from '0x4AE3C000' to '0x4AE3C1F0'
    2. DCAN2: from '0x48480000' to '0x484801F0'

    Thanks & Regards,
    Vivek Dhande.

    Texas Instruments (India) Pvt Ltd

  • Hello Vivek

    I'm not really sure that I'm stuck in Utils_dcanWrite() function, nevertheless here is DCAN register dump. We are using DCAN1 module. Did I make it correct: I used Code Composer Studio Memory browser, and at the moment my programm stuck I used Save Memory function to create .dat file. In target options I set Start address as 0x4AE3C000 and length as 496 memory words. Format is 32-Bit Hex - TI Style. Is it OK?

    Also I figured out that as expected after stuck I end up in Idle task end never go back to my task. Is that OK if I try to use my second task which is for checking 1st task state, as some kind of whatchdog task, and it will delete 1st task if it is blocked for too long time and create again in runtime? Can I do that? Something like this:

    BOOLEAN waitForUDS;
        UInt32 start_time;
    
        while (1)
        {
            if (UDStask != NULL) Task_stat(UDStask, &statbuf);
            if (statbuf.mode == Task_Mode_BLOCKED) //Clock_start(UdsClock);
            {
                waitForUDS = TRUE;
                start_time = Clock_getTicks();
                while (waitForUDS)
                {
                    Task_sleep(50);
                    if (UDStask != NULL) Task_stat(UDStask, &statbuf);
                    if ((statbuf.mode == Task_Mode_BLOCKED) && (Clock_getTicks() - start_time > 3000))
                    {
                        waitForUDS = FALSE;
                        Task_delete(&UDStask);
                        memset(&UDstaskBuffer, 0, sizeof(UDSstackBuffer));
                        Task_create(UDS_Task, &UDSparams, &eb);
                    }
                    else if (statbuf.mode != Task_Mode_BLOCKED)
                    {
                        waitForUDS = FALSE;
                    }
                }
            }
            Task_sleep(5000);
        }

     

    Regards, D.K. Tovmachenko

    DCAN1 dump.dat

  • Hi Dmitriy,

    Thanks for the register dump. I am looking at it and will get back to you ASAP.

    I do not think it is a good idea to use the second task to watch first task as a watchdog.  I think figuring out why the first task is hung and solve it there is the best course of action.

    Thanks & Regards,
    Vivek Dhande.

    Texas Instruments (India) Pvt Ltd

  • Hello, Vivek

    Eventually, I think I found the reason my task became blocked. It blocked because of Utils_dcanWaitForTxComplete() function, where we call BspOsal_semWait(dcanTxMsgObj.dcanTxMsgAckObj[txMbxIndex].semTxComplete, BSP_OSAL_WAIT_FOREVER), and as I understand, dcanTxMsgObj.dcanTxMsgAckObj[0].semTxComplete semaphore is never posted. So now I'm using a crutch: I made a gobal function which post that particular semaphore and I call it in my watchdog task if 1st task  is blocked for a certain time. Is there some way to post that semaphor correctly? Why does it doesnt post anywhere at the first place?

    Regards, D.K. Tovmachenko.

  • Hi Dmitriy,

    From the register dump, it looks like you don't have any outgoing or incoming message pending. This is the reason that task goes in Idle/blocked state.

    At what point did you take this register dump? 

    Can you please answer the following questions (sorry for the inconvenience if I am repeating older questions):

    • Can you please provide message details (IDs) that are supposed to be received on TDA3x?
    • Same above for transmission.
    • Can you please also provide mailbox configuration details (especially for Rx)?

    Thanks & Regards,
    Vivek Dhande.

    Texas Instruments (India) Pvt Ltd

  • Hello Vivek.

    We made some changes in system_dcan.c to make tda3 receive several IDs:

    static Void System_dcanInitCfgStruct(dcanConfig_t * dcanConfig)
    {
        Int i;
        UInt8 msgData[] = {0xAA,0xEE,0xBB,0xFF,0xCC,0xDD,0x55,0xAA};
    
        dcanConfig->enableLoopback     = FALSE;
        dcanConfig->enablePeriodicTx   = FALSE;
        dcanConfig->rxMsgId[0]         = 0xC1;
    	dcanConfig->rxMsgId[1]		   = 0xC2;
    	dcanConfig->rxMsgId[2]		   = SPEED_ID;
    	dcanConfig->rxMsgId[3]	       = TURN_ID;
    	dcanConfig->rxMsgId[4]		   = WHEEL_ID;
        dcanConfig->rxMsgId[5]         = 0x7D4;
        dcanConfig->rxMsgId[6]         = 0x7D5;
    	//dcanConfig->rxMsgId[0]	       = TURN_ID;
    	dcanConfig->rxMsgIdCnt		   = 7;
    	//dcanConfig->rxMsgIdCnt		   = 1;
        dcanConfig->txMsgId            = 0x7C4;
        dcanConfig->enableSendRxAck    = FALSE;
        dcanConfig->enableReceiveRxAck = FALSE;
        dcanConfig->txAckMsgId         = 0xC4;
        dcanConfig->rxAckMsgId         = 0xC5;
        dcanConfig->rxMsgCb            = System_dcanRxMsgHandler;
        dcanConfig->rxAckMsgCb         = System_dcanRxAckMsgHandler;
        dcanConfig->txMsgPeriod_ms     = SYSTEM_DCAN_TX_PRD_MS;
        dcanConfig->dcanCntrlIntrId    = SYSTEM_DCAN_INTR_ID;
        dcanConfig->dcanTxTskPri       = SYSTEM_DCAN_TX_TSK_PRI;
        dcanConfig->dcanRxTskPri       = SYSTEM_DCAN_RX_TSK_PRI;
        dcanConfig->dcanInputClk_hz    = SYSTEM_DCAN_INPUT_CLK;
        dcanConfig->dcanBaudRate_hz    = SYSTEM_DCAN_BIT_RATE;
        dcanConfig->enableTxMsgCycle   = FALSE;
        dcanConfig->dcanTxPrdMsg.dataLength = UTILS_ARRAYSIZE(msgData);
        for ( i = 0 ; i < UTILS_ARRAYSIZE(msgData); i++)
        {
            dcanConfig->dcanTxPrdMsg.msgData[i] = msgData[i];
        }
    
    }

    I use ID 0x7D4 to send 3 different types of messages. Problems starts when I send one single message with some other ID. It could be any ID, both from init or not, for example it could be 0xC1. This is for Rx. For Tx we use only one ID - 0x7C4.

    I took that register dump exactly after I send 0xC1 message while sending 3 messages with ID 0x7D4. After receiving 0xC1 message Tx stoped, and after that I stoped to debug and took the dump.

    There is mailbox configuration. We changed Rx mailbox a little bit and left Tx as it was written:

    static void Utils_dcanInitRxMsgObjParams(dcanMsgObjCfgParams_t *pDcanRxCfgPrms,
    	UInt32 msgId, UInt32 msgType)
    {
    	/*Intialize DCAN Rx Config Params*/
    	pDcanRxCfgPrms->xIdFlagMask = 0x1;
    	pDcanRxCfgPrms->dirMask = 0x1;
    	pDcanRxCfgPrms->msgIdentifierMask = 0x1FFFFFFF;
    
    	pDcanRxCfgPrms->msgValid = TRUE;
    	pDcanRxCfgPrms->xIdFlag = msgType;
    	pDcanRxCfgPrms->direction = DCAN_DIR_RX;
    	if (FALSE == pDcanRxCfgPrms->xIdFlag)
    	{
    		msgId = (msgId & 0x7FF) << 18;
    	}
    	pDcanRxCfgPrms->msgIdentifier = msgId;
    
    	pDcanRxCfgPrms->uMaskUsed = FALSE;
    	pDcanRxCfgPrms->intEnable = TRUE;
    	pDcanRxCfgPrms->remoteEnable = FALSE;
    
    	pDcanRxCfgPrms->fifoEOBFlag = TRUE;
    
    }
    
    
    static void Utils_dcanInitTxMsgObjParams(dcanMsgObjCfgParams_t *pDcanTxCfgPrms,
    	UInt32 msgId, UInt32 msgType)
    {
    	/*Intialize DCAN tx Config Params*/
    	pDcanTxCfgPrms->xIdFlagMask = 0x1;
    	pDcanTxCfgPrms->dirMask = 0x1;
    	pDcanTxCfgPrms->msgIdentifierMask = 0x1FFFFFFF;
    
    	pDcanTxCfgPrms->msgValid = TRUE;
    	pDcanTxCfgPrms->xIdFlag = msgType;
    	pDcanTxCfgPrms->direction = DCAN_DIR_TX;
    	if (FALSE == pDcanTxCfgPrms->xIdFlag)
    	{
    		msgId = (msgId & 0x7FF) << 18;
    	}
    	pDcanTxCfgPrms->msgIdentifier = msgId;
    
    	pDcanTxCfgPrms->uMaskUsed = TRUE;
    	pDcanTxCfgPrms->intEnable = TRUE;
    	pDcanTxCfgPrms->remoteEnable = FALSE;
    
    	pDcanTxCfgPrms->fifoEOBFlag = TRUE;
    }

    If you need any additional information please ask.

    Best regards, D.K. Tovmcachenko

  • Hi Dmitriy,

    Thanks for the detailed response. From your last reply and earlier one with PCAN snapshot, when you send any ID apart from '0x7D4' from PCAN, TDA3 stops transmission.You send message with ID '0x7C4' from TDA3 when you receive message with ID '0x7D4'. Pleas correct if my understanding is wrong. 

    Can you please check Rx, Tx handling on TDA3x? Especially for the scenario explained in your latest reply. What is the expected behaviour in this case?

    Also, is there any handshake between TDA3 and PCAN like PCAN responds to any message or it just sends out messages contuniusly w/o any ack from TDA3?

    Thanks & Regards,
    Vivek Dhande.

    Texas Instruments (India) Pvt Ltd

  • Hello Vivek.

    Yes, you understood it pretty well, TDA send 0x7C4 in responce on 0x7D4, and during that time if TDA receive some ID apart of  0x7D4, it stops transmission. But it happens only when there is at least two 0x7D4 messages per second.

    Can you please specify wich handlers do you need. Does it this handlers?

    This screenshots were take after stuck situation.

    About TDA and PCAN: PCAN continiously send 0x7D4 messages and recieve any messages from TDA, there is no other connection between them. Its like a stress test for TDA. We trying to make TDA works with overloaded CANbus.

    Actually, I think I figured out what is blocking my task. Apparently, it have been blocked by BspOsal_semWait function, which is called in  Utils_dcanWaitForTxComplete. BspOsal_semWait have 'dcanTxMsgObj.dcanTxMsgAckObj[txMbxIndex].semTxComplete' as input paramenter, and in my situation txMbxIndex is equal to 0. That function timeout is BSP_OSAL_WAIT_FOREVER. So when I post that semaphore in additional task (after 1st task blocked for a certain time), which is checking 1st task state, everething continue to work well. But this doesnt really solve the problem.

    Best regards, D.K. Tovmachenko.

  • Hi Dmitriy,

        Can you please elaborate more on your last point (posted below)?

    Actually, I think I figured out what is blocking my task. Apparently, it have been blocked by BspOsal_semWait function, which is called in  Utils_dcanWaitForTxComplete. BspOsal_semWait have 'dcanTxMsgObj.dcanTxMsgAckObj[txMbxIndex].semTxComplete' as input paramenter, and in my situation txMbxIndex is equal to 0. That function timeout is BSP_OSAL_WAIT_FOREVER. So when I post that semaphore in additional task (after 1st task blocked for a certain time), which is checking 1st task state, everething continue to work well. But this doesnt really solve the problem.

    Thanks & Regards,
    Vivek Dhande.

    Texas Instruments (India) Pvt Ltd

  • Hello Vivek.

    As I said before, I created the task which purpose is to check state of my primary task. If primary task is blocked for too long time that task post semaphore. By debuging in CCS I figured out, that my primary task is blocked somewhere in utils_dcan.c function Utils_dcanWaitForTxComplete(UInt32 txMbxIndex). In that function there is only one resource that can block task - BspOsal_semWait(). Obviously, that function pend semaphore somewhere inside, and it takes handler of that semaphore as input parameter. By printing txMbxIndex in runtime I got that index - 0. So I created function which post that semaphore and use it in my watchdog task. It turns out, my watchdog task implicitly change that semaphore timeout to timeout I determine in my task. That way my programm works well by now, but it doesnt solve the problem, I still dont know why does my task get blocked and how can I unblock it without using the crutch.

    Regards, D.K.Tovmachenko.

  • Hi Dmitriy,

    Thanks for the details.

    From your previous register dump and observations, it looks like the DCAN module is working fine but the task is somehow getting blocked.

    We have to debug this further in-depth, can you please do the following:

    • Can you please implement a kind of event logging along with timestamps (this could be as simple as prints)? Add these events for the following:
      • The event in the ISR along with a source of interrupt like is it Tx or Rx interrupt and also include Msg Id in the details
      • The event in  the main task after receiving semaphore
      • The event at a place where semaphore is posted
      • The event for queue management places

    Please make sure to have timestamps included in the logging. This will help us to determine what exactly is going in the system. You can also add more events points as per your interests.

    Thanks & Regards,
    Vivek Dhande.

    Texas Instruments (India) Pvt Ltd

  • Hi Vivek,

    Can you please specify, what information do you need to be loged by these events besides timestamps. Should it be CAN log, register dump for each mentioned events, or maybe you need some additional information? Regarding event in  the main task after receiving semaphore, do you mean the place where task pend that semaphore? Cause I dont really know it, I tracked it only to BspOsal_semWait() function, afterwards CCS started to mess with debugging, it started to went throught a lot of files and cicles, and show messages like "cannot open source file", so I really lost a track of it. Also, the first event you mentioned about ISR, havent I already send you PCAN-View screenshot where you can find timestamp and message ID both, along with message type and data bytes? Or have I misunderstood you? Please explain these points to me so that I can fulfill them.

    Best regards, D.K. Tovmachenko.

  • Hi Dmitriy,

    Since there are multiple tasks and previous registers dumps did not give any information about failures, I wanted to know what exactly is happening in the system. Like when the message has received or transmitted,  when semaphore was posted and when it was received, when task got blocked and when it got unblocked. Details about queue management. I want details like that. This can be done through the ways that I suggested in my last reply.

    I do not need a Register dump for each event. I just need the events and time-stamp at which it had occurred. 

    For example, getting Tx interrupt is an event and log this with a timestamp. So event logging could as simple as 2 arrays. One containing event code and other containing timestamps at the same index. This event codes could be a simple number starting from '0' and increasing further. Here is an example of event codes:

    • '0' for Tx interrupt
    • '1' for Rx interrupt
    • '2' for semaphore post
    • '3' after semaphore reception and so on
    • You can have many events like these (like Q management, error interrupt, etc). More the events, more are the data points for debugging. 

    So, if you receive Tx interrupt, put '0' value in event code array at some index (let's say x). Put the current timestamp at the 'x' index of another time-stamp array. Similarly, if you receive Rx interrupt, put '1' value in event code array at some index (let's say y). Put the current timestamp at the 'y' index of another time-stamp array.

    I hope this cleared your doubts about event logging.

    Thanks & Regards,
    Vivek Dhande.

    Texas Instruments (India) Pvt Ltd

  • Hello.

    We changed to VisionSDK version 3.08, reattached all our files, and somehow this problem disappear, now task doesnt blocking. Thank you dor all your help.

    Best regards, D.K. Tovmachenko.