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 #else
80 #define PRINTF(...)
81 #endif
82 /*---------------------------------------------------------------------------*/
83 extern int cc1200_rx_interrupt(void);
84 /*---------------------------------------------------------------------------*/
85 void
86 cc1200_int_handler(gpio_hal_pin_mask_t pin_mask)
87 {
88  /* To keep the gpio_register_callback happy */
89  cc1200_rx_interrupt();
90 }
91 /*---------------------------------------------------------------------------*/
92 void
93 cc1200_arch_spi_select(void)
94 {
95  /* Set CSn to low (0) */
96  GPIO_CLR_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
97  /* The MISO pin should go low before chip is fully enabled. */
99  GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK) == 0,
100  RTIMER_SECOND / 100);
101 }
102 /*---------------------------------------------------------------------------*/
103 void
104 cc1200_arch_spi_deselect(void)
105 {
106  /* Set CSn to high (1) */
107  GPIO_SET_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
108 }
109 /*---------------------------------------------------------------------------*/
110 int
111 cc1200_arch_spi_rw_byte(uint8_t c)
112 {
113  SPI_WAITFORTx_BEFORE();
114  SPIX_BUF(CC1200_SPI_INSTANCE) = c;
115  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
116  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
117  c = SPIX_BUF(CC1200_SPI_INSTANCE);
118 
119  return c;
120 }
121 /*---------------------------------------------------------------------------*/
122 int
123 cc1200_arch_spi_rw(uint8_t *inbuf, const uint8_t *write_buf, uint16_t len)
124 {
125  int i;
126  uint8_t c;
127 
128  if((inbuf == NULL && write_buf == NULL) || len <= 0) {
129  return 1;
130  } else if(inbuf == NULL) {
131  for(i = 0; i < len; i++) {
132  SPI_WAITFORTx_BEFORE();
133  SPIX_BUF(CC1200_SPI_INSTANCE) = write_buf[i];
134  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
135  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
136  c = SPIX_BUF(CC1200_SPI_INSTANCE);
137  /* read and discard to avoid "variable set but not used" warning */
138  (void)c;
139  }
140  } else if(write_buf == NULL) {
141  for(i = 0; i < len; i++) {
142  SPI_WAITFORTx_BEFORE();
143  SPIX_BUF(CC1200_SPI_INSTANCE) = 0;
144  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
145  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
146  inbuf[i] = SPIX_BUF(CC1200_SPI_INSTANCE);
147  }
148  } else {
149  for(i = 0; i < len; i++) {
150  SPI_WAITFORTx_BEFORE();
151  SPIX_BUF(CC1200_SPI_INSTANCE) = write_buf[i];
152  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
153  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
154  inbuf[i] = SPIX_BUF(CC1200_SPI_INSTANCE);
155  }
156  }
157  return 0;
158 }
159 /*---------------------------------------------------------------------------*/
160 static gpio_hal_event_handler_t interrupt_handler = {
161  .next = NULL,
162  .handler = cc1200_int_handler,
163  .pin_mask =
164  (gpio_hal_pin_to_mask(CC1200_GDO0_PIN) << (CC1200_GDO0_PORT << 3)) |
165  (gpio_hal_pin_to_mask(CC1200_GDO2_PIN) << (CC1200_GDO2_PORT << 3))
166 };
167 /*---------------------------------------------------------------------------*/
168 void
169 cc1200_arch_gpio0_setup_irq(int rising)
170 {
171 
172  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
173  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
174  GPIO_DETECT_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
175  GPIO_TRIGGER_SINGLE_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
176 
177  if(rising) {
178  GPIO_DETECT_RISING(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
179  } else {
180  GPIO_DETECT_FALLING(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
181  }
182 
183  GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
184  ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE);
185  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
186  gpio_hal_register_handler(&interrupt_handler);
187 }
188 /*---------------------------------------------------------------------------*/
189 void
190 cc1200_arch_gpio2_setup_irq(int rising)
191 {
192 
193  GPIO_SOFTWARE_CONTROL(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
194  GPIO_SET_INPUT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
195  GPIO_DETECT_EDGE(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
196  GPIO_TRIGGER_SINGLE_EDGE(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
197 
198  if(rising) {
199  GPIO_DETECT_RISING(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
200  } else {
201  GPIO_DETECT_FALLING(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
202  }
203 
204  GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
205  ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE);
206  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
207  gpio_hal_register_handler(&interrupt_handler);
208 }
209 /*---------------------------------------------------------------------------*/
210 void
211 cc1200_arch_gpio0_enable_irq(void)
212 {
213  GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
214  ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_PUE);
215  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
216 }
217 /*---------------------------------------------------------------------------*/
218 void
219 cc1200_arch_gpio0_disable_irq(void)
220 {
221  GPIO_DISABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
222 }
223 /*---------------------------------------------------------------------------*/
224 void
225 cc1200_arch_gpio2_enable_irq(void)
226 {
227  GPIO_ENABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
228  ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_PUE);
229  NVIC_EnableIRQ(CC1200_GPIOx_VECTOR);
230 }
231 /*---------------------------------------------------------------------------*/
232 void
233 cc1200_arch_gpio2_disable_irq(void)
234 {
235  GPIO_DISABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
236 }
237 /*---------------------------------------------------------------------------*/
238 int
239 cc1200_arch_gpio0_read_pin(void)
240 {
241  return (GPIO_READ_PIN(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK) ? 1 : 0);
242 }
243 /*---------------------------------------------------------------------------*/
244 int
245 cc1200_arch_gpio2_read_pin(void)
246 {
247  return GPIO_READ_PIN(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
248 }
249 /*---------------------------------------------------------------------------*/
250 int
251 cc1200_arch_gpio3_read_pin(void)
252 {
253  return 0x00;
254 }
255 /*---------------------------------------------------------------------------*/
256 void
257 cc1200_arch_init(void)
258 {
259  /* First leave RESET high */
260  GPIO_SOFTWARE_CONTROL(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
261  GPIO_SET_OUTPUT(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
262  ioc_set_over(CC1200_RESET_PORT, CC1200_RESET_PIN, IOC_OVERRIDE_OE);
263  GPIO_SET_PIN(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
264 
265  /* Initialize CSn, enable CSn and then wait for MISO to go low*/
266  spix_cs_init(CC1200_SPI_CSN_PORT, CC1200_SPI_CSN_PIN);
267 
268  /* Initialize SPI */
269  spix_init(CC1200_SPI_INSTANCE);
270 
271  /* Configure GPIOx */
272  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
273  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
274  GPIO_SOFTWARE_CONTROL(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
275  GPIO_SET_INPUT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
276 
277  /* Leave CSn as default */
278  cc1200_arch_spi_deselect();
279 
280  /* Ensure MISO is high */
282  GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK),
283  RTIMER_SECOND / 10);
284 }
285 /*---------------------------------------------------------------------------*/
286 /**
287  * @}
288  * @}
289  */
Datatype for GPIO event handlers.
Definition: gpio-hal.h:180
#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.
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
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 RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
#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:142
#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:255
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.