4.1. Main Application

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

4.1.1. Implementation Notes

4.1.1.1. MCAF R1 – R5

Prior to MCAF R6, the main application was tightly integrated with MCAF, while keeping the responsibility for the user interface entirely within the External Interface component.

4.1.1.2. MCAF R6

The main application has been rewritten to include a sample application. The sample application interacts with MCAF through the Motion Control API (MCAPI) to control and obtain feedback from the motor.

4.1.1.3. MCAF R7

The main application now utilizes the Motion Control API as the single point of interface to MCAF, reducing exposure to MCAF internals.

  • Sample application can attempt to restart the motor while it is stopping

  • Added two new files: mcaf_main.c and mcaf_sample_application.h

  • Moved the definition of MCAF_MOTOR_DATA motor and MCAF_SYSTEM_DATA systemData from

    sample_mcaf_application.c to mcaf_main.c

  • Updated the function signature of APP_ApplicationInitialize() and APP_ApplicationStep() to include a pointer to the MCAPI data structure.

  • Moved MCAF_Init() and MCAF_MainLoop() to mcaf_main.c

4.1.1.3.1. Sample Application

The sample application user interface behavior can be summarized as follows:

  • If the motor is stopping/stopped, then the primary pushbutton starts the motor. If the primary pushbutton is pressed during the STOPPING state, the state machine will behave differently depending on the stopping mode:

  • If the motor is starting/running, then the primary pushbutton stops the motor.

  • If the motor is in fault condition, then the primary pushbutton clears all pending faults.

  • If MCAF is in one of its test modes, then the primary pushbutton and the secondary pushbutton do not have any effect.

  • The secondary pushbutton changes the direction of rotation.

  • The potentiometer sets the speed reference for the motor, with minimum and maximum limits as defined by MCAF and made available through MCAPI functions MCAPI_VelocityReferenceMinimumGet() and MCAPI_VelocityReferenceMaximumGet() respectively.

  • The pushbutton and potentiometer user interface can be disabled in the sample application by clearing hardwareUiEnabled in the application data structure, for instance using a real-time diagnostic tool like X2C-Scope.

See External Interface for implementation details of the user interface for pushbuttons.

The user interface for LEDs is defined and implemented by the External Interface component.

4.1.1.4. 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_ADC_ISR macro.

mcaf_main
mcaf_main.c
mcaf_main.h

Main MCAF entry points called from main() (initialization and main loop)

Provides MCAF_MainInit() and MCAF_MainLoop(). These are the entry points for MCAF from the main().

mcaf_sample_application
mcaf_sample_application.c
mcaf_sample_application.h

Sample application

Sample application starts/stops the motor using pushbuttons and sets motor speed reference using the potentiometer.

mcaf_traps
mcaf_traps.c
mcaf_traps.h

Trap interrupt handlers

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.c
system_state.h

System state variable type definitions

Defines the main MCAF_MOTOR_DATA and MCAF_SYSTEM_DATA structure types.

4.1.1.4.1. 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().