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_abort does not return

Hello,

I have a project that uses the IPC stream module with the PSP McASP driver.

It has a task that receives data for processing as below:

Stream_create()

for all buffers

    Stream_issue()

for(;;)

    if reset_flag == true

        Stream_abort()

        Stream_delete()

        Stream_create()

        for all buffers

            Stream_issue()

        reset_flag = false

    Stream_reclaim()

    //Processing

    Stream_issue()

 

It works fine until the reset_flag is set. Stream_abort is called but does not return.

Another higher priority task is running that also does stream handling on the McASP, but it is using a different McASP instance and stream handle.

The stack before execution goes elsewhere is:

0 ti_psp_mcasp_Mcasp_localSubmitIoctl__I(struct ti_psp_mcasp_Mcasp_ChannelObj *, unsigned int, void *, void *, struct xdc_runtime_Error_Block *) at mcasp_ioctl.c:140 0xc31d5c80   
1 ti_psp_mcasp_Mcasp_control__F(struct ti_psp_mcasp_Mcasp_Object *, void *, unsigned int, unsigned int, struct xdc_runtime_Error_Block *) at mcasp.c:1459 0xc320e5f4   
2 ti_psp_mcasp_Mcasp_control__E(struct ti_psp_mcasp_Mcasp_Object *, void *, unsigned int, unsigned int, struct xdc_runtime_Error_Block *) at appdsp_x674.c:24306 0xc321a304   
3 ti_sdo_io_IDriver_control(struct ti_sdo_io_IDriver___Object *, void *, unsigned int, unsigned int, struct xdc_runtime_Error_Block *) at IDriver.h:148 0xc321a6cc   
4 ti_sdo_io_converters_DriverAdapter_control__F(struct ti_sdo_io_converters_DriverAdapter_Object *, unsigned int, unsigned int, struct xdc_runtime_Error_Block *) at DriverAdapter.c:127 0xc321a9d0   
5 ti_sdo_io_converters_DriverAdapter_control__E(struct ti_sdo_io_converters_DriverAdapter_Object *, unsigned int, unsigned int, struct xdc_runtime_Error_Block *) at appdsp_x674.c:24534 0xc321a980   
6 ti_sdo_io_IConverter_control(struct ti_sdo_io_IConverter___Object *, unsigned int, unsigned int, struct xdc_runtime_Error_Block *) at IConverter.h:162 0xc321a5c8   
7 ti_sdo_io_Stream_abort__F(struct ti_sdo_io_Stream_Object *, struct xdc_runtime_Error_Block *) at Stream.c:136 0xc3218c58   
8 mcasp_os_close(struct unknown *) at mcasp_os_dspbios6.c:295 0xc31e0bca   
9 mcasp_close(struct unknown *) at mcasp.c:490 0xc31fbff0   

Attached are the RTA Raw Logs of the execution. There appear to be continuous hardware interrupts and thus the EventCombiner_dispatcher is running continuously.

 

Any suggestions as to what might be causing the interrupts and run-away execution would be greatly appreciated.

