查看: 4819|回复: 1

[原创] 【经验分享】唤醒源咋不靠谱?

[复制链接]

该用户从未签到

656

主题

6312

帖子

0

超级版主

Rank: 8Rank: 8

积分
20205
最后登录
2024-5-11
发表于 2018-4-25 17:21:18 | 显示全部楼层 |阅读模式
本帖最后由 小恩GG 于 2018-4-25 17:23 编辑

唤醒源咋不靠谱?
Ø 问题描述
        客户碰到如下问题:
        LPC11U68 的[url=http://www.nxp.com/support/developer-resources/software-development-tools/lpc-developer-resources-/lpcopen-libraries-and-examples/lpcopen-software-development-platform-lpc11xxPCOPEN-SOFTWARE-FOR-LPC11XX]LPCOpen软件包[/url]中存在periph_pinint例程,演示了引脚中断唤醒sleep模式下的MCU的应用过程。并且在参考手册UM10732中,更是提到引脚中断可以用于唤醒Deep-sleep和Power-down模式下的MCU(如图1所示),所以客户根据参考手册的说明修正了periph_pinint例程后,进行了测试(如下所示),但结果并没有如参考手册所讲,引脚中断没有唤醒Deep-sleep和Power-down模式下的MCU。

2018-04-25_16-32-59.jpg

图 1
  
#include  "board.h"
  
  
/* Mapped to PIO0_1, ISP_EN  button on LPCXpresso board */
  #define GPIO_PININT_PIN 0 /* GPIO pin number mapped to PININT */
  #define GPIO_PININT_PORT 1 /* GPIO port number mapped to PININT */
  #define GPIO_PININT_INDEX 0 /* PININT index used for GPIO mapping */
  
  
void  PIN_INT0_IRQHandler(void)
  {
        Chip_PININT_ClearIntStatus(LPC_PININT,  PININTCH(GPIO_PININT_INDEX));
        //Board_LED_Toggle(0);
  }
  
  
int main(void)
  {
  uint32_t i,num;
  
SystemCoreClockUpdate();
  Board_Init();
  Board_LED_Set(0, 0);
  
  
//P1.0 Interrupt Wakeup---------------------------------------------------------------------------------------------
  /* We'll use an optional IOCON filter (0) with a divider of 64 for the
  input pin to be used for PININT */
  Chip_Clock_SetIOCONFiltClockDiv(0, 64);
  
  
/* Configure GPIO pin as  input */
  Chip_GPIO_SetPinDIRInput(LPC_GPIO, GPIO_PININT_PORT, GPIO_PININT_PIN);
  
  
/* Configure pin as GPIO  with pullup and use optional IOCON divider
  0 with 3 filter clocks for input filtering */
  Chip_IOCON_PinMuxSet(LPC_IOCON, GPIO_PININT_PORT, GPIO_PININT_PIN,
  (IOCON_FUNC0 | IOCON_MODE_PULLUP | IOCON_CLKDIV(0) | IOCON_S_MODE(3)));
  
  
/* Enable PININT clock */
  Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_PINT);
  
  
/* Configure interrupt  channel for the GPIO pin in SysCon block */
  Chip_SYSCTL_SetPinInterrupt(GPIO_PININT_INDEX, GPIO_PININT_PORT,  GPIO_PININT_PIN);
  
Chip_SYSCTL_EnableStartPin(0);
  
  
/* Configure channel  interrupt as edge sensitive and falling edge interrupt */
  Chip_PININT_ClearIntStatus(LPC_PININT, PININTCH(GPIO_PININT_INDEX));
  Chip_PININT_SetPinModeEdge(LPC_PININT, PININTCH(GPIO_PININT_INDEX));
  Chip_PININT_EnableIntLow(LPC_PININT, PININTCH(GPIO_PININT_INDEX));
  
  
/* Enable interrupt in the  NVIC */
  NVIC_ClearPendingIRQ(PIN_INT0_IRQn);
  NVIC_EnableIRQ(PIN_INT0_IRQn);
  
  
Board_LED_Set(0, 1);
  for (i = 0; i < 4000000; i++);
  for (i = 0; i < 4000000; i++);
  for (i = 0; i < 4000000; i++);
  Board_LED_Set(0, 0);
  
  
num = 1; //Select sleep  mode 0:sleep 1:deep sleep
  
  
/* Go to sleep mode - LED  will toggle on each wakeup event */
  while (1)
  {
        //sleep LED
        Board_LED_Set(2, 1);
        for (i = 0; i < 1800000; i++);
        Board_LED_Set(2, 0);
  
      switch  (num)
        {
           case 0:
                 DEBUGOUT("sleep  mode\r\n\r\n");
                 for  (i = 0; i < 1800000; i++);
  
               Chip_PMU_SleepState(LPC_PMU);
  
               DEBUGOUT("sleep  mode-WAKEUP\r\n\r\n");
                 for  (i = 0; i < 1800000; i++);
                 break;
          case 1:
                 DEBUGOUT("Deep  Sleep mode\r\n\r\n");
                 for  (i = 0; i < 1800000; i++);
  
  
               /*  We can optionally call Chip_SYSCTL_SetDeepSleepPD() to power down the
                 BOD  and WDT if we aren't using them in deep sleep modes. */
                 Chip_SYSCTL_SetDeepSleepPD(SYSCTL_DEEPSLP_BOD_PD  | SYSCTL_DEEPSLP_WDTOSC_PD);
  
  
               /*  We should call Chip_SYSCTL_SetWakeup() to setup any peripherals we want
                    to  power back up on wakeup. For this example, we'll power back up the IRC,
                 FLASH,  the system oscillator, and the PLL */
                 Chip_SYSCTL_SetWakeup(~(SYSCTL_SLPWAKE_IRCOUT_PD  | SYSCTL_SLPWAKE_IRC_PD |
                 SYSCTL_SLPWAKE_FLASH_PD  | SYSCTL_SLPWAKE_SYSOSC_PD |                 SYSCTL_SLPWAKE_SYSPLL_PD));
  
  
               /*  Enter MCU Deep Sleep mode */
                 Chip_PMU_DeepSleepState(LPC_PMU);
  
  
               /*  Power anything back up here that isn't powered up on wakeup. The example
                 code  below powers back up the BOD and WDT oscillator, which weren't setup to
                  power  up in the Chip_SYSCTL_SetWakeup() function. */
                 Chip_SYSCTL_SetDeepSleepPD(0);
  
  
                DEBUGOUT("Deep  Sleep mode-WAKEUP\r\n\r\n");
                 for  (i = 0; i < 1800000; i++);
  
               break;
           }
  
      }
  
return 0;
  
}
  
  
Ø 问题解决
        通过现象复现,基本上确认了引脚中断唤醒Deep-sleep和Power-down模式下的MCU是无效,后面会进一步求证是文档书写错误还是漏写了某些步骤,而目前只能使用其他解决方案,比如:GroupedGPIO 输入中断,实现代码如下:

  
