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/*---------------------------------------------------------------------------*/
87bool
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/*---------------------------------------------------------------------------*/
98spi_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/*---------------------------------------------------------------------------*/
112spi_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/*---------------------------------------------------------------------------*/
126spi_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/*---------------------------------------------------------------------------*/
140spi_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/*---------------------------------------------------------------------------*/
154spi_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/*---------------------------------------------------------------------------*/
192spi_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/*---------------------------------------------------------------------------*/
215spi_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 */
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_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
spi_status_t spi_release(const spi_device_t *dev)
Closes and then unlocks an SPI controller.
Definition: spi.c:57
spi_status_t spi_arch_close_and_unlock(const spi_device_t *dev)
Closes and unlocks an SPI controller.
Definition: spi-arch.c:268
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
#define SPI_DEVICE_PORT(member, device)
Retrieve the SPI device's port number if applicable.
Definition: spi.h:129
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 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
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_deselect(const spi_device_t *dev)
Deselects the SPI peripheral.
Definition: spi.c:80
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_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_acquire(const spi_device_t *dev)
Locks and then opens an SPI controller.
Definition: spi.c:46
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_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
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_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_select(const spi_device_t *dev)
Selects the SPI peripheral.
Definition: spi.c:68
Header file for the SPI HAL.
SPI Device Configuration.
Definition: spi.h:100