There are a few questions:
Is this a good approach?
Yes. Perhaps there is an argument in favor of placing the ISR in the same module as the access functions and the data that it shares, considering it to be an access function that allows it to directly read data without access shell overhead.
Is it better / worse / equal to just have a bunch of global variables?
Much worse. With global, where are you going to place the access mutex, data validation or breakpoints? It enhances modular communication and should always be minimized.
Any serious flaws?
Not really. There is overhead for features that can be critical in an ISR; but if this is a problem, you will not call printf() in ISR! You can mitigate any possible performance degradation by applying my previous suggestion about placing ISRs in a data module or embedding code, but your compiler can ignore it and can do it if debugging is enabled, and it can also be built-in regardless of whether optimization is enabled. Some compilers have a βforcedβ built-in extension that the compiler cannot ignore; but it is not tolerated.
One of the significant advantages is that if the variable is non-atomic, you need an access protection mechanism to ensure consistent access - and this is most easily and safely done using access functions. In this case, you may have get / set functions that can disable and enable the interrupt around access again, for example, or use rotation lock (suitable for writing ISR and normal context), and not vice versa. here - do not block the ISR indefinitely!).
I also thought that I could use some kind of mix, as if you had global variables that allowed you to directly manipulate ISRs (as function calls from ISR are sometimes called) and functions in each other case. Would be better?
Not really - see my point above about function call overhead and placing ISRs with data. The problem with calling functions in the ISR is rarely related to temporary problems, but rather because the function designer may not have designed it to safely and efficiently call from the ISR and may use an excessive stack, non-deterministic runtime, wait or wait, or lack of re-entry or thread safety. For example, calling third-party or standard library functions may not be logical; calling functions that you specifically wrote and developed for this purpose and meet your specific constraints are not necessarily a problem.
All you need to know about why globals are a bad idea, and suitable ways to avoid them, can be found in Jack Hansl's article "Aox on the Globals" - this is also an interesting read.