mbed

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Oct 28 11:17:30 2016 +0100
Revision:
149:156823d33999
Parent:
targets/hal/TARGET_NORDIC/TARGET_NRF5/spi_api.c@144:ef7eb2e8f9f7
Child:
150:02e0a0aed4ec
This updates the lib to the mbed lib v128

NOTE: This release includes a restructuring of the file and directory locations and thus some
include paths in your code may need updating accordingly.

Who changed what in which revision?

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