XMega 128A1 Power Reduction PRE stops PORTQ wakeup. Why?

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I need some independent confirmation of what I think is an XMega128A1 chip bug. I have Rev H. parts.

I have a button hooked up to bit-2 of PORTQ. The button pulls to ground. There is an external pull-up resistor on this button. In the XMega bit-2 of most ports will asynchronously wake the part up from sleep, even if no clocks are running.

Using the code below, I found that if I set the bit to disable PORTE SPI in the PORTE Power Reduction register, then my asynchronous interrupt on PORTQ stops working. This makes no sense at all to me, PRE changes PORTQ???. Did I uncover another XMega bug, or am I missing something?

I can't try different bit-2's of other ports in my hardware. I'd be curious if other PR settings stop async. IRQ's from working on other ports, in your XMega hardware.

void hardware_sleep( void )
{
  /* I know that Interrupts are on when I get here: */
  AVR_ENTER_CRITICAL_REGION();

  hardware_setup();                       /* Put all I/O in known state */
  PORTA.PIN1CTRL = PORT_OPC_BUSKEEPER_gc; /* LOW_BAT_bm; Hold current state on Low Battery while sleeping */

  /* Turn off all unused subsystems in the Power Reduction registers: */
  PR.PRGEN  = (PR_AES_bm|PR_EBI_bm|PR_EVSYS_bm|PR_DMA_bm); /* RTC Is running */
  PR.PRPA   = (PR_DAC_bm|PR_ADC_bm|PR_AC_bm);
  PR.PRPB   = (PR_DAC_bm|PR_ADC_bm|PR_AC_bm);
  PR.PRPC   = (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm);
  PR.PRPD   = (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm);

//PR.PRPE   = (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm);/* This stops PORTQ Async. IRQ */
  PR.PRPE   = (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|          PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm);/* PORTQ wakes up */

  PR.PRPF   = (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm);

  CCPWrite(&MCU.MCUCR, MCU_JTAGD_bm);    /* Disables JTAG during sleep */

  PORTQ.OUT = 0;                                              /* No outputs on this port */
  PORTQ.PIN3CTRL =  PORT_OPC_PULLDOWN_gc;                     /* RevB PCBs have PQ3 grounded, so we can tell them apart from RevA */
  PORTQ.PIN2CTRL = (PORT_OPC_PULLUP_gc|PORT_ISC_FALLING_gc);  /* Pullup BUTTON_ALARM_bm, enabled falling Alarm button IRQ */
  PORTQ.INTCTRL  = PORT_INT0LVL_LO_gc;
  PORTQ.INT0MASK = BUTTON_ALARM_bm;
  PMIC.CTRL     |= PMIC_LOLVLEX_bm;

  SLEEP.CTRL  = (SLEEP_SMODE_PSAVE_gc|SLEEP_SEN_bm);    /* Set sleep mode to Power Save, asynchronous I/O wakeup, RTC runs if enabled, enable Sleep instruction */

  AVR_LEAVE_CRITICAL_REGION();

  sleep_cpu();                           /* AVR Sleep instruction */
  SLEEP.CTRL &= (uint8_t) ~SLEEP_SEN_bm; /* Disable Sleep instruction */

  CCPWrite( &RST.CTRL, RST_SWRST_bm );   /* Issue a Software Reset to initilize the CPU */
}