diff --git a/common/app.h b/common/app.h index 4e01627..ff86688 100644 --- a/common/app.h +++ b/common/app.h @@ -35,34 +35,55 @@ #include "sam.h" #include "pins.h" -/** @brief A function you will implement to initialize your application state. The app_init function is called after - * system clocks are initialized, and before anything else. - * @details Use this function to set up any internal data structures or state required by your app, and set up any - * low-level parameters like CPU speed or microcontroller register configuration. - * @note If your application plans to use the real-time clock perhiperal, you should call the `rtc_init` function here. +/** @brief A function you will implement to initialize your application's low- + * level setup. The app_init function is called after system clocks are + * initialized, and before anything else. + * @details You may be wondering why there is an `app_init` function as well as + * an `app_setup` function. The main difference is that app_init is + * only meant to be callec once, at boot, whereas you might want to + * call app_setup multiple times, for example if you want to disable + * some peripherals before entering STANDBY mode, and re-enable them + * after waking up. In essence, you should set up anything that will + * run forever in app_init, whereas anything that could get turned off + * in the course of execution should be set up in app_setup. + * @note If your application plans to use the real-time clock perhiperal, you + * probably want to call the `rtc_init` function here. */ void app_init(void); -/** @brief A function you will implement to set up your application. The app_setup function is like setup() in Arduino. - * It is called once when the program begins. You should set pin modes and enable any peripherals you want to - * set up (real-time clock, I2C, etc.) Depending on your application, you may or may not want to configure - * sensors here. For example, a low-power accelerometer that will run at all times should be configured here, - * whereas you may want to enable a more power-hungry sensor only when you need it. +/** @brief OPTIONAL: A function you may implement to restore state after waking + * up from BACKUP mode on the SAM L21 or L22. This function is called + * after system_init, but before app_setup. You can stash a bit of your + * application state in the RTC's BKUP and GPn registers, and use this + * function as an opportinity to restore it before app_setup is called. + * @note You do not need to implement this function unless you are using the + * SAM L21 or L22 and you want to restore state from BACKUP mode. + */ +void app_wake_from_backup(void); + +/** @brief A function you will implement to set up your app. The app_setup + * function is like setup() in Arduino. It is called once when the + * program begins, after app_init and app_wake_from_backup, if it + * exists. You should use this function to set up your application + * state and configure any peripherals you need to use. */ void app_setup(void); -/** @brief A function you will implement to serve as the app's main run loop. This method will be called repeatedly, - * or if you enter STANDBY mode, as soon as the device wakes from that mode. - * @note In order to wake from STANDBY mode, you must set up an interrupt or wake source. Otherwise your app will - * remain in STANDBY indefinitely. - * @return You should return true if your app is prepared to enter STANDBY mode. If you return false, your app's - * app_loop method will be called again immediately. +/** @brief A function you will implement to serve as the app's main run loop. + * This method will be called repeatedly, or if you enter STANDBY mode, + * as soon as the device wakes from that mode. + * @note In order to wake from STANDBY mode, you must set up an interrupt or + * wake source. Otherwise your app will remain in STANDBY indefinitely. + * @return true if your app is prepared to enter STANDBY mode. If you return + * false, your app's app_loop method will be called again immediately. */ bool app_loop(void); -/** @brief OPTIONAL: A function to yield control of the CPU to other tasks. This function is called in the delay - * function to allow other tasks to run while the CPU is busy waiting. By default, this function - * does nothing, but if you are using the USB peripheral, you should implement this function and call - * `tud_task` at minumum, along with any other USB-related tasks you need to run. +/** @brief OPTIONAL: A function to yield control of the CPU to other tasks. + * This function is called in the delay function to allow other tasks + * to run while the CPU is busy waiting. By default, this function does + * nothing, but if you are using the USB peripheral, you should + * implement this function and call `tud_task` at minumum, along with + * any other USB-related tasks you need to run. */ void yield(void); diff --git a/common/delay.c b/common/delay.c index 495fea5..e3a984b 100644 --- a/common/delay.c +++ b/common/delay.c @@ -1,12 +1,7 @@ #include "delay.h" #include "sam.h" #include "system.h" - -static void __empty() { - // Empty -} - -void yield(void) __attribute__ ((weak, alias("__empty"))); +#include "app.h" void delay_init(void) { SysTick->LOAD = SysTick_LOAD_RELOAD_Msk; diff --git a/main.c b/main.c index c9128ed..64e7736 100644 --- a/main.c +++ b/main.c @@ -8,8 +8,6 @@ #include "system.h" #include "delay.h" -void _enter_standby_mode(void); - int main(void) { // set up system clocks sys_init(); @@ -20,7 +18,8 @@ int main(void) { // allow application to do its own initialization app_init(); - // TODO: restore from BACKUP state + // restore from BACKUP state + app_wake_from_backup(); // allow application to do its initial setup app_setup(); @@ -35,3 +34,11 @@ int main(void) { return 0; } + +static void __empty() { + // Empty +} + +void app_wake_from_backup(void) __attribute__ ((weak, alias("__empty"))); + +void yield(void) __attribute__ ((weak, alias("__empty")));