Getters and setters is a really nice idea but may incur a time penalty for the function calls. In an interrupt routine (probably calling the 'setter'), the delay may be objectionable.
Yes, but I think you didn't quite get my point/approach. I'm not advocating putting a bunch of globals in ONE file with getters and setters for everyone else as someone else suggested. I would actually find this almost as spaghetti-like as the direct externing of globals... I'm saying to make things truly modular.
What it means here is that typically, I would declare (as static volatile) the variable in question in the same source file where the ISR lies, and every other function that has to have fast and direct access to the variable.
No time penalty. Try and make all time-critical functions related to this within the same scope, while keeping a modular logic. In the OP's case, a "timer" module handling all tasks related to the timer for instance: ISR, resetting the counter, and anything else around it (possibly functions that convert the counter to a scaled time value if needed, etc.)
Getters and setters is a really nice idea but may incur a time penalty for the function calls. In an interrupt routine (probably calling the 'setter'), the delay may be objectionable.
Of course there is also a delay for the 'getter' call. Whether it matters depends on the application.
Getters or special setters (like a counter reset) would be for the "outside" world and less time-critical uses. So as said above, try and think of all the time-critical uses and keep that inside one module.
For instance, for a timer counter like in the simple OP's example. Some overhead in the getter is no problem here as long as you can guarantee that the getter's overhead is less than the period between two interrupt calls. Which will be very often the case. In many cases, if a getter's overhead is unacceptable, that usually means that the logical and maybe only option would be to perform the given task that reads the variable inside of the ISR anyway...
Of course as I said, you don't have to stubbornly follow this way of doing things in particular cases where directly accessing the variable would still be the only option. There may be cases obviously where this modularity makes things awkward. Common sense always helps.
Or, we can declare the functions as 'inline' and eliminate the overhead of the function call. This look appealing! We get the benefit of using getters and setters with no overhead for function call/return.
Yes, you can do that.
I think it has been mentioned earlier in the thread (didn't read it all again), some have suggested that inlining may occur even without declaring functions as "inline". If in separate source files, I wouldn't count on that in the general case. I think this would lie in the "LTO" category (link-time optimizations), and depending on the compiler, that may or may not be available, may or may not handle inlining by itself, and may or may not require a special extra compiler option to be enabled.