# 4.1. Main Application

As mentioned in the section on scheduling, the main application consists of a portion of code that executes in `main()` and a portion that executes in the ADC ISR.

## 4.1.1. Implementation Notes

### 4.1.1.1. Modules

Module | Files | Description | Comments
--- | --- | --- | ---
`isr` | `isr.c` | Top-level ISR | The main control ISR function runs on a periodic basis. It is triggered at the completion of ADC sampling, which in turn is triggered once per PWM cycle, as mentioned in the Scheduling section. It contains profiling logic: generates a pulse on a GPIO pin that starts on ISR entry and ends on ISR exit capture of timer counter (see test harness) Various ISR subtasks are executed in rough order of priority (state machine tasks first, test harness and diagnostic tasks last). The actual name of the ADC ISR function is hardware-dependent and is encapsulated in the HAL by the `HAL_ADC1_ISR` macro.
`main` | `main.c` | Main entry point containing `main()` | This module is fairly simple and consists of an initialization and a main loop function, which are used in `main()` as shown below in Listing 4.1: Listing 4.1 `main.c` (excerpt)
    int main(void)
    {
        MCAF_MainInit();
        while (true)
        {
            MCAF_MainLoop();
        }
    }
`system_init` | `system_init.c` `system_init.h` | System initialization | Initializes state variables and special function registers prior to the main loop (intended to be called in `MCAF_MainInit()`) `MCAF_SystemInit` — called at the beginning of `MCAF_MainInit()` to initialize certain SFRs and system-wide state variables as soon as possible. `MCAF_SystemStart` — called near the end of `MCAF_MainInit()` for deferred initialization. This includes code to enable interrupts, and therefore main-thread code that executes prior to `MCAF_SystemStart` is not prone to race conditions caused by conflicts with an ISR that has just been enabled.
`system_state` | `system_state.h` | System state variable type definitions | Defines the main `MCAF_MOTOR_DATA` and `MCAF_SYSTEM_DATA` structure types.
`traps` | `traps.c` `traps.h` | Trap interrupt handlers | See section below

### 4.1.1.2. Trap-handler module

Hardware trap vectors in dsPIC® DSC devices contain handlers for events like a stack overflow, or an address alignment error. In the MCAF, these are located in the `traps` module. The normal handling logic is to signal a nonrecoverable error, by calling the `halt_on_error()` function, which records an error code and goes into an endless loop to flash the LEDs to indicate an error code via `MCAF_UiFlashErrorCodeForever()` as discussed in the UI module.

Two minor deviations from this behavior:

- DMA write collision: this occurs when the CPU and a DMA channel write to the same address (in which case the CPU “wins” and the DMA write is ignored). This condition is not considered an error in this application, and arises in rare cases for one variant of the diagnostic module which utilizes the DMA for reading and writing the UART. The DMA trap handler increments a counter for assessing the frequency of DMA write collisions.
- Stack overflow: a stack overflow is a nonrecoverable error, but is slightly different in that the stack pointer (W15 on dsPIC® DSC devices) may not be valid. In this condition, the MCAF takes extra care by using a small “failsafe stack”, which is a static area of memory reserved for this case, and is large enough to cover the stack requirements needed by the `MCAF_UiFlashErrorCodeForever()` function.

In addition to hardware traps, the `traps` module also includes logic to examine cause of reset, so that in the event of a watchdog reset, a nonrecoverable error can be signaled via `MCAF_UiFlashErrorCodeForever()`.