BRT Community

General Category => Discussion - MCU => Topic started by: A.STARR@NIWA.CO.NZ on May 06, 2021, 04:42:37 AM

Title: GPIO interrupt wakeup from power-down mode
Post by: A.STARR@NIWA.CO.NZ on May 06, 2021, 04:42:37 AM
I have successfully used the code below (at the start of main() ) to set the FT908 to wake from power-down mode with a falling edge on GPIO57:

Code: [Select]

gpio_function(57, pad_gpio57);
gpio_dir(57, pad_dir_input);
gpio_pull(57, pad_pull_pullup);
interrupt_attach(interrupt_gpio, (uint8_t)interrupt_gpio, ISR_gpio);
gpio_interrupt_enable(57, gpio_int_edge_falling);
interrupt_enable_globally();
SYS->PMCFG_L &= ~MASK_SYS_PMCFG_PM_PWRDN_MODE;
SYS->PMCFG_L |= MASK_SYS_PMCFG_PM_PWRDN;

However, when I change the GPIO pin from 57 to 49 (making the appropriate code changes), the FT908 will no longer wake up. Is it not possible to use GPIO49 for this? I'd like to wake the FT908 from power-down on receiving a break character on UART0, which is why want to use UART0_RXD/GPIO49 (I have had no luck trying to use the UART0 interrupt to wake the system).
The idea being that once the system is awake, the code then reconfigures GPIO49 to UART0_RXD and enables UART0.

Any suggestions appreciated, thanks
Title: Re: GPIO interrupt wakeup from power-down mode
Post by: A.STARR@NIWA.CO.NZ on May 06, 2021, 06:27:04 AM
Actually, after further testing I've discovered that the FT908 is in fact coming out of power-down mode on receiving the falling edge of a break character on GPIO49. But I've had to put a for..next loop immediately after the power-down command, or else UART0 doesn't seem to work. Is this because the system takes some time to come out of power-down mode?

Code: [Select]
   
gpio_function(49, pad_gpio49);
gpio_dir(49, pad_dir_input);
gpio_pull(49, pad_pull_pullup);
interrupt_attach(interrupt_gpio, (uint8_t)interrupt_gpio, ISR_gpio);
gpio_interrupt_enable(49, gpio_int_edge_falling);
interrupt_enable_globally();
SYS->PMCFG_L &= ~MASK_SYS_PMCFG_PM_PWRDN_MODE;
SYS->PMCFG_L |= MASK_SYS_PMCFG_PM_PWRDN;

for(unsigned long i=0; i<3000; i++);

/* Enable the UART Device... */
sys_enable(sys_device_uart0);

/* Make GPIO48 function as UART0_TXD and GPIO49 function as UART0_RXD... */
gpio_function(48, pad_uart0_txd); /* UART0 TXD */
gpio_function(49, pad_uart0_rxd); /* UART0 RXD */
gpio_function(50, pad_uart0_rts); /* UART0 RTS */
gpio_function(51, pad_uart0_cts); /* UART0 CTS */
uart_open(UART0,                    /* Device */
1,                        /* Prescaler = 1 */
UART_DIVIDER_1200_BAUD,
uart_data_bits_8,         /* No. Data Bits */
uart_parity_none,         /* Parity */
uart_stop_bits_1);        /* No. Stop Bits */

uartrb_setup(UART0, uartrb_flow_none); //flow control handled in uartrb code

etc.

My next problem is that the power-down seems to trash my DLOG partition:

Code: [Select]
void load_config(void)
{
   int pgsz, pages;

   dlog_init( __dlog_partition, &pgsz, &pages);
   dlog_read (CONF_PAGE, (uint32_t *)confbuf);
   memcpy(&conf, confbuf, sizeof(struct Conf));
   if((conf.start != START_MARKER_VAL) || (conf.stop != END_MARKER_VAL))
   {
      memcpy(&conf, &default_conf, sizeof(struct Conf));
      save_config();
   }
}

load_config() is called straight after UART0 is initialised, and reads a page of data from the DLOG partition and uses it to populate a Conf struct. It appears to crash at the first memcpy after dlog_read(). Could the problem be power-down mode not preserving the RAM?

Note: load_config() works fine if I remove the power-down code.

