Contiki 3.x
cc1200-zoul-arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Zolertia
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  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*---------------------------------------------------------------------------*/
32 /**
33  * \addtogroup zoul
34  * @{
35  *
36  * \defgroup zoul-cc1200 Zoul CC1200 arch
37  *
38  * CC1200 Zoul arch specifics
39  * @{
40  *
41  * \file
42  * CC1200 Zoul arch specifics
43  */
44 /*---------------------------------------------------------------------------*/
45 #include "contiki.h"
46 #include "contiki-net.h"
47 #include "dev/leds.h"
48 #include "reg.h"
49 #include "spi-arch.h"
50 #include "dev/ioc.h"
51 #include "dev/sys-ctrl.h"
52 #include "dev/spi.h"
53 #include "dev/ssi.h"
54 #include "dev/gpio.h"
55 #include <stdio.h>
56 /*---------------------------------------------------------------------------*/
57 #define CC1200_SPI_CLK_PORT_BASE GPIO_PORT_TO_BASE(SPI0_CLK_PORT)
58 #define CC1200_SPI_CLK_PIN_MASK GPIO_PIN_MASK(SPI0_CLK_PIN)
59 #define CC1200_SPI_MOSI_PORT_BASE GPIO_PORT_TO_BASE(SPI0_TX_PORT)
60 #define CC1200_SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI0_TX_PIN)
61 #define CC1200_SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI0_RX_PORT)
62 #define CC1200_SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI0_RX_PIN)
63 #define CC1200_SPI_CSN_PORT_BASE GPIO_PORT_TO_BASE(CC1200_SPI_CSN_PORT)
64 #define CC1200_SPI_CSN_PIN_MASK GPIO_PIN_MASK(CC1200_SPI_CSN_PIN)
65 #define CC1200_GDO0_PORT_BASE GPIO_PORT_TO_BASE(CC1200_GDO0_PORT)
66 #define CC1200_GDO0_PIN_MASK GPIO_PIN_MASK(CC1200_GDO0_PIN)
67 #define CC1200_GDO2_PORT_BASE GPIO_PORT_TO_BASE(CC1200_GDO2_PORT)
68 #define CC1200_GDO2_PIN_MASK GPIO_PIN_MASK(CC1200_GDO2_PIN)
69 #define CC1200_RESET_PORT_BASE GPIO_PORT_TO_BASE(CC1200_RESET_PORT)
70 #define CC1200_RESET_PIN_MASK GPIO_PIN_MASK(CC1200_RESET_PIN)
71 /*---------------------------------------------------------------------------*/
72 #ifndef DEBUG_CC1200_ARCH
73 #define DEBUG_CC1200_ARCH 0
74 #endif
75 /*---------------------------------------------------------------------------*/
76 #if DEBUG_CC1200_ARCH > 0
77 #define PRINTF(...) printf(__VA_ARGS__)
78 #define BUSYWAIT_UNTIL(cond, max_time) \
79  do { \
80  rtimer_clock_t t0; \
81  t0 = RTIMER_NOW(); \
82  while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) {} \
83  if(!(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time)))) { \
84  printf("ARCH: Timeout exceeded in line %d!\n", __LINE__); \
85  } \
86  } while(0)
87 #else
88 #define PRINTF(...)
89 #define BUSYWAIT_UNTIL(cond, max_time) while(!cond)
90 #endif
91 /*---------------------------------------------------------------------------*/
92 extern int cc1200_rx_interrupt(void);
93 /*---------------------------------------------------------------------------*/
94 void
95 cc1200_int_handler(uint8_t port, uint8_t pin)
96 {
97  /* To keep the gpio_register_callback happy */
98  cc1200_rx_interrupt();
99 }
100 /*---------------------------------------------------------------------------*/
101 void
102 cc1200_arch_spi_select(void)
103 {
104  /* Set CSn to low (0) */
105  GPIO_CLR_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
106  /* The MISO pin should go low before chip is fully enabled. */
107  BUSYWAIT_UNTIL(
108  GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK) == 0,
109  RTIMER_SECOND / 100);
110 }
111 /*---------------------------------------------------------------------------*/
112 void
113 cc1200_arch_spi_deselect(void)
114 {
115  /* Set CSn to high (1) */
116  GPIO_SET_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
117 }
118 /*---------------------------------------------------------------------------*/
119 int
120 cc1200_arch_spi_rw_byte(uint8_t c)
121 {
122  SPI_WAITFORTx_BEFORE();
123  SPIX_BUF(CC1200_SPI_INSTANCE) = c;
124  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
125  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
126  c = SPIX_BUF(CC1200_SPI_INSTANCE);
127 
128  return c;
129 }
130 /*---------------------------------------------------------------------------*/
131 int
132 cc1200_arch_spi_rw(uint8_t *inbuf, const uint8_t *write_buf, uint16_t len)
133 {
134  int i;
135  uint8_t c;
136 
137  if((inbuf == NULL && write_buf == NULL) || len <= 0) {
138  return 1;
139  } else if(inbuf == NULL) {
140  for(i = 0; i < len; i++) {
141  SPI_WAITFORTx_BEFORE();
142  SPIX_BUF(CC1200_SPI_INSTANCE) = write_buf[i];
143  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
144  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
145  c = SPIX_BUF(CC1200_SPI_INSTANCE);
146  /* read and discard to avoid "variable set but not used" warning */
147  (void)c;
148  }
149  } else if(write_buf == NULL) {
150  for(i = 0; i < len; i++) {
151  SPI_WAITFORTx_BEFORE();
152  SPIX_BUF(CC1200_SPI_INSTANCE) = 0;
153  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
154  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
155  inbuf[i] = SPIX_BUF(CC1200_SPI_INSTANCE);
156  }
157  } else {
158  for(i = 0; i < len; i++) {
159  SPI_WAITFORTx_BEFORE();
160  SPIX_BUF(CC1200_SPI_INSTANCE) = write_buf[i];
161  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
162  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
163  inbuf[i] = SPIX_BUF(CC1200_SPI_INSTANCE);
164  }
165  }
166  return 0;
167 }
168 /*---------------------------------------------------------------------------*/
169 void
170 cc1200_arch_gpio0_setup_irq(int rising)
171 {
172 
173  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
174  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
175  GPIO_DETECT_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
176  GPIO_TRIGGER_SINGLE_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
177 
178  if(rising) {
179  GPIO_DETECT_RISING(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
180  } else {
181  GPIO_DETECT_FALLING(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
182  }
183 
184  GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
185  ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE);
186  nvic_interrupt_enable(CC1200_GPIOx_VECTOR);
187  gpio_register_callback(cc1200_int_handler, CC1200_GDO0_PORT,
188  CC1200_GDO0_PIN);
189 }
190 /*---------------------------------------------------------------------------*/
191 void
192 cc1200_arch_gpio2_setup_irq(int rising)
193 {
194 
195  GPIO_SOFTWARE_CONTROL(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
196  GPIO_SET_INPUT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
197  GPIO_DETECT_EDGE(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
198  GPIO_TRIGGER_SINGLE_EDGE(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
199 
200  if(rising) {
201  GPIO_DETECT_RISING(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
202  } else {
203  GPIO_DETECT_FALLING(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
204  }
205 
206  GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
207  ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE);
208  nvic_interrupt_enable(CC1200_GPIOx_VECTOR);
209  gpio_register_callback(cc1200_int_handler, CC1200_GDO2_PORT,
210  CC1200_GDO2_PIN);
211 }
212 /*---------------------------------------------------------------------------*/
213 void
214 cc1200_arch_gpio0_enable_irq(void)
215 {
216  GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
217  ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE);
218  nvic_interrupt_enable(CC1200_GPIOx_VECTOR);
219 }
220 /*---------------------------------------------------------------------------*/
221 void
222 cc1200_arch_gpio0_disable_irq(void)
223 {
224  GPIO_DISABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
225 }
226 /*---------------------------------------------------------------------------*/
227 void
228 cc1200_arch_gpio2_enable_irq(void)
229 {
230  GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
231  ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE);
232  nvic_interrupt_enable(CC1200_GPIOx_VECTOR);
233 }
234 /*---------------------------------------------------------------------------*/
235 void
236 cc1200_arch_gpio2_disable_irq(void)
237 {
238  GPIO_DISABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
239 }
240 /*---------------------------------------------------------------------------*/
241 int
242 cc1200_arch_gpio0_read_pin(void)
243 {
244  return GPIO_READ_PIN(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
245 }
246 /*---------------------------------------------------------------------------*/
247 int
248 cc1200_arch_gpio2_read_pin(void)
249 {
250  return GPIO_READ_PIN(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
251 }
252 /*---------------------------------------------------------------------------*/
253 int
254 cc1200_arch_gpio3_read_pin(void)
255 {
256  return 0x00;
257 }
258 /*---------------------------------------------------------------------------*/
259 void
260 cc1200_arch_init(void)
261 {
262  /* First leave RESET high */
263  GPIO_SOFTWARE_CONTROL(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
264  GPIO_SET_OUTPUT(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
265  ioc_set_over(CC1200_RESET_PORT, CC1200_RESET_PIN, IOC_OVERRIDE_OE);
266  GPIO_SET_PIN(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
267 
268  /* Initialize CSn, enable CSn and then wait for MISO to go low*/
269  spix_cs_init(CC1200_SPI_CSN_PORT, CC1200_SPI_CSN_PIN);
270 
271  /* Initialize SPI */
272  spix_init(CC1200_SPI_INSTANCE);
273 
274  /* Configure GPIOx */
275  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
276  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
277  GPIO_SOFTWARE_CONTROL(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
278  GPIO_SET_INPUT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
279 
280  /* Leave CSn as default */
281  cc1200_arch_spi_deselect();
282 
283  /* Ensure MISO is high */
284  BUSYWAIT_UNTIL(
285  GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK),
286  RTIMER_SECOND / 10);
287 }
288 /*---------------------------------------------------------------------------*/
289 /**
290  * @}
291  * @}
292  */
293 
#define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on single edge (controlled by G...
Definition: gpio.h:178
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:202
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:93
Header file with register manipulation macro definitions.
#define IOC_OVERRIDE_PUE
Pull Up Enable.
Definition: ioc.h:223
Header file for the cc2538 SPI driver, including macros for the implementation of the low-level SPI p...
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
Definition: gpio.h:155
#define IOC_OVERRIDE_OE
Output Enable.
Definition: ioc.h:222
#define GPIO_DETECT_FALLING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on falling edge.
Definition: gpio.h:194
void spix_init(uint8_t spi)
Initialize the SPI bus for the instance given.
Definition: spi.c:207
#define GPIO_READ_PIN(PORT_BASE, PIN_MASK)
Read pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:148
#define GPIO_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition: gpio.h:114
#define GPIO_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:107
void spix_cs_init(uint8_t port, uint8_t pin)
Configure a GPIO to be the chip select pin.
Definition: spi.c:319
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:100
#define NULL
The null pointer.
Header file with declarations for the I/O Control module.
#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:259
Header file for the cc2538 System Control driver.
Header file for the cc2538 Synchronous Serial Interface.
#define GPIO_DETECT_RISING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on rising edge.
Definition: gpio.h:186
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
Definition: nvic.c:64
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:210
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
Definition: gpio.c:56