AnsweredAssumed Answered

interrupts sharing array with main loop

Question asked by ttemple on Feb 16, 2018
Latest reply on Feb 22, 2018 by Jithul_Janardhanan

I have interrupt handlers attached to the SPORT1 and SPORT0 signals.  One is a transmit interrupt, and the other is a receive interrupt.  I also have other interrupts occurring, and a main loop.  I am having problems that seem to be related to improperly handling data that is being manipulated by interrupts and main loop code.  I am looking for clear guidance on the proper patterns to use when handling arrays of data, and other data, both in interrupt handlers and the main loop.

I am fairly experienced in multi-threaded programming, as in the C++/windows realm, so I understand the basic issues, but I am not as familiar with the issue as it applies to C and microcontrollers and DSP's.

 

In case it matters, my hardware is the 21262, and I'm using VisualDSP V5.1.2.

 

On the receive side, my incoming buffer is:

int inbuf[200];

In the interrupt handler, I am looking at the first element in the incoming data to see if data is present.  When data is present, I copy the buffer to a buffer of commands that gets processed in my main loop.

 

My command buffers looks like this:

volatile int cmdbuf[2][200];

extern int volatile status;   // status flags are bits within this int.

In my interrupt handler, I do something like this:

void rx_int(int sig_num)
{
    // if the input buffer is marked as a command block
    if ((inbuf[0] & 0xffff) == 0xa2a2)   // <-- magic number that marks a command block
    {
        // and my command buffer is empty
        if(cmdbuf[0][0] == 0)    // <-- first element of 0 means the buffer is empty
        {
            // copy the incoming data to a command buffer
            memcpy(cmdbuf[0], inbuf, 200);
            // marker to the main loop that a buffer was loaded.
            status |= CMD_BUF_LOADED;
        }
    }
}


I connect the interrupt like this:

Interruptf(SIG_SP0, rx_int);

 

 

In my main loop, I call a function something like this:

 

process_buffer
{
    // if the buffer loaded flag is on

   // if((cmdbuf[0][0] & 0xffff) == 0xa2a2)  // <-- this did not seem to work reliably...
    if(status & CMD_BUF_LOADED)    // <-- this seems reliable
    {
       // process the command buffer
        process_commands();

        // mark the command buffer as empty
        cmdbuf[0][0] = 0;

        // clear the buffer loaded status flag
        asm("push sts");                  // <-- I believe this is necessary, but is this the right way?
        status &= ~CMD_BUF_LOADED;
        asm("pop sts");                   // <-- ditto...
    }
}

 

I have many questions concerning this code, based upon much trial and error, and strange behavior.  When I tried to rely upon cmdbuf[0][0] as a marker for data present, I would get many false entries into the process_commands().  It was as though the value was not being read each time the function was called.  Using the status flag seems reliable.  I don't understand why I can't come up with a construction that completely relies upon the first element in the array being a status value that the interrupt and the main code use to determine the buffer status.  No matter what I tried, I couldn't seem to crack it.

 

1) The description for Interruptf indicates that it does not pass the signal number to the function, yet it seems that I have to make my function signature for rx_int include an int parameter.  I then get a 'remark' that the parameter is not used when I build.  Not a big deal, but is there a way to do this that doesn't produce the remark?

 

2) I believe that the interrupt functions are doing push sts upon entry, and pop sts upon exit.  Is this for sure the case?  In other words, do I ever have to do this within interrupt code?

 

3) If #2 is true, on the occasion that I make function calls from an interrupt handler, I presume that those functions are covered by the push sts that occurs in the interrupt function that is calling those functions.  Is that correct?

for example:

void isr(int sig)
{
    // I assume that push sts has been called before I get here.

    call_some_function();  // <-- is the code in this function now protected by the push sts?

    // I assume that pop sts will be called as this exits...
}

 

4) I would like clear guidance on how to deal with the 'volatile' aspects of the arrays.  I have had much trouble getting predictable behavior out of this code, and have tried many things.  I feel like I am missing some major points about how to handle data that is being manipulated both in the interrupt handlers and the main loop.  I have done a good bit of research, and have just not found clear information, especially with the arrays.

 

I have resorted to accessing the arrays with this type of construction:

 

int volatile * inbufptr = &inbuf[0];
if((inbufptr[0] & 0xffff) == 0xa2a5)...

 

I believe this to be creating a pointer to volatile int, in an effort to make sure that the compiler is not optimizing things out when I'm reading and writing the arrays.

 

I tried a number of ways to declare the arrays volatile, and could not seem to feel like the behavior was any more predictable than without.  When I went to the pointers to volatile int, my situation seemed to improve.

 

5) In my main loop code, it seems clear that when I write the 'status' variable, I must protect against interrupts.  This is currently being done in the way I have shown.  Is this the proper way to do such things?  Is there a 'C' construction that is more appropriate for this?

 

6) in the interrupt service, I am not doing anything to protect the write of 'status'.  Is it correct that I don't need protection here, if the push sts occurs before entering my interrupt function?

 

If there is a good source of guidance on how to properly deal with interrupt handlers with VisualDSP, that would help tremendously.

Outcomes