Wakeup From UART
Requirements
This example has been made with GAP9, and EvalKit Board 2.0, and an external UART device. For pads numbers, please refer to the documentation of EvalKit Board version 2.0. Please note that the TX & RTS pads must be Always On so they can be controlled during sleep.
Description
This example shows how to wake up gap9 from light sleep, using an external UART device.
As you can see on this example, we open an UART device, and use it. Then we go into ligt sleep, by asking to be wake up from the external UART device on the RX pin. When receiving a byte on this pin, gap9 will wake up and will be back where we stopped. Before continuing as before, we need to do two things:
Setting pads back to their configuration
Getting the UART device back (restoring the link to the instance)
Once we do these two steps, we can use our UART again as before.
How to use
As you can see in the upper description, to wake up gap9, a byte must be sent on
the RX pin. To do so, use your external UART device, and send a byte through the
UART. To finish the example, please send BUFFER_SIZE
bytes, at least.
How to run
First, flash the code on the MRAM:
cmake -B build
cmake --build build -t flash
Then, put boot pads to the MRAM configuration, and run your application by pressing the reset button on the EvalKit Board.
Limitations
Be aware that using an UART link to wake up GAP will not prevent to lose some bytes if you send a frame. Only one byte is useful to wake up GAP! During sleep the UART FIFO is not configured and so the bytes, following the first one, will be lost while the FIFO is not configured back.
On the example you can see #define BYTES_LOST
to define the number of bytes
that are lost at wake up. This define depends of the baudrate.
Code
/*
* Copyright (c) GreenWaves Technologies 2022
* All rights reserved.
*/
/*
* Example wake up from UART on light sleep
*
* Please, read the README to get more information on what this example does,
* and how to use it.
*/
// Global include
#include "pmsis.h"
// DEFINES
#define UART_ID 0
#define BUFFER_SIZE ( 16 * 3 )
#define BYTES_LOST 33 // Bytes lost while RTS is still low. Do not read them. Depend of the baudrate !
#define PAD_UART0_RX ( PI_PAD_067 ) // CN2 Pin 6
#define PAD_UART0_TX ( PI_PAD_041 ) // CN3 Pin 8
#define PAD_UART0_RTS ( PI_PAD_042 ) // CN4 Pin 10
#define PAD_UART0_CTS ( PI_PAD_034 ) // CN2 Pin 4
// Global variable
PI_L2 uint8_t buffer[BUFFER_SIZE];
/*
* Functions
*/
static void setup_fc_pads(void)
{
pi_pad_function_set(PAD_UART0_CTS, PI_PAD_FUNC0);
pi_pad_function_set(PAD_UART0_RTS, PI_PAD_FUNC0);
pi_pad_mux_group_set(PAD_UART0_CTS, PI_PAD_MUX_GROUP_UART0_CTS);
/* PI_PAD_MUX_GROUP_UART0_CTS is by default on pad 62
* Changing its function to prevent conflicts
*/
pi_pad_function_set(PI_PAD_062, PI_PAD_FUNC0);
pi_pad_mux_group_set(PI_PAD_062, PI_PAD_MUX_GROUP_PWM7);
pi_pad_mux_group_set(PAD_UART0_RTS, PI_PAD_MUX_GROUP_UART0_RTS);
/* PI_PAD_MUX_GROUP_UART0_RTS is by default on pad 63
* Changing its function to prevent conflicts
*/
pi_pad_function_set(PI_PAD_063, PI_PAD_FUNC0);
pi_pad_mux_group_set(PI_PAD_063, PI_PAD_MUX_GROUP_PWM7);
}
static void setup_pads(void)
{
pi_pad_function_set(PAD_UART0_RX, PI_PAD_FUNC0);
pi_pad_function_set(PAD_UART0_TX, PI_PAD_FUNC0);
pi_pad_mux_group_set(PAD_UART0_RX, PI_PAD_MUX_GROUP_UART0_RX);
/* PI_PAD_MUX_GROUP_UART0_RX is available by default on pad 60
* We need to set another function (with a lower priority) to this pad 60 to
* prevent conflits
*/
pi_pad_function_set(PI_PAD_060, PI_PAD_FUNC0);
pi_pad_mux_group_set(PI_PAD_060, PI_PAD_MUX_GROUP_PWM7);
pi_pad_mux_group_set(PAD_UART0_TX, PI_PAD_MUX_GROUP_UART0_TX);
/* PI_PAD_MUX_GROUP_UART0_TX is by default on pad 61
* Changing its function to prevent conflicts
*/
pi_pad_function_set(PI_PAD_061, PI_PAD_FUNC0);
pi_pad_mux_group_set(PI_PAD_061, PI_PAD_MUX_GROUP_PWM7);
if (CONFIG_EXAMPLE_UART_FC == 1)
setup_fc_pads();
}
static int8_t light_sleep(pi_device_t *uart)
{
printf("Going to light sleep\n");
// Set source for wakeup
if (pi_uart_ioctl(uart, PI_UART_IOCTL_CHIP_WAKEUP_UART_RX, (void *) PAD_UART0_RX))
{
printf("This UART RX pad (%d) can not be configured as a wake up source \
from uart\n", PAD_UART0_RX);
return -1;
}
// Configure AO pads for sleep
// TX -> output to high value
pi_pad_sleep_cfg_set(PAD_UART0_TX, PI_PAD_SLEEP_CFG_OUTPUT_ENABLED | PI_PAD_SLEEP_CFG_OUTPUT_VALUE_1);
// RTS -> output to low value
pi_pad_sleep_cfg_set(PAD_UART0_RTS, PI_PAD_SLEEP_CFG_OUTPUT_ENABLED);
// Force AO pads to their sleep mode configuration to force RTS pad to 0
pi_pad_sleep_cfg_force(1);
// Set sleep mode and go to sleep
pi_pmu_domain_state_change(PI_PMU_DOMAIN_CHIP, PI_PMU_DOMAIN_STATE_LIGHT_SLEEP, 0);
/*
* At wake up we will fall back here
*/
printf("Back from light sleep\n");
return 0;
}
/*
* Main function
* Returned values:
* 0 = Success
* -1 = Error in configuration
* -2 = Error with light sleep
*/
int main(void)
{
printf("\n*** Entering main controller ***\n\n");
printf("*** Example wake up from UART ***\n");
// Before using uart, pads must be set properly
setup_pads();
// Configuring UART and oppening it
pi_device_t uart;
struct pi_uart_conf conf;
pi_uart_conf_init(&conf);
conf.baudrate_bps = CONFIG_EXAMPLE_UART_BPS;
conf.enable_tx = 1;
conf.enable_rx = 1;
conf.uart_id = UART_ID;
conf.use_ctrl_flow = CONFIG_EXAMPLE_UART_FC;
conf.rts_pad = PAD_UART0_RTS;
conf.use_fast_clk = 1;
pi_open_from_conf(&uart, &conf);
if (pi_uart_open(&uart))
{
printf("ERROR - Failed to open uart\n");
return -1;
}
// Using UART
for (uint8_t i = 0; i < BUFFER_SIZE; i++)
{
buffer[i] = i;
}
pi_uart_write(&uart, buffer, BUFFER_SIZE);
/*
* Here you should have received "buffer" data on your external UART
* device.
*/
memset(buffer, '\0', BUFFER_SIZE);
// Going to light sleep
if (light_sleep(&uart))
{
return -2;
}
/*
* After light sleep we need to do two things:
* - Setting pads back to their configuration
* - Gettting UART device back
*/
setup_pads();
pi_uart_ioctl(&uart, PI_UART_IOCTL_DEVICE_GET, (void *) UART_ID);
/*
* Then we can continue our app
*/
// Get data on UART
pi_uart_read(&uart, buffer, BUFFER_SIZE-BYTES_LOST);
printf("Received: %s\n", buffer);
// END
printf("END of the example\n");
return 0;
}
# Board and platform selection
CONFIG_BOARD_GAP9MOD_V1_0_B=y
CONFIG_BOARD_GAP9EVK_V2_0=y
CONFIG_PLATFORM_BOARD=y
# Mandatory
CONFIG_SLEEP_WITH_RETENTION=y
CONFIG_DRIVER_TYPE_FLASH=y
CONFIG_DRIVER_MRAM=y
CONFIG_DRIVER_MRAM_AS_DEFAULT=y
CONFIG_BOOT_DEVICE_MRAM=y
CONFIG_DRIVER_UDMAUART=y
# Options
CONFIG_EXAMPLE_UART_BPS=921600
CONFIG_EXAMPLE_UART_FC=y
CONFIG_IO_TYPE_DISABLED=y
#CONFIG_IO_TYPE_UART=y
#CONFIG_IO_UART_ITF_1=y