Project

General

Profile

Interrupting the ARM from the DSP

Added by Mary Frantz about 6 years ago

I would like to have the DSP (running BIOS 5) interrupt the ARM (running Linux MDK_2012-08-10)

In the DSP Code:

    while(1)
    {

        TSK_sleep(5000);    // msec

        SETBIT(SYSCONFIG->CHIPSIG, 0x01);

        }

ARM code method 1 (use sigaction())


void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
}

void function_calledFromMain()
{
     struct sigaction query_action, new_action;

          /* Set up the structure to specify the new action. */
         new_action.sa_handler = sig_handler;
         //sigemptyset (&new_action.sa_mask);
         // Block every signal during the handler
         sigfillset(&new_action.sa_mask);
         //new_action.sa_flags = 0;
         // Restart the interrupted system call, if at all possible so it doesn't fail
         new_action.sa_flags = SA_RESTART;

         sigaction (SIGINT, &new_action, NULL);

         if (sigaction (SIGINT, NULL, &query_action) < 0)
             printf("sigaction error.\n");                     /* sigaction returns -1 in case of error. */
         else if (query_action.sa_handler == SIG_DFL)
             printf("SIGINT is default, fatal\n");            /* SIGINT is handled in the default, fatal manner. */
         else if (query_action.sa_handler == SIG_IGN)
             printf("SIGINT is ignored.\n");                /* SIGINT is ignored. */
         else
             printf("SIGINT is programmer defined. \n");    /* A programmer-defined signal handler is in effect. */
}

The call to sigaction() apparently succeeds, and "SIGINT is programmer defined." appears on the console.

I set a breakpoint in sig_handler(), but it is never reached. I don't see the printf("received SIGINT") output in the console either. In this case the debugger shows a SIGINT was received by main() but it does not terminate the process.

ARM code Method 2 (using signalfd()):

int gfdSigInt;

void function_calledFromMain()
{
    sigset_t mask;

    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);

    /* Block signals so that they aren't handled
        according to their default dispositions */
    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
         error(0, errno, "sigprocmask()");
    gfdSigInt = signalfd(-1, &mask, 0);
    if (gfdSigInt == -1)
          error(0, errno, "signalfd()");

}

void task_startedFromMain()
{
    while(!gQuit)
    {

        // Wait for SIGINT from DSP
        s = read(gfdSigInt, &fdsi, sizeof(struct signalfd_siginfo));
        if (s != sizeof(struct signalfd_siginfo))
            error(0, errno, "read gfdSigInt");

        if (fdsi.ssi_signo == SIGINT)
        {
            printf("Got SIGINT\n");
        }

    }
}

I put a breakpoint following the read(gfdSinInt ...) but it is never reached.

If I do nothing about SIGINT, the ARM program terminates.

What am I missing? Is this the right way to detect an interrupt initiated by the DSP?

Is there a way to respond only to the specific interrupt raised by setting a bit in CHIPSIG?

Mary


Replies (4)

RE: Interrupting the ARM from the DSP - Added by Gregory Gluszek about 6 years ago

Hello Mary,

I'm not sure what the problem is in your specific example as we almost always use DSPLink to to communicate between the ARM and DSP. We have wrapper classes that allow for passing messages between the DSP and ARM, and utilizing those classes might provide an easier solution for allowing the DSP to interrupt the ARM. The DSP Hello World Example shows basic usage of these classes if you are not familiar with them already.

Hope this helps.

Thanks,
Greg

RE: Interrupting the ARM from the DSP - Added by Mary Frantz about 6 years ago

Yes, I am familiar with DSPLink and am using it. However, I have time requirement that DSPLink cannot meet. Polling uses too much CPU time. Interrupt would be the most efficient. I just need to know how to connect the CHIPSIG interrupt to user space.

Mary

RE: Interrupting the ARM from the DSP - Added by Michael Williamson about 6 years ago

I think that you are confusing signals and interrupts a bit.

You need to write some kernel module code to register an ISR handler for the CHIPSIG (which may already being used by DSPLINK) and forward/create the signal condition you are trying to catch in user space.

If you are already using DSPLINK, you could try to use the NOTIFY framework which sounds like what you want to do.

As an aside, the next MDK release will be migrating from DSPLINK to SYSLINK/IPC as TI is moving away from DSPLINK. However, the libraries for DSPLINK should support your immediate need.

-Mike

RE: Interrupting the ARM from the DSP - Added by Mary Frantz about 6 years ago

Thanks. This does what I wanted.

On the DSP side:

#include <notify.h>

int main(int argc, char* argv[])
{
    // initialize the DSPLink system
    tcCL_IPCInit::GetInstance();  

    // Launch an initialization task
       TSK_Attrs* lpAttrs = new TSK_Attrs;
    *lpAttrs           = TSK_ATTRS;
    lpAttrs->name      = "Initialize DLPLink";
    lpAttrs->stacksize = 8192*2;
    lpAttrs->priority  = 5;
    TSK_create((Fxn)DSPLINK_initialize,lpAttrs);

    return 0;
}

void DSPLINK_initialize()
{  

        // ...
        // Initialize DSPLINK first as in HelloWorldDSP example
        // ...
    while(1)
    {

        TSK_sleep(5000);    // msec

        NOTIFY_notify(1,    // Processor ID to send notification to
              0,        // IPS ID to be used
              5,        // IPS event number
              0x12345678);    // 32 bit information to be sent across
        }
}

On ARM side:


int main(int argc, char* argv[])
{
    // ...
    // Initialize DSPLINK as in HelloWorldDSP example
    // ...

    // see http://processors.wiki.ti.com/index.php/Notify_Module_Overview
    gArg = 0xABCDABCD;

    DSP_STATUS status;
    status = NOTIFY_register(0,     // processor to talk with
                0,            // IPS ID to be used
                5,            // IPS event number
                DATA_callbackOutputs,    // callback function
                &gArg);            // parameter for call back function

}

void DATA_callbackOutputs(Uint32 eventNo, void *pArg, void *pInfo)
{
    printf("In DATA_callbackOutputs:  eventNo %u, pArg %x, pInfo %x",
            eventNo, *(int *)pArg, (uint32_t *)pInfo);
}

This message appears on the console every 5 seconds:

"In DATA_callbackOutputs: eventNo 5, pArg abcdabcd, pInfo 12345678"

Side note:
Even though I was already using DSPLINK to start the DSP app and send messages back and forth, I slso had to copy over some header files from the MDK for the DSP compiler, and change the name from DSPLINK_init() to DSPLINK_initialize(). The relevant header files to #include <notifiy.h> are located here:
MDK_2012-08-10/sw/3rdparty/dsplink_linux_1_65_00_03/dsplink/dsp

    (1-4/4)
    Add picture from clipboard (Maximum size: 500 MB)