#include  "board.h"
  
  
/*****************************************************************************
  
* Private types/enumerations/variables
  
****************************************************************************/
  
  
  
/* These two inputs for  GROUP GPIO Interrupt 0. */
  
#define  LEFT_SWITCH_PORT    0
  
#define  LEFT_SWITCH_BIT     1
  
#define UP_SWITCH_PORT      0
  
#define UP_SWITCH_BIT       16
  
  
  
/*****************************************************************************
  
* Public types/enumerations/variables
  
****************************************************************************/
  
  
/*****************************************************************************
  
* Private functions
  
****************************************************************************/
  
  
/*****************************************************************************
  
* Public functions
  
****************************************************************************/
  
  
/**
  
* @brief     Handle  Group GPIO 0 interrupt
  
* @return   Nothing
  
*/
  
void GINT0_IRQHandler(void)
  
{
  
          Chip_GPIOGP_ClearIntStatus(LPC_GPIOGROUP, 0);
  
          Board_LED_Toggle(0);
  
}
  
  
/**
  
* @brief     Handle  Group GPIO 1 interrupt
  
* @return   Nothing
  
*/
  
void GINT1_IRQHandler(void)
  
{
  
          Chip_GPIOGP_ClearIntStatus(LPC_GPIOGROUP, 1);
  
          Board_LED_Toggle(1);
  
}
  
  
/**
  
* @brief     Main  program body
  
* @return   Does  not return
  
*/
  
