/** * \brief Disable a peripheral's clock from its base address. * * Disables the clock to a peripheral, given its base address. If the peripheral * has an associated clock on the HSB bus, this will be disabled also. * * \param module Pointer to the module's base address. */ void sysclk_disable_peripheral_clock(const volatile void *module) { switch ((uintptr_t)module) { #if !SAM4LS case AESA_ADDR: sysclk_disable_hsb_module(SYSCLK_AESA_HSB); break; #endif case IISC_ADDR: sysclk_disable_pba_module(SYSCLK_IISC); break; case SPI_ADDR: sysclk_disable_pba_module(SYSCLK_SPI); break; case TC0_ADDR: sysclk_disable_pba_module(SYSCLK_TC0); break; case TC1_ADDR: sysclk_disable_pba_module(SYSCLK_TC1); break; case TWIM0_ADDR: sysclk_disable_pba_module(SYSCLK_TWIM0); break; case TWIS0_ADDR: sysclk_disable_pba_module(SYSCLK_TWIS0); break; case TWIM1_ADDR: sysclk_disable_pba_module(SYSCLK_TWIM1); break; case TWIS1_ADDR: sysclk_disable_pba_module(SYSCLK_TWIS1); break; case USART0_ADDR: sysclk_disable_pba_module(SYSCLK_USART0); break; case USART1_ADDR: sysclk_disable_pba_module(SYSCLK_USART1); break; case USART2_ADDR: sysclk_disable_pba_module(SYSCLK_USART2); break; case USART3_ADDR: sysclk_disable_pba_module(SYSCLK_USART3); break; case ADCIFE_ADDR: sysclk_disable_pba_module(SYSCLK_ADCIFE); break; case DACC_ADDR: sysclk_disable_pba_module(SYSCLK_DACC); break; case ACIFC_ADDR: sysclk_disable_pba_module(SYSCLK_ACIFC); break; case GLOC_ADDR: sysclk_disable_pba_module(SYSCLK_GLOC); break; case ABDACB_ADDR: sysclk_disable_pba_module(SYSCLK_ABDACB); break; case TRNG_ADDR: sysclk_disable_pba_module(SYSCLK_TRNG); break; case PARC_ADDR: sysclk_disable_pba_module(SYSCLK_PARC); break; case CATB_ADDR: sysclk_disable_pba_module(SYSCLK_CATB); break; case TWIM2_ADDR: sysclk_disable_pba_module(SYSCLK_TWIM2); break; case TWIM3_ADDR: sysclk_disable_pba_module(SYSCLK_TWIM3); break; #if !SAM4LS case LCDCA_ADDR: sysclk_disable_pba_module(SYSCLK_LCDCA); break; #endif case HFLASHC_ADDR: sysclk_disable_pbb_module(SYSCLK_HFLASHC_REGS); break; case HCACHE_ADDR: sysclk_disable_hsb_module(SYSCLK_HRAMC1_DATA); sysclk_disable_pbb_module(SYSCLK_HRAMC1_REGS); break; case HMATRIX_ADDR: sysclk_disable_pbb_module(SYSCLK_HMATRIX); break; case PDCA_ADDR: sysclk_disable_hsb_module(SYSCLK_PDCA_HSB); sysclk_disable_pbb_module(SYSCLK_PDCA_PB); break; case CRCCU_ADDR: sysclk_disable_hsb_module(SYSCLK_CRCCU_DATA); sysclk_disable_pbb_module(SYSCLK_CRCCU_REGS); break; case USBC_ADDR: sysclk_disable_hsb_module(SYSCLK_USBC_DATA); sysclk_disable_pbb_module(SYSCLK_USBC_REGS); break; case PEVC_ADDR: sysclk_disable_pbb_module(SYSCLK_PEVC); break; case PM_ADDR: sysclk_disable_pbc_module(SYSCLK_PM); break; case CHIPID_ADDR: sysclk_disable_pbc_module(SYSCLK_CHIPID); break; case SCIF_ADDR: sysclk_disable_pbc_module(SYSCLK_SCIF); break; case FREQM_ADDR: sysclk_disable_pbc_module(SYSCLK_FREQM); break; case GPIO_ADDR: sysclk_disable_pbc_module(SYSCLK_GPIO); break; case BPM_ADDR: sysclk_disable_pbd_module(SYSCLK_BPM); break; case BSCIF_ADDR: sysclk_disable_pbd_module(SYSCLK_BSCIF); break; case AST_ADDR: sysclk_disable_pbd_module(SYSCLK_AST); break; case WDT_ADDR: sysclk_disable_pbd_module(SYSCLK_WDT); break; case EIC_ADDR: sysclk_disable_pbd_module(SYSCLK_EIC); break; case PICOUART_ADDR: sysclk_disable_pbd_module(SYSCLK_PICOUART); break; default: Assert(false); return; } // Disable PBA divided clock if possible. #define PBADIV_CLKSRC_MASK ((1 << SYSCLK_TC0) | \ (1 << SYSCLK_TC1) | \ (1 << SYSCLK_USART0) | \ (1 << SYSCLK_USART1) | \ (1 << SYSCLK_USART2) | \ (1 << SYSCLK_USART3)) if ((PM->PM_PBAMASK & PBADIV_CLKSRC_MASK) == 0) { sysclk_disable_pba_divmask(PBA_DIVMASK_Msk); } }
/** * \brief Initializes the ACIFB module with trigger * - Start the GCLK for ACIFB * - Initialize the trigger mode & compare interrupts for ACIFB * * \retval STATUS_OK Configuration OK * \retval ERR_TIMEOUT Timeout on configuring ACIFB module * \retval ERR_BUSY ACIFB module unable to configure the trigger */ static status_code_t ac_init() { /* struct genclk_config gcfg; */ uint32_t div = sysclk_get_pba_hz() / AC_GCLK_FREQUENCY; scif_gc_setup(AC_GCLK_ID, AC_GCLK_SRC, AVR32_GC_DIV_CLOCK, div); /* Now enable the generic clock */ scif_gc_enable(AC_GCLK_ID); /* GPIO pin/acifb - function map. */ static const gpio_map_t ACIFB_GPIO_MAP = { {EXAMPLE_ACIFBP_PIN, EXAMPLE_ACIFBP_FUNCTION}, {EXAMPLE_ACIFBN_PIN, EXAMPLE_ACIFBN_FUNCTION}, }; /* ACIFB Configuration */ const acifb_t acifb_opt = { .sut = 6, /* Resolution mode */ .actest = TESTMODE_OFF, .eventen = true }; /* ACIFB Channel Configuration */ const acifb_channel_t acifb_channel_opt = { /* Filter length */ .filter_len = 0, /* Hysteresis value */ .hysteresis_value = 0, /* Output event when ACOUT is zero? */ .event_negative = false, /* Output event when ACOUT is one? */ .event_positive = false, /* Set the positive input */ .positive_input = PI_ACP, /* Set the negative input */ .negative_input = NI_ACN, /* Set the comparator mode */ .mode = MODE_EVENT_TRIGGERED, /* Interrupt settings */ .interrupt_settings = IS_VINP_LT_VINN, /* Analog comparator channel number */ .ac_n = EXAMPLE_ACIFB_CHANNEL }; /* Enable Analog Comparator clock */ sysclk_enable_pba_module(SYSCLK_ACIFB); /* Disable pullup on ACIFB channel input pins */ gpio_disable_pin_pull_up(EXAMPLE_ACIFBP_PIN); gpio_disable_pin_pull_up(EXAMPLE_ACIFBN_PIN); /* Enable the ACIFB pins */ gpio_enable_module(ACIFB_GPIO_MAP, sizeof(ACIFB_GPIO_MAP) / sizeof(ACIFB_GPIO_MAP[0])); /* Configure the ACIFB peripheral */ acifb_setup_and_enable(acifb, &acifb_opt); /* Configure the ACIFB channel with interrupt & trigger */ acifb_channels_setup(acifb, &acifb_channel_opt, AC_NB_CHANNELS); /* Disable global interrupts */ cpu_irq_disable(); /* * Initialize the interrupt vectors * Note: This function adds nothing for IAR as the interrupts are * handled by the IAR compiler itself. It provides an abstraction * between GCC & IAR compiler to use interrupts. * Refer function implementation in interrupt_avr32.h */ irq_initialize_vectors(); /* * Register the ACIFB interrupt handler * Note: This function adds nothing for IAR as the interrupts are * handled by the IAR compiler itself. It provides an abstraction * between GCC & IAR compiler to use interrupts. * Refer function implementation in interrupt_avr32.h */ irq_register_handler(&ACIFB_interrupt_handler, AVR32_ACIFB_IRQ, AC_INTERRUPT_PRIORITY); /* Enable Analog Comparator Channel interrupt */ acifb_enable_comparison_interrupt(acifb, EXAMPLE_ACIFB_CHANNEL); /* Enable global interrupts */ cpu_irq_enable(); return STATUS_OK; } /* End of ac_init() */ /** * \brief Asynchronous Timer Initialization * - Start the 32KHz Oscillator * - Initializes the AST module with periodic trigger events * * \retval STATUS_OK Configuration OK * \retval ERR_BUSY Error in configuring the AST module */ static status_code_t ast_init() { /* Initial Count value to write in AST */ unsigned long ast_counter = 0; /* Set the prescaler to set a periodic trigger from AST */ avr32_ast_pir0_t pir = { .insel = AST_TRIGGER_PRESCALER }; /* Set the OSC32 parameters */ scif_osc32_opt_t osc32_opt = { .mode = SCIF_OSC_MODE_2PIN_CRYSTAL_HICUR, .startup = OSC32_STARTUP_8192, .pinsel = BOARD_OSC32_PINSEL, .en1k = false, .en32k = true }; /* Enable the 32KHz Oscillator */ scif_start_osc32(&osc32_opt, true); /* Enable the Peripheral Event System Clock */ sysclk_enable_hsb_module(SYSCLK_EVENT); /* Enable PBA clock for AST clock to switch its source */ sysclk_enable_pba_module(SYSCLK_AST); /* Initialize the AST in counter mode */ if (!ast_init_counter(&AVR32_AST, AST_CLOCK_SOURCE, AST_PRESCALER, ast_counter)) { return ERR_BUSY; } /* Initialize the periodic value register with the prescaler */ ast_set_periodic0_value(&AVR32_AST, pir); /* Enable the AST periodic event */ ast_enable_periodic0(&AVR32_AST); /* Clear All AST Interrupt request and clear SR */ ast_clear_all_status_flags(&AVR32_AST); /* Enable the AST */ ast_enable(&AVR32_AST); /* Disable PBA clock for AST after switching its source to OSC32 */ sysclk_disable_pba_module(SYSCLK_AST); return STATUS_OK; } /* End of ast_init() */ /** * \brief Low Power Configuration * Initializes the power saving measures to reduce power consumption * - Enable pull-ups on GPIO pins * - Disable the clocks to unwanted modules * - Disable internal voltage regulator when in 1.8V supply mode */ static void power_save_measures_init() { uint8_t i; uint32_t gpio_mask[AVR32_GPIO_PORT_LENGTH] = {0}; /* * Enable internal pull-ups on all unused GPIO pins * Note: Pull-ups on Oscillator or JTAG pins can be enabled only if they * are not used as an oscillator or JTAG pin respectively. */ for (i = 0; i < (sizeof(gpio_used_pins) / sizeof(uint32_t)); i++) { gpio_mask[gpio_used_pins[i] >> 5] |= 1 << (gpio_used_pins[i] & 0x1F); } for (i = 0; i < AVR32_GPIO_PORT_LENGTH; i++) { gpio_configure_group(i, ~(gpio_mask[i]), GPIO_PULL_UP | GPIO_DIR_INPUT); } /* Disable OCD clock which is not disabled by sysclk service */ sysclk_disable_cpu_module(SYSCLK_OCD); #if POWER_SUPPLY_MODE_1_8V /* * When using 1.8V Single supply mode, the Voltage Regulator can be * shut-down using the code below, in-order to save power. * See Voltage Regulator Calibration Register in datasheet for more *info. * CAUTION: When using 3.3V Single supply mode, the Voltage Regulator * cannot be shut-down and the application will hang in this loop. */ uint32_t tmp = (AVR32_SCIF.vregcr); tmp &= (~(1 << 5 | 1 << 18)); AVR32_SCIF.unlock = 0xAA000000 | AVR32_SCIF_VREGCR; AVR32_SCIF.vregcr = tmp; /* Wait until internal voltage regulator is disabled. */ while ((AVR32_SCIF.vregcr & 0x00040020)) { } #endif } /* End of power_save_measures_init() */
/** * \brief Main Application Routine * - Initialize the system clocks * - Initialize the sleep manager * - Initialize the power save measures * - Initialize the ACIFB module * - Initialize the AST to trigger ACIFB at regular intervals * - Go to STATIC sleep mode and wake up on a touch status change */ int main(void) { /* Switch on the STATUS LED */ gpio_clr_gpio_pin(STATUS_LED); /* Switch off the error LED. */ gpio_set_gpio_pin(ERROR_LED); /* * Initialize the system clock. * Note: Clock settings are specified in conf_clock.h */ sysclk_init(); /* * Initialize the sleep manager. * Note: CONFIG_SLEEPMGR_ENABLE should have been defined in conf_sleepmgr.h */ sleepmgr_init(); /* Lock required sleep mode. */ sleepmgr_lock_mode(SLEEPMGR_STATIC); /* Initialize the delay routines */ delay_init(sysclk_get_cpu_hz()); /* Initialize the power saving features */ power_save_measures_init(); /* Switch off the error LED. */ gpio_set_gpio_pin(ERROR_LED); #if DEBUG_MESSAGES /* Enable the clock to USART interface */ sysclk_enable_peripheral_clock(DBG_USART); /* Initialize the USART interface to print trace messages */ init_dbg_rs232(sysclk_get_pba_hz()); print_dbg("\r Sleepwalking with ACIFB Module in UC3L \n"); print_dbg("\r Initializing ACIFB Module..... \n"); #endif /* Initialize the Analog Comparator peripheral */ if (ac_init() != STATUS_OK) { #if DEBUG_MESSAGES /* Error initializing the ACIFB peripheral */ print_dbg("\r Error initializing Analog Comparator module \n"); #endif while (1) { delay_ms(LED_DELAY); gpio_tgl_gpio_pin(ERROR_LED); } } #if DEBUG_MESSAGES print_dbg("\r ACIFB Module initialized. \n"); print_dbg("\r Initializing AST Module..... \n"); #endif /* Initialize the AST peripheral */ if (ast_init() != STATUS_OK) { #if DEBUG_MESSAGES print_dbg("\r Error initializing AST module \n"); #endif /* Error initializing the AST peripheral */ while (1) { delay_ms(LED_DELAY); gpio_tgl_gpio_pin(ERROR_LED); } } #if DEBUG_MESSAGES print_dbg("\r AST Module initialized. \n"); #endif /* Application routine */ while (1) { /* Enable Asynchronous wake-up for ACIFB */ pm_asyn_wake_up_enable(AVR32_PM_AWEN_ACIFBWEN_MASK); #if DEBUG_MESSAGES print_dbg("\r Going to STATIC sleep mode \n"); print_dbg( "\r Wake up only when input is higher than threshold \n"); #endif /* Switch off the status LED */ gpio_set_gpio_pin(STATUS_LED); /* Disable GPIO clock before entering sleep mode */ sysclk_disable_pba_module(SYSCLK_GPIO); AVR32_INTC.ipr[0]; /* Enter STATIC sleep mode */ sleepmgr_enter_sleep(); /* Enable GPIO clock after waking from sleep mode */ sysclk_enable_pba_module(SYSCLK_GPIO); /* Switch on the status LED */ gpio_clr_gpio_pin(STATUS_LED); #if DEBUG_MESSAGES print_dbg("\r Output higher than threshold \n"); print_dbg("\n"); #else /* LED on for few ms */ delay_ms(LED_DELAY); #endif /* Clear the wake up & enable it to enter sleep mode again */ pm_asyn_wake_up_disable(AVR32_PM_AWEN_ACIFBWEN_MASK); /* Clear All AST Interrupt request and clear SR */ ast_clear_all_status_flags(&AVR32_AST); } return 0; } /* End of main() */
/** * \brief Initializes the ADCIFB module with trigger * - Initialize the trigger mode & compare interrupts for ADCIFB * * \retval STATUS_OK Configuration OK * \retval ERR_TIMEOUT Timeout on configuring ADCIFB module * \retval ERR_BUSY ADCIFB module unable to configure the trigger */ static status_code_t adc_init() { /* GPIO pin/adc - function map. */ static const gpio_map_t ADCIFB_GPIO_MAP = { {EXAMPLE_ADCIFB_PIN, EXAMPLE_ADCIFB_FUNCTION} }; /* ADCIFB Configuration */ adcifb_opt_t adcifb_opt = { /* Resolution mode */ .resolution = AVR32_ADCIFB_ACR_RES_10BIT, /* Channels Sample & Hold Time in [0,15] */ .shtim = ADC_SAMPLE_HOLD_TIME, /* ADC Clock Prescaler */ .ratio_clkadcifb_clkadc = (sysclk_get_pba_hz()) / ADC_FREQUENCY, .startup = ADC_STARTUP_TIME, /* ADCIFB Sleep Mode enabled */ .sleep_mode_enable = true }; /* Disable pull up on ADCIFB channel input pin */ gpio_disable_pin_pull_up(EXAMPLE_ADCIFB_PIN); /* Enable the ADC pins */ gpio_enable_module(ADCIFB_GPIO_MAP, sizeof(ADCIFB_GPIO_MAP) / sizeof(ADCIFB_GPIO_MAP[0])); /* Enable ADCIFB clock */ sysclk_enable_pba_module(SYSCLK_ADCIFB); /* Configure the ADCIFB peripheral */ if (adcifb_configure(adcifb, &adcifb_opt)) { /* Error configuring the ADCIFB */ return ERR_TIMEOUT; } /* Configure the trigger for ADCIFB peripheral */ if (adcifb_configure_trigger(adcifb, AVR32_ADCIFB_TRGR_TRGMOD_EVT, 0)) { /* Error configuring the trigger for ADCIFB */ return ERR_BUSY; } /* Enable ADCIFB Channel 0 */ adcifb_channels_enable(adcifb, EXAMPLE_ADCIFB_CHANNEL); /* Disable global interrupts */ cpu_irq_disable(); /* * Initialize the interrupt vectors * Note: This function adds nothing for IAR as the interrupts are * handled by the IAR compiler itself. It provides an abstraction * between GCC & IAR compiler to use interrupts. * Refer function implementation in interrupt_avr32.h */ irq_initialize_vectors(); /* * Register the ADCIFB interrupt handler * Note: This function adds nothing for IAR as the interrupts are * handled by the IAR compiler itself. It provides an abstraction * between GCC & IAR compiler to use interrupts. * Refer function implementation in interrupt_avr32.h */ irq_register_handler(&ADCIFB_interrupt_handler, AVR32_ADCIFB_IRQ, ADC_INTERRUPT_PRIORITY); /* * Set the threshold value in CVR.LV register to generate interrupt * when the value detected is above the threshold. * 1.500 V with 10-bit resolution */ adcifb_set_high_compare_value(adcifb, ADC_COMPARE_VALUE); /* Enable the Analog Compare option in ADCIFB */ adcifb_enable_analog_compare_mode(adcifb); /* Enable the data ready interrupt for ADCIFB */ adcifb_enable_compare_gt_interrupt(adcifb); return STATUS_OK; } /* End of adc_init() */ /** * \brief Asynchronous Timer Initialization * - Start the 32KHz Oscillator * - Initializes the AST module with periodic trigger events * * \retval STATUS_OK Configuration OK * \retval ERR_TIMEOUT Error in configuring the AST module */ static status_code_t ast_init() { /* Initial Count value to write in AST */ unsigned long ast_counter = 0; /* Set the prescaler to set a periodic trigger from AST */ avr32_ast_pir0_t pir = { .insel = AST_TRIGGER_PRESCALER }; /* Set the OSC32 parameters */ scif_osc32_opt_t osc32_opt = { .mode = SCIF_OSC_MODE_2PIN_CRYSTAL_HICUR, .startup = OSC32_STARTUP_8192, .pinsel = BOARD_OSC32_PINSEL, .en1k = false, .en32k = true }; /* Enable the 32KHz Oscillator */ scif_start_osc32(&osc32_opt, true); /* Enable the Peripheral Event System Clock */ sysclk_enable_hsb_module(SYSCLK_EVENT); /* Enable PBA clock for AST clock to switch its source */ sysclk_enable_pba_module(SYSCLK_AST); /* Initialize the AST in counter mode */ if (!ast_init_counter(&AVR32_AST, AST_CLOCK_SOURCE, AST_PRESCALER, ast_counter)) { return ERR_TIMEOUT; } /* Initialize the periodic value register with the prescaler */ ast_set_periodic0_value(&AVR32_AST, pir); /* Enable the AST periodic event */ ast_enable_periodic0(&AVR32_AST); /* Clear All AST Interrupt request and clear SR */ ast_clear_all_status_flags(&AVR32_AST); /* Enable the AST */ ast_enable(&AVR32_AST); /* Disable PBA clock for AST after switching its source to OSC32 */ sysclk_disable_pba_module(SYSCLK_AST); return STATUS_OK; } /* End of ast_init() */ /** * \brief Low Power Configuration * Initializes the power saving measures to reduce power consumption * - Enable pullups on GPIO pins * - Disable the clocks to unused modules * - Disable internal voltage regulator when in 1.8V supply mode */ static void power_save_measures_init() { uint8_t i; uint32_t gpio_mask[AVR32_GPIO_PORT_LENGTH] = {0}; /* * Enable internal pull-ups on all unused GPIO pins * Note: Pull-ups on Oscillator or JTAG pins can be enabled only if they * are not used as an oscillator or JTAG pin respectively. */ for (i = 0; i < (sizeof(gpio_used_pins) / sizeof(uint32_t)); i++) { gpio_mask[gpio_used_pins[i] >> 5] |= 1 << (gpio_used_pins[i] & 0x1F); } for (i = 0; i < AVR32_GPIO_PORT_LENGTH; i++) { gpio_configure_group(i, ~(gpio_mask[i]), GPIO_PULL_UP | GPIO_DIR_INPUT); } /* Disable OCD clock which is not disabled by sysclk service */ sysclk_disable_cpu_module(SYSCLK_OCD); #if POWER_SUPPLY_MODE_1_8V /* * When using 1.8V Single supply mode, the Voltage Regulator can be * shut-down using the code below, in-order to save power. * See Voltage Regulator Calibration Register in datasheet for more *info. * CAUTION: When using 3.3V Single supply mode, the Voltage Regulator * cannot be shut-down and the application will hang in this loop. */ uint32_t tmp = (AVR32_SCIF.vregcr); tmp &= (~(1 << 5 | 1 << 18)); AVR32_SCIF.unlock = 0xAA000000 | AVR32_SCIF_VREGCR; AVR32_SCIF.vregcr = tmp; /* Wait until internal voltage regulator is disabled. */ while ((AVR32_SCIF.vregcr & 0x00040020)) { } #endif } /* End of power_save_measures_init() */
static status_code_t ast_init() { /* Initial Count value to write in AST */ unsigned long ast_counter = 0; /* Set the prescaler to set a periodic trigger from AST */ avr32_ast_pir0_t pir = { .insel = AST_TRIGGER_PRESCALER }; /* Set the OSC32 parameters */ scif_osc32_opt_t osc32_opt = { #if BOARD_OSC32_IS_XTAL .mode = SCIF_OSC_MODE_2PIN_CRYSTAL_HICUR, #else .mode = SCIF_OSC_MODE_EXT_CLK, #endif .startup = OSC32_STARTUP_8192, .pinsel = BOARD_OSC32_PINSEL, .en1k = false, .en32k = true }; /* Enable the 32KHz Oscillator */ scif_start_osc32(&osc32_opt, true); /* Enable the Peripheral Event System Clock */ sysclk_enable_hsb_module(SYSCLK_EVENT); /* Enable PBA clock for AST clock to switch its source */ sysclk_enable_pba_module(SYSCLK_AST); /* Initialize the AST in counter mode */ if (!ast_init_counter(&AVR32_AST, AST_CLOCK_SOURCE, AST_PRESCALER, ast_counter)) { return ERR_BUSY; /* Check AST timer */ } /* Initialize the periodic value register with the prescaler */ ast_set_periodic0_value(&AVR32_AST, pir); /* Enable the AST periodic event */ ast_enable_periodic0(&AVR32_AST); /* Clear All AST Interrupt request and clear SR */ ast_clear_all_status_flags(&AVR32_AST); /* Enable the AST */ ast_enable(&AVR32_AST); /* Disable PBA clock for AST after switching its source to OSC32 */ sysclk_disable_pba_module(SYSCLK_AST); return STATUS_OK; } /* End of ast_init() */ #endif /** * \brief Low Power Configuration * Initializes the power saving measures to reduce power consumption * - Enable pull ups on GPIO pins * - Disable the clocks to unwanted modules * - Disable internal voltage regulator when in 1.8V supply mode */ void power_save_measures_init() { uint8_t i; uint32_t gpio_mask[AVR32_GPIO_PORT_LENGTH] = {0}; /* * Enable internal pull-ups on all unused GPIO pins * Note: Pull-ups on Oscillator or JTAG pins can be enabled only if they * are not used as an oscillator or JTAG pin respectively. */ for (i = 0; i < (sizeof(gpio_used_pins) / sizeof(uint32_t)); i++) { gpio_mask[gpio_used_pins[i] >> 5] |= 1 << (gpio_used_pins[i] & 0x1F); } for (i = 0; i < AVR32_GPIO_PORT_LENGTH; i++) { gpio_configure_group(i, gpio_mask[i], GPIO_PULL_UP | GPIO_DIR_INPUT); } /* Disable OCD clock which is not disabled by sysclk service */ sysclk_disable_cpu_module(SYSCLK_OCD); #if POWER_SUPPLY_MODE_1_8V /* * When using 1.8V Single supply mode, the Voltage Regulator can be * shut-down using the code below, in-order to save power. * See Voltage Regulator Calibration Register in datasheet for more *info. * CAUTION: When using 3.3V Single supply mode, the Voltage Regulator * cannot be shut-down and the application will hang in this loop. */ uint32_t tmp = (AVR32_SCIF.vregcr); tmp &= (~(1 << 5)); AVR32_SCIF.unlock = 0xAA000000 | AVR32_SCIF_VREGCR; AVR32_SCIF.vregcr = tmp; /* Wait until internal voltage regulator is disabled. */ while ((AVR32_SCIF.vregcr & 0x20)) { } #endif } /* End of power_save_measures_init() */
/** * \brief Main Application Routine * - Initialize the system clocks * - Initialize the sleep manager * - Initialize the power save measures * - Initialize the touch library and sensors * - Initialize the AST to trigger CAT at regular intervals * - Go to STATIC sleep mode and wake up on a touch status change */ int main(void) { #if DEF_TOUCH_QDEBUG_ENABLE == 1 uint32_t delay_counter; #endif uint32_t i; /* Switch on the STATUS LED */ gpio_clr_gpio_pin(STATUS_LED); /* Switch off the error LED. */ gpio_set_gpio_pin(ERROR_LED); /* * Initialize the system clock. * Note: Clock settings are specified in conf_clock.h */ sysclk_init(); /* * Initialize the sleep manager. * Note: CONFIG_SLEEPMGR_ENABLE should have been defined in conf_sleepmgr.h */ sleepmgr_init(); /* Lock required sleep mode. */ sleepmgr_lock_mode(SLEEPMGR_STATIC); /* Initialize the power saving features */ power_save_measures_init(); /* Switch off the error LED. */ gpio_set_gpio_pin(ERROR_LED); #if DEF_TOUCH_QDEBUG_ENABLE == 0 /* Initialize the AST peripheral */ if (ast_init() != STATUS_OK) { /* Error initializing the AST peripheral */ while (1) { for (i = 0; i < 10000; i++) { } gpio_tgl_gpio_pin(ERROR_LED); } } #endif /* Initialize the touch library */ if (touch_api_init() != STATUS_OK) { /* Error initializing the touch sensors */ while (1) { for (i = 0; i < 10000; i++) { } gpio_tgl_gpio_pin(ERROR_LED); } } #if DEF_TOUCH_QDEBUG_ENABLE == 1 /* Enable PBA clock for AST clock to switch its source */ sysclk_enable_peripheral_clock(QDEBUG_USART); /* * Initialize the QDebug interface. * QT600 USB Bridge two-way QDebug communication. */ QDebug_Init(); #endif /* Turn OFF the Status LED */ gpio_set_gpio_pin(STATUS_LED); /* Loop forever */ while (1) { #if DEF_TOUCH_QDEBUG_ENABLE == 1 /* Process any commands received from QTouch Studio. */ QDebug_ProcessCommands(); /* * Send out the Touch debug information data each time when * Touch measurement process is completed. * param - 0x000A -> Enable TOUCH_STATUS_CHANGE & * TOUCH_CHANNEL_REF_CHANGE * qt_lib_flags always for Autonomous QTouch. */ QDebug_SendData(0x000A); /* Delay to avoid sending the data to QTouch Studio too frequently. */ for (delay_counter = 0u; delay_counter < 1200u; delay_counter++) { } #else /* Enable Asynchronous Wakeup for CAT module */ pm_asyn_wake_up_enable(AVR32_PM_AWEN_CATWEN_MASK); /* Disable GPIO clock after waking from sleep mode */ sysclk_disable_pba_module(SYSCLK_GPIO); /* Enter STATIC sleep mode */ sleepmgr_enter_sleep(); /* Disable Asynchronous Wakeup for CAT module. */ pm_asyn_wake_up_disable(AVR32_PM_AWEN_CATWEN_MASK); /* Clear All AST Interrupt request and clear SR */ ast_clear_all_status_flags(&AVR32_AST); /** * When woken up by Autonomous QTouch interrupt, the * touch_at_status_change_interrupt_callback() is called that * updates the autonomous_qtouch_in_touch status flag. */ /* Host application code goes here */ #endif } } /* End of main() */