USBComposite send data from within interrupts

Post here first, or if you can't find a relevant section!
cptcredible
Posts: 13
Joined: Fri Apr 24, 2020 5:03 am

USBComposite send data from within interrupts

Post by cptcredible »

I am making a guitar pedal synchronizing thingamajig and as part of that i want to receive clock pulses from analog sequencers and output a MIDI clock via USB and serial. To get the timing accurate enough I have attached an interrupt to a pin monitoring the clock pulses coming in.
Ideally I would send USBmidi clock messages from within this interrupt, but doing so freezes the STM32f103C8t6.

Is there any way to get this working?
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USBComposite send data from within interrupts

Post by ag123 »

normally one shouldn't handle an interrupt within an interrupt, there is a chance though i'm not sure if usb uses interrupts itself, and you are trying to do so within another interrupt?
usb is async, which ever way one tries it remains that way
cptcredible
Posts: 13
Joined: Fri Apr 24, 2020 5:03 am

Re: USBComposite send data from within interrupts

Post by cptcredible »

upon closer investigation it seems I can send some data as long as it's only one packet?

this works:
CompositeSerial.print("I can send a lot of data as long as it is all sent as one packet like this.");

this fails:
CompositeSerial.print("two");
CompositeSerial.print("lines");

this also fails:
CompositeSerial.println("fail");

So luckily I can reliably send one umidi.sendSync() midi clock sync message per interrupt
but in some situations I need to send umidi.sendStop(); and umidi.sendStart(); in one interrupt, and that fails.
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USBComposite send data from within interrupts

Post by ag123 »

my guess if you are simply using serial, the default usb-serial 'driver' may work better,
on stm32f401 with the usb-serial CDC (vcp) 'driver'
viewtopic.php?f=24&t=452
i actually got 1.2 Mbps, well that is hardly worth bragging as usb full speed is 12 Mbps. there are probably other deiays.
but nevertheless it is possibly much faster than many usb-uart dongles which may cap at 115200 bps
phil bowles
Posts: 13
Joined: Mon May 25, 2020 10:15 am

Re: USBComposite send data from within interrupts

Post by phil bowles »

You should never try to do "real work" inside an ISR. You should do the absolute minimum possible such as set a global flag (usually marked 'volatile') then get out immediately. You should certainly never try to call anything else that uses or requires interrupts. If you do then, well...you already know what usually happens.

In the main loop / thread check the flag then do what you need to do, then reset it.
cptcredible
Posts: 13
Joined: Fri Apr 24, 2020 5:03 am

Re: USBComposite send data from within interrupts

Post by cptcredible »

ag123 wrote: Wed Jul 08, 2020 10:31 pm my guess if you are simply using serial, the default usb-serial 'driver' may work better,
on stm32f401 with the usb-serial CDC (vcp) 'driver'
I am using USB midi, just using serial for debug.
cptcredible
Posts: 13
Joined: Fri Apr 24, 2020 5:03 am

Re: USBComposite send data from within interrupts

Post by cptcredible »

phil bowles wrote: Thu Jul 09, 2020 5:02 am You should never try to do "real work" inside an ISR. You should do the absolute minimum possible such as set a global flag (usually marked 'volatile') then get out immediately. You should certainly never try to call anything else that uses or requires interrupts. If you do then, well...you already know what usually happens.

In the main loop / thread check the flag then do what you need to do, then reset it.
Yeah, I realise i am being quite naughty. I strive to do keep the interrupts short and sweet, but there are so many timing sensitive things I need to do in this code that I ended up with more and more in the interrupts (one systick monitoring a rotary encoder and handling an internal clock to send pulses / midi timing out over USB and serial and one pin interrupt to catch incoming analog clock pulses) Everything seems to run very stably for as long as i have tested (5hrs or so) but this issue of sending more USB messages breaks it.

I am doing some occasional division in the interrupts to calculate BPM from pulse period, unsigned long microseconds / 30000000
I am used to avoiding these kinds of operations on Atmegas, are they fast enough to be negligable on the STM32f103C8t6 though?
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: USBComposite send data from within interrupts

Post by ag123 »

one way though is to hook up st-link and a debugger, it may help to figure out the problems and give hints on optimizations.
to improve throughput, one way though is to send in batch, that works in the default usb cdc serial.
but throughput is not the same as time sensitive responsiveness.

i think usb hid has got a means to specify the interrupt rates from the host, but i'm not sure how or if it is supported in USBComposite.
if that can be used, there is probably no need for code changes and you can influence the response rates sending commands from the host.
phil bowles
Posts: 13
Joined: Mon May 25, 2020 10:15 am

Re: USBComposite send data from within interrupts

Post by phil bowles »

"but there are so many timing sensitive things I need to do in this code that I ended up with more and more in the interrupts"

Just set more flags in the ISR. Put the body of the code in the main loop. If using this strategy, you have "too much to do" or "run out of time" then the simple truth is you are using the wrong MCU for the job. ANother approach is so use different interrupts for each sub-task...but again if you don't have enough interrupts...wrong MCU.

In its simplest form (and scaled up for for easy comprehension) if you are trying to execute code every second that takes 1.001 seconds to run...your code is always going to crash, and cannot ever be run successfully on that MCU, no matter how hard you try.
Squonk42
Posts: 16
Joined: Sat Dec 21, 2019 8:35 am

Re: USBComposite send data from within interrupts

Post by Squonk42 »

I agree with Phil: IRQ handlers should be fast and short, just clear the interrupt, set some flags, record accurate time stamps, and put received data into a FIFO.

Then handle all lengthy / complex operations in the main loop, possibly going back to deep sleep if there is nothing to do.

And if you really have many tasks to do in parallel, separate your code into several coroutines launched from main loop. Each coroutine can be just a standard function containing a switch on the current task state and exiting the function asap, going back where it left on the next loop. You are then implementing a cheap tickless, collaborative (non preemptive) multitasking system.

If you want a preemptive and/or clocked system, then use an RTOS.
Post Reply

Return to “General discussion”