AVR SD Safety Framework 1.0.0
Loading...
Searching...
No Matches
Main Example

Example main file for demonstrating usage of the Framework Task Managers. More...

Topics

 Configuration validator
 Provides optional compile-time validation checks for all Framework configuration macros and constants.

Files

file  main_example.c
 Example main file for demonstrating usage of the Framework Task Managers.
file  main_example.h
 Defines configurations used in main_example.c.

Macros

#define STARTUP_SCHEDULE_LEN   3U
 Configures the schedule length of the example Application Startup Schedule.
#define SCHEDULE_LEN   3U
 Configures the schedule length of the example Application Schedule.
#define DUR_UNTIL_NEXT_SCHEDULE   500UL
 Configures the duration in system clock cycles until the first Task in the next example Application schedule is run, after completing the last Task in the previous one.
#define DUR_EXAMPLE_PADDING   82400UL
 Configures additional padding, in system clock cycles, for the default schedule.

Functions

void PreMain (void)
 Runs the Pre-startup Task Manager before entering Main.
int main (void)
 Runs the Startup, Scheduler and optionally Shutdown Task Managers.
 ISR_BADISR_vect ()
 Runs the Interrupts Task Manager to handle interrupt requests without a dedicated ISR.
 ISR_NMI_vect ()
 Runs the Interrupts Task Manager to handle a Non-maskable Interrupt (NMI).
 ISR_BOD_VLM_vect ()
 Runs the Interrupts Task Manager to handle a Brown-out Detector (BOD) interrupt.
 ISR_ERRCTRL_INT_vect ()
 Runs the Interrupts Task Manager to handle a Error Controller (ERRCTRL) channel interrupt.
 ISR_CLKCTRL_INT_vect ()
 Runs the Interrupts Task Manager to handle a Clock Controller (CLKCTRL) interrupt.
 ISR_SLPCTRL_INT_vect ()
 Runs the Interrupts Task Manager to handle a Sleep Controller (SLPCTRL) interrupt.
 ISR_SWDT_INT_vect ()
 Runs the Interrupts Task Manager to handle a Synchronous Watchdog Timer (SWDT) interrupt.
 ISR_NVMCTRL_ERROR_vect ()
 Runs the Interrupts Task Manager to handle a NVM Controller (NVMCTRL) error interrupt.
 ISR_RAMCTRL_INT_vect ()
 Runs the Interrupts Task Manager to handle a RAM Controller (RAMCTRL) error interrupt.
 ISR_CRCSCAN_INT_vect ()
 Runs the Interrupts Task Manager to handle a CRC Scan (CRCSCAN) interrupt.

Variables

 FUSES
 Sets a Framework compatible User Fuses configuration.
 LOCKBITS = LOCKBITS_DEFAULT
 Sets a Memory Sections Access Protection (Lock) Configuration.
volatile bool suspendScheduler = false
 Defines an example boolean for the Application to optionally start the Shutdown sequence.
const scheduleEntry_t appStartupSchedule [STARTUP_SCHEDULE_LEN]
 Defines an example Application Startup Schedule with optional Tasks.
const scheduleEntry_t appSchedule [SCHEDULE_LEN]
 Defines an example Application Schedule with optional Tasks.
const scheduleEntry_t appShutdownTask
 Defines an example Application Shutdown Task schedule entry.

Detailed Description

Example main file for demonstrating usage of the Framework Task Managers.

UML Class Diagrams

UML Activity Diagrams

UML Sequence Diagrams

Macro Definition Documentation

◆ DUR_EXAMPLE_PADDING

#define DUR_EXAMPLE_PADDING   82400UL

Configures additional padding, in system clock cycles, for the default schedule.

This macro is used to pad the duration of a default schedule Task to ensure that TM_Scheduler calls T_HandleWatchdog in the open window.

For the application to run reliably it is important that the total duration of the schedule lands in the open window of the windowed WDT. The open and closed window values should normally be chosen to fit with the Task(s) that will be in the application schedule, however the default values are set to larger values than necessary to make it possible to add application Task(s) to this example without editing the Tasks Config. For the total default schedule duration to reach the open window it needs to be padded with this duration. When adding application Task(s) these clock cycles being used to pad the schedule can be redistributed onto the application Task(s).

The number of system clock cycles elapsed during a WDT window is given by:

 cycles_system = (cycles_WDT / (frq_OSC32K * tol_OSC32K)) * frq_MCLK * tol_MCLK

where cycles_X is the elapsed clock-cycle count, frq_X is the clock frequency, and tol_X is the clock-tolerance factor.

