Ejemplo n.º 1
0
/*---------------------------------------------------------------------------*/
void
rf_core_setup_interrupts()
{
  bool interrupts_disabled;

  /* We are already turned on by the caller, so this should not happen */
  if(!rf_core_is_accessible()) {
    PRINTF("setup_interrupts: No access\n");
    return;
  }

  /* Disable interrupts */
  interrupts_disabled = ti_lib_int_master_disable();

  /* Set all interrupt channels to CPE0 channel, error to CPE1 */
  HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;

  /* Acknowledge configured interrupts */
  HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS;

  /* Clear interrupt flags, active low clear(?) */
  HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;

  ti_lib_int_pend_clear(INT_RF_CPE0);
  ti_lib_int_pend_clear(INT_RF_CPE1);
  ti_lib_int_enable(INT_RF_CPE0);
  ti_lib_int_enable(INT_RF_CPE1);

  if(!interrupts_disabled) {
    ti_lib_int_master_enable();
  }
}
Ejemplo n.º 2
0
/*---------------------------------------------------------------------------*/
void
cc26xx_rf_cpe0_isr(void)
{
  ENERGEST_ON(ENERGEST_TYPE_IRQ);

  if(!rf_core_is_accessible()) {
    printf("RF ISR called but RF not ready... PANIC!!\n");
    if(rf_core_power_up() != RF_CORE_CMD_OK) {
      PRINTF("rf_core_power_up() failed\n");
      return;
    }
  }

  ti_lib_int_master_disable();

  if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
    process_poll(&rf_core_process);
  }

  if(RF_CORE_DEBUG_CRC) {
    if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
      rx_nok_isr();
    }
  }

  /* Clear interrupt flags */
  HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
  ti_lib_int_master_enable();

  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
