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.

Stream_reclaim and/or Stream_write: how to reclaim packet after Timeout

Hi

I'm using the IPC function Stream_write (which itself contains Stream_issue and Stream_reclaim) together with the I2C PSP Driver. I set a timeout value for the Stream_write function in case of wrong addressing in I2C.

When I receive a timeout and try to write again via I2C I receive the assertion "assertion failure: A_pendingReclaims: Packets issued but not reclaimed"

The cdoc documentation as well as the IPC_Users_Guide.pdf tell that one has to use Stream_abort() on a timed out Stream Handle to be able to Stream_reclaim the packet after this call. So I implemented this (the remaining part of the project is left as delivered by the pspdriver package):

size = Stream_write(
                i2c_outHandle,
                &dataBuffer,
                (SizeT)dataBuffer.bufLen,
                50,
                eb);

    if ((TRUE == Error_check(eb)) && (dataBuffer.bufLen != size))
    {
       
        Stream_abort(i2c_outHandle, NULL);
        Stream_reclaim(i2c_outHandle, (Ptr *)&dataBuffer, BIOS_WAIT_FOREVER, NULL, NULL);
       
        System_printf("I2c Write: Data Write Failed: %d\n",Error_getCode(eb));
    }

The packet will not be received even though abort was called. I instead stay in the Stream_reclaim function forever