With a main clock frequency of 20 MHz with 2% tolerance, a WDT clock frequency of 32.768 kHz with 10% tolerance, a total WWDT timeout of 192 cycles, a closed window of 128 cycles, the total schedule length should be between approximately 88500 and 104400 cycles, giving a target of 96500 cycles. Subtracting DUR_RUN_NEXT_LATENT_FAULT_DIAG, DUR_HANDLE_NOTIFICATION_ERRORS and DUR_UNTIL_NEXT_SCHEDULE from the total default schedule duration yields approximately 83000 system clock cycles.

Max cycles_system elapsed during closed window:

 cycles_system = (128 / (32768 * 0.9)) * 20000000 * 1.02 = 88542

Min cycles_system elapsed before timeout:

 cycles_system = (192 / (32768 * 1.1)) * 20000000 * 0.98 = 104403

To properly account for tolerances the closed window should be calculated with its slowest OSC32K and fastest MCLK. While the total timeout should be calculated using the fastest OSC32K and slowest MCLK. See the calculations above. This yields the tightest window, but will ensure stable WDT handling across devices in production.

◆ DUR_UNTIL_NEXT_SCHEDULE

#define DUR_UNTIL_NEXT_SCHEDULE   500UL

Configures the duration in system clock cycles until the first Task in the next example Application schedule is run, after completing the last Task in the previous one.

This macro is used to ensure a fixed run-time duration of function calls in the application schedule. See Measurements page for more information.

Note
The total duration of all Tasks in the schedule, combined with this value, is intended to be longer than WWDT_CLOSED_WINDOW and slightly less than the configured Watchdog timeout, to ensure timely execution and clearing within Fault Detection Time Interval (FDTI). See

TM_Scheduler for the full requirement.

Note
This example value is chosen to fit within the open window given the default configurations in tasks_config.h, particularly the values in WWDT_CLOSED_WINDOW,

WWDT_OPEN_WINDOW and the default durations used in the example appSchedule. It also assumes DIAG_PERIODIC_WDT_COUNT is set to DISABLED.

  • Maximum measured execution time with no errors (rounded up): 400 cycles
  • Default with tolerance: 500 cycles

◆ SCHEDULE_LEN

#define SCHEDULE_LEN   3U

Configures the schedule length of the example Application Schedule.

◆ STARTUP_SCHEDULE_LEN

#define STARTUP_SCHEDULE_LEN   3U

Configures the schedule length of the example Application Startup Schedule.

Function Documentation

◆ ISR_BADISR_vect()

ISR_BADISR_vect ( )

Runs the Interrupts Task Manager to handle interrupt requests without a dedicated ISR.

Here is the call graph for this function:

◆ ISR_BOD_VLM_vect()

ISR_BOD_VLM_vect ( )

Runs the Interrupts Task Manager to handle a Brown-out Detector (BOD) interrupt.

Here is the call graph for this function:

◆ ISR_CLKCTRL_INT_vect()

ISR_CLKCTRL_INT_vect ( )

Runs the Interrupts Task Manager to handle a Clock Controller (CLKCTRL) interrupt.

Here is the call graph for this function:

◆ ISR_CRCSCAN_INT_vect()

ISR_CRCSCAN_INT_vect ( )

Runs the Interrupts Task Manager to handle a CRC Scan (CRCSCAN) interrupt.

Here is the call graph for this function:

◆ ISR_ERRCTRL_INT_vect()

ISR_ERRCTRL_INT_vect ( )

Runs the Interrupts Task Manager to handle a Error Controller (ERRCTRL) channel interrupt.

Here is the call graph for this function:

◆ ISR_NMI_vect()

ISR_NMI_vect ( )

Runs the Interrupts Task Manager to handle a Non-maskable Interrupt (NMI).

Here is the call graph for this function:

◆ ISR_NVMCTRL_ERROR_vect()

ISR_NVMCTRL_ERROR_vect ( )

Runs the Interrupts Task Manager to handle a NVM Controller (NVMCTRL) error interrupt.

Here is the call graph for this function:

◆ ISR_RAMCTRL_INT_vect()

ISR_RAMCTRL_INT_vect ( )

Runs the Interrupts Task Manager to handle a RAM Controller (RAMCTRL) error interrupt.

Here is the call graph for this function:

◆ ISR_SLPCTRL_INT_vect()

ISR_SLPCTRL_INT_vect ( )

Runs the Interrupts Task Manager to handle a Sleep Controller (SLPCTRL) interrupt.

Here is the call graph for this function:

◆ ISR_SWDT_INT_vect()

ISR_SWDT_INT_vect ( )

Runs the Interrupts Task Manager to handle a Synchronous Watchdog Timer (SWDT) interrupt.

Here is the call graph for this function:

◆ main()

int main ( void )

Runs the Startup, Scheduler and optionally Shutdown Task Managers.

