rt 0.19.1

A real-time operating system capable of full preemption
Documentation
#pragma once

#include <stdint.h>

struct vim
{
    uint32_t irqindex;
    uint32_t fiqindex;
    uint32_t padding0[2];
    uint32_t firqpr[4];
    uint32_t intreq[4];
    uint32_t reqenaset[4];
    uint32_t reqenaclr[4];
    uint32_t wakeenaset[4];
    uint32_t wakeenaclr[4];
    void (*irqvecreg)(void);
    void (*fiqvecreg)(void);
    uint32_t capevt;
    uint32_t : 32;
    uint32_t chanctrl[32];
};

struct vim_parity
{
    uint32_t padding0[59];
    uint32_t parflg;
    uint32_t parctl;
    uint32_t adderr;
    void (*fbparerr)(void);
};

#define VIM_NUM_CHANNELS 127

struct vim_table
{
    void (*phantom)(void);
    void (*channel[VIM_NUM_CHANNELS])(void);
};

#define VIM_BASE 0xFFFFFE00UL

static volatile struct vim *const VIM = (volatile struct vim *)VIM_BASE;

static volatile struct vim_parity *const VIM_PARITY =
    (volatile struct vim_parity *)0xFFFFFD00UL;

static volatile struct vim_table *const VIM_TABLE =
    (volatile struct vim_table *)0xFFF82000UL;

#define VIM_PARCTL_ENABLE (UINT32_C(0xA))

static inline void vim_enable(uint32_t channel)
{
    VIM->reqenaset[channel / 32] = UINT32_C(1) << (channel % 32);
}

static inline void vim_disable(uint32_t channel)
{
    VIM->reqenaclr[channel / 32] = UINT32_C(1) << (channel % 32);
}

static inline void vim_clear(uint32_t channel)
{
    VIM->intreq[channel / 32] = UINT32_C(1) << (channel % 32);
}

static inline void vim_set_req(uint32_t channel, uint32_t req)
{
    const uint32_t reg = channel / 4;
    const uint32_t shift = (3 - (channel % 4)) * 8;
    const uint32_t mask = UINT32_C(0xFF) << shift;
    VIM->chanctrl[reg] = ((VIM->chanctrl[reg] & ~mask) | (req << shift));
}

static inline void vim_set_is_fiq(uint32_t channel)
{
    VIM->firqpr[channel / 32] |= UINT32_C(1) << (channel % 32);
}

static inline void vim_clear_is_fiq(uint32_t channel)
{
    VIM->firqpr[channel / 32] &= ~(UINT32_C(1) << (channel % 32));
}

static inline void vim_set_phantom_handler(void (*handler)(void))
{
    VIM_TABLE->phantom = handler;
}

static inline void vim_set_handler(uint32_t channel, void (*handler)(void))
{
    VIM_TABLE->channel[channel] = handler;
}

static inline void vim_channel_init(uint32_t channel, uint32_t req,
                                    void (*handler)(void))
{
    vim_set_req(channel, req);
    vim_set_handler(channel, handler);
    vim_enable(channel);
}