SizeT Stream_reclaim(Stream_Object *obj, Ptr *bufp, UInt timeout, UArg *arg,
    Error_Block *eb)
{

(...)

while (obj->ready == 0) {
        if (!Sync_wait(obj->complete, timeout, eb)) { //<- stays here forever
            if (timeout != 0) {
                Error_raise(eb, Stream_E_timeout, timeout, 0);
            }
            return (0);
        }
    };

(...)

Thanks for any help on this
Stefan


  • Hi Stefan,

     

    Please refer the following thread:

    http://e2e.ti.com/support/embedded/f/355/p/108846/390550.aspx#390550

     

    Thanks & regards,

    Raghavendra

     

  • David Friedland,

    I rejected your suggestion, since the Thread Raghavendra linked did not solve the problem. Instead he suggested in the mentioned thread that I should look for help in this thread since it's not a PSPDRIVERS issue but a problem with the stream and thereby a IPC issue.

    Dear IPC Team,

    I would really appreciate help on this, since a firmware which crashes when an I2C Device does not respond is really not an option for my task.

    Best Regards
    Stefan

  • Hi Stefan,

    Can you include the code you used to create the Stream?

    Todd

  • I used the I2C Sample project provided by the PSPDRIVER library (unmodified source with ti.platforms.evmOMAPL138 on the ARM processor). When I then initiate an I2C transfer with a wrong address/no device responding I receive the assertion described above.

    If you do have the I2C Sample project you can have a look at this project, if not I will post itt on monday when I'm back at my working place

    Thanks and best regards
    Stefan

  • Hi Stefan,

    It would be great if you could send the sample (I'm not sure which version you are using). Also, which version of IPC are you using?

    Can you make sure the Stream_write is timing out. (e.g. Error_check(eb) == TRUE and  Error_getId(eb) == Stream_E_timeout).

    Todd

  • Hi Todd,

    first my RTSC setup:

    • XDCtools version 3.20.8.88
    • EDMA3 ow Level Driver (2.11.0)
    • Inter-processor Communication (1.22.5.27)
    • PSP DRIVERS (2.10.1)
    • SYS/BIOS (6.31.4.27)

    I checked the timeout: The Stream is timing out and the according error is set.

    I attached the project, you do need to have EDMA3 LLD(because is used by I2CDriver) and PSP DRIVERS(because .cfg file) installed though. I removed the Debug files to save space. If you want them too just tell me...

    8738.i2cSample_arm.zip

    Thanks
    Stefan

  • Hi Stefan,

    Thanks. Unfortunately I cannot find the hardware to test it on.

    How many times does the Stream_write() succeed before the timeout occurs?

    Todd

  • Hi Todd,

    there is no succesful write (which is because no device is on the i2c bus). The timeout occurs directly at the beginning. Though it should be able to restore the stream to try it again, shouldn't it?

    Thanks
    Stefan

  • Hi Stefan,

    The Stream_abort() call is only needed when Stream_reclaim times out (or if the app wants to cancel an IO request). The User Guide describes this in the Stream_abort API section.

    If there is a timeout with Stream_write(), it is done internally (actually it is in the Stream_submit() function). So you can remove the Stream_abort and Stream_reclaim from your error handling path.

    Sorry I did not see this sooner.

    Todd

  • Hi Todd,

    On a Timeout of Stream_write (= timeout of Stream_reclaim internal in Stream_write):

    • when I have the two lines (Stream_abort() and Stream_reclaim()) in my code, the program will stay stuck in the Stream_reclaim() (as it would in the Stream_write function if it wasn't called with a timeout).
    • when I remove the two lines I get the assertion mentioned above at the next Stream_write() call:
      "assertion failure: A_pendingReclaims: Packets issued but not reclaimed"

    Were you able to reproduce this error?

    Thanks
    Stefan

  • Stefan,

    The A_pendingReclaims issue looks like a bug with the I2C driver. I tried looking at the code, but nothing jumps out (doesn't help that I've never used I2C!). Can someone on the PSP team help with this?

    Todd

  • Todd,

  • Hi Stefan,

     

    When you configure i2c in DMA mode of operation and if there is a NACK interrupt, you cannot recover back and continue further(perform another request - bufLen = 2u or more!!). The reason behind this is, In the dma mode of operation when the bufLen is 2, the EDMA will be programmed for 2 byte data transfer. Initially the address is copied onto the i2c shift register, and then the EDMA copies the first data onto the i2c buffer register. Since a wrong address is specified, a NACK interrupt is triggered followed by STOP bit and i2C stalls. Because of this, no event is being generated to the EDMA for the second data by i2C and hence, transfer does not complete and no edma callback is called. In the edma callback (cancel the current IOP, Ensure i2c is ready for next operation, ensure that all the IOPs will be aborted, Power OFF the module, Invoke Application callback for this channel) all these operations are done. If the callback itself is not called, all these operations are not done. 

    What you can possibly try is, in the i2cSample.cfg file, make the following changes:

    /*Configure the modules*/

    I2c.edmaEnable = false;

    var i2cPrms = new I2c.Params();

    i2cPrms.instNum   = 0;

    i2cPrms.opMode    = I2c.OpMode_INTERRUPT; /* Configure in INTERRUPT mode*/

    And in the i2cSample_io.c file, place the Error_init(eb); just before calling Stream_write(...) in the function i2cExpander_WritePort0(...) . DO NOT make any other changes!.

     

    This can help you in recovering back and going ahead in performing the next request. (look in i2cIntrHandler(...) to understand more)

     

    Thanks & regards,

    Raghavendra

     

  • Hi Raghavendra,

    I did as you proposed and changed to interrupt. Now it works as it should. Though as far as I understand the EDMA mode should also be supported with the I2c Driver shouldn't it?

    Raghavendra Maddikery said:

    The reason behind this is, In the dma mode of operation when the bufLen is 2, the EDMA will be programmed for 2 byte data transfer. Initially the address is copied onto the i2c shift register, and then the EDMA copies the first data onto the i2c buffer register. Since a wrong address is specified, a NACK interrupt is triggered followed by STOP bit and i2C stalls. Because of this, no event is being generated to the EDMA for the second data by i2C and hence, transfer does not complete and no edma callback is called. In the edma callback (cancel the current IOP, Ensure i2c is ready for next operation, ensure that all the IOPs will be aborted, Power OFF the module, Invoke Application callback for this channel) all these operations are done. If the callback itself is not called, all these operations are not done. 

    Ok I understand the background of this problem now. Is there a function which can be called to do the operations the Callback normally does (resetting I2C and EDMA to allow to work with them again).

    I think normally one would want to be able to run the application even when a NACK is received. So there should be a possibility to try again, as it is implemented for Interrupts. Is it not possible to have it that way for EDMA as well?

    Thanks
    Stefan

  • Hi Stefan,

     

    Stefan Koehler said:
    Ok I understand the background of this problem now. Is there a function which can be called to do the operations the Callback normally does (resetting I2C and EDMA to allow to work with them again)

    Yes, you can do this!. But, since you have a specific requirement wherein you are providing a wrong slave address and getting a NACK, and since you are not getting a EDMA callback for 2 byte transaction, because of which the stream layer callback function is not called to release the IO packet in the stream layer.

    On this basis i can provide you a solution. Here, on occurance of a NACK, we are completing the transaction (which releases the IO packet by calling app callback)

    Attached is the difference report of I2c.c file. Please refer it and modify the i2c driver (I2c.c file, Line: 2200) as shown in the report.

    1376.I2c_Report.html

     

    NOTE: I2c_Modified.c file changes have to be implemented in the I2c driver.

     

    This should solve the issue for your requirement. Please try this, and let us know the results.

     

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra,

    thanks for the suggestion. I tried it but it didn't help. Now I added a syntax error into the i2c.c and found out that the i2c libraries don't seem to rebuild when adding changes to i2c.c.

    How do I force a rebuild of the i2c libraries?

    Thanks
    Stefan

  • Hi Stefan,

     

    Without doing any modifications in the I2c driver, Is the I2c driver building?. Please check this first..

    Are you doing a "xdc build"  or a "CCS build"??.

    Stefan Koehler said:
    I tried it but it didn't help

     

    I suppose you have a issue in building the driver and application, and need to fix this first.

     

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra,

     

    Raghavendra Maddikery said:

    Without doing any modifications in the I2c driver, Is the I2c driver building?. Please check this first..

    Are you doing a "xdc build"  or a "CCS build"??.

    That's my problem at the moment. I'm building the i2cSample in CCS4 while I modified the i2c.c of the i2c driver in the pspdriver directory. First I thought the driver would be rebuild automatically when it detects that it had changes in the i2c.c file.

    It seems though that I have to rebuild the i2c Driver manually. Yet I don't know how. I tried to locate a CCS project file for the I2cDriver in the pspdrivers subdirectory but couldn't find one.

    Thanks,
    Stefan

  • Hi Stefan,

     

    There is no CCS project available for I2C driver. You need to build it using xdc build only!. Please refer section 1.3.3 (point 2) of C6748_BIOSPSP_Userguide.doc

    Only the the I2C sample can be built using CCS build or xdc build.

     

    Please try this.. 

     

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra

    I tried as described in the Userguide and got the following error:

    C:\Programme\Texas Instruments\pspdrivers_02_10_01\packages\ti\psp\i2c>xdc clean


    C:\Programme\Texas Instruments\pspdrivers_02_10_01\packages\ti\psp\i2c>xdc
    making package.mak (because of package.bld) ...
    generating interfaces for package ti.psp.i2c (because package/package.xdc.inc is
     older than package.xdc) ...
        translating I2c
    "ti/psp/i2c/I2c.xdc", line 17:  can't find imported unit: ti.sdo.io.DriverTypes
    (ti.sdo.io.DriverTypes)
    error:  compilation failed: parser failed
    gmake.exe: *** [package/package.xdc.inc] Error 1

    Thanks,
    Stefan

  • Hi Stefan,

     

    Please refer the C6748_BIOSPSP_Userguide.doc for details regarding building the PSP package. Please make sure you have installed all the required tools mentioned in the section 1.1.5 of the userguide. Also setting up the environment variables is very important for building the PSP package(Section 1.3.3 point 3!)

    From your error log, it looks like you have either not installed IPC, or not included its path in the XDCPATH environment variable. 

    Following all the steps mentioned in the Userguide, you should be able to build the driver and the sample application of BIOS PSP successfully.

     

    Regards,

    Raghavendra

  • Hi Raghavendra,

    sorry for the late reply. But other matters in the project have been more pressing in the last week. I was now able to test your proposed solution and it works fine for my current case! I still have to find a I2C device to see if actual data transfer is happening.

    1) Now maybe you could tell me what exactly I am doing by applying these changes to the I2C Driver?
    2) Why is this not a standard behaviour - I would think one never wants to have the whole application crash when a I2C device does not respond.
    3) Are there any disadvantages I should know of in your solution?

    Thanks and best regards

    Stefan

  • Hi Stefan,

     

    Not a problem, its good to know that its working fine now!! after implementing the changes. It would be more helpful if you also verify if actual data transfer is happening and let us know the results..

    The changes mentioned are appropriate to the i2c driver. When there is a NACK interrupt and i2c being configured in DMA mode, it was not being handled correctly in the driver due to which you were facing such an issue (Defect in the driver). We have always tested the i2c driver with a slave device, and has worked for us all time. But in this scenario, we have hit the issue. There are no disadvantages with these changes, but in fact it is a very appropriate way of handling the error interrupt (NACK).

    Now that its working incorporating the changes, an IR (Incident Report) will be raised to keep in track of this issue. 

     

    Thanks & regards,

    Raghavendra

     

     

  • Hi Raghavendra,

    finally I got an I2C Device with which i can test the changes to the driver.

    1) First of all the transmission itself works with the changes we applied to the driver.

    2) When i disconnect the device and I use a message of dataBuffer.bufLen = 2u the timeout appears as hoped everytime I try to send a message.

    3) One problem though: My I2C Device has a command of dataBuffer.bufLen = 1u. When I timeout for this buffer length i get the following error. Connecting the device again I am not able to start a transmission since no Packets seem to be available.

    (...)
    Stream_create(inHandle) returned status = 0
    ti.sdo.io.Stream: line 482: E_timeOut: Error in Timeout
    I2c Write: Data Write Failed: 0
    ti.sdo.io.Stream: line 294: E_noPackets: No packets available. maxIssues is 2
    I2c Write: Data Write Failed: 0
    ti.sdo.io.Stream: line 294: E_noPackets: No packets available. maxIssues is 2
    I2c Write: Data Write Failed: 0

    (...)

    Thanks
    Stefan