This example main function demonstrates how TM_Startup can be used with an example appStartupSchedule and how TM_Scheduler can be used with an example appSchedule. In addition it shows that suspendScheduler can optionally be set to true to use TM_Shutdown with an example appShutdownTask.

Note

For usage of the Pre-Startup Task Manager see PreMain.

Note
For usage of the Interrupts Task Manager see each Interrupt Service Routine (ISR) in

ISR_BADISR_vect, ISR_NMI_vect, ISR_BOD_VLM_vect, ISR_ERRCTRL_INT_vect, ISR_CLKCTRL_INT_vect, ISR_SLPCTRL_INT_vect, ISR_SWDT_INT_vect, ISR_NVMCTRL_ERROR_vect, ISR_RAMCTRL_INT_vect and ISR_CRCSCAN_INT_vect.

Return values
EXIT_FAILUREThe TM_Shutdown function returned instead of ending in a device reset.
int main(void)
{
// Initialize Safety System and run all Tasks in Startup Schedule with fixed execution time
while (suspendScheduler == false) // Managed by the Application
{
// Manage Watchdogs and run all Tasks in Schedule with fixed execution time
}
// Enter Safe State and maintain safe deep sleep, ending in a system reset
TM_Shutdown(appShutdownTask); // Optional Task Manager depending on the Application requirements
return EXIT_FAILURE; // Never expect to reach this point
}
Here is the call graph for this function:

◆ PreMain()

void PreMain ( void )

Runs the Pre-startup Task Manager before entering Main.

This function is placed in the .init3 memory section in order to execute the Pre-startup sequence before entering the main function.

Note

See init3 for an overview of the .initN sections.

The TM_PreStartup function is placed in the .init3 section for the following reasons: Since TM_PreStartup is responsible for immediately ensuring that the device is in a Safe State after a reset, it should be called as soon as possible after a reset. However, in order to safely execute code that performs compares with zero and calls other functions, it should run after the .init2 memory section. The Pre-startup sequence involves multiple device resets as a result of performing error injection diagnostics. In order to reduce the execution time of the sequence, the function is called before the .init4 memory section to avoid copying data from Flash to RAM multiple times. However, this leads to certain restrictions for all functions running in .init3, since the full C environment is not initialized.

Warning

Functions called inside .init3 must adhere to restrictions listed in init3.

Warning

This function will reset the device as part of normal execution.

static void INIT3_SECTION PreMain(void)
{
// Execute the Pre-startup sequence
TM_PreStartup(); // Results in multiple device resets, returns when sequence is completed
}

Variable Documentation

◆ appSchedule

const scheduleEntry_t appSchedule[SCHEDULE_LEN]

Defines an example Application Schedule with optional Tasks.

This example Application Schedule is used as input to TM_Scheduler to demonstrate usage of an application-specific Schedule. The Schedule is intended to be filled with application-specific Tasks that implements both safety and non-safety related Application requirements, and can optionally include Tasks provided by the Framework.

Each Task in the Schedule is configured with a fixed duration in system clock cycles, ensuring a fixed schedule execution time, to ensure the Watchdog is cleared within FDTI without any additional timing resources. The configured durations must account for the Worst Case Execution Time (WCET), including handling of errors reported by Tasks or through interrupts. The total Application Schedule execution time should be set to be slightly lower than the WDT timeout (with clock tolerances), which is configured using WWDT_CLOSED_WINDOW and WWDT_OPEN_WINDOW.

In this example schedule, optional Tasks are included to ensure that any errId_t reported with NOTIFICATION error criticality is handled within the FDTI, and one latent fault diagnostic is run each schedule window. However, this might not be required for the Application. See Tips and Tricks for information on using the optional Tasks in the Schedule, recommended scheduling order and additional optional Tasks that can be included.

Note

See Tips and Tricks for information on options for having a dynamic or static schedule.

[2U] = { NULL, 0U } // TODO: Add application-specific Tasks to the Schedule
};

◆ appShutdownTask

const scheduleEntry_t appShutdownTask

Defines an example Application Shutdown Task schedule entry.

This example Application Shutdown Task schedule entry is used as input to TM_Shutdown to demonstrate usage. The schedule entry is intended to be set to an application-specific Task that is responsible for making the Application ready for the shutdown procedure. This could include disabling peripherals and external circuits, sending a message or configuring the periodic wakeup source(s) used to manage the watchdog and determine when to exit the Shutdown sequence.

In this example, the schedule entry is set to NULL to skip Task execution, since the implementation is specific to the Application.

NULL, 0U // TODO: Add application-specific Task to Shutdown procedure
};

◆ appStartupSchedule

const scheduleEntry_t appStartupSchedule[STARTUP_SCHEDULE_LEN]

