diff --git a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx index 15d971004..6922b45fc 100644 --- a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -68,8 +68,8 @@ CONTIKI_CPU_DIRS += ../arm/common/dbg-io ### CPU-dependent source files CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c soc-rtc.c uart.c -CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c -CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c +CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c aux-ctrl.c +CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c adc-sensor.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c oscillators.c CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c diff --git a/cpu/cc26xx-cc13xx/dev/adc-sensor.c b/cpu/cc26xx-cc13xx/dev/adc-sensor.c new file mode 100644 index 000000000..3ccf90e6d --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/adc-sensor.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bristol.ac.uk + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 cc26xx-adc-sensor + * @{ + * + * \file + * Driver for the CC13xx/CC26xx ADC + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/adc-sensor.h" +#include "gpio-interrupt.h" +#include "sys/timer.h" +#include "lpm.h" + +#include "ti-lib.h" +#include "driverlib/aux_adc.h" +#include "aux-ctrl.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +static uint8_t channel = ADC_COMPB_IN_AUXIO0; +static bool is_active = false; + +static aux_consumer_module_t adc_aux = { + .clocks = AUX_WUC_ADI_CLOCK | AUX_WUC_ANAIF_CLOCK | AUX_WUC_SMPH_CLOCK +}; +/*---------------------------------------------------------------------------*/ +static int +config(int type, int c) +{ + switch(type) { + case SENSORS_ACTIVE: + is_active = c; + + if(is_active) { + /* Request AUX access, with ADI and SMPH clocks */ + aux_ctrl_register_consumer(&adc_aux); + + ti_lib_aux_adc_select_input(channel); + } else { + aux_ctrl_unregister_consumer(&adc_aux); + } + break; + + case ADC_SENSOR_SET_CHANNEL: + channel = c; + if(is_active) { + ti_lib_aux_adc_select_input(channel); + } + break; + + default: + break; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + if(is_active) { + return 1; + } + break; + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + if(type == ADC_SENSOR_VALUE) { + int val; + + if(!is_active) { + puts("ADC not active"); + return 0; + } + + ti_lib_aux_adc_enable_sync(AUXADC_REF_FIXED, AUXADC_SAMPLE_TIME_2P7_US, + AUXADC_TRIGGER_MANUAL); + + ti_lib_aux_adc_gen_manual_trigger(); + val = ti_lib_aux_adc_read_fifo(); + + ti_lib_aux_adc_disable(); + + return val; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, config, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx-cc13xx/dev/adc-sensor.h b/cpu/cc26xx-cc13xx/dev/adc-sensor.h new file mode 100644 index 000000000..fd8f71537 --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/adc-sensor.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bristol.ac.uk + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 cc26xx + * @{ + * + * \defgroup cc26xx-adc-sensor CC13xx/CC26xx ADC Sensor + * @{ + * + * \file + * Header file for the CC13xx/CC26xx ADC driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef ADC_SENSOR_H_ +#define ADC_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define ADC_SENSOR "ADC" +/*---------------------------------------------------------------------------*/ +#define ADC_SENSOR_VALUE 0 +/*---------------------------------------------------------------------------*/ +/* configuration commands */ +#define ADC_SENSOR_SET_CHANNEL 1 /* takes ADC_COMPB_IN_AUXIxx as parameter */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor adc_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* ADC_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx-cc13xx/dev/aux-ctrl.c b/cpu/cc26xx-cc13xx/dev/aux-ctrl.c new file mode 100644 index 000000000..eb316d3df --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/aux-ctrl.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.ac.uk/ + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/aux-ctrl.h" +#include "lib/list.h" + +#include "ti-lib.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +LIST(consumers_list); +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_register_consumer(aux_consumer_module_t *consumer) +{ + bool interrupts_disabled = ti_lib_int_master_disable(); + + list_add(consumers_list, consumer); + + aux_ctrl_power_up(); + + ti_lib_aux_wuc_clock_enable(consumer->clocks); + while(ti_lib_aux_wuc_clock_status(consumer->clocks) != AUX_WUC_CLOCK_READY); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_unregister_consumer(aux_consumer_module_t *consumer) +{ + bool interrupts_disabled = ti_lib_int_master_disable(); + + list_remove(consumers_list, consumer); + + aux_ctrl_power_down(false); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_power_up() +{ + /* Don't if we have no consumers */ + if(list_head(consumers_list) == NULL) { + return; + } + + ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_WAKEUP); + while(!(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON)); +} +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_power_down(bool force) +{ + aux_consumer_module_t *consumer; + uint32_t clocks_in_use = 0; + + if(!force) { + /* Visit all modules and release clocks */ + for(consumer = list_head(consumers_list); consumer != NULL; + consumer = consumer->next) { + clocks_in_use |= consumer->clocks; + } + + /* If any clocks are still in use, AUX needs to stay powered and clocked */ + if(clocks_in_use) { + ti_lib_aon_wuc_aux_power_down_config(AONWUC_CLOCK_SRC_LF); + return; + } + } + + /* No clock for AUX in power down */ + ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); + + /* Disable retention */ + ti_lib_aon_wuc_aux_sram_config(false); + + /* Turn off AUX */ + ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_ALLOW_SLEEP); + ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); + while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx-cc13xx/dev/aux-ctrl.h b/cpu/cc26xx-cc13xx/dev/aux-ctrl.h new file mode 100644 index 000000000..8e65a7844 --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/aux-ctrl.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.ac.uk/ + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 cc26xx + * @{ + * + * \defgroup cc26xx-aux-ctrl CC13xx/CC26xx AUX domain controller + * + * CC13xx/CC26xx AUX domain power management controller + * + * @{ + * + * \file + * Header file for the management of the CC13xx/CC26xx AUX domain + */ +/*---------------------------------------------------------------------------*/ +#ifndef AUX_CTRL_H_ +#define AUX_CTRL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief The data structure to be used for modules that require access to AUX + * + * The clocks field should specify the clocks (within AUX) that your module + * requires in order to perform its functionality. Those clocks are an ORd + * value of AUX_WUC_xxxx_CLOCK. For instance, the oscillators module specifies + * AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + */ +typedef struct aux_consumer_module { + struct aux_consumer_module *next; + uint32_t clocks; +} aux_consumer_module_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Register a module that no longer requires access to the AUX power domain + * \param consumer A pointer to the data structure of your AUX consumer + * + * Call this function if you are developing a module that requires access to + * hardware within the AUX PD. Calling this function will achieve a number of + * things: + * + * - It will power up the AUX PD + * - It will enable the AUX clocks that you require + * + * If you call this function, AUX will stay powered-on and clocked during deep + * sleep, and retention will be enabled (so that you can e.g. use the sensor + * controller to monitor peripherals while the main MCU in deep sleep). If you + * do not need AUX enabled during deep sleep, you must release it by calling + * aux_ctrl_unregister_consumer() + * + * \sa aux_ctrl_unregister_consumer + */ +void aux_ctrl_register_consumer(aux_consumer_module_t *consumer); + +/** + * \brief Deregister a module that no longer requires access to the AUX power domain + * \param consumer A pointer to the data structure of your AUX consumer + * + * When your module is finished using features provided from within the AUX + * domain, you should call this function to signal that AUX is no longer + * required, so that the LPM module can power it down in deep sleep. If there + * are no more registered consumers left, this function will also power down + * AUX. + * + * \sa aux_ctrl_register_consumer + * \sa aux_ctrl_power_down + */ +void aux_ctrl_unregister_consumer(aux_consumer_module_t *consumer); + +/** + * \brief Power-up the AUX power domain + * + * This function will power up the AUX power-domain, but only if there are + * registered consumers for it. If there are not, the PD will stay off. + * + * This function will automatically get called by the LPM module whenever the + * chip comes out of deep sleep. + * + * User applications will normally not need to call this function. if you are + * developing a user application that requires access, to AUX, you should + * normally call aux_ctrl_register_consumer(), which will automatically power + * up AUX for you, if it's not already powered. + */ +void aux_ctrl_power_up(void); + +/** + * \brief Power down the AUX power domain + * \param force Force the power down irrespective of registered consumers + * + * This function will shut down the AUX power-domain. + * + * The shutdown is unconditional if force is true. If force is false and there + * are registered consumers, the power-down will be suppressed. + * + * This function will automatically get called by the LPM module whenever the + * chip tries to enter deep sleep or shuts down. + * + * User applications will normally not need to call this function. if you are + * developing a user application that no longer requires access, to AUX, you + * should normally simply release it by calling aux_ctrl_unregister_consumer(). + * If no other consumers are using AUX, then the lpm module will shut it down. + */ +void aux_ctrl_power_down(bool force); +/*---------------------------------------------------------------------------*/ +#endif /* AUX_CTRL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx-cc13xx/dev/oscillators.c b/cpu/cc26xx-cc13xx/dev/oscillators.c index 99ba8f841..7890a8e55 100644 --- a/cpu/cc26xx-cc13xx/dev/oscillators.c +++ b/cpu/cc26xx-cc13xx/dev/oscillators.c @@ -37,44 +37,18 @@ */ /*---------------------------------------------------------------------------*/ #include "ti-lib.h" +#include "aux-ctrl.h" #include /*---------------------------------------------------------------------------*/ -static uint32_t -osc_interface_en(void) -{ - uint32_t smph_clk_state; - - /* Enable OSC DIG interface to change clock sources */ - ti_lib_osc_interface_enable(); - - /* Save the state of the SMPH clock within AUX */ - smph_clk_state = ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK); - - /* Make sure the SMPH clock within AUX is enabled */ - ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK); - while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY); - - return smph_clk_state; -} -/*---------------------------------------------------------------------------*/ -static void -osc_interface_dis(uint32_t smph_clk_state) -{ - /* If the SMPH clock was off, turn it back off */ - if(smph_clk_state == AUX_WUC_CLOCK_OFF) { - ti_lib_aux_wuc_clock_disable(AUX_WUC_SMPH_CLOCK); - } - - /* Disable OSC DIG interface */ - ti_lib_osc_interface_disable(); -} -/*---------------------------------------------------------------------------*/ void oscillators_select_lf_xosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); /* Switch LF clock source to the LF XOSC if required */ if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF) { @@ -91,15 +65,18 @@ oscillators_select_lf_xosc(void) 0x3); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_select_lf_rcosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); /* Switch LF clock source to the LF XOSC if required */ if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_RCOSC_LF) { @@ -109,15 +86,18 @@ oscillators_select_lf_rcosc(void) while(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_RCOSC_LF); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_request_hf_xosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { /* @@ -128,30 +108,36 @@ oscillators_request_hf_xosc(void) ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_XOSC_HF); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_switch_to_hf_xosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { /* Switch the HF clock source (cc26xxware executes this from ROM) */ ti_lib_osc_hf_source_switch(); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_switch_to_hf_rc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); /* Set all clock sources to the HF RC Osc */ ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_RCOSC_HF); @@ -162,8 +148,8 @@ oscillators_switch_to_hf_rc(void) ti_lib_osc_hf_source_switch(); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/cpu/cc26xx-cc13xx/lpm.c b/cpu/cc26xx-cc13xx/lpm.c index eec8ed66d..686065c73 100644 --- a/cpu/cc26xx-cc13xx/lpm.c +++ b/cpu/cc26xx-cc13xx/lpm.c @@ -46,6 +46,7 @@ #include "lpm.h" #include "sys/energest.h" #include "lib/list.h" +#include "dev/aux-ctrl.h" #include "dev/leds.h" #include "dev/watchdog.h" #include "dev/soc-rtc.h" @@ -53,6 +54,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ #if ENERGEST_CONF_ON static unsigned long irq_energest = 0; @@ -90,8 +92,8 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on) { lpm_registered_module_t *module; int i; - uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | - wake_on; + uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | wake_on; + aux_consumer_module_t aux = { .clocks = AUX_WUC_OSCCTRL_CLOCK }; /* This procedure may not be interrupted */ ti_lib_int_master_disable(); @@ -135,16 +137,16 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on) ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH); + /* Register an aux-ctrl consumer to avoid powercycling AUX twice in a row */ + aux_ctrl_register_consumer(&aux); oscillators_switch_to_hf_rc(); oscillators_select_lf_rcosc(); - /* Configure clock sources for MCU and AUX: No clock */ + /* Configure clock sources for MCU: No clock */ ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); - ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); - /* Disable SRAM and AUX retentions */ + /* Disable SRAM retention */ ti_lib_aon_wuc_mcu_sram_config(0); - ti_lib_aon_wuc_aux_sram_config(false); /* * Request CPU, SYSBYS and VIMS PD off. @@ -157,9 +159,8 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on) ti_lib_aon_wuc_jtag_power_off(); /* Turn off AUX */ - ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); + aux_ctrl_power_down(true); ti_lib_aon_wuc_domain_power_down_enable(); - while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); /* * Request MCU VD power off. @@ -222,6 +223,9 @@ wake_up(void) /* Check operating conditions, optimally choose DCDC versus GLDO */ ti_lib_sys_ctrl_dcdc_voltage_conditional_control(); + /* Fire up AUX is the user has requested this */ + aux_ctrl_power_up(); + /* * We may or may not have been woken up by an AON RTC tick. If not, we need * to adjust our software tick counter @@ -306,17 +310,16 @@ deep_sleep(void) */ oscillators_switch_to_hf_rc(); - /* Configure clock sources for MCU and AUX: No clock */ + /* Shut Down the AUX if the user application is not using it */ + aux_ctrl_power_down(false); + + /* Configure clock sources for MCU: No clock */ ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); - ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); /* Full RAM retention. */ ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); - /* Disable retention of AUX RAM */ - ti_lib_aon_wuc_aux_sram_config(false); - /* * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off * already @@ -327,10 +330,8 @@ deep_sleep(void) /* Request JTAG domain power off */ ti_lib_aon_wuc_jtag_power_off(); - /* Turn off AUX */ - ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); + /* Allow MCU and AUX powerdown */ ti_lib_aon_wuc_domain_power_down_enable(); - while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); /* Configure the recharge controller */ ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE); diff --git a/cpu/cc26xx-cc13xx/ti-lib.h b/cpu/cc26xx-cc13xx/ti-lib.h index cbf9a8e61..c08d05ce3 100644 --- a/cpu/cc26xx-cc13xx/ti-lib.h +++ b/cpu/cc26xx-cc13xx/ti-lib.h @@ -139,6 +139,26 @@ #define ti_lib_aon_wuc_osc_config(...) AONWUCOscConfig(__VA_ARGS__) #define ti_lib_aon_wuc_jtag_power_off(...) AONWUCJtagPowerOff(__VA_ARGS__) /*---------------------------------------------------------------------------*/ +/* aux_adc.h */ +#include "driverlib/aux_adc.h" + +#define ti_lib_aux_adc_disable(...) AUXADCDisable(__VA_ARGS__) +#define ti_lib_aux_adc_enable_async(...) AUXADCEnableAsync(__VA_ARGS__) +#define ti_lib_aux_adc_enable_sync(...) AUXADCEnableSync(__VA_ARGS__) +#define ti_lib_aux_adc_disable_input_scaling(...) AUXADCDisableInputScaling(__VA_ARGS__) +#define ti_lib_aux_adc_flush_fifo(...) AUXADCFlushFifo(__VA_ARGS__) +#define ti_lib_aux_adc_gen_manual_trigger(...) AUXADCGenManualTrigger(__VA_ARGS__) +#define ti_lib_aux_adc_get_fifo_status(...) AUXADCGetFifoStatus(__VA_ARGS__) +#define ti_lib_aux_adc_read_fifo(...) AUXADCReadFifo(__VA_ARGS__) +#define ti_lib_aux_adc_pop_fifo(...) AUXADCPopFifo(__VA_ARGS__) +#define ti_lib_aux_adc_select_input(...) AUXADCSelectInput(__VA_ARGS__) +#define ti_lib_aux_adc_get_adjustment_gain(...) AUXADCGetAdjustmentGain(__VA_ARGS__) +#define ti_lib_aux_adc_get_adjustment_offset(...) AUXADCGetAdjustmentOffset(__VA_ARGS__) +#define ti_lib_aux_adc_value_to_microvolts(...) AUXADCValueToMicrovolts(__VA_ARGS__) +#define ti_lib_aux_adc_microvolts_to_value(...) AUXADCMicrovoltsToValue(__VA_ARGS__) +#define ti_lib_aux_adc_adjust_value_for_gain_and_offset(...) AUXADCAdjustValueForGainAndOffset(__VA_ARGS__) +#define ti_lib_aux_adc_unadjust_value_for_gain_and_offset(...) AUXADCUnadjustValueForGainAndOffset(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ /* aux_wuc.h */ #include "driverlib/aux_wuc.h" diff --git a/examples/cc26xx/cc26xx-demo.c b/examples/cc26xx/cc26xx-demo.c index 53c607837..50d2190d3 100644 --- a/examples/cc26xx/cc26xx-demo.c +++ b/examples/cc26xx/cc26xx-demo.c @@ -337,6 +337,15 @@ get_sync_sensor_readings(void) value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); printf("Bat: Volt=%d mV\n", (value * 125) >> 5); +#if BOARD_SMARTRF06EB + SENSORS_ACTIVATE(als_sensor); + + value = als_sensor.value(0); + printf("ALS: %d raw\n", value); + + SENSORS_DEACTIVATE(als_sensor); +#endif + return; } /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/srf06/Makefile.srf06 b/platform/srf06-cc26xx/srf06/Makefile.srf06 index afdeeddec..44d115ec8 100644 --- a/platform/srf06-cc26xx/srf06/Makefile.srf06 +++ b/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -3,6 +3,7 @@ CFLAGS += -DBOARD_SMARTRF06EB=1 CONTIKI_TARGET_DIRS += srf06 BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c +BOARD_SOURCEFILES += als-sensor.c ### Signal that we can be programmed with cc2538-bsl BOARD_SUPPORTS_BSL=1 diff --git a/platform/srf06-cc26xx/srf06/als-sensor.c b/platform/srf06-cc26xx/srf06/als-sensor.c new file mode 100644 index 000000000..f149d16a1 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/als-sensor.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.ac.uk/ + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 srf06-common-peripherals + * @{ + * + * \file + * Driver for the SmartRF06EB ALS when a CC13xx/CC26xxEM is mounted on it + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "srf06/als-sensor.h" +#include "sys/timer.h" +#include "dev/adc-sensor.h" +#include "dev/aux-ctrl.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +static aux_consumer_module_t als_aux = { + .clocks = AUX_WUC_ADI_CLOCK | AUX_WUC_ANAIF_CLOCK | AUX_WUC_SMPH_CLOCK +}; +/*---------------------------------------------------------------------------*/ +static int +config(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); + break; + case SENSORS_ACTIVE: + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); + ti_lib_ioc_port_configure_set(BOARD_IOID_ALS_OUT, IOC_PORT_GPIO, + IOC_STD_OUTPUT); + ti_lib_gpio_dir_mode_set(BOARD_ALS_OUT, GPIO_DIR_MODE_IN); + + if(enable) { + ti_lib_gpio_pin_write(BOARD_ALS_PWR, 1); + aux_ctrl_register_consumer(&als_aux); + ti_lib_aux_adc_select_input(ADC_COMPB_IN_AUXIO7); + clock_delay_usec(2000); + } else { + ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); + aux_ctrl_unregister_consumer(&als_aux); + } + break; + default: + break; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + int val; + + ti_lib_aux_adc_enable_sync(AUXADC_REF_VDDS_REL, AUXADC_SAMPLE_TIME_2P7_US, + AUXADC_TRIGGER_MANUAL); + ti_lib_aux_adc_gen_manual_trigger(); + val = ti_lib_aux_adc_read_fifo(); + ti_lib_aux_adc_disable(); + + return val; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(als_sensor, ALS_SENSOR, value, config, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/als-sensor.h b/platform/srf06-cc26xx/srf06/als-sensor.h new file mode 100644 index 000000000..5d70478f8 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/als-sensor.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.ac.uk/ + * 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 copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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 srf06-common-peripherals + * @{ + * + * \file + * Header file for the SmartRF06EB + CC13xx/CC26xxEM ALS Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef ALS_SENSOR_H_ +#define ALS_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define ALS_SENSOR "ALS" +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor als_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* ALS_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/board-peripherals.h b/platform/srf06-cc26xx/srf06/board-peripherals.h index d76936c2d..c709ec963 100644 --- a/platform/srf06-cc26xx/srf06/board-peripherals.h +++ b/platform/srf06-cc26xx/srf06/board-peripherals.h @@ -45,7 +45,7 @@ #ifndef BOARD_PERIPHERALS_H_ #define BOARD_PERIPHERALS_H_ /*---------------------------------------------------------------------------*/ -/* ToDo: Include things here */ +#include "als-sensor.h" /*---------------------------------------------------------------------------*/ #endif /* BOARD_PERIPHERALS_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/srf06/board.c b/platform/srf06-cc26xx/srf06/board.c index 9f53e8ae8..15528f79a 100644 --- a/platform/srf06-cc26xx/srf06/board.c +++ b/platform/srf06-cc26xx/srf06/board.c @@ -46,6 +46,16 @@ #include /*---------------------------------------------------------------------------*/ static void +lpm_handler(uint8_t mode) +{ + /* Ambient light sensor (off, output low) */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); + ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_ALS_OUT, IOC_NO_IOPULL); +} +/*---------------------------------------------------------------------------*/ +static void wakeup_handler(void) { /* Turn on the PERIPH PD */ @@ -60,7 +70,7 @@ wakeup_handler(void) * getting notified before deep sleep. All we need is to be notified when we * wake up so we can turn power domains back on */ -LPM_MODULE(srf_module, NULL, NULL, wakeup_handler, LPM_DOMAIN_NONE); +LPM_MODULE(srf_module, NULL, lpm_handler, wakeup_handler, LPM_DOMAIN_NONE); /*---------------------------------------------------------------------------*/ static void configure_unused_pins(void) @@ -72,12 +82,6 @@ configure_unused_pins(void) /* Accelerometer (PWR output low, CSn output, high) */ ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_PWR); ti_lib_gpio_pin_write(BOARD_ACC_PWR, 0); - - /* Ambient light sensor (off, output low) */ - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); - ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_ALS_OUT, IOC_NO_IOPULL); } /*---------------------------------------------------------------------------*/ void diff --git a/platform/srf06-cc26xx/srf06/srf06-sensors.c b/platform/srf06-cc26xx/srf06/srf06-sensors.c index 9f05c1917..5f65a0cb2 100644 --- a/platform/srf06-cc26xx/srf06/srf06-sensors.c +++ b/platform/srf06-cc26xx/srf06/srf06-sensors.c @@ -39,11 +39,12 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "srf06/button-sensor.h" +#include "srf06/als-sensor.h" #include /*---------------------------------------------------------------------------*/ /** \brief Exports a global symbol to be used by the sensor API */ SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, - &button_up_sensor, &button_down_sensor); + &button_up_sensor, &button_down_sensor, &als_sensor); /*---------------------------------------------------------------------------*/ /** @} */