Hi,
I want to use a few global register variables (r2, r3, r4) to implement several timers with a single hardware timer:
// System Timer Resolution Unit = ms #define SYSTEM_TIMER_RESOLUTION 10 #define set_ms_timer(timer, ms) {timer = ((ms + SYSTEM_TIMER_RESOLUTION / 2) / SYSTEM_TIMER_RESOLUTION);} register uint8_t isr_temp asm("r2"); register uint8_t shtxx_response_timeout asm ("r3"); register uint8_t measurement_cycle asm ("r4"); void init_system_timer (void) { shtxx_response_timeout = 0; measurement_cycle = 0; // Set Timer1 To Generate Compare Interrupt With The Intervall Time Defined In // SYSTEM_TIMER_RESOLUTION OCR1A = (F_CPU / 8 + 500 / SYSTEM_TIMER_RESOLUTION) / (1000 / SYSTEM_TIMER_RESOLUTION) - 1; // Enable Interrupt On Compare A Match TIMSK1 = (1 << OCIE1A); // Set CTC Mode, Run Timer With F_CPU / 8 TCCR1A = 0; TCCR1B = (1 << WGM12) | (1 << CS11); } ISR (TIMER1_COMPA_vect, ISR_NAKED) { asm volatile ("in %0, %1" : "=r" (isr_temp) : "I" (_SFR_IO_ADDR(SREG))); // Decrement register variable shtxx_response_ms_timeout If It Is Not Zero asm volatile ( "cpse %0, __zero_reg__" "\n\t" "dec %0" : "+r" (shtxx_response_timeout) : "0" (shtxx_response_timeout) ); // Decrement register variable measurement_cycle If It Is Not Zero asm volatile ( "cpse %0, __zero_reg__" "\n\t" "dec %0" : "+r" (measurement_cycle) : "0" (measurement_cycle) ); asm volatile ("out %0, %1" :: "I" (_SFR_IO_ADDR(SREG)), "r" (isr_temp)); reti(); }
This should enable me to start a software timer this way:
set_ms_timer (measurement_cycle, 100);
And then I can simply poll the register variable if a timeout had occured:
if (measurement_cycle == 0) { // Do Something }
The problem is that the GCC optimizer detects that the register variable is never changed inside the code (only inside the ISR) and thus deletes the if (measurement_cycle == 0) relevant stuff.
Is there a way to tell the compiler to not delete that code? Of course without using a volatile declared SRAM variable which will blow up my sweet tight ISR.
Regards
Sebastian