Defines an example Application Startup Schedule with optional Tasks.

This example Application Startup Schedule is used as input to TM_Startup to demonstrate usage of an application-specific Startup Schedule. The Startup Schedule is intended to be filled with application-specific Tasks that initializes the Application according to both safety and non-safety requirements, and can optionally include Tasks provided by the Framework.

Each Task in the schedule is configured with a fixed duration in system clock cycles, ensuring a fixed Startup sequence execution time. The configured durations must account for Worst Case Execution Time (WCET), including error handling. The total Application Startup Schedule execution time must be accounted for when configuring the INIT_WDT_DURATION.

In this example schedule, optional but recommended Framework Tasks are included to ensure handling of the determined reset reason in T_HandleResetReason and that any errId_t reported with NOTIFICATION error criticality is handled before exiting the Safe State.

Note

Set the resetReasonCallback and notificationErrorCallback configuration for application-specific reset and error handling.

Note

See Tips and Tricks for information on using the optional Tasks in the Startup Schedule, recommended scheduling order and additional optional Tasks that can be included.

[0U] = { &T_HandleResetReason, DUR_HANDLE_RESET_REASON }, // Optional Task
[2U] = { NULL, 0U } // TODO: Add application-specific Tasks to the Startup Schedule
};

◆ FUSES

FUSES
Initial value:
= {
.WDTCFG = WINDOW_OFF_gc | PERIOD_OFF_gc,
.BODCFG = LVL_BODLEVEL1_gc | SAMPFREQ_128HZ_gc | ACTIVE_ENABLE_gc | SLEEP_ENABLE_gc,
.SYSCFG0 = FUSE_SYSCFG0_DEFAULT,
.SYSCFG1 = WDTMON_ON_gc | MVSYSCFG_DUAL_gc | SUT_0MS_gc,
.CODESIZE = FUSE_CODESIZE_DEFAULT,
.BOOTSIZE = FUSE_BOOTSIZE_DEFAULT,
.PDICFG = FUSE_PDICFG_DEFAULT,
}

Sets a Framework compatible User Fuses configuration.

This struct is used to write to the User Fuses when programming the device. It is configured to be compatible with Framework requirements:

The Watchdog Timer (WDT) is explicitly not enabled through fuses, since this sets the LOCK bit, preventing reconfiguration of the WDT timeout and mode. The Framework reconfigures the watchdog at multiple stages as part of normal execution flow.

The Brown-out Detector (BOD) configuration follows safety-related best practices by being set to run in Continuous mode, using the Level 1 threshold and is enabled during device sleep. The sample frequency configuration does not have an effect in Continuous mode. The Framework assumes the BOD is initialized when configuring and enabling the Voltage Level Monitor (VLM).

System Configuration 0 is set to default values because these settings are specific to the Application. Enabling automatic CRCSCAN of the Boot section in Flash is recommended, but requires that the expected checksum is added at the end of the Boot section when programming the device. If this is enabled, it is recommended to clear the CRCSCAN Done flag in the Application Startup Schedule.

System Configuration 1 follows safety-related best practices by explicitly enabling the WDT Clock Monitor feature, even while the device is in Standby or Power-Down sleep modes, to ensure detection of a WDT clock source failure. The other settings are specific to the Application and set to default values.

The Flash memory sections settings are specific to the Application and set to default values.

The Program and Debug Interface Disable (PDID) security feature is set to the default value during development, but recommended to be activated to avoid modification of the Flash in the deployed Application.

◆ LOCKBITS

LOCKBITS = LOCKBITS_DEFAULT

Sets a Memory Sections Access Protection (Lock) Configuration.

This struct is used to write a Key value to the Lock Fuse when programming the device in order to select whether the device should be locked or unlocked. Locking the device not only prevents Flash access, but also enables several safety-related internal hardware monitors that prevents the Unified Program and Debug Interface (UPDI), On-chip Debugging (OCD) and Design-For-Test (DFT) systems from affecting device behavior. The Key is set to the default value to prevent the device from being locked during development.

Warning
Modifying the default value will Lock the device. The only way to unlock the device is a Chip Erase, given that PDID is not activated.

◆ suspendScheduler

volatile bool suspendScheduler = false

Defines an example boolean for the Application to optionally start the Shutdown sequence.

This boolean is used in the main function example to demonstrate how the Application can exit Mission Mode and start the Shutdown sequence, using TM_Shutdown, by setting it to true. This can be done by an application-specific Task running in the Scheduler or in an Interrupt Service Routine (ISR).

Note

The boolean is not defined statically as it is intended to be declared externally in a headerfile in order to provide access to the Application when testing the example.

Note
Declared volatile since it may be written from an ISR while being polled in main.