Basically, I implement code using uart0,uart1,ADC,I2C for EPROM and temperature chip, SPI for the external flash and lsm6dsl chip.
I use a Zephyr timer to keep a one second time base waking up the program for a main loop check if there is anything to be done and then going back to sleep.
Periodically, the temperature, accelerometer & ADC are all read and the results stored in the EEPROM.
Between samples all of those module should be inactive.
I tried using the pm_device_state_set() function on the high level devices (EEPROM , SI7050, ExternalFlash & LSM6DSL) but saw the code was not implemented.
pm_device_state_set(si7050_dev,device_power_state,NULL, NULL);
I then tried using the pm_device_state_set() function on the lower level I2C and SPI which did not return errors.
void ami_board_SwPMState(unsigned char which,uint32_t device_power_state)
{
#if defined(CONFIG_BOARD_NRF9160AXION_NRF9160NS)
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
const struct device *dev;
switch (which){
case AMI_BOARD_DEV_SPI3:
dev = spi_3_dev;
break;
case AMI_BOARD_DEV_I2C2:
dev = i2c_2_dev;
break;
default:
return;
} // switch
if (dev!=NULL){
int err = pm_device_state_set(dev,device_power_state,NULL, NULL);
//-------------------------------------------------------------------------
// No error
//-------------------------------------------------------------------------
if (!err) {
Uart0 is used for printk and my debug information and also for incoming bytes in a direct serial connection for initial unit configuration, if needed after power up.
Uart1 is used for nRf52 BLE chip communications when needed. In battery operated mode the BLE chip is not powered.
I understand from the forum (many post are old and do not have used defines) that there is code to disable and enable the uarts dynamically in code.
It seems this does not work when asynch mode is used but only with the interrupt mode since a loop in the uart shutdown code hangs in asynch mode.
Below is my code for uart0. It seems to work but I do not know what conf file definitions I should use for both uaart0 & uart1.
//-----------------------------------------------------------------------------
// uart_CB
// Description
// Callback for async UART communication
// Parameters
// gps_data
// Returns
//-----------------------------------------------------------------------------
static void uart_cb(const struct device *x,void *user_data)
{
uart_irq_update(x);
int data_length = 0;
if (uart_irq_rx_ready(x)) {
data_length = uart_fifo_read(x, uart_buf, sizeof(uart_buf));
//-------------------------------------------------------------------------
// Make sure that there is no overflow
//-------------------------------------------------------------------------
...
}
bool ami_uart_boot_Init(void)
{
//---------------------------------------------------------------------------
// Bind UART
//---------------------------------------------------------------------------
uart_dev = device_get_binding("UART_0");
if (uart_dev == NULL) {
d_printf(LINE_INFO,kDbg_Info|kDbg_General,"Failed to get UART device\n");
return false;
}
//---------------------------------------------------------------------------
// Set Interrupt callback
//---------------------------------------------------------------------------
uart_irq_callback_set(uart_dev, uart_cb);
//---------------------------------------------------------------------------
// Enable RX interrupt enbale
//---------------------------------------------------------------------------
uart_irq_rx_enable(uart_dev);
//---------------------------------------------------------------------------
// Nothing to send
//---------------------------------------------------------------------------
atomic_set(&msg_to_send_direct_connect,0);
//---------------------------------------------------------------------------
// Set Boot driver is active
//---------------------------------------------------------------------------
bBootDriverActive = TRUE;
return TRUE;
} // ami_uart_boot_Init
//-----------------------------------------------------------------------------
// ami_uart_boot_ReInit
// Description
// Change RXD back to an input and reenable uart
// Parameters
// Returns
// TRUE = OK
//-----------------------------------------------------------------------------
bool ami_uart_boot_ReInit(void)
{
NRF_UARTE0_NS->ENABLE = 8;
NRF_UARTE0_NS->TASKS_STARTRX = 1;
NRF_UARTE0_NS->TASKS_STARTTX = 1;
//---------------------------------------------------------------------------
// Set Boot driver is active
//---------------------------------------------------------------------------
bBootDriverActive = TRUE;
return TRUE;
} //ami_uart_boot_ReInit
//-----------------------------------------------------------------------------
// ami_uart_boot_DeInit
// Description
//
// Parameters
// Returns
//-----------------------------------------------------------------------------
void ami_uart_boot_DeInit(void)
{
//---------------------------------------------------------------------------
// Turn off debug information in printk
//---------------------------------------------------------------------------
gDisablePrintk = true;
//---------------------------------------------------------------------------
// Low power
// When putting the system in low power and the peripheral is not needed,
// lowest possible power consumption is achieved by stopping, and then disabling the peripheral.
// The STOPTX and STOPRX tasks may not be always needed (the peripheral might already be stopped),
// but if STOPTX and/or STOPRX is sent, software shall wait until the TXSTOPPED and/or RXTO event is received in response,
// before disabling the peripheral through the ENABLE register.
//---------------------------------------------------------------------------
NRF_UARTE0_NS->TASKS_STOPRX=1;
while(NRF_UARTE0_NS->EVENTS_RXTO == 0);
NRF_UARTE0_NS->EVENTS_RXTO = 0;
NRF_UARTE0_NS->TASKS_STOPTX = 1;
while(NRF_UARTE0_NS->EVENTS_TXSTOPPED == 0);
NRF_UARTE0_NS->EVENTS_TXSTOPPED = 0;
NRF_UARTE0_NS->ENABLE = 0;
NRF_UARTE0_NS->PSEL.TXD = 0xFFFFFFFF;
//---------------------------------------------------------------------------
// Set BOOT Txd P0.1
//---------------------------------------------------------------------------
NRF_P0_NS->OUTSET = (1 << 1);
//---------------------------------------------------------------------------
// Set BOOT Rxd P0.0
//---------------------------------------------------------------------------
NRF_P0_NS->OUTSET = (1 << 0);
//---------------------------------------------------------------------------
// RXD is now an input change to an output high!
//---------------------------------------------------------------------------
// ?!? ami_board_ConfigPin( AMI_BOARD_OUT_BOOT_RXD,GPIO_OUTPUT_HIGH);
//---------------------------------------------------------------------------
// Set Boot driver is NOT active
//---------------------------------------------------------------------------
bBootDriverActive = FALSE;
//---------------------------------------------------------------------------
// Cancel staying awake because of Debug & Direct connect
//---------------------------------------------------------------------------
ami_main_CancelStayAwake(AQUA_MAIN_AWAKE_BOOT_DIRECT | AQUA_MAIN_AWAKE_DEBUG);
} // ami_uart_boot_DeInit
This morning I performed some current tests with our hardware guy (Meeting).
ADC:
I left the ADC in the overlay file "okay" but did not reference it in my code and the current was about 900ua.
I called adc_channel_setup() and adc_read_async() every 3 minutes and the current was about 1000ua.
I set the ADC in the overlay file "disabled" and the current was also 900ua.
The base line current was when one uart was not stopped so may be the ADC is not being disabled automatically.
Uart0 & Uart1:
At startup I just disabled uart1 as above.
When after using uart0, when sleeping I did not call the uart0 disable code, I got the 900ua baseline current.
When after using uart0, when sleep I performed the uart0 code above, I got a 480ua to 490ua draw.
Again I use a timer that wakes the program up once a second and if nothing is needed to be done goes back to sleep.
Evidently something is still on.
Thanks David