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.

DSPLink makes Linux hang on starting DSP

Hello,

We are currently experiencing problems with the DSPLink kernel driver and library for Linux. The processor on which we are developing is the OMAP L-137. DSPLink is purely used for the DSPLink PROC component to LoadFirmware, Start and Stop the DSP. There is no DSP/Bios configured in the DSP Firmware, since we are not using DSP/BIOS. The version in $DSPLINK/gpp/config.bld is 1.61.03.

 We have two DSP applications, a small test image which initializes interrupts, generates and receives ARM <-> DSP interrupts, toggles LEDs and writes to memory. This image is about 150 Kb.  The second image is our final DSP image which has to run on our end-product. This image does more initialization of for example DMA, EMIF and GPIO. This image is debug about 600Kb and release 500Kb.

 Both DSP images run without problems when they are sent to the board using CCS4, this also does not interfere with Linux (e.g. Serial console can still be used and SSH connections to the board can still be made). For this reason I assume there is nothing in the DSP Code that stops the ARM from executing.

 When I use the DSPLink shared object in combination with the DSPLink kernel module this results in problems. The DSP Test image runs without problems, DSPLink can: setup, attach, load firmware, start, stop and shutdown. When I’m using the final DSP image DSPLink can; setup, attach and load firmware.  Starting the DSP results in a hang of Linux and requires me to reboot the board. When I connect the debugger I can see that the PC of the ARM is still changing.  

 I’ve added the complete tracing to DSPLink but this does not give me sufficient information on where the root of the problem lies. As can been seen below nothing happens after leaving DA8XXGEM_halPwrCtrl.

Test Image

Final image

Entered DSP_start ()

       dspId  [0x0]

       dspAddr       [0x11806f20]

Entered DA8XXGEM_start ()

       dspId  [0x0]

       dspState      [0xbf026e70]

       dspAddr       [0x11806f20]

Entered DA8XXGEM_addrConvert ()

       dspId  [0x0]

       dspState      [0xbf026e70]

       addr   [0xc3e00000]

       type   [0x1]

DA8XXGEM_addrConvert addr [0xc3e00000] convAddr [0xc387e000]

Leaving DA8XXGEM_addrConvert ()

Entered DA8XXGEM_halBootCtrl ()

       halObj [0xc3886000]

       cmd    [0x0]

       arg    [0xc3e00000]

Leaving DA8XXGEM_halBootCtrl ()   status [0x8000]

Entered DA8XXGEM_halPwrCtrl ()

       halObj [0xc3886000]

       cmd    [0x3]

       arg    [0x0]

Leaving DA8XXGEM_halPwrCtrl ()    status [0x8000]

DSP started !

Leavin‡DA8XXGEM_start () status [0x8000]

Leaving DSP_start ()       status [0x8000]

Leaving PMGR_PROC_start () status [0x8000]

Leaving DRV_CallAPI ()     status [0x8000]

Leaving DRV_Ioctl ()       status [0x8000]

Entered DRV_Ioctl ()

       inode  [0xc2988950]

       filp   [0xc307b780]

       cmd    [0x6c09]

       args   [0xbe9bf9a8]

Entered DRV_CallAPI ()

       cmd    [0x6c09]

       args   [0xc2633ef4]

Entered PMGR_PROC_getState ()

       procId [0x0]

       status [0x8000]

Leaving PMGR_PROC_getState ()     status [0x8000]

Entered DSP_start ()

       dspId  [0x0]

       dspAddr       [0x1181e780]

Entered DA8XXGEM_start ()

       dspId  [0x0]

       dspState      [0xbf026ed0]

       dspAddr       [0x1181e780]

Entered DA8XXGEM_addrConvert ()

       dspId  [0x0]

       dspState      [0xbf026ed0]

       addr   [0xc3e00000]

       type   [0x1]

DA8XXGEM_addrConvert addr [0xc3e00000] convAddr [0xc387e000]

Leaving DA8XXGEM_addrConvert ()

Entered DA8XXGEM_halBootCtrl ()

       halObj [0xc3886000]

       cmd    [0x0]

       arg    [0xc3e00000]

Leaving DA8XXGEM_halBootCtrl ()   status [0x8000]

