/* * Copyright (c) 2016, 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-revb-test * @{ * * Test the RE-Mote's power management features, shutdown mode and battery * management. * * @{ * * \author * Aitor Mejias * Antonio Lignan */ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "cpu.h" #include "sys/process.h" #include "dev/leds.h" #include "dev/sys-ctrl.h" #include "lib/list.h" #include "power-mgmt.h" #include "rtcc.h" #include #include #include /*---------------------------------------------------------------------------*/ static struct etimer et; /*---------------------------------------------------------------------------*/ /* RE-Mote revision B, low-power PIC version */ #define PM_EXPECTED_VERSION 0x20 /*---------------------------------------------------------------------------*/ #define TEST_LEDS_FAIL leds_off(LEDS_ALL); \ leds_on(LEDS_RED); \ PROCESS_EXIT(); /*---------------------------------------------------------------------------*/ #define TEST_ALARM_SECOND 15 /*---------------------------------------------------------------------------*/ PROCESS(test_remote_pm, "RE-Mote rev.B Power Management Test"); AUTOSTART_PROCESSES(&test_remote_pm); /*---------------------------------------------------------------------------*/ static uint8_t rtc_buffer[sizeof(simple_td_map)]; static simple_td_map *simple_td = (simple_td_map *)rtc_buffer; /*---------------------------------------------------------------------------*/ PROCESS_THREAD(test_remote_pm, ev, data) { static uint8_t aux; static uint16_t voltage; static uint32_t cycles; PROCESS_BEGIN(); aux = 0; cycles = 0; /* Initialize the power management block and signal the low-power PIC */ if(pm_enable() != PM_SUCCESS) { printf("PM: Failed to initialize\n"); TEST_LEDS_FAIL; } printf("PM: enabled!\n"); /* Retrieve the firmware version and check expected */ if((pm_get_fw_ver(&aux) == PM_ERROR) || (aux != PM_EXPECTED_VERSION)) { printf("PM: unexpected version 0x%02X\n", aux); TEST_LEDS_FAIL; } printf("PM: firmware version 0x%02X OK\n", aux); /* Read the battery voltage level */ if(pm_get_voltage(&voltage) != PM_SUCCESS) { printf("PM: error retrieving voltage\n"); TEST_LEDS_FAIL; } printf("PM: Voltage (raw) = %u\n", voltage); /* Note: if running the following test while the RE-Mote is powered over USB * will show the command execution, but it will not put the board in shutdown * mode. If powering the RE-Mote with an external battery the shutdown mode * will operate as intended, and the RE-Mote will restart and run the tests * from the start after waking-up off the shutdown mode. * * The first test shows how to use the "soft" shutdown mode, being the low * power PIC the one counting cycles and restarting the system off shutdown * mode. * * Each restart cycle is tracked by the low-power PIC, we can use this value * to determine how many times we have entered shutdown mode, thus choosing * a specific configuration or behaviour. For the next examples we are going * to trigger a "soft" mode each even number, and "hard" if odd. */ cycles = pm_get_num_cycles(); printf("PM: cycle number %lu\n", cycles); if((cycles % 2) == 0) { /* Set the timeout */ if(pm_set_timeout(PM_SOFT_SHTDN_5_7_SEC) != PM_SUCCESS) { printf("PM: error setting timeout for soft shutdown mode\n"); TEST_LEDS_FAIL; } printf("PM: Soft shutdown, timeout set to %lu\n", pm_get_timeout()); leds_off(LEDS_ALL); leds_on(LEDS_PURPLE); /* Wait just enough to be able to check the LED result */ etimer_set(&et, CLOCK_SECOND * 3); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); /* Enter soft shut*/ if(pm_shutdown_now(PM_SOFT_SLEEP_CONFIG) == PM_SUCCESS) { printf("PM: Good night!\n"); } else { printf("PM: error shutting down the system!\n"); TEST_LEDS_FAIL; } /* Exit and wait the next cycle */ PROCESS_EXIT(); } /* Configure the RTCC to schedule a "hard" restart of the shutdown mode, * waking up from a RTCC interrupt to the low-power PIC */ printf("PM\n"); if(rtcc_get_time_date(simple_td) == AB08_ERROR) { printf("PM: Couldn't read time and date\n"); TEST_LEDS_FAIL; } printf("PM: Configured time: "); rtcc_print(RTCC_PRINT_DATE_DEC); /* Configure the RTCC to trigger an alarm tick */ printf("\nPM: Setting an alarm to tick in %u seconds\n", TEST_ALARM_SECOND); if(rtcc_date_increment_seconds(simple_td, TEST_ALARM_SECOND) == AB08_ERROR) { printf("PM: could not increment the next alarm date\n"); TEST_LEDS_FAIL; } /* Set the timeout to zero to avoid the PIC being awake while waiting for the * RTCC system to kick-in */ if(pm_set_timeout(0x00) != PM_SUCCESS) { printf("PM: couldn't clear the shutdown period\n"); TEST_LEDS_FAIL; } /* We use the RTCC_REPEAT_DAY as we want the RTCC to match the given date */ if(rtcc_set_alarm_time_date(simple_td, RTCC_ALARM_ON, RTCC_REPEAT_DAY, RTCC_TRIGGER_INT2) == AB08_ERROR) { printf("PM: couldn't set the alarm\n"); TEST_LEDS_FAIL; } printf("PM: Alarm set to match: "); rtcc_print(RTCC_PRINT_ALARM_DEC); leds_off(LEDS_ALL); leds_on(LEDS_BLUE); etimer_set(&et, CLOCK_SECOND * 3); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); if(pm_shutdown_now(PM_HARD_SLEEP_CONFIG) == PM_SUCCESS) { printf("PM: good night!\n"); } else { printf("PM: error shutting down the system!\n"); TEST_LEDS_FAIL; } PROCESS_END(); } /*---------------------------------------------------------------------------*/ /** * @} * @} */