/** * \brief This function enables the AST Periodic interrupt. * * \param ast Base address of the AST (i.e. &AVR32_AST). * \param periodic_channel AST Periodic Channel */ void ast_enable_periodic_interrupt(volatile avr32_ast_t *ast, uint8_t periodic_channel) { /* Enable the AST Periodic Asynchronous Wake-up */ if (periodic_channel) { ast_enable_interrupt(ast, AVR32_AST_IER_PER1_MASK); } else { ast_enable_interrupt(ast, AVR32_AST_IER_PER0_MASK); } }
/** * \brief This function enables the AST Alarm interrupt. * * \param ast Base address of the AST (i.e. &AVR32_AST). * \param alarm_channel AST Alarm Channel */ void ast_enable_alarm_interrupt(volatile avr32_ast_t *ast, uint8_t alarm_channel) { /* Enable the AST Alarm Asynchronous Wake-up */ if (alarm_channel) { ast_enable_interrupt(ast, AVR32_AST_IER_ALARM1_MASK); } else { ast_enable_interrupt(ast, AVR32_AST_IER_ALARM0_MASK); } }
/** * \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); }
/** * \brief main function : do init and loop. */ int main(void) { uint32_t ast_alarm, ast_counter; uint8_t key; /* Initialize the SAM system. */ sysclk_init(); board_init(); /* Initialize the console uart. */ configure_console(); /* Output example information. */ printf("-- AST Example 2 in counter mode --\r\n"); printf("-- %s\n\r", BOARD_NAME); printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__); printf("Config AST with 32 KHz oscillator.\r\n"); printf("Use alarm0 to wakeup from low power mode.\r\n"); config_ast(); /* AST and EIC can wakeup the device. */ config_wakeup(); while (1) { /* let the user select the low power mode. */ key = 0; while ((key < 0x31) || (key > 0x37)) { /* Display menu */ display_menu(); scanf("%c", (char *)&key); } key = key - '0'; /* ast_init_counter Set Alarm to current time+6 seconds. */ ast_counter = ast_read_counter_value(AST); ast_alarm = ast_counter + 6; ast_write_alarm0_value(AST, ast_alarm); ast_enable_interrupt(AST, AST_INTERRUPT_ALARM); /* Go into selected low power mode. */ bpm_sleep(BPM, key); while (flag == false); flag = true; /* After wake up, clear the Alarm0. */ ast_clear_interrupt_flag(AST, AST_INTERRUPT_ALARM); /* Output the counter value. */ ast_counter = ast_read_counter_value(AST); printf("\n\r Counter value: %02u \n\r", ast_counter); } }
/* 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); }
/** * \brief This function enables the AST Ready interrupt. * * \param ast Base address of the AST (i.e. &AVR32_AST). */ void ast_enable_clkrdy_interrupt(volatile avr32_ast_t *ast) { /* Enable the AST Counter Overflow Asynchronous Wake-up */ ast_enable_interrupt(ast, AVR32_AST_IER_CLKRDY_MASK); }