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:
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;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 & 0xffff) == 0xa2a2) // <-- magic number that marks a command block
// and my command buffer is empty
if(cmdbuf == 0) // <-- first element of 0 means the buffer is empty
// copy the incoming data to a command buffer
memcpy(cmdbuf, inbuf, 200);
// marker to the main loop that a buffer was loaded.
status |= CMD_BUF_LOADED;
I connect the interrupt like this:
In my main loop, I call a function something like this:
// if the buffer loaded flag is on
// if((cmdbuf & 0xffff) == 0xa2a2) // <-- this did not seem to work reliably...
if(status & CMD_BUF_LOADED) // <-- this seems reliable
// process the command buffer
// mark the command buffer as empty
cmdbuf = 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 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?
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;
if((inbufptr & 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.