mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /*
elessair 0:f269e3021894 2 * Copyright (c) 2013 Nordic Semiconductor ASA
elessair 0:f269e3021894 3 * All rights reserved.
elessair 0:f269e3021894 4 *
elessair 0:f269e3021894 5 * Redistribution and use in source and binary forms, with or without modification,
elessair 0:f269e3021894 6 * are permitted provided that the following conditions are met:
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * 1. Redistributions of source code must retain the above copyright notice, this list
elessair 0:f269e3021894 9 * of conditions and the following disclaimer.
elessair 0:f269e3021894 10 *
elessair 0:f269e3021894 11 * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
elessair 0:f269e3021894 12 * integrated circuit in a product or a software update for such product, must reproduce
elessair 0:f269e3021894 13 * the above copyright notice, this list of conditions and the following disclaimer in
elessair 0:f269e3021894 14 * the documentation and/or other materials provided with the distribution.
elessair 0:f269e3021894 15 *
elessair 0:f269e3021894 16 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
elessair 0:f269e3021894 17 * used to endorse or promote products derived from this software without specific prior
elessair 0:f269e3021894 18 * written permission.
elessair 0:f269e3021894 19 *
elessair 0:f269e3021894 20 * 4. This software, with or without modification, must only be used with a
elessair 0:f269e3021894 21 * Nordic Semiconductor ASA integrated circuit.
elessair 0:f269e3021894 22 *
elessair 0:f269e3021894 23 * 5. Any software provided in binary or object form under this license must not be reverse
elessair 0:f269e3021894 24 * engineered, decompiled, modified and/or disassembled.
elessair 0:f269e3021894 25 *
elessair 0:f269e3021894 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
elessair 0:f269e3021894 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
elessair 0:f269e3021894 28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
elessair 0:f269e3021894 29 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
elessair 0:f269e3021894 30 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
elessair 0:f269e3021894 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
elessair 0:f269e3021894 32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
elessair 0:f269e3021894 33 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
elessair 0:f269e3021894 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
elessair 0:f269e3021894 35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
elessair 0:f269e3021894 36 *
elessair 0:f269e3021894 37 */
elessair 0:f269e3021894 38
elessair 0:f269e3021894 39
elessair 0:f269e3021894 40 #include "spi_api.h"
elessair 0:f269e3021894 41
elessair 0:f269e3021894 42 #if DEVICE_SPI
elessair 0:f269e3021894 43
elessair 0:f269e3021894 44 #include "cmsis.h"
elessair 0:f269e3021894 45 #include "pinmap.h"
elessair 0:f269e3021894 46 #include "mbed_assert.h"
elessair 0:f269e3021894 47 #include "mbed_error.h"
elessair 0:f269e3021894 48 #include "nrf_drv_spi.h"
elessair 0:f269e3021894 49 #include "nrf_drv_spis.h"
elessair 0:f269e3021894 50 #include "app_util_platform.h"
elessair 0:f269e3021894 51
elessair 0:f269e3021894 52 #if DEVICE_SPI_ASYNCH
elessair 0:f269e3021894 53 #define SPI_IDX(obj) ((obj)->spi.spi_idx)
elessair 0:f269e3021894 54 #else
elessair 0:f269e3021894 55 #define SPI_IDX(obj) ((obj)->spi_idx)
elessair 0:f269e3021894 56 #endif
elessair 0:f269e3021894 57 #define SPI_INFO(obj) (&m_spi_info[SPI_IDX(obj)])
elessair 0:f269e3021894 58 #define MASTER_INST(obj) (&m_instances[SPI_IDX(obj)].master)
elessair 0:f269e3021894 59 #define SLAVE_INST(obj) (&m_instances[SPI_IDX(obj)].slave)
elessair 0:f269e3021894 60
elessair 0:f269e3021894 61 typedef struct {
elessair 0:f269e3021894 62 bool initialized;
elessair 0:f269e3021894 63 bool master;
elessair 0:f269e3021894 64 uint8_t sck_pin;
elessair 0:f269e3021894 65 uint8_t mosi_pin;
elessair 0:f269e3021894 66 uint8_t miso_pin;
elessair 0:f269e3021894 67 uint8_t ss_pin;
elessair 0:f269e3021894 68 uint8_t spi_mode;
elessair 0:f269e3021894 69 nrf_drv_spi_frequency_t frequency;
elessair 0:f269e3021894 70 volatile union {
elessair 0:f269e3021894 71 bool busy; // master
elessair 0:f269e3021894 72 bool readable; // slave
elessair 0:f269e3021894 73 } flag;
elessair 0:f269e3021894 74 volatile uint8_t tx_buf;
elessair 0:f269e3021894 75 volatile uint8_t rx_buf;
elessair 0:f269e3021894 76
elessair 0:f269e3021894 77 #if DEVICE_SPI_ASYNCH
elessair 0:f269e3021894 78 uint32_t handler;
elessair 0:f269e3021894 79 uint32_t event;
elessair 0:f269e3021894 80 #endif
elessair 0:f269e3021894 81 } spi_info_t;
elessair 0:f269e3021894 82 static spi_info_t m_spi_info[SPI_COUNT];
elessair 0:f269e3021894 83
elessair 0:f269e3021894 84 typedef struct {
elessair 0:f269e3021894 85 nrf_drv_spi_t master;
elessair 0:f269e3021894 86 nrf_drv_spis_t slave;
elessair 0:f269e3021894 87 } sdk_driver_instances_t;
elessair 0:f269e3021894 88 static sdk_driver_instances_t m_instances[SPI_COUNT] = {
elessair 0:f269e3021894 89 #if SPI0_ENABLED
elessair 0:f269e3021894 90 {
elessair 0:f269e3021894 91 NRF_DRV_SPI_INSTANCE(0),
elessair 0:f269e3021894 92 NRF_DRV_SPIS_INSTANCE(0)
elessair 0:f269e3021894 93 },
elessair 0:f269e3021894 94 #endif
elessair 0:f269e3021894 95 #if SPI1_ENABLED
elessair 0:f269e3021894 96 {
elessair 0:f269e3021894 97 NRF_DRV_SPI_INSTANCE(1),
elessair 0:f269e3021894 98 NRF_DRV_SPIS_INSTANCE(1)
elessair 0:f269e3021894 99 },
elessair 0:f269e3021894 100 #endif
elessair 0:f269e3021894 101 #if SPI2_ENABLED
elessair 0:f269e3021894 102 {
elessair 0:f269e3021894 103 NRF_DRV_SPI_INSTANCE(2),
elessair 0:f269e3021894 104 NRF_DRV_SPIS_INSTANCE(2)
elessair 0:f269e3021894 105 },
elessair 0:f269e3021894 106 #endif
elessair 0:f269e3021894 107 };
elessair 0:f269e3021894 108
elessair 0:f269e3021894 109 static void master_event_handler(uint8_t spi_idx,
elessair 0:f269e3021894 110 nrf_drv_spi_evt_t const *p_event)
elessair 0:f269e3021894 111 {
elessair 0:f269e3021894 112 spi_info_t *p_spi_info = &m_spi_info[spi_idx];
elessair 0:f269e3021894 113
elessair 0:f269e3021894 114 if (p_event->type == NRF_DRV_SPI_EVENT_DONE) {
elessair 0:f269e3021894 115 p_spi_info->flag.busy = false;
elessair 0:f269e3021894 116 if (p_spi_info->handler) {
elessair 0:f269e3021894 117 void (*handler)(void) = (void (*)(void))p_spi_info->handler;
elessair 0:f269e3021894 118 p_spi_info->handler = 0;
elessair 0:f269e3021894 119 handler();
elessair 0:f269e3021894 120 }
elessair 0:f269e3021894 121 }
elessair 0:f269e3021894 122 }
elessair 0:f269e3021894 123 #define MASTER_EVENT_HANDLER(idx) \
elessair 0:f269e3021894 124 static void master_event_handler_##idx(nrf_drv_spi_evt_t const *p_event) { \
elessair 0:f269e3021894 125 master_event_handler(SPI##idx##_INSTANCE_INDEX, p_event); \
elessair 0:f269e3021894 126 }
elessair 0:f269e3021894 127 #if SPI0_ENABLED
elessair 0:f269e3021894 128 MASTER_EVENT_HANDLER(0)
elessair 0:f269e3021894 129 #endif
elessair 0:f269e3021894 130 #if SPI1_ENABLED
elessair 0:f269e3021894 131 MASTER_EVENT_HANDLER(1)
elessair 0:f269e3021894 132 #endif
elessair 0:f269e3021894 133 #if SPI2_ENABLED
elessair 0:f269e3021894 134 MASTER_EVENT_HANDLER(2)
elessair 0:f269e3021894 135 #endif
elessair 0:f269e3021894 136
elessair 0:f269e3021894 137 static nrf_drv_spi_handler_t const m_master_event_handlers[SPI_COUNT] = {
elessair 0:f269e3021894 138 #if SPI0_ENABLED
elessair 0:f269e3021894 139 master_event_handler_0,
elessair 0:f269e3021894 140 #endif
elessair 0:f269e3021894 141 #if SPI1_ENABLED
elessair 0:f269e3021894 142 master_event_handler_1,
elessair 0:f269e3021894 143 #endif
elessair 0:f269e3021894 144 #if SPI2_ENABLED
elessair 0:f269e3021894 145 master_event_handler_2,
elessair 0:f269e3021894 146 #endif
elessair 0:f269e3021894 147 };
elessair 0:f269e3021894 148
elessair 0:f269e3021894 149
elessair 0:f269e3021894 150 static void slave_event_handler(uint8_t spi_idx,
elessair 0:f269e3021894 151 nrf_drv_spis_event_t event)
elessair 0:f269e3021894 152 {
elessair 0:f269e3021894 153 spi_info_t *p_spi_info = &m_spi_info[spi_idx];
elessair 0:f269e3021894 154
elessair 0:f269e3021894 155 if (event.evt_type == NRF_DRV_SPIS_XFER_DONE) {
elessair 0:f269e3021894 156 // Signal that there is some data received that could be read.
elessair 0:f269e3021894 157 p_spi_info->flag.readable = true;
elessair 0:f269e3021894 158
elessair 0:f269e3021894 159 // And prepare for the next transfer.
elessair 0:f269e3021894 160 // Previous data set in 'spi_slave_write' (if any) has been transmitted,
elessair 0:f269e3021894 161 // now use the default one, until some new is set by 'spi_slave_write'.
elessair 0:f269e3021894 162 p_spi_info->tx_buf = NRF_DRV_SPIS_DEFAULT_ORC;
elessair 0:f269e3021894 163 nrf_drv_spis_buffers_set(&m_instances[spi_idx].slave,
elessair 0:f269e3021894 164 (uint8_t const *)&p_spi_info->tx_buf, 1,
elessair 0:f269e3021894 165 (uint8_t *)&p_spi_info->rx_buf, 1);
elessair 0:f269e3021894 166 }
elessair 0:f269e3021894 167 }
elessair 0:f269e3021894 168 #define SLAVE_EVENT_HANDLER(idx) \
elessair 0:f269e3021894 169 static void slave_event_handler_##idx(nrf_drv_spis_event_t event) { \
elessair 0:f269e3021894 170 slave_event_handler(SPIS##idx##_INSTANCE_INDEX, event); \
elessair 0:f269e3021894 171 }
elessair 0:f269e3021894 172 #if SPIS0_ENABLED
elessair 0:f269e3021894 173 SLAVE_EVENT_HANDLER(0)
elessair 0:f269e3021894 174 #endif
elessair 0:f269e3021894 175 #if SPIS1_ENABLED
elessair 0:f269e3021894 176 SLAVE_EVENT_HANDLER(1)
elessair 0:f269e3021894 177 #endif
elessair 0:f269e3021894 178 #if SPIS2_ENABLED
elessair 0:f269e3021894 179 SLAVE_EVENT_HANDLER(2)
elessair 0:f269e3021894 180 #endif
elessair 0:f269e3021894 181
elessair 0:f269e3021894 182 static nrf_drv_spis_event_handler_t const m_slave_event_handlers[SPIS_COUNT] = {
elessair 0:f269e3021894 183 #if SPIS0_ENABLED
elessair 0:f269e3021894 184 slave_event_handler_0,
elessair 0:f269e3021894 185 #endif
elessair 0:f269e3021894 186 #if SPIS1_ENABLED
elessair 0:f269e3021894 187 slave_event_handler_1,
elessair 0:f269e3021894 188 #endif
elessair 0:f269e3021894 189 #if SPIS2_ENABLED
elessair 0:f269e3021894 190 slave_event_handler_2,
elessair 0:f269e3021894 191 #endif
elessair 0:f269e3021894 192 };
elessair 0:f269e3021894 193
elessair 0:f269e3021894 194 static void prepare_master_config(nrf_drv_spi_config_t *p_config,
elessair 0:f269e3021894 195 spi_info_t const *p_spi_info)
elessair 0:f269e3021894 196 {
elessair 0:f269e3021894 197 p_config->sck_pin = p_spi_info->sck_pin;
elessair 0:f269e3021894 198 p_config->mosi_pin = p_spi_info->mosi_pin;
elessair 0:f269e3021894 199 p_config->miso_pin = p_spi_info->miso_pin;
elessair 0:f269e3021894 200 p_config->ss_pin = p_spi_info->ss_pin;
elessair 0:f269e3021894 201 p_config->frequency = p_spi_info->frequency;
elessair 0:f269e3021894 202 p_config->mode = (nrf_drv_spi_mode_t)p_spi_info->spi_mode;
elessair 0:f269e3021894 203
elessair 0:f269e3021894 204 p_config->irq_priority = APP_IRQ_PRIORITY_LOW;
elessair 0:f269e3021894 205 p_config->orc = 0xFF;
elessair 0:f269e3021894 206 p_config->bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
elessair 0:f269e3021894 207 }
elessair 0:f269e3021894 208
elessair 0:f269e3021894 209 static void prepare_slave_config(nrf_drv_spis_config_t *p_config,
elessair 0:f269e3021894 210 spi_info_t const *p_spi_info)
elessair 0:f269e3021894 211 {
elessair 0:f269e3021894 212 p_config->sck_pin = p_spi_info->sck_pin;
elessair 0:f269e3021894 213 p_config->mosi_pin = p_spi_info->mosi_pin;
elessair 0:f269e3021894 214 p_config->miso_pin = p_spi_info->miso_pin;
elessair 0:f269e3021894 215 p_config->csn_pin = p_spi_info->ss_pin;
elessair 0:f269e3021894 216 p_config->mode = (nrf_drv_spis_mode_t)p_spi_info->spi_mode;
elessair 0:f269e3021894 217
elessair 0:f269e3021894 218 p_config->irq_priority = APP_IRQ_PRIORITY_LOW;
elessair 0:f269e3021894 219 p_config->orc = NRF_DRV_SPIS_DEFAULT_ORC;
elessair 0:f269e3021894 220 p_config->def = NRF_DRV_SPIS_DEFAULT_DEF;
elessair 0:f269e3021894 221 p_config->bit_order = NRF_DRV_SPIS_BIT_ORDER_MSB_FIRST;
elessair 0:f269e3021894 222 p_config->csn_pullup = NRF_DRV_SPIS_DEFAULT_CSN_PULLUP;
elessair 0:f269e3021894 223 p_config->miso_drive = NRF_DRV_SPIS_DEFAULT_MISO_DRIVE;
elessair 0:f269e3021894 224 }
elessair 0:f269e3021894 225
elessair 0:f269e3021894 226 void spi_init(spi_t *obj,
elessair 0:f269e3021894 227 PinName mosi, PinName miso, PinName sclk, PinName ssel)
elessair 0:f269e3021894 228 {
elessair 0:f269e3021894 229 int i;
elessair 0:f269e3021894 230 for (i = 0; i < SPI_COUNT; ++i) {
elessair 0:f269e3021894 231 spi_info_t *p_spi_info = &m_spi_info[i];
elessair 0:f269e3021894 232 if (!p_spi_info->initialized) {
elessair 0:f269e3021894 233 p_spi_info->sck_pin = (uint8_t)sclk;
elessair 0:f269e3021894 234 p_spi_info->mosi_pin = (mosi != NC) ?
elessair 0:f269e3021894 235 (uint8_t)mosi : NRF_DRV_SPI_PIN_NOT_USED;
elessair 0:f269e3021894 236 p_spi_info->miso_pin = (miso != NC) ?
elessair 0:f269e3021894 237 (uint8_t)miso : NRF_DRV_SPI_PIN_NOT_USED;
elessair 0:f269e3021894 238 p_spi_info->ss_pin = (ssel != NC) ?
elessair 0:f269e3021894 239 (uint8_t)ssel : NRF_DRV_SPI_PIN_NOT_USED;
elessair 0:f269e3021894 240 p_spi_info->spi_mode = (uint8_t)NRF_DRV_SPI_MODE_0;
elessair 0:f269e3021894 241 p_spi_info->frequency = NRF_DRV_SPI_FREQ_1M;
elessair 0:f269e3021894 242
elessair 0:f269e3021894 243 // By default each SPI instance is initialized to work as a master.
elessair 0:f269e3021894 244 // Should the slave mode be used, the instance will be reconfigured
elessair 0:f269e3021894 245 // appropriately in 'spi_format'.
elessair 0:f269e3021894 246 nrf_drv_spi_config_t config;
elessair 0:f269e3021894 247 prepare_master_config(&config, p_spi_info);
elessair 0:f269e3021894 248
elessair 0:f269e3021894 249 nrf_drv_spi_t const *p_spi = &m_instances[i].master;
elessair 0:f269e3021894 250 ret_code_t ret_code = nrf_drv_spi_init(p_spi,
elessair 0:f269e3021894 251 &config, m_master_event_handlers[i]);
elessair 0:f269e3021894 252 if (ret_code == NRF_SUCCESS) {
elessair 0:f269e3021894 253 p_spi_info->initialized = true;
elessair 0:f269e3021894 254 p_spi_info->master = true;
elessair 0:f269e3021894 255 p_spi_info->flag.busy = false;
elessair 0:f269e3021894 256 #if DEVICE_SPI_ASYNCH
elessair 0:f269e3021894 257 p_spi_info->handler = 0;
elessair 0:f269e3021894 258 #endif
elessair 0:f269e3021894 259 SPI_IDX(obj) = i;
elessair 0:f269e3021894 260
elessair 0:f269e3021894 261 return;
elessair 0:f269e3021894 262 }
elessair 0:f269e3021894 263 }
elessair 0:f269e3021894 264 }
elessair 0:f269e3021894 265
elessair 0:f269e3021894 266 // No available peripheral
elessair 0:f269e3021894 267 error("No available SPI peripheral\r\n");
elessair 0:f269e3021894 268 }
elessair 0:f269e3021894 269
elessair 0:f269e3021894 270 void spi_free(spi_t *obj)
elessair 0:f269e3021894 271 {
elessair 0:f269e3021894 272 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 273 if (p_spi_info->master) {
elessair 0:f269e3021894 274 nrf_drv_spi_uninit(MASTER_INST(obj));
elessair 0:f269e3021894 275 }
elessair 0:f269e3021894 276 else {
elessair 0:f269e3021894 277 nrf_drv_spis_uninit(SLAVE_INST(obj));
elessair 0:f269e3021894 278 }
elessair 0:f269e3021894 279 p_spi_info->initialized = false;
elessair 0:f269e3021894 280 }
elessair 0:f269e3021894 281
elessair 0:f269e3021894 282 int spi_busy(spi_t *obj)
elessair 0:f269e3021894 283 {
elessair 0:f269e3021894 284 return (int)(SPI_INFO(obj)->flag.busy);
elessair 0:f269e3021894 285 }
elessair 0:f269e3021894 286
elessair 0:f269e3021894 287 void spi_format(spi_t *obj, int bits, int mode, int slave)
elessair 0:f269e3021894 288 {
elessair 0:f269e3021894 289 if (bits != 8) {
elessair 0:f269e3021894 290 error("Only 8-bits SPI is supported\r\n");
elessair 0:f269e3021894 291 }
elessair 0:f269e3021894 292 if (mode > 3) {
elessair 0:f269e3021894 293 error("SPI format error\r\n");
elessair 0:f269e3021894 294 }
elessair 0:f269e3021894 295
elessair 0:f269e3021894 296 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 297
elessair 0:f269e3021894 298 if (slave)
elessair 0:f269e3021894 299 {
elessair 0:f269e3021894 300 nrf_drv_spis_mode_t spi_modes[4] = {
elessair 0:f269e3021894 301 NRF_DRV_SPIS_MODE_0,
elessair 0:f269e3021894 302 NRF_DRV_SPIS_MODE_1,
elessair 0:f269e3021894 303 NRF_DRV_SPIS_MODE_2,
elessair 0:f269e3021894 304 NRF_DRV_SPIS_MODE_3,
elessair 0:f269e3021894 305 };
elessair 0:f269e3021894 306 nrf_drv_spis_mode_t new_mode = spi_modes[mode];
elessair 0:f269e3021894 307
elessair 0:f269e3021894 308 // If the peripheral is currently working as a master, the SDK driver
elessair 0:f269e3021894 309 // it uses needs to be switched from SPI to SPIS.
elessair 0:f269e3021894 310 if (p_spi_info->master) {
elessair 0:f269e3021894 311 nrf_drv_spi_uninit(MASTER_INST(obj));
elessair 0:f269e3021894 312 }
elessair 0:f269e3021894 313 // I the SPI mode has to be changed, the SDK's SPIS driver needs to be
elessair 0:f269e3021894 314 // re-initialized (there is no other way to change its configuration).
elessair 0:f269e3021894 315 else if (p_spi_info->spi_mode != (uint8_t)new_mode) {
elessair 0:f269e3021894 316 nrf_drv_spis_uninit(SLAVE_INST(obj));
elessair 0:f269e3021894 317 }
elessair 0:f269e3021894 318 else {
elessair 0:f269e3021894 319 return;
elessair 0:f269e3021894 320 }
elessair 0:f269e3021894 321
elessair 0:f269e3021894 322 p_spi_info->spi_mode = (uint8_t)new_mode;
elessair 0:f269e3021894 323 p_spi_info->master = false;
elessair 0:f269e3021894 324 p_spi_info->flag.readable = false;
elessair 0:f269e3021894 325
elessair 0:f269e3021894 326 // Initialize SDK's SPIS driver with the new configuration.
elessair 0:f269e3021894 327 nrf_drv_spis_config_t config;
elessair 0:f269e3021894 328 prepare_slave_config(&config, p_spi_info);
elessair 0:f269e3021894 329 (void)nrf_drv_spis_init(SLAVE_INST(obj), &config,
elessair 0:f269e3021894 330 m_slave_event_handlers[SPI_IDX(obj)]);
elessair 0:f269e3021894 331
elessair 0:f269e3021894 332 // Prepare the slave for transfer.
elessair 0:f269e3021894 333 p_spi_info->tx_buf = NRF_DRV_SPIS_DEFAULT_ORC;
elessair 0:f269e3021894 334 nrf_drv_spis_buffers_set(SLAVE_INST(obj),
elessair 0:f269e3021894 335 (uint8_t const *)&p_spi_info->tx_buf, 1,
elessair 0:f269e3021894 336 (uint8_t *)&p_spi_info->rx_buf, 1);
elessair 0:f269e3021894 337 }
elessair 0:f269e3021894 338 else // master
elessair 0:f269e3021894 339 {
elessair 0:f269e3021894 340 nrf_drv_spi_mode_t spi_modes[4] = {
elessair 0:f269e3021894 341 NRF_DRV_SPI_MODE_0,
elessair 0:f269e3021894 342 NRF_DRV_SPI_MODE_1,
elessair 0:f269e3021894 343 NRF_DRV_SPI_MODE_2,
elessair 0:f269e3021894 344 NRF_DRV_SPI_MODE_3,
elessair 0:f269e3021894 345 };
elessair 0:f269e3021894 346 nrf_drv_spi_mode_t new_mode = spi_modes[mode];
elessair 0:f269e3021894 347
elessair 0:f269e3021894 348 // If the peripheral is currently working as a slave, the SDK driver
elessair 0:f269e3021894 349 // it uses needs to be switched from SPIS to SPI.
elessair 0:f269e3021894 350 if (!p_spi_info->master) {
elessair 0:f269e3021894 351 nrf_drv_spis_uninit(SLAVE_INST(obj));
elessair 0:f269e3021894 352 }
elessair 0:f269e3021894 353 // I the SPI mode has to be changed, the SDK's SPI driver needs to be
elessair 0:f269e3021894 354 // re-initialized (there is no other way to change its configuration).
elessair 0:f269e3021894 355 else if (p_spi_info->spi_mode != (uint8_t)new_mode) {
elessair 0:f269e3021894 356 nrf_drv_spi_uninit(MASTER_INST(obj));
elessair 0:f269e3021894 357 }
elessair 0:f269e3021894 358 else {
elessair 0:f269e3021894 359 return;
elessair 0:f269e3021894 360 }
elessair 0:f269e3021894 361
elessair 0:f269e3021894 362 p_spi_info->spi_mode = (uint8_t)new_mode;
elessair 0:f269e3021894 363 p_spi_info->master = true;
elessair 0:f269e3021894 364 p_spi_info->flag.busy = false;
elessair 0:f269e3021894 365
elessair 0:f269e3021894 366 // Initialize SDK's SPI driver with the new configuration.
elessair 0:f269e3021894 367 nrf_drv_spi_config_t config;
elessair 0:f269e3021894 368 prepare_master_config(&config, p_spi_info);
elessair 0:f269e3021894 369 (void)nrf_drv_spi_init(MASTER_INST(obj), &config,
elessair 0:f269e3021894 370 m_master_event_handlers[SPI_IDX(obj)]);
elessair 0:f269e3021894 371 }
elessair 0:f269e3021894 372 }
elessair 0:f269e3021894 373
elessair 0:f269e3021894 374 static nrf_drv_spi_frequency_t freq_translate(int hz)
elessair 0:f269e3021894 375 {
elessair 0:f269e3021894 376 nrf_drv_spi_frequency_t frequency;
elessair 0:f269e3021894 377 if (hz<250000) { //125Kbps
elessair 0:f269e3021894 378 frequency = NRF_DRV_SPI_FREQ_125K;
elessair 0:f269e3021894 379 } else if (hz<500000) { //250Kbps
elessair 0:f269e3021894 380 frequency = NRF_DRV_SPI_FREQ_250K;
elessair 0:f269e3021894 381 } else if (hz<1000000) { //500Kbps
elessair 0:f269e3021894 382 frequency = NRF_DRV_SPI_FREQ_500K;
elessair 0:f269e3021894 383 } else if (hz<2000000) { //1Mbps
elessair 0:f269e3021894 384 frequency = NRF_DRV_SPI_FREQ_1M;
elessair 0:f269e3021894 385 } else if (hz<4000000) { //2Mbps
elessair 0:f269e3021894 386 frequency = NRF_DRV_SPI_FREQ_2M;
elessair 0:f269e3021894 387 } else if (hz<8000000) { //4Mbps
elessair 0:f269e3021894 388 frequency = NRF_DRV_SPI_FREQ_4M;
elessair 0:f269e3021894 389 } else { //8Mbps
elessair 0:f269e3021894 390 frequency = NRF_DRV_SPI_FREQ_8M;
elessair 0:f269e3021894 391 }
elessair 0:f269e3021894 392 return frequency;
elessair 0:f269e3021894 393 }
elessair 0:f269e3021894 394
elessair 0:f269e3021894 395 void spi_frequency(spi_t *obj, int hz)
elessair 0:f269e3021894 396 {
elessair 0:f269e3021894 397 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 398 nrf_drv_spi_frequency_t new_frequency = freq_translate(hz);
elessair 0:f269e3021894 399
elessair 0:f269e3021894 400 if (p_spi_info->master)
elessair 0:f269e3021894 401 {
elessair 0:f269e3021894 402 if (p_spi_info->frequency != new_frequency) {
elessair 0:f269e3021894 403 p_spi_info->frequency = new_frequency;
elessair 0:f269e3021894 404
elessair 0:f269e3021894 405 nrf_drv_spi_config_t config;
elessair 0:f269e3021894 406 prepare_master_config(&config, p_spi_info);
elessair 0:f269e3021894 407
elessair 0:f269e3021894 408 nrf_drv_spi_t const *p_spi = MASTER_INST(obj);
elessair 0:f269e3021894 409 nrf_drv_spi_uninit(p_spi);
elessair 0:f269e3021894 410 (void)nrf_drv_spi_init(p_spi, &config,
elessair 0:f269e3021894 411 m_master_event_handlers[SPI_IDX(obj)]);
elessair 0:f269e3021894 412 }
elessair 0:f269e3021894 413 }
elessair 0:f269e3021894 414 // There is no need to set anything in slaves when it comes to frequency,
elessair 0:f269e3021894 415 // since slaves just synchronize with the clock provided by a master.
elessair 0:f269e3021894 416 }
elessair 0:f269e3021894 417
elessair 0:f269e3021894 418 int spi_master_write(spi_t *obj, int value)
elessair 0:f269e3021894 419 {
elessair 0:f269e3021894 420 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 421
elessair 0:f269e3021894 422 #if DEVICE_SPI_ASYNCH
elessair 0:f269e3021894 423 while (p_spi_info->flag.busy) {
elessair 0:f269e3021894 424 }
elessair 0:f269e3021894 425 #endif
elessair 0:f269e3021894 426
elessair 0:f269e3021894 427 p_spi_info->tx_buf = value;
elessair 0:f269e3021894 428 p_spi_info->flag.busy = true;
elessair 0:f269e3021894 429 (void)nrf_drv_spi_transfer(MASTER_INST(obj),
elessair 0:f269e3021894 430 (uint8_t const *)&p_spi_info->tx_buf, 1,
elessair 0:f269e3021894 431 (uint8_t *)&p_spi_info->rx_buf, 1);
elessair 0:f269e3021894 432 while (p_spi_info->flag.busy) {
elessair 0:f269e3021894 433 }
elessair 0:f269e3021894 434
elessair 0:f269e3021894 435 return p_spi_info->rx_buf;
elessair 0:f269e3021894 436 }
elessair 0:f269e3021894 437
elessair 0:f269e3021894 438 int spi_slave_receive(spi_t *obj)
elessair 0:f269e3021894 439 {
elessair 0:f269e3021894 440 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 441 MBED_ASSERT(!p_spi_info->master);
elessair 0:f269e3021894 442 return p_spi_info->flag.readable;
elessair 0:f269e3021894 443 ;
elessair 0:f269e3021894 444 }
elessair 0:f269e3021894 445
elessair 0:f269e3021894 446 int spi_slave_read(spi_t *obj)
elessair 0:f269e3021894 447 {
elessair 0:f269e3021894 448 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 449 MBED_ASSERT(!p_spi_info->master);
elessair 0:f269e3021894 450 while (!p_spi_info->flag.readable) {
elessair 0:f269e3021894 451 }
elessair 0:f269e3021894 452 p_spi_info->flag.readable = false;
elessair 0:f269e3021894 453 return p_spi_info->rx_buf;
elessair 0:f269e3021894 454 }
elessair 0:f269e3021894 455
elessair 0:f269e3021894 456 void spi_slave_write(spi_t *obj, int value)
elessair 0:f269e3021894 457 {
elessair 0:f269e3021894 458 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 459 MBED_ASSERT(!p_spi_info->master);
elessair 0:f269e3021894 460
elessair 0:f269e3021894 461 p_spi_info->tx_buf = (uint8_t)value;
elessair 0:f269e3021894 462 }
elessair 0:f269e3021894 463
elessair 0:f269e3021894 464 #if DEVICE_SPI_ASYNCH
elessair 0:f269e3021894 465
elessair 0:f269e3021894 466 void spi_master_transfer(spi_t *obj,
elessair 0:f269e3021894 467 const void *tx, size_t tx_length,
elessair 0:f269e3021894 468 void *rx, size_t rx_length, uint8_t bit_width,
elessair 0:f269e3021894 469 uint32_t handler, uint32_t event, DMAUsage hint)
elessair 0:f269e3021894 470 {
elessair 0:f269e3021894 471 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 472 MBED_ASSERT(p_spi_info->master);
elessair 0:f269e3021894 473 (void)hint;
elessair 0:f269e3021894 474 (void)bit_width;
elessair 0:f269e3021894 475
elessair 0:f269e3021894 476 p_spi_info->handler = handler;
elessair 0:f269e3021894 477 p_spi_info->event = event;
elessair 0:f269e3021894 478
elessair 0:f269e3021894 479 p_spi_info->flag.busy = true;
elessair 0:f269e3021894 480 (void)nrf_drv_spi_transfer(MASTER_INST(obj),
elessair 0:f269e3021894 481 (uint8_t const *)tx, tx_length,
elessair 0:f269e3021894 482 (uint8_t *)rx, rx_length);
elessair 0:f269e3021894 483 }
elessair 0:f269e3021894 484
elessair 0:f269e3021894 485 uint32_t spi_irq_handler_asynch(spi_t *obj)
elessair 0:f269e3021894 486 {
elessair 0:f269e3021894 487 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 488 MBED_ASSERT(p_spi_info->master);
elessair 0:f269e3021894 489 return p_spi_info->event & SPI_EVENT_COMPLETE;
elessair 0:f269e3021894 490 }
elessair 0:f269e3021894 491
elessair 0:f269e3021894 492 uint8_t spi_active(spi_t *obj)
elessair 0:f269e3021894 493 {
elessair 0:f269e3021894 494 spi_info_t *p_spi_info = SPI_INFO(obj);
elessair 0:f269e3021894 495 MBED_ASSERT(p_spi_info->master);
elessair 0:f269e3021894 496 return p_spi_info->flag.busy;
elessair 0:f269e3021894 497 }
elessair 0:f269e3021894 498
elessair 0:f269e3021894 499 void spi_abort_asynch(spi_t *obj)
elessair 0:f269e3021894 500 {
elessair 0:f269e3021894 501 MBED_ASSERT(SPI_INFO(obj)->master);
elessair 0:f269e3021894 502 nrf_drv_spi_abort(MASTER_INST(obj));
elessair 0:f269e3021894 503 }
elessair 0:f269e3021894 504
elessair 0:f269e3021894 505 #endif // DEVICE_SPI_ASYNCH
elessair 0:f269e3021894 506
elessair 0:f269e3021894 507 #endif // DEVICE_SPI