Ejemplo n.º 3
0
/*---------------------------------------------------------------------------*/
void board_init()
{
	uint8_t int_disabled = ti_lib_int_master_disable();

	/* Turn on relevant PDs */
	wakeup_handler();

	/* Enable GPIO peripheral */
	ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO);

	/* Apply settings and wait for them to take effect */
	ti_lib_prcm_load_set();
	while (!ti_lib_prcm_load_get()) ;

	lpm_register_module(&srf_module);

	/* Re-enable interrupt if initially enabled. */
	if (!int_disabled) {
		ti_lib_int_master_enable();
	}

	/* Init of PWM */
	pwm_init();

}
Ejemplo n.º 4
0
/*---------------------------------------------------------------------------*/
void
rf_core_power_down()
{
  bool interrupts_disabled = ti_lib_int_master_disable();
  ti_lib_int_disable(INT_RF_CPE0);
  ti_lib_int_disable(INT_RF_CPE1);

  if(rf_core_is_accessible()) {
    HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
    HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;

    /* need to send FS_POWERDOWN or analog components will use power */
    fs_powerdown();
  }

  /* Shut down the RFCORE clock domain in the MCU VD */
  ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
  ti_lib_prcm_load_set();
  while(!ti_lib_prcm_load_get());

  /* Turn off RFCORE PD */
  ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE);
  while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
        != PRCM_DOMAIN_POWER_OFF);

  ti_lib_int_pend_clear(INT_RF_CPE0);
  ti_lib_int_pend_clear(INT_RF_CPE1);
  ti_lib_int_enable(INT_RF_CPE0);
  ti_lib_int_enable(INT_RF_CPE1);
  if(!interrupts_disabled) {
    ti_lib_int_master_enable();
  }
}
Ejemplo n.º 5
0
/*---------------------------------------------------------------------------*/
void
cc26xx_uart_init()
{
  bool interrupts_disabled;

  /* Return early if disabled by user conf or if ports are misconfigured */
  if(usable() == false) {
    return;
  }

  /* Disable Interrupts */
  interrupts_disabled = ti_lib_int_master_disable();

  /* Register ourselves with the LPM module */
  lpm_register_module(&uart_module);

  /* Only TX and EN to start with. RX will be enabled only if needed */
  input_handler = NULL;

  /*
   * init() won't actually fire up the UART. We turn it on only when (and if)
   * it gets requested, either to enable input or to send out a character
   *
   * Thus, we simply re-enable processor interrupts here
   */
  if(!interrupts_disabled) {
    ti_lib_int_master_enable();
  }
}
Ejemplo n.º 6
0
/*---------------------------------------------------------------------------*/
void
board_init()
{
  /* Disable global interrupts */
  bool int_disabled = ti_lib_int_master_disable();

  /* Turn on relevant PDs */
  wakeup_handler();

  /* Enable GPIO peripheral */
  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO);

  /* Apply settings and wait for them to take effect */
  ti_lib_prcm_load_set();
  while(!ti_lib_prcm_load_get());

  /* Make sure the external flash is in the lower power mode */
  ext_flash_init();

  lpm_register_module(&launchpad_module);

  /* For unsupported peripherals, select a default pin configuration */
  configure_unused_pins();

  /* Re-enable interrupt if initially enabled. */
  if(!int_disabled) {
    ti_lib_int_master_enable();
  }
}
Ejemplo n.º 7
0
/*---------------------------------------------------------------------------*/
void
board_init()
{
  /* Disable global interrupts */
  uint8_t int_disabled = ti_lib_int_master_disable();

  power_domains_on();

  /* Configure all clock domains to run at full speed */
  ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SYSBUS, PRCM_CLOCK_DIV_1);
  ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_CPU, PRCM_CLOCK_DIV_1);
  ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_TIMER, PRCM_CLOCK_DIV_1);
  ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SERIAL, PRCM_CLOCK_DIV_1);
  ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_PERIPH, PRCM_CLOCK_DIV_1);

  /* Enable GPIO peripheral */
  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO);

  /* Apply settings and wait for them to take effect */
  ti_lib_prcm_load_set();
  while(!ti_lib_prcm_load_get());

  /* Enable GPT0 module - Wait for the clock to be enabled */
  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0);
  ti_lib_prcm_load_set();
  while(!ti_lib_prcm_load_get());

  /* Keys (input pullup) */
  ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_LEFT);
  ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_RIGHT);
  ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_LEFT, IOC_IOPULL_UP);
  ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP);

  /* I2C controller */
  board_i2c_init();

  /* Sensor interface */
  ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
  ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN);

  ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_REED_RELAY);
  ti_lib_ioc_io_port_pull_set(BOARD_IOID_REED_RELAY, IOC_IOPULL_DOWN);

  ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER);

  /* Flash interface */
  ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS);
  ti_lib_gpio_pin_write(BOARD_FLASH_CS, 1);

  buzzer_init();

  lpm_register_module(&sensortag_module);

  /* Re-enable interrupt if initially enabled. */
  if(!int_disabled) {
    ti_lib_int_master_enable();
  }
}
Ejemplo n.º 8
0
/*---------------------------------------------------------------------------*/
uint_fast8_t
rf_core_send_cmd(uint32_t cmd, uint32_t *status)
{
  uint32_t timeout_count = 0;
  bool interrupts_disabled;
  bool is_radio_op = false;

  /* If cmd is 4-byte aligned, then it's a radio OP. Clear the status field */
  if((cmd & 0x03) == 0) {
    is_radio_op = true;
    ((rfc_radioOp_t *)cmd)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
  }

  /*
   * Make sure ContikiMAC doesn't turn us off from within an interrupt while
   * we are accessing RF Core registers
   */
  interrupts_disabled = ti_lib_int_master_disable();

  if(!rf_core_is_accessible()) {
    PRINTF("rf_core_send_cmd: RF was off\n");
    if(!interrupts_disabled) {
      ti_lib_int_master_enable();
    }
    return RF_CORE_CMD_ERROR;
  }

  if(is_radio_op) {
    uint16_t command_no = ((rfc_radioOp_t *)cmd)->commandNo;
    if((command_no & RF_CORE_COMMAND_PROTOCOL_MASK) != RF_CORE_COMMAND_PROTOCOL_COMMON &&
       (command_no & RF_CORE_COMMAND_TYPE_MASK) == RF_CORE_COMMAND_TYPE_RADIO_OP) {
      last_radio_op = (rfc_radioOp_t *)cmd;
    }
  }

  HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
  do {
    *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
    if(++timeout_count > 50000) {
      PRINTF("rf_core_send_cmd: 0x%08lx Timeout\n", cmd);
      if(!interrupts_disabled) {
        ti_lib_int_master_enable();
      }
      return RF_CORE_CMD_ERROR;
    }
  } while(*status == RF_CORE_CMDSTA_PENDING);

  if(!interrupts_disabled) {
    ti_lib_int_master_enable();
  }

  /*
   * If we reach here the command is no longer pending. It is either completed
   * successfully or with error
   */
  return (*status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_DONE;
}
Ejemplo n.º 9
0
/*---------------------------------------------------------------------------*/
void
gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f)
{
  uint8_t interrupts_disabled = ti_lib_int_master_disable();

  /* Clear interrupts on specified pins */
  ti_lib_gpio_event_clear(1 << ioid);

  handlers[ioid] = f;

  /* Re-enable interrupts */
  if(!interrupts_disabled) {
    ti_lib_int_master_enable();
  }
}
Ejemplo n.º 10
0
/*---------------------------------------------------------------------------*/
int
rf_core_power_up()
{
  uint32_t cmd_status;
  bool interrupts_disabled = ti_lib_int_master_disable();

  ti_lib_int_pend_clear(INT_RF_CPE0);
  ti_lib_int_pend_clear(INT_RF_CPE1);
  ti_lib_int_disable(INT_RF_CPE0);
  ti_lib_int_disable(INT_RF_CPE1);

  /* Enable RF Core power domain */
  ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE);
  while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
        != PRCM_DOMAIN_POWER_ON);

  ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE);
  ti_lib_prcm_load_set();
  while(!ti_lib_prcm_load_get());

  while(!rf_core_is_accessible()) {
    PRINTF("rf_core_power_up: Not ready\n");
  }

  HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
  HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
  ti_lib_int_enable(INT_RF_CPE0);
  ti_lib_int_enable(INT_RF_CPE1);

  if(!interrupts_disabled) {
    ti_lib_int_master_enable();
  }

  /* Let CPE boot */
  HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;

  /* Send ping (to verify RFCore is ready and alive) */
  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CORE_CMD_OK) {
    PRINTF("rf_core_power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status);
    return RF_CORE_CMD_ERROR;
  }

  return RF_CORE_CMD_OK;
}
Ejemplo n.º 11
0
/*---------------------------------------------------------------------------*/
void
cc26xx_rf_cpe0_isr(void)
{
  ENERGEST_ON(ENERGEST_TYPE_IRQ);

  if(!rf_core_is_accessible()) {
    printf("RF ISR called but RF not ready... PANIC!!\n");
    if(rf_core_power_up() != RF_CORE_CMD_OK) {
      PRINTF("rf_core_power_up() failed\n");
      return;
    }
  }

  ti_lib_int_master_disable();

  if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
    /* Clear the RX_ENTRY_DONE interrupt flag */
    HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFF7FFFFF;
    process_poll(&rf_core_process);
  }

  if(RF_CORE_DEBUG_CRC) {
    if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
      /* Clear the RX_NOK interrupt flag */
      HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFDFFFF;
      rx_nok_isr();
    }
  }

  if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) &
     (IRQ_LAST_FG_COMMAND_DONE | IRQ_LAST_COMMAND_DONE)) {
    /* Clear the two TX-related interrupt flags */
    HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFFFFF5;
  }

  ti_lib_int_master_enable();

  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
