From 5e14c22c983b3844216616a616fd641383032ff0 Mon Sep 17 00:00:00 2001 From: Antonio Lignan Date: Wed, 16 Dec 2015 18:57:28 +0100 Subject: [PATCH 1/2] Add support for the RE-Mote on-board power management feature --- examples/zolertia/zoul/power-mgmt/Makefile | 8 + .../zoul/power-mgmt/test-power-mgmt.c | 195 ++++++++++++++++ platform/zoul/remote/Makefile.remote | 2 +- platform/zoul/remote/board.h | 20 +- platform/zoul/remote/power-mgmt.c | 220 ++++++++++++++++++ platform/zoul/remote/power-mgmt.h | 187 +++++++++++++++ 6 files changed, 619 insertions(+), 13 deletions(-) create mode 100644 examples/zolertia/zoul/power-mgmt/Makefile create mode 100644 examples/zolertia/zoul/power-mgmt/test-power-mgmt.c create mode 100644 platform/zoul/remote/power-mgmt.c create mode 100644 platform/zoul/remote/power-mgmt.h diff --git a/examples/zolertia/zoul/power-mgmt/Makefile b/examples/zolertia/zoul/power-mgmt/Makefile new file mode 100644 index 000000000..c574add4f --- /dev/null +++ b/examples/zolertia/zoul/power-mgmt/Makefile @@ -0,0 +1,8 @@ +CONTIKI_PROJECT = test-power-mgmt + +TARGET = zoul + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/zolertia/zoul/power-mgmt/test-power-mgmt.c b/examples/zolertia/zoul/power-mgmt/test-power-mgmt.c new file mode 100644 index 000000000..aefc718bd --- /dev/null +++ b/examples/zolertia/zoul/power-mgmt/test-power-mgmt.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-examples + * @{ + * + * \defgroup remote-power-management-test RE-Mote power management example + * + * Test the RE-Mote's power management features, shutdown mode and battery + * management + * + * @{ + * + * \author + * Antonio Lignan + * Aitor Mejias + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "cpu.h" +#include "sys/etimer.h" +#include "sys/process.h" +#include "dev/leds.h" +#include "dev/sys-ctrl.h" +#include "dev/gpio.h" +#include "lib/list.h" +#include "power-mgmt.h" +#include +#include +/*---------------------------------------------------------------------------*/ +/* RE-Mote revision A */ +#define PM_EXPECTED_VERSION 0x00 +#define ENTER_SHUTDOWN_COUNT 10 +/*---------------------------------------------------------------------------*/ +PROCESS(test_remote_pm, "RE-Mote Power Management Test"); +AUTOSTART_PROCESSES(&test_remote_pm); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +static char * +print_pm(uint8_t state) +{ + switch(state) { + case PM_SYSOFF_ON: + return "Battery on"; + case PM_SYSOFF_OFF: + return "Battery off"; + case PM_TIMER_ENABLED: + return "Nano Timer enabled"; + case PM_TIMER_DISABLED: + return "Nano Timer disabled"; + case PM_AWAITING_RTC_EVENT: + return "Awaiting RTC event"; + default: + return "UNKNOWN"; + } +} +/*---------------------------------------------------------------------------*/ +static int8_t +get_status(uint8_t mask, uint8_t *val) +{ + uint8_t status, print_msg; + + /* Retrieve the status of the power management block */ + if(pm_get_state(&status) != PM_SUCCESS) { + printf("Failed to retrieve the power management status\n"); + return PM_ERROR; + } + + if(!mask) { + printf("STATUS %u\n", status); + *val = PM_IDLE; + return PM_SUCCESS; + } + + /* Read back ony the requested status bit */ + switch(mask) { + case PM_SYSOFF_ON_MASK: + print_msg = (status & mask) ? PM_SYSOFF_ON : PM_SYSOFF_OFF; + break; + case PM_TIMER_ENABLED_MASK: + print_msg = (status & mask) ? PM_TIMER_ENABLED : PM_TIMER_DISABLED; + break; + case PM_AWAITING_RTC_EVENT_MASK: + print_msg = (status & mask) ? PM_AWAITING_RTC_EVENT : PM_AWAITING_RTC_DIS; + break; + default: + return PM_ERROR; + } + + printf("Status -> %s\n", print_pm(print_msg)); + *val = print_msg; + return PM_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(test_remote_pm, ev, data) +{ + static uint8_t aux; + + PROCESS_BEGIN(); + + /* Configures the pins and initializes the driver */ + if(pm_init() != PM_SUCCESS) { + printf("Failed to initialize\n"); + PROCESS_EXIT(); + } + + /* Get the current firmware version to track the driver implementation on the + * low-power MCU + */ + if(pm_get_firmware_version(&aux) != PM_SUCCESS) { + printf("Failed to retrieve PIC's fw version\n"); + PROCESS_EXIT(); + } + printf("Firmware PIC-Power Manager Version: V0.%u\n", aux); + + if(aux != PM_EXPECTED_VERSION) { + printf("Unexpected firmware version\n"); + PROCESS_EXIT(); + } + + /* Enables the nano timer, the power management block will be driven by the + * nano timer now, putting the node in shutdown mode every minute (as + * default). For this test you need to disconnect the USB cable off to power + * the RE-Mote ONLY from the external battery, so after veryfing the above + * works, disconnect the USB cable and hit the reset button + * When the nano timer is enabled, the external battery is shutdown for a + * couple of usecs, so the CC2538 is restarted. After this as the nano timer + * is enabled, then it will run as intended + */ + + if(get_status(PM_TIMER_ENABLED_MASK, &aux) != PM_SUCCESS) { + PROCESS_EXIT(); + } + + if(aux == PM_TIMER_DISABLED) { + printf("Enabling the nano Timer...\n"); + if(pm_enable_timer() != PM_SUCCESS) { + printf("Failed to set the nano Timer\n"); + PROCESS_EXIT(); + } + } + + /* At this point as the RE-Mote is powered over USB you should see the prints, + * disconnect the USB cable and power only with the external battery. If + * something fails, then you should not see the red LED blinking + */ + aux = 0; + + while(1){ + etimer_set(&et, CLOCK_SECOND); + PROCESS_WAIT_EVENT(); + aux++; + + /* Enter shutdown mode before the shutdown period (1 min) expires */ + if((aux % ENTER_SHUTDOWN_COUNT) == 0) { + /* Say goodnight */ + PM_SHUTDOWN_NOW; + printf("Goodnight!\n"); + } + + leds_toggle(LEDS_RED); + } + + PROCESS_END(); +} + diff --git a/platform/zoul/remote/Makefile.remote b/platform/zoul/remote/Makefile.remote index b7c469840..11f5ebe3a 100644 --- a/platform/zoul/remote/Makefile.remote +++ b/platform/zoul/remote/Makefile.remote @@ -1,2 +1,2 @@ MOTELIST_ZOLERTIA = remote -BOARD_SOURCEFILES += board.c antenna-sw.c rtcc.c +BOARD_SOURCEFILES += board.c antenna-sw.c rtcc.c power-mgmt.c diff --git a/platform/zoul/remote/board.h b/platform/zoul/remote/board.h index 2578ec544..a249ff1bf 100644 --- a/platform/zoul/remote/board.h +++ b/platform/zoul/remote/board.h @@ -348,31 +348,27 @@ /** @} */ /*---------------------------------------------------------------------------*/ /** - * \name Shutdown Mode + * \name Power management and shutdown mode * * The shutdown mode is an ultra-low power operation mode that effectively * powers-down the entire RE-Mote (CC2538, CC1200, attached sensors, etc) and * only keeps running a power gating timer (NanoTimer), the on-board RTC and * an ultra-low power consumption MCU (PIC12F635). The Shutdown mode allows: * - * - Put the RE-Mote in an ultra-low power sleep (shutdown) drawing 350nA avg. + * - Put the RE-Mote in an ultra-low power sleep (shutdown) drawing <200nA avg. * - Periodically awake and execute tasks, being the shutdown period selectable * via R47 resistor value (22KOhm as default for 1 minute shutdown period). - * - Enter shutdown mode before the shutdown period expiration, by sending a - * pulse to SHUTDOWN_DONE. - * - * To enable or disable the shutdown mode a well-known sequence has to be sent - * to the PIC12F635 via its 1-Wire pin, when the shutdown mode is enabled, - * confirmation is done by the PIC echoing-back the command to the CC2538. + * - Enter shutdown mode before the shutdown period expiration, by invoking the + * PM_SHUTDOWN_NOW macrp * * The shutdown mode can be disabled by hardware by short-circuiting or placing * an 0Ohm resistor across W1 pad. * @{ */ -#define SHUTDOWN_DONE_PORT GPIO_D_NUM -#define SHUTDOWN_DONE_PIN 0 -#define SHUTDOWN_ENABLE_PORT GPIO_D_NUM -#define SHUTDOWN_ENABLE_PIN 1 +#define PM_DONE_PORT GPIO_D_NUM +#define PM_DONE_PIN 0 +#define PM_CMD_PORT GPIO_D_NUM +#define PM_CMD_PIN 1 /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/platform/zoul/remote/power-mgmt.c b/platform/zoul/remote/power-mgmt.c new file mode 100644 index 000000000..b0a09100b --- /dev/null +++ b/platform/zoul/remote/power-mgmt.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-power-mgmt + * @{ + * + * RE-Mote power management and shutdown mode + * @{ + * + * \author + * Aitor Mejias + * Antonio Lignan + */ +/* -------------------------------------------------------------------------- */ +#include +#include +#include "contiki.h" +#include "dev/gpio.h" +#include "sys/rtimer.h" +#include "power-mgmt.h" +/* -------------------------------------------------------------------------- */ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/* -------------------------------------------------------------------------- */ +#define PM_CMD_LINE_SET GPIO_SET_PIN(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK) +#define PM_CMD_LINE_CLR GPIO_CLR_PIN(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK) +#define PM_CMD_LINE_READ GPIO_READ_PIN(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK) +#define PM_CMD_AS_OUTPUT GPIO_SET_OUTPUT(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK) +#define PM_CMD_AS_INPUT GPIO_SET_INPUT(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK) +/* -------------------------------------------------------------------------- */ +#define PM_NUMBITS(X) (1 << ((X) - 1)) +/* -------------------------------------------------------------------------- */ +static uint8_t initialized = 0; +static uint8_t getData = 0; +/* -------------------------------------------------------------------------- */ +static int8_t +pm_get_ack(void) +{ + uint16_t error = PM_ERROR; + PM_CMD_AS_INPUT; + clock_delay_usec(PM_3_MILISECOND); + if(PM_CMD_LINE_READ) { + error = PM_SUCCESS; + } + + clock_delay_usec(PM_10_MILISECOND); + PM_CMD_AS_OUTPUT; + return error; +} +/* -------------------------------------------------------------------------- */ +static int8_t +pm_send_cmd(uint8_t cmd) +{ + uint8_t i; + + PRINTF("PM: cmd %u\n", cmd); + + /* Enter command mode */ + PM_CMD_LINE_SET; + clock_delay_usec(PM_1_MILISECOND); + PM_CMD_LINE_CLR; + + /* Send command */ + for (i = PM_MAX_BITS; i > 0; i--) { + clock_delay_usec(PM_1_MILISECOND); + + if (cmd & PM_NUMBITS(i)) { + PM_CMD_LINE_SET; + } + else PM_CMD_LINE_CLR; + } + + clock_delay_usec(PM_1_MILISECOND); + PM_CMD_LINE_CLR; + + /* Receive command reply if any */ + if((cmd == PM_CMD_GET_STATE) || (cmd == PM_CMD_GET_FW_VERSION)) { + PM_CMD_AS_INPUT; + clock_delay_usec(PM_2_2_MILISECOND); + for (i = PM_MAX_BITS; i > 0; i--) { + clock_delay_usec(PM_1_MILISECOND); + PM_CMD_LINE_READ ? (getData |= PM_NUMBITS(i)) : (getData &= ~PM_NUMBITS(i)); + } + + PRINTF("PM: getData = 0x%02X\n", getData); + clock_delay_usec(PM_2_2_MILISECOND); + PM_CMD_AS_OUTPUT; + PM_CMD_LINE_CLR; + + clock_delay_usec(PM_2_2_MILISECOND); + + return PM_SUCCESS; + } + + /* Default case */ + clock_delay_usec(PM_1_MILISECOND); + + return pm_get_ack(); +} +/* -------------------------------------------------------------------------- */ +int8_t +pm_init(void) +{ + /* Configure and clear immediately */ + GPIO_SOFTWARE_CONTROL(PM_DONE_PORT_BASE, PM_DONE_PIN_MASK); + GPIO_SET_OUTPUT(PM_DONE_PORT_BASE, PM_DONE_PIN_MASK); + GPIO_CLR_PIN(PM_DONE_PORT_BASE, PM_DONE_PIN_MASK); + + /* Set as output/low to set IDLE state */ + GPIO_SOFTWARE_CONTROL(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK); + PM_CMD_AS_OUTPUT; + PM_CMD_LINE_CLR; + + /* Ensure the battery charger is on, so we don't lock ourselves out and left + * stranded in a state the CC2538 and components are kept off + */ + + if(pm_send_cmd(PM_CMD_PWR_ON) == PM_SUCCESS) { + initialized = 1; + PRINTF("PM: Initialized\n"); + return PM_SUCCESS; + } + + PRINTF("PM: Failed to initialize\n"); + return PM_ERROR; +} +/* -------------------------------------------------------------------------- */ +int8_t +pm_enable_timer(void) +{ + if(!initialized) { + return PM_ERROR; + } + + if(pm_send_cmd(PM_CMD_DTIMER_ON) == PM_SUCCESS) { + return PM_SUCCESS; + } + return PM_ERROR; +} +/* -------------------------------------------------------------------------- */ +int8_t +pm_disable_timer(void) +{ + if(!initialized) { + return PM_ERROR; + } + + if(pm_send_cmd(PM_CMD_DTIMER_OFF) == PM_SUCCESS) { + return PM_SUCCESS; + } + return PM_ERROR; +} +/* -------------------------------------------------------------------------- */ +int8_t +pm_get_state(uint8_t *state) +{ + if(!initialized) { + return PM_ERROR; + } + + if(pm_send_cmd(PM_CMD_GET_STATE) == PM_SUCCESS) { + *state = getData; + PRINTF("PM: state %u\n", getData); + + return PM_SUCCESS; + } + return PM_ERROR; +} +/* -------------------------------------------------------------------------- */ +int8_t +pm_get_firmware_version(uint8_t *state) +{ + if(!initialized) { + return PM_ERROR; + } + + if (pm_send_cmd(PM_CMD_GET_FW_VERSION) == PM_SUCCESS) { + *state = getData; + printf("PM: FW Version %u\n", getData); + return PM_SUCCESS; + } + return PM_ERROR; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/zoul/remote/power-mgmt.h b/platform/zoul/remote/power-mgmt.h new file mode 100644 index 000000000..0504f9dba --- /dev/null +++ b/platform/zoul/remote/power-mgmt.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote + * @{ + * + * \defgroup remote-power-mgmt RE-Mote power management driver + * + * The power management module is composed by a nano-watt (gating) timer and an + * ultra-low power MCU, driving the RE-Mote power supply when connected to an + * external battery, and allowing an application to enter a so-called "shutdown + * mode". + * While in shutdown mode, only the RTCC and the power management block is on, + * effectively reducing the RE-Mote power consumption down to <~200nA. The + * nano Timer allows the RE-Mote to be awaken off shutdown mode after a given + * period (from 100ms to 2 hours, default is 1 minute). To change the shutdown + * period, the R47 resistor (at the DELAY input pin, see the RE-Mote datasheet) + * has to be changed. + * See the TPL5110 datasheet ((Table 2 and 3) for more information about the R47 + * resistor value, below is a table resuming most common periods: + * + * +------------+------------+ + * | R47 (Ohm) | Time | + * +------------+------------+ + * | 500 | 100ms | + * +------------+------------+ + * | 2.5K | 500ms | + * +------------+------------+ + * | 5.202K | 1s | + * +------------+------------+ + * | 22.021K | 1min | + * +------------+------------+ + * | 42.887K | 5min | + * +------------+------------+ + * | 57.434K | 10min | + * +------------+------------+ + * | 92.233K | 30min | + * +------------+------------+ + * | 170K | 2h | + * +------------+------------+ + * + * An application can enter the shutdown mode before the shutdown period expires + * by invoking the PM_SHUTDOWN_NOW macro. + * The on-board RTCC can also be used to drive the CC2538 off PM3 power mode, if + * the application requires to retain RAM. Note that while in shutdown mode the + * RE-Mote will be powered off. + * + * @{ + * + * \file + * Header file for the RE-Mote Power Management driver + */ +/* -------------------------------------------------------------------------- */ +#ifndef POWER_MGMT_H_ +#define POWER_MGMT_H_ +#include "dev/gpio.h" +/* -------------------------------------------------------------------------- */ +#define PM_CMD_PORT_BASE GPIO_PORT_TO_BASE(PM_CMD_PORT) +#define PM_CMD_PIN_MASK GPIO_PIN_MASK(PM_CMD_PIN) +#define PM_DONE_PORT_BASE GPIO_PORT_TO_BASE(PM_DONE_PORT) +#define PM_DONE_PIN_MASK GPIO_PIN_MASK(PM_DONE_PIN) +/* -------------------------------------------------------------------------- */ +/** \name Power Management return values + * @{ + */ +#define PM_SUCCESS 0 +#define PM_ERROR (-1) +#define PM_MAX_BITS 8 +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name Power Management "done" signal + * @{ + */ +#define PM_SHUTDOWN_NOW GPIO_SET_PIN(PM_DONE_PORT_BASE, PM_DONE_PIN_MASK) +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name Power Management timing values + * @{ + */ +#define PM_1_MILISECOND 1000L +#define PM_2_2_MILISECOND 2200L +#define PM_3_MILISECOND 3000L +#define PM_10_MILISECOND 10000L +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name Power Management commands + * @{ + */ +typedef enum { + PM_CMD_PWR_ON = 0x34, + PM_CMD_PWR_OFF = 0x35, + PM_CMD_RST_HARD = 0x36, + PM_CMD_RST_TIMED = 0x37, /* Not implemented */ + PM_CMD_DTIMER_ON = 0x38, + PM_CMD_DTIMER_OFF = 0x39, + PM_CMD_DTIMER_TIMED = 0x3A, /* Not implemented */ + PM_CMD_PARAM_SET_MAX_TIME = 0x3B, /* Not implemented */ + PM_CMD_GET_STATE = 0x3C, + PM_CMD_GET_FW_VERSION = 0x3D, + PM_MAX_NUM_CMDS +} pm_cmd_t; +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name Power Management status and masks + * @{ + */ +typedef enum { + PM_IDLE, + PM_SYSOFF_OFF, + PM_SYSOFF_ON, + PM_TIMER_DISABLED, + PM_TIMER_ENABLED, + PM_AWAITING_RTC_DIS, /* Not implemented */ + PM_AWAITING_RTC_EVENT, /* Not implemented */ +} pm_state_t; + +#define PM_SYSOFF_ON_MASK 0x01 +#define PM_TIMER_ENABLED_MASK 0x02 +#define PM_AWAITING_RTC_EVENT_MASK 0x04 + +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name Power Management functions + * @{ + */ +/** \brief Initializes the Power Management driver + * \return \c PM_SUCCESS if initialized, else \c PM_ERROR + */ +int8_t pm_init(void); +/* -------------------------------------------------------------------------- */ +/** \brief Enable the shutdown mode, periodically driven by the Nano Timer + * \return \c PM_SUCCESS if successful, else \c PM_ERROR + */ +int8_t pm_enable_timer(void); +/* -------------------------------------------------------------------------- */ +/** \brief Disable the Nano Timer + * \return \c PM_SUCCESS if successful, else \c PM_ERROR + */ +int8_t pm_disable_timer(void); +/* -------------------------------------------------------------------------- */ +/** \brief Get the current state of the power management module + * \param state Pointer to a variable to save the state + * \return \c PM_SUCCESS if successful, else \c PM_ERROR + */ +int8_t pm_get_state(uint8_t *state); +/* -------------------------------------------------------------------------- */ +/** \brief Get the firmware version of the power management module + * \param state Pointer to a variable to save the state + * \return \c PM_SUCCESS if successful, else \c PM_ERROR + */ +int8_t pm_get_firmware_version(uint8_t *state); +/* -------------------------------------------------------------------------- */ +/** @} */ +#endif /* POWER_MGMT_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ From 36ddb737e16712e46baa87c56207244ef9b00f72 Mon Sep 17 00:00:00 2001 From: Antonio Lignan Date: Tue, 22 Dec 2015 15:16:55 +0100 Subject: [PATCH 2/2] Refactored the example to broadcast a message to the zoul-demo example --- examples/zolertia/zoul/Makefile | 2 +- examples/zolertia/zoul/power-mgmt/Makefile | 8 ---- examples/zolertia/zoul/project-conf.h | 2 +- .../zoul/{power-mgmt => }/test-power-mgmt.c | 39 +++++++++++++++---- examples/zolertia/zoul/zoul-demo.c | 7 +++- 5 files changed, 39 insertions(+), 19 deletions(-) delete mode 100644 examples/zolertia/zoul/power-mgmt/Makefile rename examples/zolertia/zoul/{power-mgmt => }/test-power-mgmt.c (85%) diff --git a/examples/zolertia/zoul/Makefile b/examples/zolertia/zoul/Makefile index aa371757b..beef98880 100644 --- a/examples/zolertia/zoul/Makefile +++ b/examples/zolertia/zoul/Makefile @@ -1,5 +1,5 @@ DEFINES+=PROJECT_CONF_H=\"project-conf.h\" -CONTIKI_PROJECT = zoul-demo test-tsl2563 test-sht25 test-pwm +CONTIKI_PROJECT = zoul-demo test-tsl2563 test-sht25 test-pwm test-power-mgmt CONTIKI_TARGET_SOURCEFILES += tsl2563.c sht25.c all: $(CONTIKI_PROJECT) diff --git a/examples/zolertia/zoul/power-mgmt/Makefile b/examples/zolertia/zoul/power-mgmt/Makefile deleted file mode 100644 index c574add4f..000000000 --- a/examples/zolertia/zoul/power-mgmt/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -CONTIKI_PROJECT = test-power-mgmt - -TARGET = zoul - -all: $(CONTIKI_PROJECT) - -CONTIKI = ../../../.. -include $(CONTIKI)/Makefile.include diff --git a/examples/zolertia/zoul/project-conf.h b/examples/zolertia/zoul/project-conf.h index 9ff57c953..420d9a8e0 100644 --- a/examples/zolertia/zoul/project-conf.h +++ b/examples/zolertia/zoul/project-conf.h @@ -38,7 +38,7 @@ #ifndef PROJECT_CONF_H_ #define PROJECT_CONF_H_ -#define NETSTACK_CONF_RDC nullrdc_driver +#define BROADCAST_CHANNEL 129 #endif /* PROJECT_CONF_H_ */ diff --git a/examples/zolertia/zoul/power-mgmt/test-power-mgmt.c b/examples/zolertia/zoul/test-power-mgmt.c similarity index 85% rename from examples/zolertia/zoul/power-mgmt/test-power-mgmt.c rename to examples/zolertia/zoul/test-power-mgmt.c index aefc718bd..1b0690bdb 100644 --- a/examples/zolertia/zoul/power-mgmt/test-power-mgmt.c +++ b/examples/zolertia/zoul/test-power-mgmt.c @@ -29,11 +29,9 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup remote-examples + * \addtogroup remote-power-management-test * @{ * - * \defgroup remote-power-management-test RE-Mote power management example - * * Test the RE-Mote's power management features, shutdown mode and battery * management * @@ -53,6 +51,8 @@ #include "dev/gpio.h" #include "lib/list.h" #include "power-mgmt.h" +#include "net/rime/broadcast.h" + #include #include /*---------------------------------------------------------------------------*/ @@ -65,6 +65,17 @@ AUTOSTART_PROCESSES(&test_remote_pm); /*---------------------------------------------------------------------------*/ static struct etimer et; /*---------------------------------------------------------------------------*/ +static void +broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from) +{ + leds_toggle(LEDS_BLUE); + printf("*** Received %u bytes from %u:%u: '0x%04x'\n", packetbuf_datalen(), + from->u8[0], from->u8[1], *(uint16_t *)packetbuf_dataptr()); +} +/*---------------------------------------------------------------------------*/ +static const struct broadcast_callbacks bc_rx = { broadcast_recv }; +static struct broadcast_conn bc; +/*---------------------------------------------------------------------------*/ static char * print_pm(uint8_t state) { @@ -173,23 +184,37 @@ PROCESS_THREAD(test_remote_pm, ev, data) * disconnect the USB cable and power only with the external battery. If * something fails, then you should not see the red LED blinking */ - aux = 0; + aux = ENTER_SHUTDOWN_COUNT; + /* Open the broadcast channel */ + broadcast_open(&bc, BROADCAST_CHANNEL, &bc_rx); + + /* Send a message */ + packetbuf_copyfrom(&aux, sizeof(aux)); + broadcast_send(&bc); + + /* And wait a few seconds before going to sleep */ while(1){ etimer_set(&et, CLOCK_SECOND); PROCESS_WAIT_EVENT(); - aux++; - /* Enter shutdown mode before the shutdown period (1 min) expires */ - if((aux % ENTER_SHUTDOWN_COUNT) == 0) { + /* Enter shutdown mode before the shutdown period (1 min default) expires */ + if(!aux) { /* Say goodnight */ PM_SHUTDOWN_NOW; printf("Goodnight!\n"); + PROCESS_EXIT(); } + aux--; leds_toggle(LEDS_RED); } PROCESS_END(); } +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/zolertia/zoul/zoul-demo.c b/examples/zolertia/zoul/zoul-demo.c index a42ef2507..ff31d5ef9 100644 --- a/examples/zolertia/zoul/zoul-demo.c +++ b/examples/zolertia/zoul/zoul-demo.c @@ -73,6 +73,7 @@ #include "dev/watchdog.h" #include "dev/serial-line.h" #include "dev/sys-ctrl.h" +#include "net/netstack.h" #include "net/rime/broadcast.h" #include @@ -86,8 +87,6 @@ #define LEDS_SERIAL_IN LEDS_GREEN #define LEDS_REBOOT LEDS_ALL #define LEDS_RF_RX (LEDS_YELLOW | LEDS_RED) -#define BROADCAST_CHANNEL 129 - #define BUTTON_PRESS_EVENT_INTERVAL (CLOCK_SECOND) /*---------------------------------------------------------------------------*/ static struct etimer et; @@ -121,6 +120,10 @@ PROCESS_THREAD(zoul_demo_process, ev, data) PROCESS_BEGIN(); counter = 0; + + /* Disable the radio duty cycle and keep the radio on */ + NETSTACK_MAC.off(1); + broadcast_open(&bc, BROADCAST_CHANNEL, &bc_rx); /* Configure the user button */