Contiki-NG
Loading...
Searching...
No Matches
power-mgmt.c
1/*
2 * Copyright (c) 2016, Zolertia - http://www.zolertia.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30/*---------------------------------------------------------------------------*/
31/**
32 * \addtogroup remote-power-mgmt-revb
33 * @{
34 * RE-Mote power management functions.
35 *
36 * @{
37 *
38 * \author
39 * Aitor Mejias <amejias@zolertia.com>
40 * Antonio Lignan <alinan@zolertia.com>
41 */
42/* -------------------------------------------------------------------------- */
43#include <stdio.h>
44#include <stdint.h>
45#include "contiki.h"
46#include "dev/gpio.h"
47#include "sys/rtimer.h"
48#include "power-mgmt.h"
49#include "dev/i2c.h"
50/* -------------------------------------------------------------------------- */
51#define DEBUG 0
52#if DEBUG
53#define PRINTF(...) printf(__VA_ARGS__)
54#else
55#define PRINTF(...)
56#endif
57/* -------------------------------------------------------------------------- */
58#define PM_ENABLE_LINE_SET GPIO_SET_PIN(PM_ENABLE_PORT_BASE, \
59 PM_ENABLE_PIN_MASK)
60#define PM_ENABLE_LINE_CLR GPIO_CLR_PIN(PM_ENABLE_PORT_BASE, \
61 PM_ENABLE_PIN_MASK)
62#define PM_ENABLE_AS_OUTPUT GPIO_SET_OUTPUT(PM_ENABLE_PORT_BASE, \
63 PM_ENABLE_PIN_MASK)
64#define PM_ENABLE_LINE_CMD PM_ENABLE_LINE_SET; \
65 clock_delay_usec(100);
66
67/* -------------------------------------------------------------------------- */
68#define PM_NUMBITS(X) (1 << ((X)-1))
69/* -------------------------------------------------------------------------- */
70static uint8_t initialized = 0;
71static uint8_t lbuf[5];
72/* -------------------------------------------------------------------------- */
73int8_t
75{
76 /* Set as output/low to set IDLE state */
77 GPIO_SOFTWARE_CONTROL(PM_ENABLE_PORT_BASE, PM_ENABLE_PIN_MASK);
78 PM_ENABLE_AS_OUTPUT;
79
80 i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN,
81 I2C_SCL_NORMAL_BUS_SPEED);
82 initialized = 1;
83 return PM_SUCCESS;
84}
85/* -------------------------------------------------------------------------- */
86static int
87pm_write_byte(uint8_t reg, uint8_t val)
88{
89 if(!initialized) {
90 return PM_ERROR;
91 }
92 lbuf[0] = reg;
93 lbuf[1] = val;
94 PM_ENABLE_LINE_CMD;
95
96 if(i2c_burst_send(PWR_MNGMT_ADDR, lbuf, 2) == I2C_MASTER_ERR_NONE) {
97 PM_ENABLE_LINE_CLR;
98 return PM_SUCCESS;
99 }
100 PM_ENABLE_LINE_CLR;
101 return PM_ERROR;
102}
103/*---------------------------------------------------------------------------*/
104static int
105pm_read_byte(uint8_t reg, uint8_t *val, uint8_t len)
106{
107 /* Detect valid register parameter */
108 if((reg < PM_VBAT) || (reg >= PM_MAX_COMMANDS) || (!len)) {
109 PRINTF("PM: invalid settings/not initialized\n");
110 return PM_ERROR;
111 }
112
113 PM_ENABLE_LINE_CMD;
114
115 if(i2c_single_send(PWR_MNGMT_ADDR, reg) == I2C_MASTER_ERR_NONE) {
116 if(i2c_burst_receive(PWR_MNGMT_ADDR, val, len) == I2C_MASTER_ERR_NONE) {
117 printf("PM: Data 0x%02X\n", *val);
118 PM_ENABLE_LINE_CLR;
119 return PM_SUCCESS;
120 }
121 }
122 PRINTF("PM: Error reading the registers\n");
123 PM_ENABLE_LINE_CLR;
124 return PM_ERROR;
125}
126/* -------------------------------------------------------------------------- */
127int8_t
129{
130 if(!initialized) {
131 return PM_ERROR;
132 }
133
134 /* Reset the low-power PIC and the whole board as a bonus */
135 lbuf[0] = PM_CMD_RST_HARD;
136 lbuf[1] = 1;
137 PM_ENABLE_LINE_CMD;
138
139 if(i2c_burst_send(PWR_MNGMT_ADDR, lbuf, 2) == I2C_MASTER_ERR_NONE) {
140 clock_delay_usec(1000);
141 PM_ENABLE_LINE_CLR;
142 return PM_SUCCESS;
143 }
144 PM_ENABLE_LINE_CLR;
145 return PM_ERROR;
146}
147/* -------------------------------------------------------------------------- */
148int8_t
149pm_set_timeout(uint32_t time)
150{
151 if(!initialized) {
152 return PM_ERROR;
153 }
154
155 if(time > PM_SOFT_SHTDN_28_DAYS) {
156 PRINTF("PM: maximum timeout is %u\n", (uint32_t)PM_SOFT_SHTDN_28_DAYS);
157 return PM_ERROR;
158 }
159
160 lbuf[0] = PM_SOFT_TIME;
161 lbuf[1] = (uint8_t)(time >> 24);
162 lbuf[2] = (uint8_t)(time >> 16) & 0xFF;
163 lbuf[3] = (uint8_t)(time >> 8) & 0xFF;
164 lbuf[4] = (uint8_t)(time & 0xFF);
165 PRINTF("PM: Timeout 0x%02x%02x%02x%02x\n", lbuf[1], lbuf[2], lbuf[3], lbuf[4]);
166
167 PM_ENABLE_LINE_CMD;
168
169 if(i2c_burst_send(PWR_MNGMT_ADDR, lbuf, 5) == I2C_MASTER_ERR_NONE) {
170 PM_ENABLE_LINE_CLR;
171 return PM_SUCCESS;
172 }
173
174 PRINTF("PM: error setting the timeout\n");
175 PM_ENABLE_LINE_CLR;
176 return PM_ERROR;
177}
178/* -------------------------------------------------------------------------- */
179uint32_t
181{
182 uint32_t retval = 0;
183 PM_ENABLE_LINE_CMD;
184
185 if(i2c_single_send(PWR_MNGMT_ADDR, PM_SOFT_TIME) == I2C_MASTER_ERR_NONE) {
186 if(i2c_burst_receive(PWR_MNGMT_ADDR, lbuf, 4) == I2C_MASTER_ERR_NONE) {
187 retval |= ((uint32_t)lbuf[0] << 24);
188 retval |= ((uint32_t)lbuf[1] << 16);
189 retval |= ((uint32_t)lbuf[2] << 8);
190 retval |= lbuf[3];
191 }
192 }
193
194 PM_ENABLE_LINE_CLR;
195 PRINTF("PM: Timeout 0x%02x%02x%02x%02x\n", lbuf[0], lbuf[1], lbuf[2], lbuf[3]);
196
197 retval *= PM_SOFT_SHTDN_INTERVAL;
198 retval /= 100;
199 return retval;
200}
201/* -------------------------------------------------------------------------- */
202uint32_t
204{
205 uint32_t retval = 0;
206 PM_ENABLE_LINE_CMD;
207
208 if(i2c_single_send(PWR_MNGMT_ADDR, PM_GET_NUM_CYCLES) == I2C_MASTER_ERR_NONE) {
209 if(i2c_burst_receive(PWR_MNGMT_ADDR, lbuf, 4) == I2C_MASTER_ERR_NONE) {
210 retval |= ((uint32_t)lbuf[0] << 24);
211 retval |= ((uint32_t)lbuf[1] << 16);
212 retval |= ((uint32_t)lbuf[2] << 8);
213 retval |= lbuf[3];
214 }
215 }
216 PM_ENABLE_LINE_CLR;
217 PRINTF("PM: Sleep cycles: 0x%02x%02x%02x%02x\n", lbuf[0], lbuf[1], lbuf[2],
218 lbuf[3]);
219 return retval;
220}
221/* -------------------------------------------------------------------------- */
222int8_t
223pm_shutdown_now(uint8_t type)
224{
225 if(!initialized) {
226 PRINTF("PM: Not initialized\n");
227 return PM_ERROR;
228 }
229
230 if((type != PM_HARD_SLEEP_CONFIG) && (type != PM_SOFT_SLEEP_CONFIG)) {
231 PRINTF("PM: Invalid shutdown mode type\n");
232 return PM_ERROR;
233 }
234
235 PM_ENABLE_LINE_CMD;
236
237 if(type == PM_HARD_SLEEP_CONFIG) {
238 pm_write_byte(PM_HARD_SLEEP_CONFIG, PM_ENABLE);
239 PM_ENABLE_LINE_CLR;
240 return PM_SUCCESS;
241 }
242
243 /* Soft sleep */
244 pm_write_byte(PM_SOFT_SLEEP_CONFIG, PM_ENABLE);
245 PM_ENABLE_LINE_CLR;
246 return PM_SUCCESS;
247}
248/* -------------------------------------------------------------------------- */
249int8_t
250pm_get_voltage(uint16_t *state)
251{
252 float result = 0x00;
253
254 if(!initialized) {
255 return PM_ERROR;
256 }
257
258 PM_ENABLE_LINE_CMD;
259 if(i2c_single_send(PWR_MNGMT_ADDR, PM_GET_VDD) == I2C_MASTER_ERR_NONE) {
260 /* Read two bytes only */
261 if(i2c_burst_receive(PWR_MNGMT_ADDR, lbuf, 2) == I2C_MASTER_ERR_NONE) {
262 *state = (uint16_t)lbuf[0] << 8;
263 *state += lbuf[1];
264
265 /* Compensation */
266 result = *state - PM_VBAT_OFF;
267 result /= PM_VBAT_MULT;
268
269 *state = (uint16_t)(result * 100);
270
271 PM_ENABLE_LINE_CLR;
272 return PM_SUCCESS;
273 }
274 }
275 PM_ENABLE_LINE_CLR;
276 return PM_ERROR;
277}
278/* -------------------------------------------------------------------------- */
279int8_t
280pm_get_fw_ver(uint8_t *fwver)
281{
282 if((!initialized) || (fwver == NULL)) {
283 return PM_ERROR;
284 }
285
286 if(pm_read_byte(PM_FW_VERSION, fwver, 1) == PM_SUCCESS) {
287 return PM_SUCCESS;
288 }
289 return PM_ERROR;
290}
291/*---------------------------------------------------------------------------*/
292/**
293 * @}
294 * @}
295 */
Header file with register and macro declarations for the cc2538 GPIO module.
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition clock.c:150
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE.
Definition gpio.h:258
uint8_t i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to send multiple bytes to a slave.
Definition i2c.c:188
void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, uint32_t bus_speed)
Initialize the I2C peripheral and pins.
Definition i2c.c:49
uint8_t i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to receive multiple bytes from a slave.
Definition i2c.c:218
uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data)
Perform all operations to send a byte to a slave.
Definition i2c.c:159
uint32_t pm_get_timeout(void)
Gets the current timeout value configured in power management module.
Definition power-mgmt.c:180
#define PWR_MNGMT_ADDR
Power Management slave address.
Definition power-mgmt.h:61
static int pm_read_byte(uint8_t reg, uint8_t *val, uint8_t len)
Definition power-mgmt.c:105
int8_t pm_get_voltage(uint16_t *state)
Reads the voltage of the external battery if connected to VIN pin.
Definition power-mgmt.c:250
static int pm_write_byte(uint8_t reg, uint8_t val)
Definition power-mgmt.c:87
int8_t pm_reset_system(void)
Restarts the on-board low-power PIC, provoking a board reset.
Definition power-mgmt.c:128
int8_t pm_enable(void)
Initializes the Power Management driver.
Definition power-mgmt.c:74
int8_t pm_get_fw_ver(uint8_t *fwver)
Gets the current firmware version of power management module.
Definition power-mgmt.c:280
uint32_t pm_get_num_cycles(void)
Gets current cycles.
Definition power-mgmt.c:203
int8_t pm_shutdown_now(uint8_t type)
Disconnects the board battery and enter shutdown mode PM_SOFT/HARD_SLEEP_CONFIG.
Definition power-mgmt.c:223
int8_t pm_set_timeout(uint32_t time)
Configure Internal Timeout for Hard and Soft shutdown modes.
Definition power-mgmt.c:149
Header file with declarations for the I2C Control module.
Header file for the RE-Mote Power Management driver.
Header file for the real-time timer module.