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/*---------------------------------------------------------------------------*/
83extern int cc1200_rx_interrupt(void);
84/*---------------------------------------------------------------------------*/
85void
86cc1200_int_handler(gpio_hal_pin_mask_t pin_mask)
87{
88 /* To keep the gpio_register_callback happy */
89 cc1200_rx_interrupt();
90}
91/*---------------------------------------------------------------------------*/
92void
93cc1200_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/*---------------------------------------------------------------------------*/
103void
104cc1200_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/*---------------------------------------------------------------------------*/
110int
111cc1200_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/*---------------------------------------------------------------------------*/
122int
123cc1200_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/*---------------------------------------------------------------------------*/
160static 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/*---------------------------------------------------------------------------*/
168void
169cc1200_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/*---------------------------------------------------------------------------*/
189void
190cc1200_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/*---------------------------------------------------------------------------*/
210void
211cc1200_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/*---------------------------------------------------------------------------*/
218void
219cc1200_arch_gpio0_disable_irq(void)
220{
221 GPIO_DISABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
222}
223/*---------------------------------------------------------------------------*/
224void
225cc1200_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/*---------------------------------------------------------------------------*/
232void
233cc1200_arch_gpio2_disable_irq(void)
234{
235 GPIO_DISABLE_INTERRUPT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
236}
237/*---------------------------------------------------------------------------*/
238int
239cc1200_arch_gpio0_read_pin(void)
240{
241 return (GPIO_READ_PIN(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK) ? 1 : 0);
242}
243/*---------------------------------------------------------------------------*/
244int
245cc1200_arch_gpio2_read_pin(void)
246{
247 return GPIO_READ_PIN(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
248}
249/*---------------------------------------------------------------------------*/
250int
251cc1200_arch_gpio3_read_pin(void)
252{
253 return 0x00;
254}
255/*---------------------------------------------------------------------------*/
256void
257cc1200_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 */
Header file for the GPIO HAL.
Header file with register and macro declarations for the cc2538 GPIO module.
#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_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
#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_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:78
#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_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:106
#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_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition: gpio.h:113
#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_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:85
#define GPIO_READ_PIN(PORT_BASE, PIN_MASK)
Read pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:147
#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
#define IOC_OVERRIDE_OE
Output Enable.
Definition: ioc.h:222
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
#define IOC_OVERRIDE_PUE
Pull Up Enable.
Definition: ioc.h:223
void spix_init(uint8_t spi)
Initialize the SPI bus for the instance given.
Definition: spi-legacy.c:213
void spix_cs_init(uint8_t port, uint8_t pin)
Configure a GPIO to be the chip select pin.
Definition: spi-legacy.c:354
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
uint32_t gpio_hal_pin_mask_t
GPIO pin mask representation.
Definition: gpio-hal.h:142
#define gpio_hal_pin_to_mask(pin)
Convert a pin to a pin mask.
Definition: gpio-hal.h:255
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
Header file with declarations for the I/O Control module.
Header file for the LED HAL.
Header file with register manipulation macro definitions.
Header file for the cc2538 SPI driver, including macros for the implementation of the low-level SPI p...
Basic SPI macros.
Header file for the cc2538 Synchronous Serial Interface.
Datatype for GPIO event handlers.
Definition: gpio-hal.h:180
Header file for the cc2538 System Control driver.