Synchronization mechanism suitable for bare metal applications
Pretty simply: don't directly work on the data the ISR modifies. Instead, in an atomic operation, copy over the potentially volatile variables from the ISR-modified location to your loop state.
Alternatively, if there's more data than you can copy atomically, you'll need to teach your ISR how to write into a ring buffer, and your main loop how to read from one, so that you're never modifying a piece of data that's still being used.
Remark: What you do sounds like 100% an application of a RTOS. These very slim pieces of operating systems are available for your CPU, too (promise! If you can run compiled C on it, someone has ported a small RTOS to it), and you should be using them, exactly because task synchronization is hard and it's a good idea to not do task juggling yourself. It's not any less &quot;bare metal&quot; (you can still write nearly exactly the same code if you want), you just get primitives for executing tasks, exchanging data etc. I don't know your MCU, but look into ChibiOS (if you want something really small) or FreeRTOS (if you want something small with a large user base).