Ejemplo n.º 12
0
/*---------------------------------------------------------------------------*/
void
cc26xx_rtc_init(void)
{
  uint32_t compare_value;
  bool interrupts_disabled;

  /* Disable and clear interrupts */
  interrupts_disabled = ti_lib_int_master_disable();

  ti_lib_aon_rtc_disable();

  ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
  ti_lib_aon_rtc_event_clear(AON_RTC_CH2);

  /* Setup the wakeup event */
  ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU0, AON_EVENT_RTC0);
  ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU1, AON_EVENT_RTC2);
  ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH2);

  /* Configure channel 2 in continuous compare, 128 ticks / sec */
  ti_lib_aon_rtc_inc_value_ch2_set(RTIMER_SECOND / CLOCK_SECOND);
  ti_lib_aon_rtc_mode_ch2_set(AON_RTC_MODE_CH2_CONTINUOUS);
  compare_value = (RTIMER_SECOND / CLOCK_SECOND) +
                  ti_lib_aon_rtc_current_compare_value_get();
  ti_lib_aon_rtc_compare_value_set(AON_RTC_CH2, compare_value);

  /* Enable channel 2 and the RTC */
  ti_lib_aon_rtc_channel_enable(AON_RTC_CH2);
  ti_lib_aon_rtc_enable();

  ti_lib_int_enable(INT_AON_RTC);

  /* Re-enable interrupts */
  if(!interrupts_disabled) {
    ti_lib_int_master_enable();
  }
}
Ejemplo n.º 13
0
/**
 * \brief Main function for CC26xx-based platforms
 *
 * The same main() is used for all supported boards
 */