Thanks again
Title: Re: GPIO interrupt wakeup from power-down mode
Post by: A.STARR@NIWA.CO.NZ on May 07, 2021, 05:40:44 AM
I found that by replacing the memcpy() calls in load_config() with a loop that uses pointers to copy the data, everything is fine.

However, now UART0 is not responding to incoming characters (I am using the uartrb code). It appears that the UART0 receive interrupt is not working. The application is still running, as I can still see messages printed from UART0 (e.g. in a continuous loop), but uartrb_available(UART0) returns no available characters.

Just to be clear, the problems don't appear unless I uncomment the following two lines near the start of main():

Code: [Select]
SYS->PMCFG_L &= ~MASK_SYS_PMCFG_PM_PWRDN_MODE;
SYS->PMCFG_L |= MASK_SYS_PMCFG_PM_PWRDN;

The idea is, the system goes into power-down on entry to main, waiting for an interrupt on GPIO49. When I send a serial character, a falling edge brings it out of power-down mode, configures UART0 for interrupt-driven buffered comms (uartrb), and prints a message. This all works fine except incoming serial characters are not being placed in the ring buffer.

It looks as though power-down mode is causing some serious problems. Any advice on this (including detailed information about what power-down actually does - there is not much in the documentation) would be greatly appreciated.
Title: Re: GPIO interrupt wakeup from power-down mode
Post by: BRT Community on May 07, 2021, 04:28:01 PM
Hello,
 
There is existing code GPIO wakeup code available with the toolchain which you can use for reference.
 
This is specifically taken from D2XX Example 1 (see AN_360 FT900 Example Applications (http://brtchip.com/wp-content/uploads/Support/Documentation/Application_Notes/ICs/MCU/AN-360-FT9xx-Example-Applications.pdf)).
The code can be found at the following location as part of the IDE:
 
C:\Users\Username\Documents\Bridgetek\FT9xx\Version\Examples\D2XX Example 1
 
#ifdef GPIO_REMOTE_WAKEUP
SetRemoteWakeup = 0;
if (RemoteWakeupEnable)
{
tfp_printf("d2xx_loopback_test1: Configuring GPIO pin to wakeup \r\n");
#if 1
/* Set up the pin */
gpio_dir(GPIO_PIN, pad_dir_input);
gpio_pull(GPIO_PIN, pad_pull_pullup);
 
 /* Attach an interrupt */
gpio_interrupt_enable(GPIO_PIN, gpio_int_edge_falling);
interrupt_attach(interrupt_gpio, (uint8_t)interrupt_gpio, ISR_gpio);
tfp_printf("d2xx_loopback_test1: GPIO pin setup for interrupt\r\n");
#endif
}
 
#endif
 
D2XXTEST__Sleep = 1;
D2XXTEST__Wakeup = 0;
 
/* Power down Mode */
SYS->PMCFG_L |= MASK_SYS_PMCFG_PM_PWRDN_MODE;
SYS->PMCFG_L |= MASK_SYS_PMCFG_PM_PWRDN;
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
 
 //wait for wakeup
 while(!D2XXTEST__Wakeup);
 
interrupt_disable_globally();
 
#ifdef GPIO_REMOTE_WAKEUP
gpio_interrupt_disable(GPIO_PIN);
interrupt_detach(interrupt_gpio);
gpio_is_interrupted(GPIO_PIN);
 
#endif
 
SYS->PMCFG_L &= ~MASK_SYS_PMCFG_PM_PWRDN_MODE;
SYS->PMCFG_L &= ~MASK_SYS_PMCFG_PM_PWRDN;

The contents in RAM should not be lost, as this is a standby mode and not POWER ON RESET.

The datalogger feature uses the on-chip flash in the FT9XX for storage.
More information can be found in AN 365 FT9xx API Programmers Manual (http://brtchip.com/wp-content/uploads/Support/Documentation/Programming_Guides/ICs/MCU/AN_365-FT9xx-API-Programmers-Manual.pdf) section 2.34 Datalogger Feature.
Example datalogger code can also be found in the Toolchain examples.

Best Regards,
BRT Community
Title: Re: GPIO interrupt wakeup from power-down mode
Post by: A.STARR@NIWA.CO.NZ on May 10, 2021, 12:43:48 AM
All working - superb!

Thanks very much