Search code examples
cembeddedmicrocontroller

How are runtime errors handled in embedded C?


Like a 'Divide by 0' error of variables in C.

int x = 0;
int y;
y = 12/x;

Solution

  • The C language does not define runtime error handling. With respect to the language it results in undefined behaviour. That does not mean that the execution environment cannot define specific behaviour or handling.

    Divide-by-zero, invalid address, invalid alignment etc. are typically handled by the runtime environment as exception handlers (in cases where the processor supports any such exceptions).

    In embedded systems, you are often responsible for providing suitable exception handlers, because the default runtime code will be generic and will not know what support a particular system has for presenting such errors. If it is a COTS board with a vendor supplied BSP you may get more, and if you are running any kind of RTOS that is more than simple scheduling kernel, that may provide support.

    For example on ARM Cortex-M using CMSIS, you typically have a startup_xxxx_.s file (where xxxx is the target device name) with for example:

    HardFault_Handler PROC
                    EXPORT  HardFault_Handler          [WEAK]
                    B       .
                    ENDP
    MemManage_Handler PROC
                    EXPORT  MemManage_Handler          [WEAK]
                    B       .
                    ENDP
    BusFault_Handler PROC
                    EXPORT  BusFault_Handler           [WEAK]
                    B       .
                    ENDP
    UsageFault_Handler PROC
                    EXPORT  UsageFault_Handler         [WEAK]
                    B       .
                    ENDP
    

    Note they all have "weak-linkage" meaning that if you defined a handler (and on Cortex-M that can be a C function) with the same name, it will override the default. So you might for example have:

    void HardFault_Handler(void)
    {
        volatile int stop = 1 ;
    
        // Emit status registers and stack dump (for example), 
        // or just a message.
        ...
    
        // If debugger is connected, halt program here
        if (CoreDebug->DHCSR & 1) {
            __breakpoint(0);
        }
    
        // infinite loop, allow debugger 
        // to force return by clearing `stop`.
        while( stop )
        {
        }
    }