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  return spi_arch_select(dev);
71 }
72 /*---------------------------------------------------------------------------*/
75 {
76  return spi_arch_deselect(dev);
77 }
78 /*---------------------------------------------------------------------------*/
79 bool
81 {
82  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
83  return false;
84  }
85 
86  return spi_arch_has_lock(dev);
87 }
88 /*---------------------------------------------------------------------------*/
90 spi_write_byte(spi_device_t *dev, uint8_t data)
91 {
92  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
93  return SPI_DEV_STATUS_EINVAL;
94  }
95 
96  if(!spi_arch_has_lock(dev)) {
97  return SPI_DEV_STATUS_BUS_LOCKED;
98  }
99 
100  return spi_arch_transfer(dev, &data, 1, 0, 0, 0);
101 }
102 /*---------------------------------------------------------------------------*/
104 spi_write(spi_device_t *dev, const uint8_t *data, int size)
105 {
106  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
107  return SPI_DEV_STATUS_EINVAL;
108  }
109 
110  if(!spi_arch_has_lock(dev)) {
111  return SPI_DEV_STATUS_BUS_LOCKED;
112  }
113 
114  return spi_arch_transfer(dev, data, size, 0, 0, 0);
115 }
116 /*---------------------------------------------------------------------------*/
118 spi_read_byte(spi_device_t *dev, uint8_t *buf)
119 {
120  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
121  return SPI_DEV_STATUS_EINVAL;
122  }
123 
124  if(!spi_arch_has_lock(dev)) {
125  return SPI_DEV_STATUS_BUS_LOCKED;
126  }
127 
128  return spi_arch_transfer(dev, NULL, 0, buf, 1, 0);
129 }
130 /*---------------------------------------------------------------------------*/
132 spi_read(spi_device_t *dev, uint8_t *buf, int size)
133 {
134  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
135  return SPI_DEV_STATUS_EINVAL;
136  }
137 
138  if(!spi_arch_has_lock(dev)) {
139  return SPI_DEV_STATUS_BUS_LOCKED;
140  }
141 
142  return spi_arch_transfer(dev, NULL, 0, buf, size, 0);
143 }
144 /*---------------------------------------------------------------------------*/
147 {
148  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
149  return SPI_DEV_STATUS_EINVAL;
150  }
151 
152  if(!spi_arch_has_lock(dev)) {
153  return SPI_DEV_STATUS_BUS_LOCKED;
154  }
155 
156  return spi_arch_transfer(dev, NULL, 0, NULL, 0, size);
157 }
158 /*---------------------------------------------------------------------------*/
161  const uint8_t *wdata, int wsize,
162  uint8_t *rbuf, int rsize, int ignore)
163 {
164  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
165  return SPI_DEV_STATUS_EINVAL;
166  }
167 
168  if(!spi_arch_has_lock(dev)) {
169  return SPI_DEV_STATUS_BUS_LOCKED;
170  }
171 
172  if(wdata == NULL && wsize > 0) {
173  return SPI_DEV_STATUS_EINVAL;
174  }
175 
176  if(rbuf == NULL && rsize > 0) {
177  return SPI_DEV_STATUS_EINVAL;
178  }
179 
180  return spi_arch_transfer(dev, wdata, wsize, rbuf, rsize, ignore);
181 }
182 /*---------------------------------------------------------------------------*/
184 spi_read_register(spi_device_t *dev, uint8_t reg, uint8_t *data, int size)
185 {
186  spi_status_t status;
187  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
188  return SPI_DEV_STATUS_EINVAL;
189  }
190 
191  /* write the register first (will read a status) */
192  status = spi_write_byte(dev, reg);
193  if(status != SPI_DEV_STATUS_OK) {
194  return status;
195  }
196 
197  /* then read the value (will read the value) */
198  status = spi_read(dev, data, size);
199  if(status != SPI_DEV_STATUS_OK) {
200  return status;
201  }
202 
203  return status;
204 }
205 /*---------------------------------------------------------------------------*/
207 spi_strobe(spi_device_t *dev, uint8_t strobe, uint8_t *result)
208 {
209  if(dev == NULL || dev->spi_controller >= SPI_CONTROLLER_COUNT) {
210  return SPI_DEV_STATUS_EINVAL;
211  }
212 
213  if(!spi_arch_has_lock(dev)) {
214  return SPI_DEV_STATUS_BUS_LOCKED;
215  }
216 
217  return spi_arch_transfer(dev, &strobe, 1, result, 1, 0);
218 }
219 /*---------------------------------------------------------------------------*/
220 /**
221  * @}
222  */
spi_status_t spi_arch_lock_and_open(spi_device_t *dev)
Locks and opens an SPI controller to the configuration specified.
Definition: spi-arch.c:171
bool spi_has_bus(spi_device_t *dev)
Checks if a device has locked an SPI controller.
Definition: spi.c:80
spi_status_t spi_read(spi_device_t *dev, uint8_t *buf, int size)
Reads a buffer from an SPI device.
Definition: spi.c:132
spi_status_t spi_write(spi_device_t *dev, const uint8_t *data, int size)
Writes a buffer to an SPI device.
Definition: spi.c:104
spi_status_t spi_read_register(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:184
bool spi_arch_has_lock(spi_device_t *dev)
Checks if a device has locked an SPI controller.
Definition: spi-arch.c:151
Header file for the SPI HAL.
spi_status_t
SPI return codes.
Definition: spi.h:80
spi_status_t spi_write_byte(spi_device_t *dev, uint8_t data)
Writes a single byte to an SPI device.
Definition: spi.c:90
spi_status_t spi_read_skip(spi_device_t *dev, int size)
Reads and ignores data from an SPI device.
Definition: spi.c:146
spi_status_t spi_strobe(spi_device_t *dev, uint8_t strobe, uint8_t *result)
Reads and Writes one byte from/to an SPI device.
Definition: spi.c:207
spi_status_t spi_deselect(spi_device_t *dev)
Deselects the SPI peripheral.
Definition: spi.c:74
spi_status_t spi_arch_deselect(spi_device_t *dev)
Deselects an SPI device.
Definition: spi-arch.c:298
spi_status_t spi_release(spi_device_t *dev)
Closes and then unlocks an SPI controller.
Definition: spi.c:57
spi_status_t spi_acquire(spi_device_t *dev)
Locks and then opens an SPI controller.
Definition: spi.c:46
spi_status_t spi_arch_transfer(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:307
spi_status_t spi_select(spi_device_t *dev)
Selects the SPI peripheral.
Definition: spi.c:68
spi_status_t spi_transfer(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:160
SPI Device Configuration.
Definition: spi.h:97
spi_status_t spi_arch_select(spi_device_t *dev)
Selects an SPI device.
Definition: spi-arch.c:285
spi_status_t spi_read_byte(spi_device_t *dev, uint8_t *buf)
Reads a single byte from an SPI device.
Definition: spi.c:118
spi_status_t spi_arch_close_and_unlock(spi_device_t *dev)
Closes and unlocks an SPI controller.
Definition: spi-arch.c:268