Contiki-NG
power-mgmt.c
1 /*
2  * Copyright (c) 2015, 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-reva
33  * @{
34  *
35  * RE-Mote power management and shutdown mode
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 /* -------------------------------------------------------------------------- */
50 #define DEBUG 0
51 #if DEBUG
52 #define PRINTF(...) printf(__VA_ARGS__)
53 #else
54 #define PRINTF(...)
55 #endif
56 /* -------------------------------------------------------------------------- */
57 #define PM_CMD_LINE_SET GPIO_SET_PIN(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK)
58 #define PM_CMD_LINE_CLR GPIO_CLR_PIN(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK)
59 #define PM_CMD_LINE_READ GPIO_READ_PIN(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK)
60 #define PM_CMD_AS_OUTPUT GPIO_SET_OUTPUT(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK)
61 #define PM_CMD_AS_INPUT GPIO_SET_INPUT(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK)
62 /* -------------------------------------------------------------------------- */
63 #define PM_NUMBITS(X) (1 << ((X) - 1))
64 /* -------------------------------------------------------------------------- */
65 static uint8_t initialized = 0;
66 static uint8_t getData = 0;
67 /* -------------------------------------------------------------------------- */
68 static int8_t
69 pm_get_ack(void)
70 {
71  uint16_t error = PM_ERROR;
72  PM_CMD_AS_INPUT;
73  clock_delay_usec(PM_3_MILISECOND);
74  if(PM_CMD_LINE_READ) {
75  error = PM_SUCCESS;
76  }
77 
78  clock_delay_usec(PM_10_MILISECOND);
79  PM_CMD_AS_OUTPUT;
80  return error;
81 }
82 /* -------------------------------------------------------------------------- */
83 static int8_t
84 pm_send_cmd(uint8_t cmd)
85 {
86  uint8_t i;
87 
88  PRINTF("PM: cmd %u\n", cmd);
89 
90  /* Enter command mode */
91  PM_CMD_LINE_SET;
92  clock_delay_usec(PM_1_MILISECOND);
93  PM_CMD_LINE_CLR;
94 
95  /* Send command */
96  for (i = PM_MAX_BITS; i > 0; i--) {
97  clock_delay_usec(PM_1_MILISECOND);
98 
99  if (cmd & PM_NUMBITS(i)) {
100  PM_CMD_LINE_SET;
101  }
102  else PM_CMD_LINE_CLR;
103  }
104 
105  clock_delay_usec(PM_1_MILISECOND);
106  PM_CMD_LINE_CLR;
107 
108  /* Receive command reply if any */
109  if((cmd == PM_CMD_GET_STATE) || (cmd == PM_CMD_GET_FW_VERSION)) {
110  PM_CMD_AS_INPUT;
111  clock_delay_usec(PM_2_2_MILISECOND);
112  for (i = PM_MAX_BITS; i > 0; i--) {
113  clock_delay_usec(PM_1_MILISECOND);
114  PM_CMD_LINE_READ ? (getData |= PM_NUMBITS(i)) : (getData &= ~PM_NUMBITS(i));
115  }
116 
117  PRINTF("PM: getData = 0x%02X\n", getData);
118  clock_delay_usec(PM_2_2_MILISECOND);
119  PM_CMD_AS_OUTPUT;
120  PM_CMD_LINE_CLR;
121 
122  clock_delay_usec(PM_2_2_MILISECOND);
123 
124  return PM_SUCCESS;
125  }
126 
127  /* Default case */
128  clock_delay_usec(PM_1_MILISECOND);
129 
130  return pm_get_ack();
131 }
132 /* -------------------------------------------------------------------------- */
133 int8_t
134 pm_init(void)
135 {
136  /* Configure and clear immediately */
137  GPIO_SOFTWARE_CONTROL(PM_DONE_PORT_BASE, PM_DONE_PIN_MASK);
138  GPIO_SET_OUTPUT(PM_DONE_PORT_BASE, PM_DONE_PIN_MASK);
139  GPIO_CLR_PIN(PM_DONE_PORT_BASE, PM_DONE_PIN_MASK);
140 
141  /* Set as output/low to set IDLE state */
142  GPIO_SOFTWARE_CONTROL(PM_CMD_PORT_BASE, PM_CMD_PIN_MASK);
143  PM_CMD_AS_OUTPUT;
144  PM_CMD_LINE_CLR;
145 
146  /* Ensure the battery charger is on, so we don't lock ourselves out and left
147  * stranded in a state the CC2538 and components are kept off
148  */
149 
150  if(pm_send_cmd(PM_CMD_PWR_ON) == PM_SUCCESS) {
151  initialized = 1;
152  PRINTF("PM: Initialized\n");
153  return PM_SUCCESS;
154  }
155 
156  PRINTF("PM: Failed to initialize\n");
157  return PM_ERROR;
158 }
159 /* -------------------------------------------------------------------------- */
160 int8_t
162 {
163  if(!initialized) {
164  return PM_ERROR;
165  }
166 
167  if(pm_send_cmd(PM_CMD_DTIMER_ON) == PM_SUCCESS) {
168  return PM_SUCCESS;
169  }
170  return PM_ERROR;
171 }
172 /* -------------------------------------------------------------------------- */
173 int8_t
175 {
176  if(!initialized) {
177  return PM_ERROR;
178  }
179 
180  if(pm_send_cmd(PM_CMD_DTIMER_OFF) == PM_SUCCESS) {
181  return PM_SUCCESS;
182  }
183  return PM_ERROR;
184 }
185 /* -------------------------------------------------------------------------- */
186 int8_t
187 pm_get_state(uint8_t *state)
188 {
189  if(!initialized) {
190  return PM_ERROR;
191  }
192 
193  if(pm_send_cmd(PM_CMD_GET_STATE) == PM_SUCCESS) {
194  *state = getData;
195  PRINTF("PM: state %u\n", getData);
196 
197  return PM_SUCCESS;
198  }
199  return PM_ERROR;
200 }
201 /* -------------------------------------------------------------------------- */
202 int8_t
203 pm_get_firmware_version(uint8_t *state)
204 {
205  if(!initialized) {
206  return PM_ERROR;
207  }
208 
209  if (pm_send_cmd(PM_CMD_GET_FW_VERSION) == PM_SUCCESS) {
210  *state = getData;
211  printf("PM: FW Version %u\n", getData);
212  return PM_SUCCESS;
213  }
214  return PM_ERROR;
215 }
216 /*---------------------------------------------------------------------------*/
217 /**
218  * @}
219  * @}
220  */
int8_t pm_get_state(uint8_t *state)
Get the current state of the power management module.
Definition: power-mgmt.c:187
Header file with register and macro declarations for the cc2538 GPIO module.
#define GPIO_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition: gpio.h:113
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
int8_t pm_init(void)
Initializes the Power Management driver.
Definition: power-mgmt.c:134
int8_t pm_get_firmware_version(uint8_t *state)
Get the firmware version of the power management module.
Definition: power-mgmt.c:203
#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
Header file for the RE-Mote Power Management driver.
Header file for the real-time timer module.
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:85
int8_t pm_enable_timer(void)
Enable the shutdown mode, periodically driven by the Nano Timer.
Definition: power-mgmt.c:161
int8_t pm_disable_timer(void)
Disable the Nano Timer.
Definition: power-mgmt.c:174