In a real-time system a correct result is not enough; the result must arrive at the right time. Keep interrupt service routines (ISRs) as short as possible. Printing, dynamic memory allocation or long loops inside an ISR delay higher-priority interrupts. Moving the work out of the ISR, using a flag or a queue, is usually enough.
Measure stack usage instead of guessing it: during a test run, fill the stack with a known pattern and record its high-water mark. Allocate frequently used buffers once at start-up and avoid dynamic memory during operation. To find timing problems, toggle a GPIO pin around the code you are measuring, or capture a trace. This gives a faster answer than reasoning about the timing on paper.
Planning a similar project?
We can talk through how the topic in this article applies to your product.