int
main(void)
{
  /* Enable flash cache and prefetch. */
  ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED);
  ti_lib_vims_configure(VIMS_BASE, true, true);

  ti_lib_int_master_disable();

  /* Set the LF XOSC as the LF system clock source */
  oscillators_select_lf_xosc();

  lpm_init();

  board_init();

  gpio_interrupt_init();

  leds_init();

  /*
   * Disable I/O pad sleep mode and open I/O latches in the AON IOC interface
   * This is only relevant when returning from shutdown (which is what froze
   * latches in the first place. Before doing these things though, we should
   * allow software to first regain control of pins
   */
  ti_lib_pwr_ctrl_io_freeze_disable();

  fade(LEDS_RED);

  ti_lib_int_master_enable();

  soc_rtc_init();
  clock_init();
  rtimer_init();

  watchdog_init();
  process_init();

  random_init(0x1234);

  /* Character I/O Initialisation */
#if CC26XX_UART_CONF_ENABLE
  cc26xx_uart_init();
#endif

  serial_line_init();

  printf("Starting " CONTIKI_VERSION_STRING "\n\r");
  printf("With DriverLib v%u.%u\n\r", DRIVERLIB_RELEASE_GROUP,
         DRIVERLIB_RELEASE_BUILD);
  printf(BOARD_STRING "\n\r");

  process_start(&etimer_process, NULL);
  ctimer_init();

  energest_init();
  ENERGEST_ON(ENERGEST_TYPE_CPU);

  fade(LEDS_YELLOW);

  printf(" Net: ");
  printf("%s\n\r", NETSTACK_NETWORK.name);
  printf(" MAC: ");
  printf("%s\n\r", NETSTACK_MAC.name);
  printf(" RDC: ");
  printf("%s", NETSTACK_RDC.name);

  if(NETSTACK_RDC.channel_check_interval() != 0) {
    printf(", Channel Check Interval: %u ticks",
           NETSTACK_RDC.channel_check_interval());
  }
  printf("\n\r");

  netstack_init();

  set_rf_params();

#if NETSTACK_CONF_WITH_IPV6
  memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));
  queuebuf_init();
  process_start(&tcpip_process, NULL);
