Contiki-NG
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 "dev/spi-arch-legacy.h"
50 #include "dev/ioc.h"
51 #include "dev/sys-ctrl.h"
52 #include "dev/spi-legacy.h"
53 #include "dev/ssi.h"
54 #include "dev/gpio.h"
55 #include "dev/gpio-hal.h"
56 #include <stdio.h>
57 /*---------------------------------------------------------------------------*/
58 #define CC1200_SPI_CLK_PORT_BASE GPIO_PORT_TO_BASE(SPI0_CLK_PORT)
59 #define CC1200_SPI_CLK_PIN_MASK GPIO_PIN_MASK(SPI0_CLK_PIN)
60 #define CC1200_SPI_MOSI_PORT_BASE GPIO_PORT_TO_BASE(SPI0_TX_PORT)
61 #define CC1200_SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI0_TX_PIN)
62 #define CC1200_SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI0_RX_PORT)
63 #define CC1200_SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI0_RX_PIN)
64 #define CC1200_SPI_CSN_PORT_BASE GPIO_PORT_TO_BASE(CC1200_SPI_CSN_PORT)
65 #define CC1200_SPI_CSN_PIN_MASK GPIO_PIN_MASK(CC1200_SPI_CSN_PIN)
66 #define CC1200_GDO0_PORT_BASE GPIO_PORT_TO_BASE(CC1200_GDO0_PORT)
67 #define CC1200_GDO0_PIN_MASK GPIO_PIN_MASK(CC1200_GDO0_PIN)
68 #define CC1200_GDO2_PORT_BASE GPIO_PORT_TO_BASE(CC1200_GDO2_PORT)
69 #define CC1200_GDO2_PIN_MASK GPIO_PIN_MASK(CC1200_GDO2_PIN)
70 #define CC1200_RESET_PORT_BASE GPIO_PORT_TO_BASE(CC1200_RESET_PORT)
71 #define CC1200_RESET_PIN_MASK GPIO_PIN_MASK(CC1200_RESET_PIN)
72 /*---------------------------------------------------------------------------*/
73 #ifndef DEBUG_CC1200_ARCH
74 #define DEBUG_CC1200_ARCH 0
75 #endif
76 /*---------------------------------------------------------------------------*/
77 #if DEBUG_CC1200_ARCH > 0
78 #define PRINTF(...) printf(__VA_ARGS__)
79 #define BUSYWAIT_UNTIL(cond, max_time) \
80  do { \
81  rtimer_clock_t t0; \
82  t0 = RTIMER_NOW(); \
83  while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))) {} \
84  if(!(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time)))) { \
85  printf("ARCH: Timeout exceeded in line %d!\n", __LINE__); \
86  } \
87  } while(0)
88 #else
89 #define PRINTF(...)
90 #define BUSYWAIT_UNTIL(cond, max_time) while(!cond)
91 #endif
92 /*---------------------------------------------------------------------------*/
93 extern int cc1200_rx_interrupt(void);
94 /*---------------------------------------------------------------------------*/
95 void
96 cc1200_int_handler(gpio_hal_pin_mask_t pin_mask)
97 {
98  /* To keep the gpio_register_callback happy */
99  cc1200_rx_interrupt();
100 }
101 /*---------------------------------------------------------------------------*/
102 void
103 cc1200_arch_spi_select(void)
104 {
105  /* Set CSn to low (0) */
106  GPIO_CLR_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
107  /* The MISO pin should go low before chip is fully enabled. */
108  BUSYWAIT_UNTIL(
109  GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK) == 0,
110  RTIMER_SECOND / 100);
111 }
112 /*---------------------------------------------------------------------------*/
113 void
114 cc1200_arch_spi_deselect(void)
115 {
116  /* Set CSn to high (1) */
117  GPIO_SET_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
118 }
119 /*---------------------------------------------------------------------------*/
120 int
121 cc1200_arch_spi_rw_byte(uint8_t c)
122 {
123  SPI_WAITFORTx_BEFORE();
124  SPIX_BUF(CC1200_SPI_INSTANCE) = c;
125  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
126  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
127  c = SPIX_BUF(CC1200_SPI_INSTANCE);
128 
129  return c;
130 }
131 /*---------------------------------------------------------------------------*/
132 int
133 cc1200_arch_spi_rw(uint8_t *inbuf, const uint8_t *write_buf, uint16_t len)
134 {
135  int i;
136  uint8_t c;
137 
138  if((inbuf == NULL && write_buf == NULL) || len <= 0) {
139  return 1;
140  } else if(inbuf == NULL) {
141  for(i = 0; i < len; i++) {
142  SPI_WAITFORTx_BEFORE();
143  SPIX_BUF(CC1200_SPI_INSTANCE) = write_buf[i];
144  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
145  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
146  c = SPIX_BUF(CC1200_SPI_INSTANCE);
147  /* read and discard to avoid "variable set but not used" warning */
148  (void)c;
149  }
150  } else if(write_buf == NULL) {
151  for(i = 0; i < len; i++) {
152  SPI_WAITFORTx_BEFORE();
153  SPIX_BUF(CC1200_SPI_INSTANCE) = 0;
154  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
155  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
156  inbuf[i] = SPIX_BUF(CC1200_SPI_INSTANCE);
157  }
158  } else {
159  for(i = 0; i < len; i++) {
160  SPI_WAITFORTx_BEFORE();
161  SPIX_BUF(CC1200_SPI_INSTANCE) = write_buf[i];
162  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
163  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
164  inbuf[i] = SPIX_BUF(CC1200_SPI_INSTANCE);
165  }
166  }
167  return 0;
168 }
169 /*---------------------------------------------------------------------------*/
170 static gpio_hal_event_handler_t interrupt_handler = {
171  .next = NULL,
172  .handler = cc1200_int_handler,
173  .pin_mask =
174  (gpio_hal_pin_to_mask(CC1200_GDO0_PIN) << (CC1200_GDO0_PORT << 3)) |
175  (gpio_hal_pin_to_mask(CC1200_GDO2_PIN) << (CC1200_GDO2_PORT << 3))
176 };
177 /*---------------------------------------------------------------------------*/
178 void
179 cc1200_arch_gpio0_setup_irq(int rising)
180 {
181 
182  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
183  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
184  GPIO_DETECT_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
185  GPIO_TRIGGER_SINGLE_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
186 
187  if(rising) {
188  GPIO_DETECT_RISING(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
189  } else {
190  GPIO_DETECT_FALLING(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
191  }
192 
193  GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
194  ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE);
195  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
196  gpio_hal_register_handler(&interrupt_handler);
197 }
198 /*---------------------------------------------------------------------------*/
199 void
200 cc1200_arch_gpio2_setup_irq(int rising)
201 {
202 
203  GPIO_SOFTWARE_CONTROL(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
204  GPIO_SET_INPUT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
205  GPIO_DETECT_EDGE(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
206  GPIO_TRIGGER_SINGLE_EDGE(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
207 
208  if(rising) {
209  GPIO_DETECT_RISING(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
210  } else {
211  GPIO_DETECT_FALLING(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
212  }
213 
214  GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
215  ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE);
216  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
217  gpio_hal_register_handler(&interrupt_handler);
218 }
219 /*---------------------------------------------------------------------------*/
220 void
221 cc1200_arch_gpio0_enable_irq(void)
222 {
223  GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
224  ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE);
225  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
226 }
227 /*---------------------------------------------------------------------------*/
228 void
229 cc1200_arch_gpio0_disable_irq(void)
230 {
231  GPIO_DISABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
232 }
233 /*---------------------------------------------------------------------------*/
234 void
235 cc1200_arch_gpio2_enable_irq(void)
236 {
237  GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
238  ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE);
239  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
240 }
241 /*---------------------------------------------------------------------------*/
242 void
243 cc1200_arch_gpio2_disable_irq(void)
244 {
245  GPIO_DISABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
246 }
247 /*---------------------------------------------------------------------------*/
248 int
249 cc1200_arch_gpio0_read_pin(void)
250 {
251  return (GPIO_READ_PIN(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK) ? 1 : 0);
252 }
253 /*---------------------------------------------------------------------------*/
254 int
255 cc1200_arch_gpio2_read_pin(void)
256 {
257  return GPIO_READ_PIN(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
258 }
259 /*---------------------------------------------------------------------------*/
260 int
261 cc1200_arch_gpio3_read_pin(void)
262 {
263  return 0x00;
264 }
265 /*---------------------------------------------------------------------------*/
266 void
267 cc1200_arch_init(void)
268 {
269  /* First leave RESET high */
270  GPIO_SOFTWARE_CONTROL(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
271  GPIO_SET_OUTPUT(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
272  ioc_set_over(CC1200_RESET_PORT, CC1200_RESET_PIN, IOC_OVERRIDE_OE);
273  GPIO_SET_PIN(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
274 
275  /* Initialize CSn, enable CSn and then wait for MISO to go low*/
276  spix_cs_init(CC1200_SPI_CSN_PORT, CC1200_SPI_CSN_PIN);
277 
278  /* Initialize SPI */
279  spix_init(CC1200_SPI_INSTANCE);
280 
281  /* Configure GPIOx */
282  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
283  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
284  GPIO_SOFTWARE_CONTROL(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
285  GPIO_SET_INPUT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
286 
287  /* Leave CSn as default */
288  cc1200_arch_spi_deselect();
289 
290  /* Ensure MISO is high */
291  BUSYWAIT_UNTIL(
292  GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK),
293  RTIMER_SECOND / 10);
294 }
295 /*---------------------------------------------------------------------------*/
296 /**
297  * @}
298  * @}
299  */
300 
Datatype for GPIO event handlers.
Definition: gpio-hal.h:127
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:201
void spix_init(uint8_t spi)
Initialize the SPI bus for the instance given.
Definition: spi-legacy.c:213
Header file for the cc2538 System Control driver.
#define GPIO_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:106
Header file for the cc2538 Synchronous Serial Interface.
Header file with register and macro declarations for the cc2538 GPIO module.
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
Definition: gpio.h:154
#define GPIO_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition: gpio.h:113
Header file with declarations for the I/O Control module.
Header file with register manipulation macro definitions.
#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:185
#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:193
#define GPIO_READ_PIN(PORT_BASE, PIN_MASK)
Read pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:147
void gpio_hal_register_handler(gpio_hal_event_handler_t *handler)
Register a function to be called whenever a pin triggers an event.
Definition: gpio-hal.c:55
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
Definition: core_cm0.h:642
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:209
#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
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:78
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:85
Basic SPI macros
uint32_t gpio_hal_pin_mask_t
GPIO pin mask representation.
Definition: gpio-hal.h:99
#define IOC_OVERRIDE_OE
Output Enable.
Definition: ioc.h:222
void spix_cs_init(uint8_t port, uint8_t pin)
Configure a GPIO to be the chip select pin.
Definition: spi-legacy.c:354
#define IOC_OVERRIDE_PUE
Pull Up Enable.
Definition: ioc.h:223
#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:177
#define gpio_hal_pin_to_mask(pin)
Convert a pin to a pin mask.
Definition: gpio-hal.h:190
Header file for the cc2538 SPI driver, including macros for the implementation of the low-level SPI p...
Header file for the GPIO HAL.
Header file for the LED HAL.