Example #1
0
static void stm32_idlepm(void)
{
  static enum pm_state_e oldstate = PM_NORMAL;
  enum pm_state_e newstate;
  int ret;

  /* The following is logic that is done after the wake-up from PM_STANDBY
   * state.  It decides whether to go back to the PM_NORMAL or to the deeper
   * power-saving mode PM_SLEEP:  If the alarm expired with no "normal"
   * wake-up event, then PM_SLEEP is entered.
   *
   * Logically, this code belongs at the end of the PM_STANDBY case below,
   * does not work in the position for some unkown reason.
   */

  if (oldstate == PM_STANDBY)
    {
      /* Were we awakened by the alarm? */

#ifdef CONFIG_RTC_ALARM
      if (g_alarmwakeup)
        {
          /* Yes.. Go to SLEEP mode */

          newstate = PM_SLEEP;
        }
      else
#endif
        {
          /* Resume normal operation */

          newstate = PM_NORMAL;
        }
    }
  else
    {
      /* Let the PM system decide, which power saving level can be obtained */

      newstate = pm_checkstate();
    }

  /* Check for state changes */

  if (newstate != oldstate)
    {
      llvdbg("newstate= %d oldstate=%d\n", newstate, oldstate);

      sched_lock();

      /* Force the global state change */

      ret = pm_changestate(newstate);
      if (ret < 0)
        {
          /* The new state change failed, revert to the preceding state */

          (void)pm_changestate(oldstate);

          /* No state change... */

          goto errout;
        }

      /* Then perform board-specific, state-dependent logic here */

      switch (newstate)
        {
        case PM_NORMAL:
          {
            /* If we just awakened from PM_STANDBY mode, then reconfigure
             * clocking.
             */

            if (oldstate == PM_STANDBY)
              {
                /* Re-enable clocking */

                stm32_clockenable();

                /* The system timer was disabled while in PM_STANDBY or
                 * PM_SLEEP modes.  But the RTC has still be running:  Reset
                 * the system time the current RTC time.
                 */

#ifdef CONFIG_RTC
                clock_synchronize();
#endif
              }
          }
          break;

        case PM_IDLE:
          {
          }
          break;

        case PM_STANDBY:
          {
            /* Set the alarm as an EXTI Line */

#ifdef CONFIG_RTC_ALARM
            stm32_rtc_alarm(CONFIG_PM_ALARM_SEC, CONFIG_PM_ALARM_NSEC, true);
#endif
            /* Wait 10ms */

            up_mdelay(10);

            /* Enter the STM32 stop mode */

            (void)stm32_pmstop(false);

            /* We have been re-awakened by some even:  A button press?
             * An alarm?  Cancel any pending alarm and resume the normal
             * operation.
             */

#ifdef CONFIG_RTC_ALARM
            stm32_exti_cancel();
            ret = stm32_rtc_cancelalarm();
            if (ret < 0)
              {
                lldbg("Warning: Cancel alarm failed\n");
              }
#endif
            /* Note:  See the additional PM_STANDBY related logic at the
             * beginning of this function.  That logic is executed after
             * this point.
             */
          }
          break;

        case PM_SLEEP:
          {
            /* We should not return from standby mode.  The only way out
             * of standby is via the reset path.
             */

            /* Configure the RTC alarm to Auto Reset the system */

#ifdef CONFIG_PM_SLEEP_WAKEUP
            stm32_rtc_alarm(CONFIG_PM_SLEEP_WAKEUP_SEC, CONFIG_PM_SLEEP_WAKEUP_NSEC, false);
#endif
            /* Wait 10ms */

            up_mdelay(10);

            /* Enter the STM32 standby mode */

            (void)stm32_pmstandby();
          }
          break;

        default:
          break;
        }

      /* Save the new state */

      oldstate = newstate;

errout:
      sched_unlock();
    }
}
int sam_bringup(void)
{
#ifdef HAVE_S25FL1
  FAR struct qspi_dev_s *qspi;
#endif
#if defined(HAVE_S25FL1) || defined(HAVE_PROGMEM_CHARDEV)
  FAR struct mtd_dev_s *mtd;
#endif
#if defined(HAVE_RTC_DSXXXX) || defined(HAVE_RTC_PCF85263)
  FAR struct i2c_master_s *i2c;
#endif
#if defined(HAVE_S25FL1_CHARDEV) || defined(HAVE_PROGMEM_CHARDEV)
  char blockdev[18];
  char chardev[12];
#endif
  int ret;

  /* Register I2C drivers on behalf of the I2C tool */

  sam_i2ctool();

#if defined(HAVE_RTC_PCF85263)
  /* Get an instance of the TWIHS0 I2C interface */

  i2c = sam_i2cbus_initialize(PCF85263_TWI_BUS);
  if (i2c == NULL)
    {
      SYSLOG("ERROR: sam_i2cbus_initialize(%d) failed\n", PCF85263_TWI_BUS);
    }
  else
    {
      /* Use the I2C interface to initialize the PCF2863 timer */

      ret = pcf85263_rtc_initialize(i2c);
      if (ret < 0)
        {
          SYSLOG("ERROR: pcf85263_rtc_initialize() failed: %d\n", ret);
        }
      else
        {
          /* Synchronize the system time to the RTC time */

          clock_synchronize();
        }
    }

#elif defined(HAVE_RTC_DSXXXX)
  /* Get an instance of the TWIHS0 I2C interface */

  i2c = sam_i2cbus_initialize(DSXXXX_TWI_BUS);
  if (i2c == NULL)
    {
      SYSLOG("ERROR: sam_i2cbus_initialize(%d) failed\n", DSXXXX_TWI_BUS);
    }
  else
    {
      /* Use the I2C interface to initialize the DSXXXX timer */

      ret = dsxxxx_rtc_initialize(i2c);
      if (ret < 0)
        {
          SYSLOG("ERROR: dsxxxx_rtc_initialize() failed: %d\n", ret);
        }
      else
        {
          /* Synchronize the system time to the RTC time */

          clock_synchronize();
        }
    }
#endif

#ifdef HAVE_MACADDR
  /* Read the Ethernet MAC address from the AT24 FLASH and configure the
   * Ethernet driver with that address.
    */

  ret = sam_emac0_setmac();
  if (ret < 0)
    {
      SYSLOG("ERROR: sam_emac0_setmac() failed: %d\n", ret);
    }
#endif

#ifdef CONFIG_FS_PROCFS
  /* Mount the procfs file system */

  ret = mount(NULL, SAMV71_PROCFS_MOUNTPOINT, "procfs", 0, NULL);
  if (ret < 0)
    {
      SYSLOG("ERROR: Failed to mount procfs at %s: %d\n",
             SAMV71_PROCFS_MOUNTPOINT, ret);
    }
#endif

#ifdef HAVE_MTDCONFIG
  /* Create an AT24xx-based MTD configuration device for storage device
   * configuration information.
   */

  ret = sam_at24config();
  if (ret < 0)
    {
      SYSLOG("ERROR: sam_at24config() failed: %d\n", ret);
    }
#endif

#ifdef HAVE_HSMCI
  /* Initialize the HSMCI0 driver */

  ret = sam_hsmci_initialize(HSMCI0_SLOTNO, HSMCI0_MINOR);
  if (ret < 0)
    {
      SYSLOG("ERROR: sam_hsmci_initialize(%d,%d) failed: %d\n",
             HSMCI0_SLOTNO, HSMCI0_MINOR, ret);
    }

#ifdef CONFIG_SAMV71XULT_HSMCI0_MOUNT
  else
    {
      /* REVISIT:  A delay seems to be required here or the mount will fail. */
      /* Mount the volume on HSMCI0 */

      ret = mount(CONFIG_SAMV71XULT_HSMCI0_MOUNT_BLKDEV,
                  CONFIG_SAMV71XULT_HSMCI0_MOUNT_MOUNTPOINT,
                  CONFIG_SAMV71XULT_HSMCI0_MOUNT_FSTYPE,
                  0, NULL);

      if (ret < 0)
        {
          SYSLOG("ERROR: Failed to mount %s: %d\n",
                 CONFIG_SAMV71XULT_HSMCI0_MOUNT_MOUNTPOINT, errno);
        }
    }

#endif /* CONFIG_SAMV71XULT_HSMCI0_MOUNT */
#endif /* HAVE_HSMCI */

#ifdef HAVE_AUTOMOUNTER
  /* Initialize the auto-mounter */

  sam_automount_initialize();
#endif

#ifdef HAVE_ROMFS
  /* Create a ROM disk for the /etc filesystem */

  ret = romdisk_register(CONFIG_SAMV71XULT_ROMFS_ROMDISK_MINOR, romfs_img,
                         NSECTORS(romfs_img_len),
                         CONFIG_SAMV71XULT_ROMFS_ROMDISK_SECTSIZE);
  if (ret < 0)
    {
      SYSLOG("ERROR: romdisk_register failed: %d\n", -ret);
    }
  else
    {
      /* Mount the file system */

      ret = mount(CONFIG_SAMV71XULT_ROMFS_ROMDISK_DEVNAME,
                  CONFIG_SAMV71XULT_ROMFS_MOUNT_MOUNTPOINT,
                  "romfs", MS_RDONLY, NULL);
      if (ret < 0)
        {
          SYSLOG("ERROR: mount(%s,%s,romfs) failed: %d\n",
                 CONFIG_SAMV71XULT_ROMFS_ROMDISK_DEVNAME,
                 CONFIG_SAMV71XULT_ROMFS_MOUNT_MOUNTPOINT, errno);
        }
    }
#endif

#ifdef HAVE_S25FL1
  /* Create an instance of the SAMV71 QSPI device driver */

  qspi = sam_qspi_initialize(0);
  if (!qspi)
    {
      SYSLOG("ERROR: sam_qspi_initialize failed\n");
    }
  else
    {
      /* Use the QSPI device instance to initialize the
       * S25FL1 device.
       */

      mtd = s25fl1_initialize(qspi, true);
      if (!mtd)
        {
          SYSLOG("ERROR: s25fl1_initialize failed\n");
        }

#ifdef HAVE_S25FL1_SMARTFS
      /* Configure the device with no partition support */

      ret = smart_initialize(S25FL1_SMART_MINOR, mtd, NULL);
      if (ret != OK)
        {
          SYSLOG("ERROR: Failed to initialize SmartFS: %d\n", ret);
        }

#elif defined(HAVE_S25FL1_NXFFS)
      /* Initialize to provide NXFFS on the S25FL1 MTD interface */

      ret = nxffs_initialize(mtd);
      if (ret < 0)
        {
         SYSLOG("ERROR: NXFFS initialization failed: %d\n", ret);
        }

      /* Mount the file system at /mnt/s25fl1 */

      ret = mount(NULL, "/mnt/s25fl1", "nxffs", 0, NULL);
      if (ret < 0)
        {
          SYSLOG("ERROR: Failed to mount the NXFFS volume: %d\n", errno);
          return ret;
        }

#else /* if  defined(HAVE_S25FL1_CHARDEV) */
      /* Use the FTL layer to wrap the MTD driver as a block driver */

      ret = ftl_initialize(S25FL1_MTD_MINOR, mtd);
      if (ret < 0)
        {
          SYSLOG("ERROR: Failed to initialize the FTL layer: %d\n", ret);
          return ret;
        }

      /* Use the minor number to create device paths */

      snprintf(blockdev, 18, "/dev/mtdblock%d", S25FL1_MTD_MINOR);
      snprintf(chardev, 12, "/dev/mtd%d", S25FL1_MTD_MINOR);

      /* Now create a character device on the block device */

      ret = bchdev_register(blockdev, chardev, false);
      if (ret < 0)
        {
          SYSLOG("ERROR: bchdev_register %s failed: %d\n", chardev, ret);
          return ret;
        }
#endif
    }
#endif

#ifdef HAVE_PROGMEM_CHARDEV
  /* Initialize the SAMV71 FLASH programming memory library */

  sam_progmem_initialize();

  /* Create an instance of the SAMV71 FLASH program memory device driver */

  mtd = progmem_initialize();
  if (!mtd)
    {
      SYSLOG("ERROR: progmem_initialize failed\n");
    }

  /* Use the FTL layer to wrap the MTD driver as a block driver */

  ret = ftl_initialize(PROGMEM_MTD_MINOR, mtd);
  if (ret < 0)
    {
      SYSLOG("ERROR: Failed to initialize the FTL layer: %d\n", ret);
      return ret;
    }

  /* Use the minor number to create device paths */

  snprintf(blockdev, 18, "/dev/mtdblock%d", PROGMEM_MTD_MINOR);
  snprintf(chardev, 12, "/dev/mtd%d", PROGMEM_MTD_MINOR);

  /* Now create a character device on the block device */

  ret = bchdev_register(blockdev, chardev, false);
  if (ret < 0)
    {
      SYSLOG("ERROR: bchdev_register %s failed: %d\n", chardev, ret);
      return ret;
    }
#endif

#ifdef HAVE_USBHOST
  /* Initialize USB host operation.  sam_usbhost_initialize() starts a thread
   * will monitor for USB connection and disconnection events.
   */

  ret = sam_usbhost_initialize();
  if (ret != OK)
    {
      SYSLOG("ERROR: Failed to initialize USB host: %d\n", ret);
    }
#endif

#ifdef HAVE_USBMONITOR
  /* Start the USB Monitor */

  ret = usbmonitor_start(0, NULL);
  if (ret != OK)
    {
      SYSLOG("ERROR: Failed to start the USB monitor: %d\n", ret);
    }
#endif

#ifdef HAVE_WM8904
  /* Configure WM8904 audio */

  ret = sam_wm8904_initialize(0);
  if (ret != OK)
    {
      SYSLOG("ERROR: Failed to initialize WM8904 audio: %d\n", ret);
    }
#endif

#ifdef HAVE_AUDIO_NULL
  /* Configure the NULL audio device */

  ret = sam_audio_null_initialize(0);
  if (ret != OK)
    {
      SYSLOG("ERROR: Failed to initialize the NULL audio device: %d\n", ret);
    }
#endif

#ifdef HAVE_ELF
  /* Initialize the ELF binary loader */

  SYSLOG("Initializing the ELF binary loader\n");
  ret = elf_initialize();
  if (ret < 0)
    {
      SYSLOG("ERROR: Initialization of the ELF loader failed: %d\n", ret);
    }
#endif

  /* If we got here then perhaps not all initialization was successful, but
   * at least enough succeeded to bring-up NSH with perhaps reduced
   * capabilities.
   */

  UNUSED(ret);
  return OK;
}