WIP deep sleep mode
This commit is contained in:
		
							parent
							
								
									8a06636833
								
							
						
					
					
						commit
						fc31739eb6
					
				| @ -23,6 +23,7 @@ typedef struct ApplicationState { | ||||
|     LightColor color; | ||||
|     uint8_t wake_count; | ||||
|     bool debounce_wait; | ||||
|     bool enter_deep_sleep; | ||||
| } ApplicationState; | ||||
| 
 | ||||
| ApplicationState application_state; | ||||
| @ -58,7 +59,10 @@ void app_init() { | ||||
|  * @see watch_enter_deep_sleep() | ||||
|  */ | ||||
| void app_wake_from_deep_sleep() { | ||||
|     // TODO: deep sleep demo
 | ||||
|     // retrieve our application state from the backup registers
 | ||||
|     application_state.mode = (ApplicationMode)watch_get_backup_data(0); | ||||
|     application_state.color = (LightColor)watch_get_backup_data(1); | ||||
|     application_state.wake_count = (uint8_t)watch_get_backup_data(2) + 1; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @ -141,6 +145,24 @@ bool app_loop() { | ||||
|     // Wait a moment to debounce button input
 | ||||
|     delay_ms(250); | ||||
| 
 | ||||
|     if (application_state.enter_deep_sleep) { | ||||
|         application_state.enter_deep_sleep = false; | ||||
| 
 | ||||
|         // stash our application state in the backup registers
 | ||||
|         watch_store_backup_data((uint32_t)application_state.mode, 0); | ||||
|         watch_store_backup_data((uint32_t)application_state.color, 1); | ||||
|         watch_store_backup_data((uint32_t)application_state.wake_count, 2); | ||||
| 
 | ||||
|         // turn off the LED
 | ||||
|         watch_set_led_off(); | ||||
| 
 | ||||
|         // wait a moment for the user's finger to be off the button
 | ||||
|         delay_ms(1000); | ||||
| 
 | ||||
|         // nap time :)
 | ||||
|         watch_enter_deep_sleep(); | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| @ -161,5 +183,7 @@ void cb_mode_pressed() { | ||||
| } | ||||
| 
 | ||||
| void cb_alarm_pressed() { | ||||
|     // TODO: deep sleep demo
 | ||||
|     if (application_state.debounce_wait) return; | ||||
|     application_state.debounce_wait = true; | ||||
|     application_state.enter_deep_sleep = true; | ||||
| } | ||||
| @ -138,14 +138,14 @@ | ||||
| // <e> Interrupt 2 Settings
 | ||||
| // <id> eic_arch_enable_irq_setting2
 | ||||
| #ifndef CONF_EIC_ENABLE_IRQ_SETTING2 | ||||
| #define CONF_EIC_ENABLE_IRQ_SETTING2 0 | ||||
| #define CONF_EIC_ENABLE_IRQ_SETTING2 1 | ||||
| #endif | ||||
| 
 | ||||
| // <q> External Interrupt 2 Filter Enable
 | ||||
| // <i> Indicates whether the external interrupt 2 filter is enabled or not
 | ||||
| // <id> eic_arch_filten2
 | ||||
| #ifndef CONF_EIC_FILTEN2 | ||||
| #define CONF_EIC_FILTEN2 0 | ||||
| #define CONF_EIC_FILTEN2 1 | ||||
| #endif | ||||
| 
 | ||||
| // <q> External Interrupt 2 Event Output Enable
 | ||||
| @ -165,7 +165,7 @@ | ||||
| // <i> This defines input sense trigger
 | ||||
| // <id> eic_arch_sense2
 | ||||
| #ifndef CONF_EIC_SENSE2 | ||||
| #define CONF_EIC_SENSE2 EIC_NMICTRL_NMISENSE_NONE_Val | ||||
| #define CONF_EIC_SENSE2 EIC_NMICTRL_NMISENSE_RISE_Val | ||||
| #endif | ||||
| 
 | ||||
| // <q> External Interrupt 2 Asynchronous Edge Detection Mode
 | ||||
| @ -264,7 +264,7 @@ | ||||
| // <e> Interrupt 5 Settings
 | ||||
| // <id> eic_arch_enable_irq_setting5
 | ||||
| #ifndef CONF_EIC_ENABLE_IRQ_SETTING5 | ||||
| #define CONF_EIC_ENABLE_IRQ_SETTING5 1 | ||||
| #define CONF_EIC_ENABLE_IRQ_SETTING5 0 | ||||
| #endif | ||||
| 
 | ||||
| // <q> External Interrupt 5 Filter Enable
 | ||||
| @ -291,7 +291,7 @@ | ||||
| // <i> This defines input sense trigger
 | ||||
| // <id> eic_arch_sense5
 | ||||
| #ifndef CONF_EIC_SENSE5 | ||||
| #define CONF_EIC_SENSE5 EIC_NMICTRL_NMISENSE_RISE_Val | ||||
| #define CONF_EIC_SENSE5 EIC_NMICTRL_NMISENSE_NONE_Val | ||||
| #endif | ||||
| 
 | ||||
| // <q> External Interrupt 5 Asynchronous Edge Detection Mode
 | ||||
| @ -313,7 +313,7 @@ | ||||
| // <i> Indicates whether the external interrupt 6 filter is enabled or not
 | ||||
| // <id> eic_arch_filten6
 | ||||
| #ifndef CONF_EIC_FILTEN6 | ||||
| #define CONF_EIC_FILTEN6 0 | ||||
| #define CONF_EIC_FILTEN6 1 | ||||
| #endif | ||||
| 
 | ||||
| // <q> External Interrupt 6 Event Output Enable
 | ||||
| @ -355,7 +355,7 @@ | ||||
| // <i> Indicates whether the external interrupt 7 filter is enabled or not
 | ||||
| // <id> eic_arch_filten7
 | ||||
| #ifndef CONF_EIC_FILTEN7 | ||||
| #define CONF_EIC_FILTEN7 0 | ||||
| #define CONF_EIC_FILTEN7 1 | ||||
| #endif | ||||
| 
 | ||||
| // <q> External Interrupt 7 Event Output Enable
 | ||||
| @ -723,7 +723,7 @@ | ||||
| 
 | ||||
| // </e>
 | ||||
| 
 | ||||
| #define CONFIG_EIC_EXTINT_MAP {5, PIN_PB05}, {6, PIN_PA22}, {7, PIN_PA23}, | ||||
| #define CONFIG_EIC_EXTINT_MAP {2, PIN_PA02}, {6, PIN_PA22}, {7, PIN_PA23}, | ||||
| 
 | ||||
| // <<< end of configuration section >>>
 | ||||
| 
 | ||||
|  | ||||
| @ -114,14 +114,14 @@ | ||||
| // <e> RTC Tamper Input 2 settings
 | ||||
| // <id> tamper_input_2_settings
 | ||||
| #ifndef CONF_TAMPER_INPUT_2_SETTINGS | ||||
| #define CONF_TAMPER_INPUT_2_SETTINGS 0 | ||||
| #define CONF_TAMPER_INPUT_2_SETTINGS 1 | ||||
| #endif | ||||
| 
 | ||||
| // <q> Tamper Level Settings
 | ||||
| // <i> Indicates Tamper input 2 level
 | ||||
| // <id> tamper_level_2
 | ||||
| #ifndef CONF_RTC_TAMP_LVL_2 | ||||
| #define CONF_RTC_TAMP_LVL_2 0 | ||||
| #define CONF_RTC_TAMP_LVL_2 1 | ||||
| #endif | ||||
| 
 | ||||
| // <o> RTC Tamper Input Action
 | ||||
| @ -132,7 +132,7 @@ | ||||
| // <i> These bits define the RTC Tamper Input Action to be performed
 | ||||
| // <id> rtc_tamper_input_action_2
 | ||||
| #ifndef CONF_RTC_TAMPER_INACT_2 | ||||
| #define CONF_RTC_TAMPER_INACT_2 0 | ||||
| #define CONF_RTC_TAMPER_INACT_2 1 | ||||
| #endif | ||||
| 
 | ||||
| // <q> Debounce Enable for Tamper Input
 | ||||
|  | ||||
| @ -77,12 +77,7 @@ enum calendar_alarm_mode { ONESHOT = 1, REPEAT }; | ||||
| /**
 | ||||
|  * \brief Prototype of callback on alarm match | ||||
|  */ | ||||
| typedef void (*calendar_drv_cb_alarm_t)(struct calendar_dev *const dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Prototype of callback on tamper detect | ||||
|  */ | ||||
| typedef void (*tamper_drv_cb_t)(struct calendar_dev *const dev); | ||||
| typedef void (*calendar_drv_cb_t)(struct calendar_dev *const dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Structure of Calendar instance | ||||
| @ -91,9 +86,11 @@ struct calendar_dev { | ||||
| 	/** Pointer to the hardware base */ | ||||
| 	void *hw; | ||||
| 	/** Alarm match callback */ | ||||
| 	calendar_drv_cb_alarm_t callback; | ||||
| 	calendar_drv_cb_t callback_alarm; | ||||
| 	/** Tamper callback */ | ||||
| 	tamper_drv_cb_t callback_tamper; | ||||
| 	calendar_drv_cb_t callback_tamper; | ||||
| 	/** Tamper callback */ | ||||
| 	calendar_drv_cb_t callback_tick; | ||||
| 	/** IRQ struct */ | ||||
| 	struct _irq_descriptor irq; | ||||
| }; | ||||
| @ -236,7 +233,7 @@ uint32_t _calendar_get_comp(struct calendar_dev *const dev); | ||||
|  * | ||||
|  * \return ERR_NONE on success, or an error code on failure. | ||||
|  */ | ||||
| int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_alarm_t callback); | ||||
| int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback); | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Set calendar IRQ | ||||
| @ -245,6 +242,16 @@ int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv | ||||
|  */ | ||||
| void _calendar_set_irq(struct calendar_dev *const dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Register callback for 1Hz tick from prescaler | ||||
|  * | ||||
|  * \param[in] dev The pointer to calendar device struct | ||||
|  * \param[in] callback The pointer to callback function | ||||
|  * | ||||
|  * \return ERR_NONE on success, or an error code on failure. | ||||
|  */ | ||||
| int32_t _prescaler_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback); | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Register callback for tamper detection | ||||
|  * | ||||
| @ -253,7 +260,7 @@ void _calendar_set_irq(struct calendar_dev *const dev); | ||||
|  * | ||||
|  * \return ERR_NONE on success, or an error code on failure. | ||||
|  */ | ||||
| int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_t callback_tamper); | ||||
| int32_t _extwake_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback); | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Find tamper is detected on specified pin | ||||
|  | ||||
| @ -99,7 +99,9 @@ int32_t _calendar_deinit(struct calendar_dev *const dev) | ||||
| 	ASSERT(dev && dev->hw); | ||||
| 
 | ||||
| 	NVIC_DisableIRQ(RTC_IRQn); | ||||
| 	dev->callback = NULL; | ||||
| 	dev->callback_alarm = NULL; | ||||
| 	dev->callback_tick = NULL; | ||||
| 	dev->callback_tamper = NULL; | ||||
| 
 | ||||
| 	hri_rtcmode0_clear_CTRLA_ENABLE_bit(dev->hw); | ||||
| 	hri_rtcmode0_set_CTRLA_SWRST_bit(dev->hw); | ||||
| @ -302,27 +304,49 @@ int32_t _tamper_disable_debounce_majority(struct calendar_dev *const dev) | ||||
| 	return return_value; | ||||
| } | ||||
| 
 | ||||
| int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_t callback_tamper) | ||||
| int32_t _prescaler_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback) | ||||
| { | ||||
| 	ASSERT(dev && dev->hw); | ||||
| 
 | ||||
| 	/* Check callback */ | ||||
| 	if (callback_tamper != NULL) { | ||||
| 	if (callback != NULL) { | ||||
| 		/* register the callback */ | ||||
| 		dev->callback_tamper = callback_tamper; | ||||
| 		dev->callback_tick = callback; | ||||
| 
 | ||||
| 		/* enable RTC_IRQn */ | ||||
| 		NVIC_ClearPendingIRQ(RTC_IRQn); | ||||
| 		NVIC_EnableIRQ(RTC_IRQn); | ||||
| 
 | ||||
| 		/* enable tamper interrupt */ | ||||
| 		/* enable periodic interrupt */ | ||||
| 		hri_rtcmode0_set_INTEN_PER7_bit(dev->hw); | ||||
| 	} else { | ||||
| 		/* disable tamper interrupt */ | ||||
| 		/* disable periodic interrupt */ | ||||
| 		hri_rtcmode0_clear_INTEN_PER7_bit(dev->hw); | ||||
| 	} | ||||
| 
 | ||||
| 		/* disable RTC_IRQn */ | ||||
| 		NVIC_DisableIRQ(RTC_IRQn); | ||||
| 	return ERR_NONE; | ||||
| } | ||||
| 
 | ||||
| // TODO: refactor this so it doesn't take a callback (it will never get called anyway)
 | ||||
| int32_t _extwake_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback) | ||||
| { | ||||
| 	ASSERT(dev && dev->hw); | ||||
| 
 | ||||
| 	/* Check callback */ | ||||
| 	if (callback != NULL) { | ||||
| 		/* register the callback */ | ||||
| 		dev->callback_tamper = callback; | ||||
| 
 | ||||
| 		/* enable RTC_IRQn */ | ||||
| 		NVIC_ClearPendingIRQ(RTC_IRQn); | ||||
| 		NVIC_EnableIRQ(RTC_IRQn); | ||||
| 
 | ||||
| 		hri_rtcmode0_clear_interrupt_TAMPER_bit(dev->hw); | ||||
| 		/* enable tamper interrupt */ | ||||
| 		hri_rtcmode0_set_INTEN_TAMPER_bit(dev->hw); | ||||
| 	} else { | ||||
| 		/* disable tamper interrupt */ | ||||
| 		hri_rtcmode0_clear_INTEN_TAMPER_bit(dev->hw); | ||||
| 	} | ||||
| 
 | ||||
| 	return ERR_NONE; | ||||
| @ -330,14 +354,14 @@ int32_t _tamper_register_callback(struct calendar_dev *const dev, tamper_drv_cb_ | ||||
| /**
 | ||||
|  * \brief Registers callback for the specified callback type | ||||
|  */ | ||||
| int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_alarm_t callback) | ||||
| int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv_cb_t callback) | ||||
| { | ||||
| 	ASSERT(dev && dev->hw); | ||||
| 
 | ||||
| 	/* Check callback */ | ||||
| 	if (callback != NULL) { | ||||
| 		/* register the callback */ | ||||
| 		dev->callback = callback; | ||||
| 		dev->callback_alarm = callback; | ||||
| 
 | ||||
| 		/* enable RTC_IRQn */ | ||||
| 		NVIC_ClearPendingIRQ(RTC_IRQn); | ||||
| @ -348,9 +372,6 @@ int32_t _calendar_register_callback(struct calendar_dev *const dev, calendar_drv | ||||
| 	} else { | ||||
| 		/* disable cmp */ | ||||
| 		hri_rtcmode0_clear_INTEN_CMP0_bit(dev->hw); | ||||
| 
 | ||||
| 		/* disable RTC_IRQn */ | ||||
| 		NVIC_DisableIRQ(RTC_IRQn); | ||||
| 	} | ||||
| 
 | ||||
| 	return ERR_NONE; | ||||
| @ -368,15 +389,18 @@ static void _rtc_interrupt_handler(struct calendar_dev *dev) | ||||
| 	uint16_t interrupt_enabled = hri_rtcmode0_read_INTEN_reg(dev->hw); | ||||
| 
 | ||||
| 	if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) { | ||||
| 		dev->callback(dev); | ||||
| 		dev->callback_alarm(dev); | ||||
| 
 | ||||
| 		/* Clear interrupt flag */ | ||||
| 		hri_rtcmode0_clear_interrupt_CMP0_bit(dev->hw); | ||||
| 	} else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_PER7) { | ||||
| 		dev->callback_tamper(dev); | ||||
| 		dev->callback_tick(dev); | ||||
| 
 | ||||
| 		/* Clear interrupt flag */ | ||||
| 		hri_rtcmode0_clear_interrupt_PER7_bit(dev->hw); | ||||
| 	} else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_TAMPER) { | ||||
| 		/* Clear interrupt flag */ | ||||
| 		hri_rtcmode0_clear_interrupt_TAMPER_bit(dev->hw); | ||||
| 	} | ||||
| } | ||||
| /**
 | ||||
|  | ||||
| @ -49,7 +49,7 @@ | ||||
| #define A2 GPIO(GPIO_PORTB, 2) | ||||
| #define D0 GPIO(GPIO_PORTB, 3) | ||||
| #define A0 GPIO(GPIO_PORTB, 4) | ||||
| #define BTN_ALARM GPIO(GPIO_PORTB, 5) | ||||
| #define BTN_ALARM GPIO(GPIO_PORTA, 2) | ||||
| #define COM0 GPIO(GPIO_PORTB, 6) | ||||
| #define COM1 GPIO(GPIO_PORTB, 7) | ||||
| #define COM2 GPIO(GPIO_PORTB, 8) | ||||
|  | ||||
| @ -50,7 +50,7 @@ void EXTERNAL_IRQ_0_init(void) { | ||||
| 	                       // <GPIO_PULL_DOWN"> Pull-down
 | ||||
| 	                       GPIO_PULL_DOWN); | ||||
| 
 | ||||
| 	gpio_set_pin_function(BTN_ALARM, PINMUX_PB05A_EIC_EXTINT5); | ||||
| 	gpio_set_pin_function(BTN_ALARM, PINMUX_PA02A_EIC_EXTINT2); | ||||
| 
 | ||||
| 	// Set pin direction to input
 | ||||
| 	gpio_set_pin_direction(BTN_LIGHT, GPIO_DIRECTION_IN); | ||||
|  | ||||
| @ -43,7 +43,6 @@ | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| HAL_GPIO_PIN(UART_TX,   B, 0) | ||||
| HAL_GPIO_PIN(UART_RX,   B, 2) | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| static void uart_init(uint32_t baud) { | ||||
| @ -51,8 +50,6 @@ static void uart_init(uint32_t baud) { | ||||
| 
 | ||||
|     HAL_GPIO_UART_TX_out(); | ||||
|     HAL_GPIO_UART_TX_pmuxen(HAL_GPIO_PMUX_C); | ||||
|     HAL_GPIO_UART_RX_in(); | ||||
|     HAL_GPIO_UART_RX_pmuxen(HAL_GPIO_PMUX_C); | ||||
| 
 | ||||
|     MCLK->APBCMASK.reg |= MCLK_APBCMASK_SERCOM3; | ||||
| 
 | ||||
| @ -92,10 +89,15 @@ int main(void) { | ||||
|     // User code. Give the app a chance to initialize its data structures and state.
 | ||||
|     app_init(); | ||||
| 
 | ||||
|     // At this point, if the RTC peripheral is enabled, we are waking from BACKUP.
 | ||||
|     // If the RTC is already enabled, we're either waking from BACKUP mode or a reset.
 | ||||
|     // Ideally we should check if the TAMPER or CMP0 (alarm) flags are set.
 | ||||
|     if (watch_rtc_is_enabled()) { | ||||
|         // User code. Give the application a chance to restore state from backup registers.
 | ||||
|         app_wake_from_deep_sleep(); | ||||
| 
 | ||||
|         // disable the tamper interrupt and clear the tamper bit
 | ||||
|         hri_rtcmode0_clear_INTEN_TAMPER_bit(RTC); | ||||
|         hri_rtcmode0_clear_interrupt_TAMPER_bit(RTC); | ||||
|     } | ||||
| 
 | ||||
|     // Watch library code. Set initial parameters for the device and enable the RTC.
 | ||||
|  | ||||
| @ -271,8 +271,7 @@ static void tick_callback(struct calendar_dev *const dev) { | ||||
| 
 | ||||
| void watch_enable_tick_callback(ext_irq_cb_t callback) { | ||||
|     tick_user_callback = callback; | ||||
|     // TODO: rename this method to reflect that it now sets the PER7 interrupt.
 | ||||
|     _tamper_register_callback(&CALENDAR_0.device, &tick_callback); | ||||
|     _prescaler_register_callback(&CALENDAR_0.device, &tick_callback); | ||||
| } | ||||
| 
 | ||||
| static bool ADC_0_ENABLED = false; | ||||
| @ -359,8 +358,27 @@ uint32_t watch_get_backup_data(uint8_t reg) { | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void watch_enter_deep_sleep(){ | ||||
|     // Not yet implemented.
 | ||||
|     // TODO: enable tamper interrupt on ALARM pin.
 | ||||
|     // sleep(5);
 | ||||
| static void extwake_callback(struct calendar_dev *const dev) { | ||||
|     // this will never get called since we are basically waking from reset
 | ||||
| } | ||||
| 
 | ||||
| void watch_enter_deep_sleep() { | ||||
|     // enable and configure the external wake interrupt
 | ||||
|     _extwake_register_callback(&CALENDAR_0.device, &extwake_callback); | ||||
|     _tamper_enable_debounce_asynchronous(&CALENDAR_0.device); | ||||
| 
 | ||||
|     // disable SLCD
 | ||||
|     slcd_sync_deinit(&SEGMENT_LCD_0); | ||||
|     hri_mclk_clear_APBCMASK_SLCD_bit(SLCD); | ||||
| 
 | ||||
|     // TODO: disable other peripherals
 | ||||
| 
 | ||||
|     // disable EIC interrupt on ALARM pin (if any) and enable RTC interrupt.
 | ||||
|     ext_irq_disable(BTN_ALARM); | ||||
|     gpio_set_pin_direction(BTN_ALARM, GPIO_DIRECTION_IN); | ||||
|     gpio_set_pin_pull_mode(BTN_ALARM, GPIO_PULL_DOWN); | ||||
|     gpio_set_pin_function(BTN_ALARM, PINMUX_PA02G_RTC_IN2); | ||||
| 
 | ||||
|     // go into backup sleep mode
 | ||||
|     sleep(5); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user