Use timer0 without affecting millis() and micros()
So I was wondering if I could attach an ISR to timer0 without affecting the above Arduino functions,


Yes. A few ways, depending on your level of comfort:


You can declare the stock Arduino Timer0 OVF "weak" and write your own where you can insert your ISR. But you have to handle the interaction between the millis() / micros() related variables.
You can modify the stock Arduino Timer0 OVF to insert your own ISR.

And – if that can be done – what would be the restrictions of such an ISR (e.g. I suppose I could not use all the timer/interrupt modes...)

The stock ISR would look like this:

ISR(TIM0_OVF_vect) {
    ...
    timer0_fract = f;
    timer0_millis = m;
    timer0_overflow_count++;

    //insert your isr here
    _mytmr0_isrptr();
}


Where _mytmr0_isrptr() is a function pointer to your own ISR handler.
The simplest is probably to use the output compare interrupts. You can get it to behave like a virtual timer and can do lots of other stuff.


Obviously, you can think of tons of other ways and this is just a starting point.


  What are those interrupts? How can I use them? –


Timer0 has three interrupts associated with it: overflow and compare channel A and channel B. The overflow interrupt is already being used by the timing functions millis() and micros(), as shown earlier.

The compare channel A/B interrupts are unused. And this discussion is about using them for timing purposes.

The general ideal is demonstrated in blog post Using Spare Output Compare Channels as Timers – the Collection.

The task there is more complicated than what you are trying to do here, but the basic ideal is the same. To do what you wanted here it is much simpler than that.

If you still cannot figure it out, I can provide you with code pieces to get you started.