int main(void)
  
{
  
          /* Generic Initialization */
  
          SystemCoreClockUpdate();
  
  
          /* Board_Init calls Chip_GPIO_Init and enables GPIO clock  if needed,
  
             Chip_GPIO_Init  is not called again */
  
          Board_Init();
  
          Board_LED_Set(0, false);
  
  
          /* Group GPIO interrupt 0 will be invoked when both the  joystick up
  
             switch and left  switch are pressed. */
  
          Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GROUP0INT);
  
          Chip_GPIO_SetPinDIRInput(LPC_GPIO, LEFT_SWITCH_PORT,  LEFT_SWITCH_BIT);
  
          Chip_GPIO_SetPinDIRInput(LPC_GPIO, UP_SWITCH_PORT,  UP_SWITCH_BIT);
  
          Chip_GPIOGP_SelectLowLevel(LPC_GPIOGROUP, 0,  LEFT_SWITCH_PORT, 1 << LEFT_SWITCH_BIT);
  
          Chip_GPIOGP_SelectLowLevel(LPC_GPIOGROUP, 0,  UP_SWITCH_PORT, 1 << UP_SWITCH_BIT);
  
          Chip_GPIOGP_EnableGroupPins(LPC_GPIOGROUP, 0,  LEFT_SWITCH_PORT, 1 << LEFT_SWITCH_BIT);
  
          Chip_GPIOGP_EnableGroupPins(LPC_GPIOGROUP, 0,  UP_SWITCH_PORT, 1 << UP_SWITCH_BIT);
  
          Chip_GPIOGP_SelectOrMode(LPC_GPIOGROUP, 0);
  
          Chip_GPIOGP_SelectEdgeMode(LPC_GPIOGROUP, 0);
  
  
     Chip_SYSCTL_EnablePeriphWakeup(SYSCTL_WAKEUP_GPIOINT0);
  
  
          /* Enable Group GPIO interrupt 0 */
  
          NVIC_EnableIRQ(GINT0_IRQn);
  
  
    /* We can optionally call  Chip_SYSCTL_SetDeepSleepPD() to power down the
  
       BOD and WDT if we aren't using them in  deep sleep modes. */
  
    Chip_SYSCTL_SetDeepSleepPD(SYSCTL_DEEPSLP_BOD_PD  | SYSCTL_DEEPSLP_WDTOSC_PD);
  
  
    /* We should call Chip_SYSCTL_SetWakeup()  to setup any peripherals we want
  
       to power back up on wakeup. For this  example, we'll power back up the IRC,
  
       FLASH, the system oscillator, and the  PLL */
  
     Chip_SYSCTL_SetWakeup(~(SYSCTL_SLPWAKE_IRCOUT_PD |  SYSCTL_SLPWAKE_IRC_PD |
  
                             SYSCTL_SLPWAKE_FLASH_PD | SYSCTL_SLPWAKE_SYSOSC_PD |  SYSCTL_SLPWAKE_SYSPLL_PD));
  
  
    /* Enter MCU Power down mode */
  
    Chip_PMU_PowerDownState(LPC_PMU);
  
  
          /* Stay in sleep mode.   All the work is done in ISRs. */
  
          while (1) {
  
                   /* Go to sleep state - will wake up  automatically on interrupt */
  
          //       Chip_PMU_SleepState(LPC_PMU);
  
          }
  
  
          /* Does not return */
  
          return 0;
  
}
  

唤醒源咋不靠谱?.pdf (272.79 KB, 下载次数: 8)
回复

使用道具 举报

  • TA的每日心情
    郁闷
    2021-6-16 01:35
  • 签到天数: 521 天

    [LV.9]以坛为家II

    1

    主题

    707

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1783
    最后登录
    2021-6-16
    发表于 2018-4-27 10:44:06 | 显示全部楼层
    感謝小恩GG大大
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-5-11 10:40 , Processed in 0.140190 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表