/** * \brief Test alarm interrupt and wakeup functions in calendar/counter mode. * * \param test Current test case. */ static void run_alarm_test(const struct test_case *test) { uint32_t ast_alarm, ast_counter; struct ast_calendar calendar; struct ast_config ast_conf; /* Enable the AST. */ ast_enable(AST); /* Set alarm 0 to interrupt after 1 second in calendar mode. */ calendar.FIELD.sec = 0; calendar.FIELD.min = 15; calendar.FIELD.hour = 12; calendar.FIELD.day = 20; calendar.FIELD.month = 9; calendar.FIELD.year = 12; ast_conf.mode = AST_CALENDAR_MODE; ast_conf.osc_type = AST_OSC_32KHZ; ast_conf.psel = AST_PSEL_32KHZ_1HZ; ast_conf.calendar = calendar; ast_set_config(AST, &ast_conf); /* Set callback for alarm0. */ ast_clear_interrupt_flag(AST, AST_INTERRUPT_ALARM); ast_write_alarm0_value(AST, calendar.field + 1); ast_set_callback(AST, AST_INTERRUPT_ALARM, ast_alarm_callback, AST_ALARM_IRQn, 1); flag = 0; delay_ms(1500); test_assert_true(test, flag == 2, "Alarm interrupt not work!"); /* Set alarm 0 to wakeup after 1 second in counter mode. */ ast_conf.mode = AST_COUNTER_MODE; ast_conf.osc_type = AST_OSC_32KHZ; ast_conf.psel = AST_PSEL_32KHZ_1HZ - 2; ast_conf.counter = 0; ast_set_config(AST, &ast_conf); /* ast_init_counter Set Alarm to current time+4 quarter second. */ ast_counter = ast_read_counter_value(AST); ast_alarm = ast_counter + 4; ast_write_alarm0_value(AST, ast_alarm); ast_enable_interrupt(AST, AST_INTERRUPT_ALARM); ast_enable_wakeup(AST, AST_WAKEUP_ALARM); /* AST can wakeup the device. */ bpm_enable_wakeup_source(BPM, (1 << BPM_BKUPWEN_AST)); flag = 0; /* Go into WAIT mode. */ bpm_sleep(BPM, BPM_SM_WAIT); delay_ms(1000); test_assert_true(test, flag == 2, "Alarm wakeup not work!"); /* Disable the AST. */ ast_disable(AST); }
/* Override the default definition of vPortSetupTimerInterrupt() that is weakly defined in the FreeRTOS Cortex-M3 port layer with a version that configures the asynchronous timer (AST) to generate the tick interrupt. */ void vPortSetupTimerInterrupt( void ) { struct ast_config ast_conf; /* Ensure the AST can bring the CPU out of sleep mode. */ sleepmgr_lock_mode( SLEEPMGR_RET ); /* Ensure the 32KHz oscillator is enabled. */ if( osc_is_ready( OSC_ID_OSC32 ) == pdFALSE ) { osc_enable( OSC_ID_OSC32 ); osc_wait_ready( OSC_ID_OSC32 ); } /* Enable the AST itself. */ ast_enable( AST ); ast_conf.mode = AST_COUNTER_MODE; /* Simple up counter. */ ast_conf.osc_type = AST_OSC_32KHZ; ast_conf.psel = 0; /* No prescale so the actual frequency is 32KHz/2. */ ast_conf.counter = 0; ast_set_config( AST, &ast_conf ); /* The AST alarm interrupt is used as the tick interrupt. Ensure the alarm status starts clear. */ ast_clear_interrupt_flag( AST, AST_INTERRUPT_ALARM ); /* Enable wakeup from alarm 0 in the AST and power manager. */ ast_enable_wakeup( AST, AST_WAKEUP_ALARM ); bpm_enable_wakeup_source( BPM, ( 1 << BPM_BKUPWEN_AST ) ); /* Tick interrupt MUST execute at the lowest interrupt priority. */ NVIC_SetPriority( AST_ALARM_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY); ast_enable_interrupt( AST, AST_INTERRUPT_ALARM ); NVIC_ClearPendingIRQ( AST_ALARM_IRQn ); NVIC_EnableIRQ( AST_ALARM_IRQn ); /* Automatically clear the counter on interrupt. */ ast_enable_counter_clear_on_alarm( AST, portAST_ALARM_CHANNEL ); /* Start with the tick active and generating a tick with regular period. */ ast_write_alarm0_value( AST, ulAlarmValueForOneTick ); ast_write_counter_value( AST, 0 ); /* See the comments where xMaximumPossibleSuppressedTicks is declared. */ xMaximumPossibleSuppressedTicks = ULONG_MAX / ulAlarmValueForOneTick; }
/** * \brief Test periodic interrupt and wakeup functions in counter mode. * * \param test Current test case. */ static void run_periodic_test(const struct test_case *test) { struct ast_config ast_conf; /* Enable the AST. */ ast_enable(AST); ast_conf.mode = AST_COUNTER_MODE; ast_conf.osc_type = AST_OSC_32KHZ; ast_conf.psel = AST_PSEL_32KHZ_1HZ; ast_conf.counter = 0; ast_set_config(AST, &ast_conf); /* Set periodic 0 to interrupt after 1/16 second in counter mode. */ ast_clear_interrupt_flag(AST, AST_INTERRUPT_PER); ast_write_periodic0_value(AST, AST_PSEL_32KHZ_1HZ - 4); /* Set callback for periodic0. */ flag = 0; ast_set_callback(AST, AST_INTERRUPT_PER, ast_per_callback, AST_PER_IRQn, 1); delay_ms(200); test_assert_true(test, flag == 1, "Periodic interrupt not work!"); /* Set periodic 0 to wakeup after 1/16 second in counter mode. */ while (!(ast_read_interrupt_mask(AST) & AST_IMR_PER0_1)) { ast_enable_interrupt(AST, AST_INTERRUPT_PER); } ast_enable_wakeup(AST, AST_WAKEUP_PER); /* AST can wakeup the device. */ bpm_enable_wakeup_source(BPM, (1 << BPM_BKUPWEN_AST)); flag = 0; /* Go into WAIT mode. */ bpm_sleep(BPM, BPM_SM_WAIT); delay_ms(200); test_assert_true(test, flag == 1, "Periodic wakeup not work!"); ast_disable_interrupt(AST, AST_INTERRUPT_PER); /* Disable the AST. */ ast_disable(AST); }
static void config_ast(void) { struct ast_config ast_conf; /* Enable osc32 oscillator*/ if (!osc_is_ready(OSC_ID_OSC32)) { osc_enable(OSC_ID_OSC32); osc_wait_ready(OSC_ID_OSC32); } /* Enable the AST */ ast_enable(AST); ast_conf.mode = AST_COUNTER_MODE; ast_conf.osc_type = AST_OSC_32KHZ; ast_conf.psel = AST_PSEL_32KHZ_1HZ; ast_conf.counter = 0; /* * Using counter mode and set it to 0. * Initialize the AST. */ if (!ast_set_config(AST, &ast_conf)) { printf("Error initializing the AST\r\n"); while (1) { } } /* First clear alarm status. */ ast_clear_interrupt_flag(AST, AST_INTERRUPT_ALARM); /* Enable wakeup from alarm0. */ ast_enable_wakeup(AST, AST_WAKEUP_ALARM); /* Set callback for alarm0. */ ast_set_callback(AST, AST_INTERRUPT_ALARM, ast_alarm_callback, AST_ALARM_IRQn, 1); /* Disable first interrupt for alarm0. */ ast_disable_interrupt(AST, AST_INTERRUPT_ALARM); }
/** * \brief Run BPM driver unit tests. */ int main(void) { struct ast_config ast_conf; const usart_serial_options_t usart_serial_options = { .baudrate = CONF_TEST_BAUDRATE, .charlength = CONF_TEST_CHARLENGTH, .paritytype = CONF_TEST_PARITY, .stopbits = CONF_TEST_STOPBITS }; sysclk_init(); board_init(); stdio_serial_init(CONF_TEST_USART, &usart_serial_options); /* Initialize AST for all tests */ /* Enable osc32 oscillator*/ if (!osc_is_ready(OSC_ID_OSC32)) { osc_enable(OSC_ID_OSC32); osc_wait_ready(OSC_ID_OSC32); } /* Enable the AST. */ ast_enable(AST); ast_conf.mode = AST_COUNTER_MODE; ast_conf.osc_type = AST_OSC_32KHZ; ast_conf.psel = AST_PSEL_32KHZ_1HZ; ast_conf.counter = 0; ast_set_config(AST, &ast_conf); /* Set periodic 0 to interrupt after 1/16 second in counter mode. */ ast_clear_interrupt_flag(AST, AST_INTERRUPT_PER); ast_write_periodic0_value(AST, AST_PSEL_32KHZ_1HZ - 2); ast_set_callback(AST, AST_INTERRUPT_PER, ast_per_callback, AST_PER_IRQn, 1); ast_enable_wakeup(AST, AST_WAKEUP_PER); /* AST can wakeup the device */ bpm_enable_wakeup_source(BPM, (1 << BPM_BKUPWEN_AST)); /** * Retain I/O lines after wakeup from backup. * Disable to undo the previous retention state then enable. */ bpm_disable_io_retention(BPM); bpm_enable_io_retention(BPM); /* Enable fast wakeup */ bpm_enable_fast_wakeup(BPM); /* Define all the test cases. */ DEFINE_TEST_CASE(backup_test, NULL, run_backup_test, NULL, "Backup Power Manager, Backup mode & wakeup."); DEFINE_TEST_CASE(ps_test, NULL, run_ps_test, NULL, "Backup Power Manager, Power Scaling."); DEFINE_TEST_CASE(ret_test, NULL, run_ret_test, NULL, "Backup Power Manager, Retention mode & wakeup."); DEFINE_TEST_CASE(wait_test, NULL, run_wait_test, NULL, "Backup Power Manager, Wait mode & wakeup."); DEFINE_TEST_CASE(sleep_3_test, NULL, run_sleep_3_test, NULL, "Backup Power Manager, Sleep mode 3 & wakeup."); DEFINE_TEST_CASE(sleep_2_test, NULL, run_sleep_2_test, NULL, "Backup Power Manager, Sleep mode 2 & wakeup."); DEFINE_TEST_CASE(sleep_1_test, NULL, run_sleep_1_test, NULL, "Backup Power Manager, Sleep mode 1 & wakeup."); DEFINE_TEST_CASE(sleep_0_test, NULL, run_sleep_0_test, NULL, "Backup Power Manager, Sleep mode 0 & wakeup."); /* Put test case addresses in an array. */ DEFINE_TEST_ARRAY(bpm_tests) = { &backup_test, &ps_test, &ret_test, &wait_test, &sleep_3_test, &sleep_2_test, &sleep_1_test, &sleep_0_test, }; /* Define the test suite. */ DEFINE_TEST_SUITE(bpm_suite, bpm_tests, "SAM BPM driver test suite"); /* Run all tests in the test suite. */ test_suite_run(&bpm_suite); /* Disable the AST */ ast_disable(AST); while (1) { /* Busy-wait forever. */ } }
int main(void) { enum sleepmgr_mode current_sleep_mode = SLEEPMGR_ACTIVE; uint32_t ast_counter = 0; /* * Initialize the synchronous clock system to the default configuration * set in conf_clock.h. * \note All non-essential peripheral clocks are initially disabled. */ sysclk_init(); /* * Initialize the resources used by this example to the default * configuration set in conf_board.h */ board_init(); /* * Turn the activity status LED on to inform the user that the device * is active. */ ioport_set_pin_level(LED_ACTIVITY_STATUS_PIN, LED_STATUS_ON); osc_priv_enable_osc32(); /* Enable the AST clock. */ ast_enable(AST); /* Initialize the AST in Counter mode. */ struct ast_config ast_conf; ast_conf.mode = AST_COUNTER_MODE; ast_conf.osc_type = AST_OSC_1KHZ; ast_conf.psel = AST_PSEL_32KHZ_1HZ - 6; ast_conf.counter = ast_counter; ast_set_config(AST, &ast_conf); /* * Configure the AST to wake up the CPU when the counter reaches the * selected periodic0 value. */ ast_write_periodic0_value(AST, AST_PSEL_32KHZ_1HZ - 3); ast_enable_wakeup(AST, AST_WAKEUP_PER); ast_enable_event(AST, AST_EVENT_PER); ast_clear_interrupt_flag(AST, AST_INTERRUPT_PER); ast_set_callback(AST, AST_INTERRUPT_PER, ast_per_interrupt_callback, AST_PER_IRQn, 0); /* AST can wakeup the device */ bpm_enable_wakeup_source(BPM, (1 << BPM_BKUPWEN_AST)); /* Initialize the sleep manager, lock initial mode.*/ sleepmgr_init(); sleepmgr_lock_mode(current_sleep_mode); while (1) { /* * Turn the activity status LED off to inform the user that the * device is in a sleep mode. */ ioport_set_pin_level(LED_ACTIVITY_STATUS_PIN, LED_STATUS_OFF); /* * Go to sleep in the deepest allowed sleep mode (i.e. no * deeper than the currently locked sleep mode). */ sleepmgr_enter_sleep(); /* * Turn the activity status LED on to inform the user that the * device is active. */ ioport_set_pin_level(LED_ACTIVITY_STATUS_PIN, LED_STATUS_ON); /* Unlock the current sleep mode. */ sleepmgr_unlock_mode(current_sleep_mode); /* Add a 3s delay. */ delay_s(3); /* Lock the next sleep mode. */ ++current_sleep_mode; if ((current_sleep_mode >= SLEEPMGR_NR_OF_MODES)) { current_sleep_mode = SLEEPMGR_ACTIVE; } sleepmgr_lock_mode(current_sleep_mode); } }