Meross MSS310

Part 5: Using a timer

Next step is to replace the dumb delay routine with a real timer controlled interrupt routine. However, our first step is to just use a timer controlled delay loop, without interrupts.

First the timer registers, we’ll use timer 0:


#define TGLB_REG        0x10000100      /* Timers global control register */

#define T0CTL_REG       0x10000110      /* Timer 0 control register */
#define T0LMT_REG       0x10000114      /* Timer 0 limit register */
#define T0_REG          0x10000118      /* Timer 0 counter register */

#define TxCTL_Tx_PRES_OFFSET 16         /* Timer 0/1 prescale offset */
#define TxCTL_TxEN           (1 << 7)   /* Timer 0/1 enable */

And here’s the relevant code which now uses this timer:


static void timer_delay(unsigned int delay_in_ms)
{
    // start by disabling timer
    write_l(T0CTL_REG, 0);
    write_l(TGLB_REG, 0);

    write_l(T0LMT_REG, delay_in_ms);

    // enable the timer, set prescale to 1ms
    write_l(T0CTL_REG, (1000 << TxCTL_Tx_PRES_OFFSET) | TxCTL_TxEN);

    while ((read_l(T0CTL_REG) & TxCTL_TxEN) != 0) {
        // busy wait until timer expires
    }
}


/* A less dumb delay routine */
static void delay()
{
    const auto milliseconds = 500;
    const auto granularity = 100;
    static_assert(milliseconds % granularity == 0,
        "milliseconds should be a multiple of granularity");
    for (auto i = 0; i < (milliseconds / granularity); i++) {
        reset_if_button_pressed();
        serial_input();
        timer_delay(granularity);
    }
}

Note that I switched to C++ meanwhile.

Now, this still uses a busy wait for the timer, but at least the timeouts can be specified exactly.

Next step: replace the busy wait with a wait for interrupt.

To be continued…