Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Microcontroller Software Timer Management via SysTick

Tech May 15 1

Data Structure Defintiion

#define MAX_TIMER_SLOTS 4 /* Total number of software timers (IDs 0 to 3) */

typedef enum {
    MODE_SINGLE_RUN = 0, /* Executes only once */
    MODE_CONTINUOUS_RUN = 1 /* Repeats automatically */
} TimerRunMode;

/* Timer context structure. Members must be declared volatile since they are 
   accessed concurrently by the ISR and the main application loop, 
   preventing compiler optimizations from causing inconsistencies. */
typedef struct {
    volatile TimerRunMode runMode; /* Timer operating mode */
    volatile uint8_t elapsed;      /* Expiration flag */
    volatile uint32_t ticksRemaining; /* Current countdown value */
    volatile uint32_t resetValue;     /* Reload value for continuous mode */
} TimerContext;

static TimerContext timerPool[MAX_TIMER_SLOTS];

Initialization

void Timers_Initialize(void) {
    for (uint8_t idx = 0; idx < MAX_TIMER_SLOTS; idx++) {
        timerPool[idx].ticksRemaining = 0;
        timerPool[idx].resetValue = 0;
        timerPool[idx].elapsed = 0;
        timerPool[idx].runMode = MODE_SINGLE_RUN; /* Default to one-shot mode */
    }

    /* Configure SysTick to trigger an interrupt every 1ms.
       SystemCoreClock represents the core clock frequency (e.g., 400MHz for STM32H7).
       SystemCoreClock / 1000 yields a 1000Hz interrupt rate (1ms period). */
    SysTick_Config(SystemCoreClock / 1000);
}

One-Shot Timer Activation

bool Timer_StartOneShot(uint8_t slotId, uint32_t duration) {
    if (slotId >= MAX_TIMER_SLOTS) {
        return false; /* Invalid ID */
    }

    ENTER_CRITICAL(); /* Disable interrupts to protect shared data */

    timerPool[slotId].ticksRemaining = duration;
    timerPool[slotId].resetValue = duration; /* Only relevant for continuous mode */
    timerPool[slotId].elapsed = 0;
    timerPool[slotId].runMode = MODE_SINGLE_RUN;

    EXIT_CRITICAL(); /* Re-enable interrupts */
    return true;
}

Periodic Timer Activatoin

bool Timer_StartPeriodic(uint8_t slotId, uint32_t interval) {
    if (slotId >= MAX_TIMER_SLOTS) {
        return false;
    }

    ENTER_CRITICAL();

    timerPool[slotId].ticksRemaining = interval;
    timerPool[slotId].resetValue = interval;
    timerPool[slotId].elapsed = 0;
    timerPool[slotId].runMode = MODE_CONTINUOUS_RUN;

    EXIT_CRITICAL();
    return true;
}

Timer Deactivation

void Timer_Deactivate(uint8_t slotId) {
    if (slotId >= MAX_TIMER_SLOTS) {
        return; /* Invalid ID, safely ignored */
    }

    ENTER_CRITICAL();

    timerPool[slotId].ticksRemaining = 0;
    timerPool[slotId].elapsed = 0;
    timerPool[slotId].runMode = MODE_SINGLE_RUN;

    EXIT_CRITICAL();
}

Expiration Check

bool Timer_HasElapsed(uint8_t slotId) {
    if (slotId >= MAX_TIMER_SLOTS) {
        return false;
    }

    if (timerPool[slotId].elapsed) {
        timerPool[slotId].elapsed = 0; /* Clear flag upon read */
        return true;
    }

    return false;
}

SysTick Interrupt Handler

static void DecrementTimerTicks(TimerContext *ctx) {
    if (ctx->ticksRemaining > 0) {
        ctx->ticksRemaining--;
        if (ctx->ticksRemaining == 0) {
            ctx->elapsed = 1;

            if (ctx->runMode == MODE_CONTINUOUS_RUN) {
                ctx->ticksRemaining = ctx->resetValue;
            }
        }
    }
}

void SysTick_IRQHandler(void) {
    for (uint8_t idx = 0; idx < MAX_TIMER_SLOTS; idx++) {
        DecrementTimerTicks(&timerPool[idx]);
    }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.