#endif /* NETSTACK_CONF_WITH_IPV6 */

  fade(LEDS_GREEN);

  process_start(&sensors_process, NULL);

  autostart_start(autostart_processes);

  watchdog_start();

  fade(LEDS_ORANGE);

  while(1) {
    uint8_t r;
    do {
      r = process_run();
      watchdog_periodic();
    } while(r > 0);

    /* Drop to some low power mode */
    lpm_drop();
  }
}
Ejemplo n.º 14
0
Archivo: lpm.c Proyecto: gnkarn/Contiki
/*---------------------------------------------------------------------------*/
void
lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
{
  lpm_registered_module_t *module;
  int i;
  uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull |
    wake_on;

  /* This procedure may not be interrupted */
  ti_lib_int_master_disable();

  /* Disable the RTC */
  ti_lib_aon_rtc_disable();
  ti_lib_aon_rtc_event_clear(AON_RTC_CH0);
  ti_lib_aon_rtc_event_clear(AON_RTC_CH1);
  ti_lib_aon_rtc_event_clear(AON_RTC_CH2);

  /* Reset AON even fabric to default wakeup sources */
  for(i = AON_EVENT_MCU_WU0; i <= AON_EVENT_MCU_WU3; i++) {
    ti_lib_aon_event_mcu_wake_up_set(i, AON_EVENT_NONE);
  }
  for(i = AON_EVENT_AUX_WU0; i <= AON_EVENT_AUX_WU2; i++) {
    ti_lib_aon_event_aux_wake_up_set(i, AON_EVENT_NONE);
  }

  ti_lib_sys_ctrl_aon_sync();

  watchdog_periodic();

  /* Notify all modules that we're shutting down */
  for(module = list_head(modules_list); module != NULL;
      module = module->next) {
    if(module->shutdown) {
      module->shutdown(LPM_MODE_SHUTDOWN);
    }
  }

  /* Configure the wakeup trigger */
  if(wakeup_pin != IOID_UNUSED) {
    ti_lib_gpio_dir_mode_set((1 << wakeup_pin), GPIO_DIR_MODE_IN);
    ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);
  }

  /* Freeze I/O latches in AON */
  ti_lib_aon_ioc_freeze_enable();

  /* Turn off RFCORE, SERIAL and PERIPH PDs. This will happen immediately */
  ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL |
                               PRCM_DOMAIN_PERIPH);

  oscillators_switch_to_hf_rc();
  oscillators_select_lf_rcosc();

  /* Configure clock sources for MCU and AUX: No clock */
  ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
  ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK);

  /* Disable SRAM and AUX retentions */
  ti_lib_aon_wuc_mcu_sram_config(0);
  ti_lib_aon_wuc_aux_sram_config(false);

  /*
   * Request CPU, SYSBYS and VIMS PD off.
   * This will only happen when the CM3 enters deep sleep
   */
  ti_lib_prcm_power_domain_off(PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS |
                               PRCM_DOMAIN_SYSBUS);

  /* Request JTAG domain power off */
  ti_lib_aon_wuc_jtag_power_off();

  /* Turn off AUX */
  ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF);
  ti_lib_aon_wuc_domain_power_down_enable();
  while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON);

  /*
   * Request MCU VD power off.
   * This will only happen when the CM3 enters deep sleep
   */
  ti_lib_prcm_mcu_power_off();

  /* Set MCU wakeup to immediate and disable virtual power off */
  ti_lib_aon_wuc_mcu_wake_up_config(MCU_IMM_WAKE_UP);
  ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE);

  /* Latch the IOs in the padring and enable I/O pad sleep mode */
  ti_lib_pwr_ctrl_io_freeze_enable();

  /* Turn off VIMS cache, CRAM and TRAM - possibly not required */
  ti_lib_prcm_cache_retention_disable();
  ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);

  /* Enable shutdown and sync AON */
  ti_lib_aon_wuc_shut_down_enable();
  ti_lib_sys_ctrl_aon_sync();

  /* Deep Sleep */
  ti_lib_prcm_deep_sleep();
}
Ejemplo n.º 15
0
Archivo: lpm.c Proyecto: gnkarn/Contiki
/*---------------------------------------------------------------------------*/
void
lpm_drop()
{
  lpm_registered_module_t *module;
  uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
  uint8_t module_pm;
  clock_time_t next_event;

  uint32_t domains = LOCKABLE_DOMAINS;

  if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(),
                     RTIMER_NOW() + STANDBY_MIN_DURATION)) {
    lpm_sleep();
    return;
  }

  /* Collect max allowed PM permission from interested modules */
  for(module = list_head(modules_list); module != NULL;
      module = module->next) {
    if(module->request_max_pm) {
      module_pm = module->request_max_pm();
      if(module_pm < max_pm) {
        max_pm = module_pm;
      }
    }
  }

  /* Check if any events fired during this process. Last chance to abort */
  if(process_nevents()) {
    return;
  }

  /* Drop */
  if(max_pm == LPM_MODE_SLEEP) {
    lpm_sleep();
  } else {
    /* Critical. Don't get interrupted! */
    ti_lib_int_master_disable();

    /*
     * Reschedule AON RTC CH1 to fire an event N ticks before the next etimer
     * event
     */
    next_event = etimer_next_expiration_time();

    if(next_event) {
      next_event = next_event - clock_time();
      soc_rtc_schedule_one_shot(AON_RTC_CH1, RTIMER_NOW() +
          (next_event * (RTIMER_SECOND / CLOCK_SECOND)));
    }

    /*
     * Notify all registered modules that we are dropping to mode X. We do not
     * need to do this for simple sleep.
     *
     * This is a chance for modules to delay us a little bit until an ongoing
     * operation has finished (e.g. uart TX) or to configure themselves for
     * deep sleep.
     *
     * At this stage, we also collect power domain locks, if any.
     * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time
     * we encounter a lock we just clear the respective bits in the 'domains'
     * variable as required by the lock. In the end the domains variable will
     * just hold whatever has not been cleared
     */
    for(module = list_head(modules_list); module != NULL;
        module = module->next) {
      if(module->shutdown) {
        module->shutdown(max_pm);
      }

      /* Clear the bits specified in the lock */
      domains &= ~module->domain_lock;
    }

    /* Pat the dog: We don't want it to shout right after we wake up */
    watchdog_periodic();

    /* Clear unacceptable bits, just in case a lock provided a bad value */
    domains &= LOCKABLE_DOMAINS;

    /*
     * Freeze the IOs on the boundary between MCU and AON. We only do this if
     * PERIPH is not needed
     */
    if(domains & PRCM_DOMAIN_PERIPH) {
      ti_lib_aon_ioc_freeze_enable();
    }

    /*
     * Among LOCKABLE_DOMAINS, turn off those that are not locked
     *
     * If domains is != 0, pass it as-is
     */
    if(domains) {
      ti_lib_prcm_power_domain_off(domains);
    }

    /*
     * Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC
     * is predominantly controlled by the RF driver. In a build with radio
     * cycling (e.g. ContikiMAC), the RF driver will request the XOSC before
     * using the Freq. Synth, and switch back to the RC when it is about to
     * turn back off.
     *
     * If the radio is on, we won't even reach here, and if it's off the HF
     * clock source should already be the HF RC.
     *
     * Nevertheless, request the switch to the HF RC explicitly here.
     */
    oscillators_switch_to_hf_rc();

    /* Configure clock sources for MCU and AUX: No clock */
    ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
    ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK);

    /* Full RAM retention. */
    ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION |
                                   MCU_RAM2_RETENTION | MCU_RAM3_RETENTION);

    /* Disable retention of AUX RAM */
    ti_lib_aon_wuc_aux_sram_config(false);

    /*
     * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off
     * already
     */
    ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU |
                                 PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS);

    /* Request JTAG domain power off */
    ti_lib_aon_wuc_jtag_power_off();

    /* Turn off AUX */
    ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF);
    ti_lib_aon_wuc_domain_power_down_enable();
    while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON);

    /* Configure the recharge controller */
    ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE);

    /*
     * If both PERIPH and SERIAL PDs are off, request the uLDO as the power
     * source while in deep sleep.
     */
    if(domains == LOCKABLE_DOMAINS) {
      ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO);
    }

    /* We are only interested in IRQ energest while idle or in LPM */
    ENERGEST_IRQ_RESTORE(irq_energest);
    ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);

    /* Sync the AON interface to ensure all writes have gone through. */
    ti_lib_sys_ctrl_aon_sync();

    /*
     * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of
     * retention mismatch between VIMS logic and cache. We wait to do this
     * until right before deep sleep to be able to use the cache for as long
     * as possible.
     */
    ti_lib_prcm_cache_retention_disable();
    ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);

    /* Deep Sleep */
    ti_lib_prcm_deep_sleep();

    /*
     * When we reach here, some interrupt woke us up. The global interrupt
     * flag is off, hence we have a chance to run things here. We will wake up
     * the chip properly, and then we will enable the global interrupt without
     * unpending events so the handlers can fire
     */
    wake_up();

    ti_lib_int_master_enable();
  }
}