1108.Stream_abort.xls

  • I have traced the issue down to running a UART stream driver in another thread. When I disabled the second McASP and UART streams, the abort sequence works correctly.

    The DSP/BIOS Inter-Processor Communication (IPC) and I/O User’s Guide (Literature Number: SPRUGO6, April 2009) says:

    2.4.9 Constraints When Using Streams
    ❏ A Stream instance can be used only by a single Task.
    ❏ Stream_issue() and Stream_reclaim() can only be called by a single thread (Task or Swi) or in the callback context.
    ❏ Stream_issue(), Stream_reclaim(), Stream_read(), and Stream_write() cannot be called from Module startup. Some drivers may require that these APIs not be called even from main() if they require hardware interrupts to enable their peripherals.

    Does this mean that ALL stream instances must be issued and reclaimed in the same thread? If so, this seems to be a major limitation and is there any way to protect against it such as using SWI syncing instead of semaphore syncing?

  • Hi David,

    A single stream instance needs to be used within one task. Other stream instances can be created and used in other tasks.

    When calling abort, an application forces the driver to return all buffers without processing them. Therefore after a call to Stream_abort(), the application still needs to call Stream_reclaim() in a loop to get back the buffers. Can you try to reclaim all the buffers after the call to abort()?

    I am not sure why there are continuous hardware interrupts after the call to Stream_abort(). I will take a look and get back to you.

    Nitya

  • Hi Nitya,

    I did discover that I couldn't call Stream_delete until all the buffers were reclaimed. Thanks though!

    However, my original problem was that execution of Stream_abort() never completed.

    I have discovered that when I just use the McASP stream drivers from one thread, it work fine. But when I open a UART stream instance in another thread, I have a problem with the McASP abort.

     

    My current direction is to remove the Stream driver from my driver stack and have the thread directly access the PSP McASP driver itself. This will give us more flexibility for control and optimization as the project continues, so it is not a large concern to me. But this does leave me with two questions:

    1. Is there a problem with the UART driver that I need to be aware of that may be affecting my system?

    2. The PSP McASP driver calls all take a Mcasp_Handle argument. I assume that it refers to the driver instance created in the .cfg file, but then what do I need to do to use it correctly?

    app.cfg:

    ...
    var mcasp0 = Mcasp.create(mcaspPrms);
    DriverTable.addMeta("/mcasp0",mcasp0);

     

    app.c:

    #include <ti/sdo/io/DriverTypes.h>
    #include <ti/sdo/io/DriverTable.h>
    #include <ti/sdo/edma3/drv/edma3_drv.h>
    #include <ti/psp/mcasp/Mcasp.h>

    channelHandle = Mcasp_open(mcasp0, NULL, mode, (UArg)mcaspParameters, cbFxn, cbArg, &eb);

  • Hi David,

    1. Is there a problem with the UART driver that I need to be aware of that may be affecting my system?

    I am not aware of any known problem with the uart driver. I  will have to consult with the PSP team.

     

    2. The PSP McASP driver calls all take a Mcasp_Handle argument. I assume that it refers to the driver instance created in the .cfg file, but then what do I need to do to use it correctly?

    To get hold of the mcasp handle change

    var mcaspo = Mcasp.create(mcaspPrms);

    to

    Program.global.mcaspo = Mcasp.create(mcaspPrms);

    in your cfg file.

     

    In your C file

    #include <xdc/cfg/global.h>

    channelHandle = Mcasp_open(mcasp0, NULL, mode, (UArg)mcaspParameters, cbFxn, cbArg, &eb);

  • Thank you!

    Do I still need to use the driver table then? Or is it just for the stream drivers?

     

  • Additionally, I like to use the mcasp0 instance variable to initialize a constant structure. But the compiler complains, understandably, that the variable is not constant. Since the variables are fixed in the building of the .cfg file, is there a way to allow it to be used as a constant declaration?

    Thanks

    David Kelly

  • The DriverTable is mainly used by Stream. However in some cases PSP stacking drivers use the DriverTable. For example the audio driver uses the DriverTable to lookup the mcasp instance.

    The statically created mcasp0 is declared as a constant in the generated header file so you should be able to use it to initialize a constant structure.

    extern const ti_psp_mcasp_Mcasp_Handle mcasp0;

     

  • I found the reason as to why the stream_abort() in my McASP stream failed when the UART stream was opened. There is a bug in the PSP driver sample code:

    In file: pspdrivers_02_00_01\packages\ti\psp\examples\evmDA830\uart\config\uartSample.cfg

    The Uart module configuration is left as default which, according to the cdoc, sets:

    config UInt32 numInstances = 1;

    The created instance then goes and opens as instance 2:

    Line 48: uartPrms.instNum   = 2;

     

    This works fine in the demo, but is overwriting my McASP instances which follows it in my project. This should be fixed in the PSP DA830 sample code.

    Additionally, perhaps the UART driver should check the instance number against the maximum number of instances allocated.

     

    David Kelly

  • I am still having issues and have narrowed the problem down to having two streams open through the same UART instance: one for input, and one for output.

    Simply opening both streams will cause an issue even if only one is submitting I/O requests (Stream_read() or Stream_write()) at run time.

    The problems I see look like memory corruption. Sometimes I get Stack Overflow exceptions (though no stacks overflowed, so it must be memory corruption elsewhere), or the drivers lock up in an endless interrupt loop as described above.

    The HWI interrupt seen in the RTDX logs is #7 though I have not set anything to use #7.

     

    My question is:

    Should a single UART driver instance be able to handle 2 streams (one input, and one output) being opened through it?

     

    Thanks

    David Kelly

  • What chip and platform are you running on?

    And which version of the PSP software?

  • TMS320DA830 (though I'm just using the DSP core so it's acting like a C6747)

    Spectrum Digital DA830 DSK Board Rev F

    bios_6_21_00_13

    ipc_1_00_05_60

    pspdrivers_02_00_01

     

    Thanks

    David Kelly

  • I have further narrowed the issue:

    The McASP Stream_abort() fails even if the UART is not opened but a second McASP stream is created (but never issued to).

    The problem seems to be associated with this part of the call stack in:

    pspdrivers_02_00_01\packages\ti\psp\mcasp\src\mcasp.c

    0. mcaspBitRemoveGblRCtl() or mcaspBitSetGblXCtl()

    1. mcaspDeactivateSmFsForRcv() or mcaspActivateSmFsForRcv()

    2. Mcasp_localAbortReset()

     

    Mcasp_localAbortReset() disables interrupts. Then mcaspBitRemoveGblRCtl or mcaspBitSetGblXCtl may call Task_sleep() while it's waiting for the McASP register to respond. Task_sleep() is not allowed to be called in the disable/restore interrupt block. This is a problem.

    If I step through the mcaspBitRemoveGblRCtl() or mcaspBitSetGblXCt(), the Task_sleep is never called because the McASP is ready by the time the register is checked and the reset succeeds. If execution is not stepped, it will sleep (my clock is set to 1 ms ticks). In some cases execution never returns. In other cases, execution returns, but the stack shows that something was executed on it (likely an interrupt inside the critical section?)

    Is there a way to break into the debugger on the interrupt call?

    Should I remove the Task_sleep() call and let the loop spin as there is already a timeout mechanism?

     

    Thanks

    David Kelly

  • Hi David,

    Yes, the Task_sleep() call is a big problem. Trying replacing it with a spin loop.  I will get back to you on the debugger question.

    Nitya

  • The busy wait loop does prevent the problem from occuring at that point, however, now execution control is lost in the step after interrupts are restored in Mcasp_localAbortReset().

    The end of the function is:

     

            /* CRITICAL SECTION  ends!                                            */
            _restore_interrupts(hwiKey);

        }while(falsewhile);
    }

     

    Going step by step, it breaks on the while() statement and then the next step now doesn't return control.

     

    David Kelly

  • Hello,

    I have further isolated the issue with Stream_abort not returning.

    In a test application, I create two tasks, one controlling a McASP input stream, and one controlling a McASP output stream. These tasks use Stream_issue and Stream_reclaim to handle I/O.

    The input McASP task periodically aborts the McASP and reopens it.

    Additionally, I have the code for a task that controls a UART output stream. It uses Stream_write to output data. THIS CODE IS NOT EXECUTED! I can comment out the whole task and the code compiles and runs perfectly.

    If the Stream_write line is commented out, the McASP abort task works fine. If the Stream_write is compiled (note that it is not used), then the McASP abort fails.

    The only major differences in the map file are the additional symbols:

    _ti_sdo_io_Stream_A_syncNonBlocking__C
    _ti_sdo_io_Stream_submit__F
    _ti_sdo_io_Stream_write__F
    _xdc_runtime_Error_getId__F
    _xdc_runtime_knl_Sync_Proxy_query__E
    _xdc_runtime_knl_Sync_query__F

    This suggests that merely linking the Stream_write function causes some problem with the Stream_abort. Enabling the UART thread does work for I/O on both the McASP and UART devices, but the Stream_abort does not.

    Can someone please confirm this?

    Thank you

    David Kelly

  • bios_6_21_00_13

    pspdrivers_02_00_01

    ipc_1_00_05_60

    edma3_lld_02_00_01_04

    xdais_6_25_01_08

    xdctools_3_16_02_32

    Code Composer Studio Version: 4.1.1.00014

     

    Below are two configurations where the Stream_abort fails to work properly:

    Configuration 1:

    Task 1: Controls a McASP input stream instance. Uses Stream_issue and Stream_reclaim. This task is running and periodically calls Stream_abort.

    Task 2: Controls a McASP output stream instance. Uses Stream_issue and Stream_reclaim. This task is running.

    Task 3: Controls a UART output stream instance. Uses Stream_write. This task is NOT running. (Code is compiled, but task is not created)

     

    Configuration 2:

    Task 1: Controls a McASP input stream instance. Uses Stream_issue and Stream_reclaim. This task is running and periodically calls Stream_abort.

    Task 2: Controls a McASP output stream instance. Uses Stream_issue and Stream_reclaim. This task is NOT running. (Code is compiled, but task is not created)

    Task 3: Controls a UART output stream instance. Uses Stream_write. This task is running.

     

    Most other combinations of tasks running or not, or Task 2 using Stream_write, works fine.

    I will soon post a sample application that shows this failure.

    David Kelly

  • Please post the sample application and I will debug it further. Thanks

     

    Nitya

  • Hello Nitya,

    Sorry for the delay, but please find the sample application attached as 4113.McASP_abort_test.zip

    There are two tasks using the Stream and PSP drivers: McASP and UART.

    The McASP task continuously transmits data using Stream_issue and Stream_reclaim, but every few seconds the stream is aborted, deleted and recreated. When it is the only task running, this works fine.

    The UART task transmits data every 10 seconds using Stream_write. When the UART task is running, the McASP abort sequence fails to return. The Stream_reclaim after the Stream_abort does not return.

     

    This is documented in main.c. If you have any questions or problems, please let me know.

     

    Thank you

    David Kelly

     

     

    The application is built with:

    CCS v4.1.1.00014
    C6000 Code Generation Tools 6.1.12
    xdctools_3_16_02_32
    bios_6_21_00_13
    pspdrivers_02_00_01
    xdais_6_25_01_08
    ipc_1_00_05_60
    edma3_lld_02_00_01_04

  • Please provide update given latest info from David.

  • Hi David,

    I just built and ran your testcase on my evmDA830 board. I am unable to see the failure The application has been running for the part 10minutes. Does the failure happen after a long time? I see the following output

    Created Stream: UART Output

    Created Stream: McASP Output

    Created Stream: McASP Output

    Created Stream: McASP Output

    Created Stream: McASP Output

    Created Stream: McASP Output

    .........

    I am using the exact same components. The only difference is that I am using CCv4.2 M9 build.

    Nitya

  • The failure would happen before the second 'Created Stream: McASP Output' on trying to abort the first McASP Stream.

    Is CCSv4.2 publicly available? I can not find it on the TI website, and all the automatic updates in CCS say that 4.1.2.00027 is the latest available.

     

    Thanks

    David Kelly

  • I can see the problem when I load the application you had attached. I will debug using that application.

    I don't think CCSv4.2 is publicly available...but the IDE should not matter.

  • Hi David,

    I see that your application gets stuck in a spurious edma interrupt during Stream_abort(). The code is stuck in the function Mcasp_localEdmaCallback(). This callback function apperas to handle the spurious call and does nothing, but gets called again and again.

    I need to find out why my application works and your does not. Can you send me your map file?

    Thanks,
    Nitya

     

  • Hi Nitya,

    I did not have the original map file from that build. I have rebuild the application and included it in the attached file, along with the map file and the version list. The IDE has received a minor update, but did not affect the result.

    Thanks

    David Kelly

    6470.McASP Abort Map.zip

     

     

  • Hi Nitya,

    I just rebuild the project with the latest code gen tools (6.1.16) and now it is working! I don't know if this was a known issue that was resolved in this version, but it has addressed this issue. In the coming week, I will do some testing on our actual application and ensure that all the issues we were seeing are resolved.

    Thanks for your investigation

    David Kelly

  • Hi David,

    I used 6.1.12 codegen tools and I did not see the problem. I spoke to the drivers team this morning and they have offered to help me debug this problem on their side. Please let me know if you still see the issue with actual application and we can debug further.

    Regards,

    Nitya