I take your described problem first
As I understand it, your goal is to create a device that, receiving commands from USB, outputs some GPIOs, such as LEDs, relays, etc. For a simple this task, your approach seems to be (if the USB layer can work with it properly).
There is a priority problem, although in this case it may happen that if you reboot the USB drive (with data from the other end of the cable), and interrupt handling will have a higher priority than the timer, GPIO processing, the GPIO side may skip marks ( like other explanations, interrupts cannot be queued).
In your case, this concerns what might be considered.
Some general recommendations
For "as little time as possible in an interrupt handler," the rationale is what others said: the OS can implement a queue, etc., however, hardware interrupts do not offer such concepts. If an event causing an interrupt occurs, the processor enters your handler. Then, until you process its source (for example, reading the receive reception register in the case of UART), you will lose all subsequent events of this event. After this moment, before exiting the handler, you can get whether the event occurred, but not how many times (if the event happened again when the processor was still processing the handler, the associated interrupt line is activated again, so after you return from the handler, the processor immediately returns it if nothing expects a higher priority).
Above, I described the general concept observed on 8-bit processors and 32-bit AVR (I have experience with them). A.
When developing such low-level systems (without an OS, one "background" task and some interruptions), it is important to understand what happens at each priority level (if you use one). In general, you do the most critical tasks in real time with the highest priority, taking care to quickly serve those who are more relaxed with lower priorities.
From another aspect, as a rule, at the design stage, you can plan how the system should respond to missed interrupts, since where there are interruptions, in any case there will be one missing. The critical data passing through the communication lines must have adequate checksums, especially the critical timer must be obtained from the counter register, and not from event counting, etc.
Another unpleasant part of interrupts is their asynchronous nature. If you fail to correctly design the associated locks, they will ultimately ruin something giving nightmares to this poorest soul who will have to debug it. "Spend as little time as possible in the interrupt handler," it is also recommended that the interrupt code be short enough, which means that less code is also needed for this problem. If you also worked with multitasking with the help of RTOS, you should know this part (there are some differences: the higher priority code for the interrupt handler does not need to be protected from the handler with a lower priority).
If you can correctly design your architecture with respect to the necessary asynchronous tasks, dispense with the OS (due to the lack of multitasking) may be even the best solution. He needs to think more about how to design it correctly, but in the future there will be much less problems with locking. I overcame some critical security projects developed within the framework of a single “task” with few interruptions, and the experience and maintenance requirements for these (especially bug tracking) were quite satisfactory compared to some other multitasking built in the company .