Contiki-NG
spi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2017, Yanzi Networks.
3  * Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
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 HOLDER 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 spi-hal
34  * @{
35  *
36  * \file
37  * Implementation of the platform-independent aspects of the SPI HAL
38  */
39 /*---------------------------------------------------------------------------*/
40 #include <dev/spi.h>
41 #include "contiki.h"
42 #include <stdint.h>
43 #include <stdbool.h>
44 /*---------------------------------------------------------------------------*/
47 {
48  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
49  return SPI_DEV_STATUS_EINVAL;
50  }
51 
52  /* lock and open the bus */
53  return spi_arch_lock_and_open(dev);
54 }
55 /*---------------------------------------------------------------------------*/
58 {
59  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
60  return SPI_DEV_STATUS_EINVAL;
61  }
62 
63  /* close and unlock the bus */
64  return spi_arch_close_and_unlock(dev);
65 }
66 /*---------------------------------------------------------------------------*/
69 {
70  if(!spi_arch_has_lock(dev)) {
71  return SPI_DEV_STATUS_BUS_NOT_OWNED;
72  }
73 
74  gpio_hal_arch_clear_pin(SPI_DEVICE_PORT(cs, dev), dev->pin_spi_cs);
75 
76  return SPI_DEV_STATUS_OK;
77 }
78 /*---------------------------------------------------------------------------*/
81 {
82  gpio_hal_arch_set_pin(SPI_DEVICE_PORT(cs, dev), dev->pin_spi_cs);
83 
84  return SPI_DEV_STATUS_OK;
85 }
86 /*---------------------------------------------------------------------------*/
87 bool
89 {
90  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
91  return false;
92  }
93 
94  return spi_arch_has_lock(dev);
95 }
96 /*---------------------------------------------------------------------------*/
98 spi_write_byte(const spi_device_t *dev, uint8_t data)
99 {
100  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
101  return SPI_DEV_STATUS_EINVAL;
102  }
103 
104  if(!spi_arch_has_lock(dev)) {
105  return SPI_DEV_STATUS_BUS_LOCKED;
106  }
107 
108  return spi_arch_transfer(dev, &data, 1, 0, 0, 0);
109 }
110 /*---------------------------------------------------------------------------*/
112 spi_write(const spi_device_t *dev, const uint8_t *data, int size)
113 {
114  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
115  return SPI_DEV_STATUS_EINVAL;
116  }
117 
118  if(!spi_arch_has_lock(dev)) {
119  return SPI_DEV_STATUS_BUS_LOCKED;
120  }
121 
122  return spi_arch_transfer(dev, data, size, 0, 0, 0);
123 }
124 /*---------------------------------------------------------------------------*/
126 spi_read_byte(const spi_device_t *dev, uint8_t *buf)
127 {
128  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
129  return SPI_DEV_STATUS_EINVAL;
130  }
131 
132  if(!spi_arch_has_lock(dev)) {
133  return SPI_DEV_STATUS_BUS_LOCKED;
134  }
135 
136  return spi_arch_transfer(dev, NULL, 0, buf, 1, 0);
137 }
138 /*---------------------------------------------------------------------------*/
140 spi_read(const spi_device_t *dev, uint8_t *buf, int size)
141 {
142  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
143  return SPI_DEV_STATUS_EINVAL;
144  }
145 
146  if(!spi_arch_has_lock(dev)) {
147  return SPI_DEV_STATUS_BUS_LOCKED;
148  }
149 
150  return spi_arch_transfer(dev, NULL, 0, buf, size, 0);
151 }
152 /*---------------------------------------------------------------------------*/
154 spi_read_skip(const spi_device_t *dev, int size)
155 {
156  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
157  return SPI_DEV_STATUS_EINVAL;
158  }
159 
160  if(!spi_arch_has_lock(dev)) {
161  return SPI_DEV_STATUS_BUS_LOCKED;
162  }
163 
164  return spi_arch_transfer(dev, NULL, 0, NULL, 0, size);
165 }
166 /*---------------------------------------------------------------------------*/
169  const uint8_t *wdata, int wsize,
170  uint8_t *rbuf, int rsize, int ignore)
171 {
172  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
173  return SPI_DEV_STATUS_EINVAL;
174  }
175 
176  if(!spi_arch_has_lock(dev)) {
177  return SPI_DEV_STATUS_BUS_LOCKED;
178  }
179 
180  if(wdata == NULL && wsize > 0) {
181  return SPI_DEV_STATUS_EINVAL;
182  }
183 
184  if(rbuf == NULL && rsize > 0) {
185  return SPI_DEV_STATUS_EINVAL;
186  }
187 
188  return spi_arch_transfer(dev, wdata, wsize, rbuf, rsize, ignore);
189 }
190 /*---------------------------------------------------------------------------*/
192 spi_read_register(const spi_device_t *dev, uint8_t reg, uint8_t *data, int size)
193 {
194  spi_status_t status;
195  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
196  return SPI_DEV_STATUS_EINVAL;
197  }
198 
199  /* write the register first (will read a status) */
200  status = spi_write_byte(dev, reg);
201  if(status != SPI_DEV_STATUS_OK) {
202  return status;
203  }
204 
205  /* then read the value (will read the value) */
206  status = spi_read(dev, data, size);
207  if(status != SPI_DEV_STATUS_OK) {
208  return status;
209  }
210 
211  return status;
212 }
213 /*---------------------------------------------------------------------------*/
215 spi_strobe(const spi_device_t *dev, uint8_t strobe, uint8_t *result)
216 {
217  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
218  return SPI_DEV_STATUS_EINVAL;
219  }
220 
221  if(!spi_arch_has_lock(dev)) {
222  return SPI_DEV_STATUS_BUS_LOCKED;
223  }
224 
225  return spi_arch_transfer(dev, &strobe, 1, result, 1, 0);
226 }
227 /*---------------------------------------------------------------------------*/
228 /**
229  * @}
230  */
bool spi_arch_has_lock(const spi_device_t *dev)
Checks if a device has locked an SPI controller.
Definition: spi-arch.c:151
spi_status_t spi_select(const spi_device_t *dev)
Selects the SPI peripheral.
Definition: spi.c:68
spi_status_t spi_read(const spi_device_t *dev, uint8_t *buf, int size)
Reads a buffer from an SPI device.
Definition: spi.c:140
spi_status_t spi_write_byte(const spi_device_t *dev, uint8_t data)
Writes a single byte to an SPI device.
Definition: spi.c:98
spi_status_t spi_arch_transfer(const spi_device_t *dev, const uint8_t *write_buf, int wlen, uint8_t *inbuf, int rlen, int ignore_len)
Performs an SPI transfer.
Definition: spi-arch.c:286
spi_status_t spi_transfer(const spi_device_t *dev, const uint8_t *wdata, int wsize, uint8_t *rbuf, int rsize, int ignore)
Performs a generic SPI transfer.
Definition: spi.c:168
Header file for the SPI HAL.
spi_status_t spi_read_skip(const spi_device_t *dev, int size)
Reads and ignores data from an SPI device.
Definition: spi.c:154
spi_status_t
SPI return codes.
Definition: spi.h:80
spi_status_t spi_arch_lock_and_open(const spi_device_t *dev)
Locks and opens an SPI controller to the configuration specified.
Definition: spi-arch.c:171
spi_status_t spi_strobe(const spi_device_t *dev, uint8_t strobe, uint8_t *result)
Reads and Writes one byte from/to an SPI device.
Definition: spi.c:215
spi_status_t spi_read_register(const spi_device_t *dev, uint8_t reg, uint8_t *data, int size)
Reads a buffer of bytes from a register of an SPI device.
Definition: spi.c:192
bool spi_has_bus(const spi_device_t *dev)
Checks if a device has locked an SPI controller.
Definition: spi.c:88
spi_status_t spi_read_byte(const spi_device_t *dev, uint8_t *buf)
Reads a single byte from an SPI device.
Definition: spi.c:126
spi_status_t spi_write(const spi_device_t *dev, const uint8_t *data, int size)
Writes a buffer to an SPI device.
Definition: spi.c:112
spi_status_t spi_acquire(const spi_device_t *dev)
Locks and then opens an SPI controller.
Definition: spi.c:46
spi_status_t spi_deselect(const spi_device_t *dev)
Deselects the SPI peripheral.
Definition: spi.c:80
SPI Device Configuration.
Definition: spi.h:100
spi_status_t spi_release(const spi_device_t *dev)
Closes and then unlocks an SPI controller.
Definition: spi.c:57
#define SPI_DEVICE_PORT(member, device)
Retrieve the SPI device&#39;s port number if applicable.
Definition: spi.h:129
spi_status_t spi_arch_close_and_unlock(const spi_device_t *dev)
Closes and unlocks an SPI controller.
Definition: spi-arch.c:268