Entered DA8XXGEM_halPwrCtrl ()

       halObj [0xc3886000]

       cmd    [0x3]

       arg    [0x0]

Leaving DA8XXGEM_halPwrCtrl ()    status [0x8000]

 I’ve added some extra code to see if that gives me more information. The code and logging is added below. This shows that after leaving  DA8XXGEM_halPwrCtrl no information is printed. For some reason the return in DA8XXGEM_halPwrCtrl does not return to DA8XXGEM_start.

da8xxgem.c

Logging

NORMAL_API

DSP_STATUS

DA8XXGEM_start (IN ProcessorId  dspId,

                  IN DSP_Object * dspState,

                  IN Uint32       dspAddr)

{

…  

        dspCfg    = LDRV_LinkCfgPtr->dspConfigs [dspId] ;

        dspObj    = dspCfg->dspObject ;

        halObj   = (DA8XXGEM_HalObj *) dspState->halObject ;

        linkDrv  = &(dspCfg->linkDrvObjects [dspObj->linkDrvId]) ;

        ipsTable = &(dspCfg->ipsTables [linkDrv->ipsTableId][0]) ;

        PRINT_Printf("PD Crash Logging dspObj == 0x%08X\n", dspObj );

                if (   (dspObj->doDspCtrl == DSP_BootMode_Boot_Pwr)

            || (dspObj->doDspCtrl == DSP_BootMode_NoLoad_NoPwr)

            || (dspObj->doDspCtrl == DSP_BootMode_NoLoad_Pwr)

            || (dspObj->doDspCtrl == DSP_BootMode_Boot_NoPwr)) {

            resetVector = dspObj->resetVector ;

            gppAddr = DA8XXGEM_addrConvert (

                                   dspId,

                                   dspState,

                                   BYTE_TO_MADU (resetVector, dspObj->maduSize),

                                   DspToGpp) ;

            if (gppAddr != ADDRMAP_INVALID) {

                /* Specify the DSP boot address in the boot config register */

                status = halObj->interface->bootCtrl (

                                                  (Pvoid) halObj,

                                                  DSP_BootCtrlCmd_SetEntryPoint,

                                                  (Pvoid) resetVector);

 

        if (DSP_SUCCEEDED (status)) {

                    /* Write the branch instruction to at the boot address to

                     * branch to _c_int00

                     */

                    entryPtAddrHi  = dspAddr >> 16 ;

                    entryPtAddrLo  = dspAddr & 0xFFFF ;

                    startOpCodeHi |= (entryPtAddrHi << 7) ;

                    startOpCodeLo |= (entryPtAddrLo << 7) ;

                    REG (gppAddr)  = startOpCodeLo ;

                    gppAddr += 4 ;

                    REG (gppAddr) = startOpCodeHi ;

                    gppAddr += 4 ;

                    REG (gppAddr) = branch        ;

                    gppAddr += 4 ;

 

                    /* Write 5 no-ops for pipeline flush */

                    REG (gppAddr) = noOp          ;

                    gppAddr += 4 ;

                    REG (gppAddr) = noOp          ;

                    gppAddr += 4 ;

                    REG (gppAddr) = noOp          ;

                    gppAddr += 4 ;

                    REG (gppAddr) = noOp          ;

                    gppAddr += 4 ;

                    REG (gppAddr) = noOp          ;

                    /* Release the DSP from reset */

                    status = halObj->interface->pwrCtrl ((Pvoid) halObj,

                                                         DSP_PwrCtrlCmd_Release,

                                                         NULL);

 

                    PRINT_Printf("PD Crash Logging LEFT PWR CTRL\n" );

                    if (DSP_FAILED (status)) {

                        SET_FAILURE_REASON ;

                    }

                    PRINT_Printf("PD Crash Logging LEFT PWR CTRL\n" );

                }

Entered DSP_start ()

       dspId  [0x0]

       dspAddr       [0x1181e780]

Entered DA8XXGEM_start ()

       dspId  [0x0]

       dspState      [0xbf026ed0]

       dspAddr       [0x1181e780]

PD Crash Logging dspObj == 0xC386E000

Entered DA8XXGEM_addrConvert ()

       dspId  [0x0]

       dspState      [0xbf026ed0]

       addr   [0xc3e00000]

       type   [0x1]

DA8XXGEM_addrConvert addr [0xc3e00000] convAddr [0xc387e000]

Leaving DA8XXGEM_addrConvert ()

Entered DA8XXGEM_halBootCtrl ()

       halObj [0xc3886000]

       cmd    [0x0]

       arg    [0xc3e00000]

Leaving DA8XXGEM_halBootCtrl ()   status [0x8000]

Entered DA8XXGEM_halPwrCtrl ()

       halObj [0xc3886000]

       cmd    [0x3]

       arg    [0x0]

Leaving DA8XXGEM_halPwrCtrl ()    status [0x8000]

 

Does anyone know what might be the source of this problem?


  • LUKLEM said:
    We are currently experiencing problems with the DSPLink kernel driver and library for Linux. The processor on which we are developing is the OMAP L-137. DSPLink is purely used for the DSPLink PROC component to LoadFirmware, Start and Stop the DSP. There is no DSP/Bios configured in the DSP Firmware, since we are not using DSP/BIOS. The version in $DSPLINK/gpp/config.bld is 1.61.03.

    To use DSPLink (also called DSP/BIOS Link), you need to have DSP/BIOS running in the DSP side or it is not supported. Please see:

    http://tiexpressdsp.com/index.php/DSPLink_Overview

    LUKLEM said:
     Both DSP images run without problems when they are sent to the board using CCS4, this also does not interfere with Linux (e.g. Serial console can still be used and SSH connections to the board can still be made). For this reason I assume there is nothing in the DSP Code that stops the ARM from executing.

     It might not interfere with the serial port, but your DSP application can overwrite some initializations made by the ARM (pinmux, etc...) that can cause problems.

  • Yeah I know that DSP/Bios should be used but it also works without DSP/Bios. I only need DSPLink load firmware, start and stop the DSP. I don't have to pass arguments etc. I have my own implementation of a shared memory communication driver.

    The fault was found in the DSP firmware. The DSP Firmware accidentally  configured an EMIF A pin as GPIO so the SDRAM was "corrupted". Thank you for your help.

    Regards,

     

  • Hi LUKLEM,

    I am working on the OMAPL1387 and i would like to do exactly the same thing that you did.

    I have a running linux and a running DSP firmware. The DSP firmware is developped with CCS and directly tested on the target. So i am sure that it is working fine. I am using DSPLink library  and i load then start my DSP firmware successfully from LINUX.

    My problem is that after the PROC_Start(), the DSP is running fine but the linux is stuck.

    As far as I understood, i have to complete the handshake with Linux  but i do not understand how can i do that. Could you help me please ? Could you exchange with me some part of the application code on the handshaking completion?

    Many thanks

    Regards

    Alex

     

     

  • Hey,

    I had the same problem at the beginning that as soon as the DSP started the ARM was stuck. I can't seem to remember what the problem was.  I can at least give you my DSP Link call sequence. If you still have problems, please let me know.

    Only a single progam can be the owner of the DSP. As soon as two programs use the DSPLink driver and perform DSP_Setup tasks etc. this can cause problems.

    Init:
     Status = PROC_setup( NULL );
     Status = PROC_attach( gcDspId, NULL );
     When an error occurs => PROC_detach( gcDspId ); PROC_destroy( );

    LoadFirmware
     IsOwner; // Just a check whether this process also initialize the PROC object
     DeviceStopped; // Check whether it's not running code
     Stat = PROC_load( gcDspId, const_cast<char*>( Path ), 0, NULL );
     
    Start
     IsOwner; 
     IsFirmwareLoaded;
     Stat = PROC_start( gcDspId );
     Result = GetDSPState( State, Result );

    Etc.

    Let me know whether this helps.

    Regards,

    Luke 

    PS.
    Do you also have the problem of stalling Linux when no debuggers are connected to the board? Because when you try to start the DSP while the debugger is connected you are not owner of the DSP. 

  • Hey,

    First of all, thanks for your help.

    I still have the problem of stalling Linux when no debugger is connected to the board.

    Otherwise, I have the same DSP Link call sequence as your own on the Linux side. 

    I can start the DSP firmware successfully but my problem is that  on the Linux side I still stall in the PROC_Start routine. I am wondering now what i have to do on the DSP side to avoid this. On the DSP Side, i use my own firmware and i do not launch any DSPLink_init function.

    Do you remenber if you have to do a specific action or a specific configuration on the DSP side ?

    Regards

    Alex.

  • No it is not required to do anything on the DSP side as far as I remember. Have you tried enabling tracing so you can see in Linux where it stalls? The driver performs a lot of steps which are not trivial to discover from the code ;). 

  • I try by my own and I am still stall just after the call of this function DRV_INVOKE (DRV_handle, CMD_PROC_START, &args);

    An more precisely, in this function : ioctl (DRV_handle->driverHandle, CMD_PROC_START, &args); 

    It looks like either waiting an anwser from the DSP or stall by my DSP firmware....

    But i can try to enable tracing.

     

  • How did you verify that the DSP firmware is running? Are you toggling a led, GPIO pin or anything?

  • Yes i am toggling a LED and i am using the DIP switch on the board to activate the LED.

  • Alex,

    Is this issue still open?

    The Linux getting stuck when PROC_start is called could be due to an overlap in the timer used for both A8 and DSP core.

    Can you check if http://processors.wiki.ti.com/index.php/Troubleshooting_DSPLink_configuration_issues#Problem:_I_see_a_crash_as_soon_as_I_run_a_DSPLink_sample.

    helps?

    Deepali

  • Deepali,

     

    This issue is not open anymore. But it was not due to an overlap in the timer 0 used for both core.

    My problem was as i am not using DSPBIOS on DSP side, i did never launch DSPLink_init in my DSP firmware. But the Linux was waiting a handshaking that never occured.

    I solved my problem by writing my own DSPLink_init in order to complete the handshaking with linux. Now it is working fine.

    Thanks for your attentiveness.

    Regards

    Alex

  • Alexandre Amiez said:

    This issue is not open anymore. But it was not due to an overlap in the timer 0 used for both core.

    My problem was as i am not using DSPBIOS on DSP side, i did never launch DSPLink_init in my DSP firmware. But the Linux was waiting a handshaking that never occured.

    I solved my problem by writing my own DSPLink_init in order to complete the handshaking with linux. Now it is working fine.

    Hi, Alexandre

    I have the similar question about how to implement a DSPLINK_init function on DSP side.

    Here is what I have to do:

    •     On both side I only need PROC component, (I re-compiled dsplinkk.ko whithout any component but PROC,but failed.)
    •     and use arm linux as a boot loader to load dsp.

    I'm wondering how can I make PROC_start not to wait for the handshake while no need to introduce the DSPLINK APIs into the dsp side code.

    Thank you!

    William

  • Hi William,

    I tried to modify PROC_Start routine in order to not wait the handshake of the DSP, but unfortunately without success.PROC_Start routine calls the DRV_INVOKE routine. Then DRV_INVOKE routine calls an board specific ioctl function and i was not able to find the source code of this function.... so i changed my strategy.

    In my solution, i do not introduce the DSPLink Apis into the dsp side code. I just introduced in my DSP firmware an init function handshaking with the GPP. In order to that, I was using the dsplink_init() function of the example audio_soc_example_1_00_00_03 given by Texas as working base. Then i preserved in this file only that was necessary and removed all the DSPLINK and DSPBIOS dependencies. 

    The share memory between GPP and DSP used to handshake is located at this address : DSPLINK_shmBaseAddress. This address is board specific and you can find it in the file link with your board in the DSPLINK directory " \dsplink_linux_1_65_00_02\dsplink\config\all ".

    Help, it helps.

    Regards

    Alex

     

     

     

  • Alex/William,

    DSPLink allows loading of a non DSPLink based executable. For this, you need to build DSPLink with only PROC component i.e. use comps=p while configuring DSPLink using dsplinkcfg script. Could you share the DSPLink release on which you are working? This was added in DSPLink release 1.60.

    Once you specify any other component, handshaking between the two cores comes into the picture. This handshake is necessary as it checks that the DSPLink configurations like memory map, version and components chosen on both cores match.

    We do not recommend updating PROC_start to remove handshake. Handskake failure indicates a deeper issue which needs to be debugged at that point rather than debugging a random failure at run time.

    Deepali