Jump to content

MIDI and interrupts


Sauraen
 Share

Recommended Posts

Hi TK,

 

I should know this already, but if a standard MIDI message (not SysEx) is received while execution is between a MIOS32_IRQ_Disable() and MIOS32_IRQ_Enable(), does the message get dropped, or does it go in some sort of queue for processing later? If so, is this allocated in real time from the heap, or something else? Is there any chance of this overflowing?

 

Is is the case that immediately upon calling MIOS32_IRQ_Enable(), the interrupt occurs and the message is processed? Or is it only once per millisecond?

 

I've been having some trouble with a custom application where everything works fine for an arbitrarily long time as long as the MIDI data being sent to the core for processing is relatively sparse, but after about 3 minutes of playing a song into it with a whole lot of data very quickly, the APP_Background() thread hangs (most likely somewhere in my code), but MIDI communication with MiosStudio and MBNG front panel control continues to work fine (i.e. FreeRTOS is still running).

 

Thanks,

Sauraen

Link to comment
Share on other sites

In general, interrupts shouldn't be disabled by more than 10 uS. Use a different method if your code accesses shared resources, e.g. use portENTER_CRITICAL() / portEXIT_CRITICAL() or a mutex if only tasks access the resource.

 

For UART based MIDI a received MIDI byte could get lost if interrupts are disabled for more than 600 uS

For USB based MIDI the host will be blocked (but it will queue the messages)

 

For transmitted MIDI streams the ringbuffer will collect data, but the size is limited. On the other hand, it can typically bridge ca. 20 mS... if your application really needs more time where the ringbuffer can't be emptied, then consider software changes, e.g. offload to tasks which are running with a priority less than 3 (MIDI is handled at priority 3)

 

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi TK,

 

Thanks for the help. Before seeing your message I tried increasing the amount of code enclosed by interrupts-disabled, that just led to increasing the frequency of hangs. Back to original code...

 

In my case I am receiving MIDI messages via USB, though I would like to make sure this will work over UART as well. The interrupts are disabled for less than 10 us at a time (writing to a register in a sound chip), but when many registers need refreshing, that function is called from a loop, so the interrupts are disabled most of the time during a longer period (e.g. 100 us), but enabled for short periods during that time. Do you expect this to be a problem? In any case the problem I'm having is not that there's a lot of MIDI messages being dropped, but that part of the application is hanging.

 

To help track down where in the execution of APP_Background it was hanging, I created a global variable that it would write different values to between executing different sections of my code. Since the MBNG frontpanel control is all still working while it's hung, I have it displaying that number on the screen, and I can get it to refresh that even after it's crashed. After doing this a few times, it appears to be crashing at random points throughout the loop of APP_Background--not just, for instance, during the sound chip refreshing routine (when interrupts are disabled), and often while it's not executing any of my own code at all. So I'm guessing the problem is not in any of the actual code being executed in APP_Background.

 

What happens if there's an error in code it's executing based on receiving a MIDI message--will that cause APP_Background to stop running, but allow future MIDI messages to be received and MBNG front panel button/LED stuff to keep working? For instance if there's an infinite loop in my MIDI handler function, would that cause the above symptoms?

Link to comment
Share on other sites

What happens if there's an error in code it's executing based on receiving a MIDI message--will that cause APP_Background to stop running, but allow future MIDI messages to be received and MBNG front panel button/LED stuff to keep working? For instance if there's an infinite loop in my MIDI handler function, would that cause the above symptoms?

 

Yes, because the Background task has the lowest priority.

 

Only tasks with the same (or higher) priority would be executed in the 1 mS window anymore.

 

See also http://svnmios.midibox.org/filedetails.php?repname=svn.mios32&path=%2Ftrunk%2Fapps%2Ftutorials%2F006_rtos_tasks%2FREADME.txt

 

The allowed priority range is between 0 and 5, where 0 is the lowest priority (equal to the APP_Background task), and 5 the highest priority.  Tasks with higher priority can always interrupt tasks with lower priority. Accordingly, tasks with lower priority will only run when no higher priority task is executed. If --- and this is the big advantage of a RTOS scheduler --- tasks at the same priority level are running for more than 1 mS (the system tick), the current task will be interrupted automatically and the next waiting task with the same priority is started. This is called preemption -> http://en.wikipedia.org/wiki/Preemption_(computing)  You will love this feature, because it allows to run time consuming loops quasi-parallel without taking care for compute time sharing (as long as tasks are running at the same priority level). 
 

Best Regards, Thorsten.

Link to comment
Share on other sites

:blush: I found the infinite loop... :bug:

If a note on was received that was unable to fit in the voices and was put on the notestack, and then the note off for that note was dropped, and then another note on was received for the same channel for the same note, AND if allowing multiple same notes was enabled, the MIDI handling routine would infinite loop.

The reason I didn't find this sooner is because I thought that if I had hung the MIDI-handling thread, the core would be unable to receive any more MIDI messages. I didn't realize that each new message could in effect spawn a new thread. Anyway, I learned some things about embedded systems OS design, so that's good. And I wound up making a stress-test MIDI file that tries to send 2.3 MB of standard MIDI messages in about 15 seconds, which now, while it still leaves the synth playing 36 hanging notes, does not leave it crashed! Thanks for the help.

Edited by Sauraen
Link to comment
Share on other sites

Yes, it's always better to accept dropped events than running into the danger of an infinite loop.

Working with the reduced resources of an embedded system means to accept potential failures which are almost everywhere.

The challenge is to design the software in a way so that a common user will never notice this ;-)

 

Best Regards, Thorsten.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...