Error module reference

Header :
#include <error.h>
Makefile : error is already included by default

Description

This module is special because it doesn't match a peripheral in the microcontroller but instead offers a common logic to handle errors used throughout the library.

Errors are defined by their severity (INFO, WARNING or CRITICAL), source module, and code. The source module can either be one of the library's modules defined in the Module enum (see the header below) or an arbitrary user module of your choice, represented by an int. The code is specific to each module and gives more specific information on the error; for library modules, see the WARN_* and ERR_* constants defined in the corresponding module header.

The Carbide module uses this module to define handlers that blink the red LED when an error occurs. Use setHandler() to define custom handlers if you want for example to mitigate or report the error.

The list of the errors that happened since the execution started is logged and can be retreived using getNumber(), get() and getLast().

API

void init()
Initialize the module. This is called internally by Core::init().
void setHandler(Severity severity, void (*handler)(Module module, int userModule, Code code))
Define a custom handler to be called when an error of the specified severity happens. It is possible for the handler to never return if the error is considered a critical failure requiring the execution to stop completely.
void happened(Module module, Code code, Severity severity)
This function is called internally when an error happens in a library module. The error will be logged and the handler will be called if defined.
void happened(int userModule, int code, Severity severity)
Call this function when an error happens in your program. The error will be logged and userModule and code will be passed to the appropriate handler if defined.
unsigned int getNumber()
Get the number of errors in the log.
const Error& get(int n)
Get the error at line n in the log. n must be between 0 and getNumber()-1.
const Error& getLast()
Get the last error recorded in the log.

Code

Header

#ifndef _ERROR_H_
#define _ERROR_H_

#include <stdint.h>

namespace Error {

    enum class Module {
        CORE,
        DMA,
        SCIF,
        BSCIF,
        PM,
        BPM,
        ADC,
        DAC,
        FLASH,
        GPIO,
        I2C,
        SPI,
        TC,
        USART,
        WDT,
        EIC,
        USB,
        CUSTOM
    };

    using Code = uint16_t;

    enum class Severity {
        INFO = 0,
        WARNING = 1,
        CRITICAL = 2
    };
    const int N_SEVERITY = 3;

    struct Error {
        unsigned long time;
        Module module;
        int userModule;
        Code code;
        Severity severity;
    };

    const int MAX_ERROR_NUMBER = 16;

    void init();
    void setHandler(Severity severity, void (*handler)(Module module, int userModule, Code code));
    void happened(Module module, Code code, Severity severity=Severity::CRITICAL);
    void happened(int userModule, int code, Severity severity=Severity::CRITICAL);
    unsigned int getNumber();
    const Error& get(unsigned int n);
    const Error& getLast();

}

#endif

Module

#include "error.h"
#include "core.h"

namespace Error {

    Error errors[MAX_ERROR_NUMBER];
    int nErrors = 0;

    void (*handlers[N_SEVERITY])(Module module, int userModule, Code code);

    void init() {
        for (int i = 0; i < N_SEVERITY; i++) {
            handlers[i] = nullptr;
        }
    }

    void setHandler(Severity severity, void (*handler)(Module module, int userModule, Code code)) {
        handlers[static_cast<int>(severity)] = handler;
    }

    void happened(Module module, int userModule, Code code, Severity severity) {
        if (nErrors < MAX_ERROR_NUMBER) {
            Error& error = errors[nErrors];
            error.time = Core::time();
            error.module = module;
            error.userModule = userModule;
            error.code = code;
            error.severity = severity;
            nErrors++;
        }
        if (handlers[static_cast<int>(severity)] != nullptr) {
            handlers[static_cast<int>(severity)](module, userModule, code);
        }
    }

    void happened(Module module, Code code, Severity severity) {
        happened(module, -1, code, severity);
    }

    void happened(int userModule, int code, Severity severity) {
        happened(static_cast<Module>(-1), userModule, static_cast<Code>(code), severity);
    }

    unsigned int getNumber() {
        return nErrors;
    }

    const Error& get(unsigned int n) {
        return errors[n];
    }

    const Error& getLast() {
        return errors[nErrors - 1];
    }
}