mbed

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Fri May 26 12:39:01 2017 +0100
Revision:
165:e614a9f1c9e2
Parent:
160:d5399cc887bb
Child:
167:e84263d55307
This updates the lib to the mbed lib v 143

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"
AnnaBridge 165:e614a9f1c9e2 51 #include "sdk_config.h"
<> 144:ef7eb2e8f9f7 52
<> 144:ef7eb2e8f9f7 53 #if DEVICE_SPI_ASYNCH
<> 144:ef7eb2e8f9f7 54 #define SPI_IDX(obj) ((obj)->spi.spi_idx)
<> 144:ef7eb2e8f9f7 55 #else
<> 144:ef7eb2e8f9f7 56 #define SPI_IDX(obj) ((obj)->spi_idx)
<> 144:ef7eb2e8f9f7 57 #endif
<> 144:ef7eb2e8f9f7 58 #define SPI_INFO(obj) (&m_spi_info[SPI_IDX(obj)])
<> 144:ef7eb2e8f9f7 59 #define MASTER_INST(obj) (&m_instances[SPI_IDX(obj)].master)
<> 144:ef7eb2e8f9f7 60 #define SLAVE_INST(obj) (&m_instances[SPI_IDX(obj)].slave)
<> 144:ef7eb2e8f9f7 61
<> 144:ef7eb2e8f9f7 62 typedef struct {
<> 144:ef7eb2e8f9f7 63 bool initialized;
<> 144:ef7eb2e8f9f7 64 bool master;
<> 144:ef7eb2e8f9f7 65 uint8_t sck_pin;
<> 144:ef7eb2e8f9f7 66 uint8_t mosi_pin;
<> 144:ef7eb2e8f9f7 67 uint8_t miso_pin;
<> 144:ef7eb2e8f9f7 68 uint8_t ss_pin;
<> 144:ef7eb2e8f9f7 69 uint8_t spi_mode;
<> 144:ef7eb2e8f9f7 70 nrf_drv_spi_frequency_t frequency;
<> 144:ef7eb2e8f9f7 71 volatile union {
<> 144:ef7eb2e8f9f7 72 bool busy; // master
<> 144:ef7eb2e8f9f7 73 bool readable; // slave
<> 144:ef7eb2e8f9f7 74 } flag;
<> 144:ef7eb2e8f9f7 75 volatile uint8_t tx_buf;
<> 144:ef7eb2e8f9f7 76 volatile uint8_t rx_buf;
<> 144:ef7eb2e8f9f7 77
<> 144:ef7eb2e8f9f7 78 #if DEVICE_SPI_ASYNCH
<> 144:ef7eb2e8f9f7 79 uint32_t handler;
<> 144:ef7eb2e8f9f7 80 uint32_t event;
<> 144:ef7eb2e8f9f7 81 #endif
<> 144:ef7eb2e8f9f7 82 } spi_info_t;
<> 144:ef7eb2e8f9f7 83 static spi_info_t m_spi_info[SPI_COUNT];
<> 144:ef7eb2e8f9f7 84
<> 144:ef7eb2e8f9f7 85 typedef struct {
<> 144:ef7eb2e8f9f7 86 nrf_drv_spi_t master;
<> 144:ef7eb2e8f9f7 87 nrf_drv_spis_t slave;
<> 144:ef7eb2e8f9f7 88 } sdk_driver_instances_t;
<> 150:02e0a0aed4ec 89
<> 150:02e0a0aed4ec 90 void SPI0_TWI0_IRQHandler(void);
<> 150:02e0a0aed4ec 91 void SPI1_TWI1_IRQHandler(void);
<> 150:02e0a0aed4ec 92 void SPIM2_SPIS2_SPI2_IRQHandler(void);
<> 150:02e0a0aed4ec 93
<> 160:d5399cc887bb 94 static const peripheral_handler_desc_t spi_handler_desc[SPI_COUNT] = {
<> 150:02e0a0aed4ec 95 #if SPI0_ENABLED
<> 150:02e0a0aed4ec 96 {
<> 160:d5399cc887bb 97 SPI0_IRQ,
<> 150:02e0a0aed4ec 98 (uint32_t) SPI0_TWI0_IRQHandler
<> 150:02e0a0aed4ec 99 },
<> 150:02e0a0aed4ec 100 #endif
<> 150:02e0a0aed4ec 101 #if SPI1_ENABLED
<> 150:02e0a0aed4ec 102 {
<> 160:d5399cc887bb 103 SPI1_IRQ,
<> 150:02e0a0aed4ec 104 (uint32_t) SPI1_TWI1_IRQHandler
<> 150:02e0a0aed4ec 105 },
<> 150:02e0a0aed4ec 106 #endif
<> 150:02e0a0aed4ec 107 #if SPI2_ENABLED
<> 150:02e0a0aed4ec 108 {
<> 160:d5399cc887bb 109 SPI2_IRQ,
<> 150:02e0a0aed4ec 110 (uint32_t) SPIM2_SPIS2_SPI2_IRQHandler
<> 150:02e0a0aed4ec 111 },
<> 150:02e0a0aed4ec 112 #endif
<> 150:02e0a0aed4ec 113 };
<> 150:02e0a0aed4ec 114
<> 150:02e0a0aed4ec 115
<> 144:ef7eb2e8f9f7 116 static sdk_driver_instances_t m_instances[SPI_COUNT] = {
<> 150:02e0a0aed4ec 117 #if SPI0_ENABLED
<> 144:ef7eb2e8f9f7 118 {
<> 144:ef7eb2e8f9f7 119 NRF_DRV_SPI_INSTANCE(0),
<> 144:ef7eb2e8f9f7 120 NRF_DRV_SPIS_INSTANCE(0)
<> 144:ef7eb2e8f9f7 121 },
<> 150:02e0a0aed4ec 122 #endif
<> 150:02e0a0aed4ec 123 #if SPI1_ENABLED
<> 144:ef7eb2e8f9f7 124 {
<> 144:ef7eb2e8f9f7 125 NRF_DRV_SPI_INSTANCE(1),
<> 144:ef7eb2e8f9f7 126 NRF_DRV_SPIS_INSTANCE(1)
<> 144:ef7eb2e8f9f7 127 },
<> 150:02e0a0aed4ec 128 #endif
<> 150:02e0a0aed4ec 129 #if SPI2_ENABLED
<> 144:ef7eb2e8f9f7 130 {
<> 144:ef7eb2e8f9f7 131 NRF_DRV_SPI_INSTANCE(2),
<> 144:ef7eb2e8f9f7 132 NRF_DRV_SPIS_INSTANCE(2)
<> 144:ef7eb2e8f9f7 133 },
<> 150:02e0a0aed4ec 134 #endif
<> 144:ef7eb2e8f9f7 135 };
<> 144:ef7eb2e8f9f7 136
<> 144:ef7eb2e8f9f7 137 static void master_event_handler(uint8_t spi_idx,
<> 144:ef7eb2e8f9f7 138 nrf_drv_spi_evt_t const *p_event)
<> 144:ef7eb2e8f9f7 139 {
<> 144:ef7eb2e8f9f7 140 spi_info_t *p_spi_info = &m_spi_info[spi_idx];
<> 144:ef7eb2e8f9f7 141
<> 144:ef7eb2e8f9f7 142 if (p_event->type == NRF_DRV_SPI_EVENT_DONE) {
<> 144:ef7eb2e8f9f7 143 p_spi_info->flag.busy = false;
<> 144:ef7eb2e8f9f7 144 if (p_spi_info->handler) {
<> 144:ef7eb2e8f9f7 145 void (*handler)(void) = (void (*)(void))p_spi_info->handler;
<> 144:ef7eb2e8f9f7 146 p_spi_info->handler = 0;
<> 144:ef7eb2e8f9f7 147 handler();
<> 144:ef7eb2e8f9f7 148 }
<> 144:ef7eb2e8f9f7 149 }
<> 144:ef7eb2e8f9f7 150 }
<> 144:ef7eb2e8f9f7 151 #define MASTER_EVENT_HANDLER(idx) \
<> 144:ef7eb2e8f9f7 152 static void master_event_handler_##idx(nrf_drv_spi_evt_t const *p_event) { \
<> 144:ef7eb2e8f9f7 153 master_event_handler(SPI##idx##_INSTANCE_INDEX, p_event); \
<> 144:ef7eb2e8f9f7 154 }
<> 144:ef7eb2e8f9f7 155 #if SPI0_ENABLED
<> 144:ef7eb2e8f9f7 156 MASTER_EVENT_HANDLER(0)
<> 144:ef7eb2e8f9f7 157 #endif
<> 144:ef7eb2e8f9f7 158 #if SPI1_ENABLED
<> 144:ef7eb2e8f9f7 159 MASTER_EVENT_HANDLER(1)
<> 144:ef7eb2e8f9f7 160 #endif
<> 144:ef7eb2e8f9f7 161 #if SPI2_ENABLED
<> 144:ef7eb2e8f9f7 162 MASTER_EVENT_HANDLER(2)
<> 144:ef7eb2e8f9f7 163 #endif
<> 144:ef7eb2e8f9f7 164
<> 144:ef7eb2e8f9f7 165 static nrf_drv_spi_handler_t const m_master_event_handlers[SPI_COUNT] = {
<> 144:ef7eb2e8f9f7 166 #if SPI0_ENABLED
<> 144:ef7eb2e8f9f7 167 master_event_handler_0,
<> 144:ef7eb2e8f9f7 168 #endif
<> 144:ef7eb2e8f9f7 169 #if SPI1_ENABLED
<> 144:ef7eb2e8f9f7 170 master_event_handler_1,
<> 144:ef7eb2e8f9f7 171 #endif
<> 144:ef7eb2e8f9f7 172 #if SPI2_ENABLED
<> 144:ef7eb2e8f9f7 173 master_event_handler_2,
<> 144:ef7eb2e8f9f7 174 #endif
<> 144:ef7eb2e8f9f7 175 };
<> 144:ef7eb2e8f9f7 176
<> 144:ef7eb2e8f9f7 177
<> 144:ef7eb2e8f9f7 178 static void slave_event_handler(uint8_t spi_idx,
<> 144:ef7eb2e8f9f7 179 nrf_drv_spis_event_t event)
<> 144:ef7eb2e8f9f7 180 {
<> 144:ef7eb2e8f9f7 181 spi_info_t *p_spi_info = &m_spi_info[spi_idx];
<> 144:ef7eb2e8f9f7 182
<> 144:ef7eb2e8f9f7 183 if (event.evt_type == NRF_DRV_SPIS_XFER_DONE) {
<> 144:ef7eb2e8f9f7 184 // Signal that there is some data received that could be read.
<> 144:ef7eb2e8f9f7 185 p_spi_info->flag.readable = true;
<> 144:ef7eb2e8f9f7 186
<> 144:ef7eb2e8f9f7 187 // And prepare for the next transfer.
<> 144:ef7eb2e8f9f7 188 // Previous data set in 'spi_slave_write' (if any) has been transmitted,
<> 144:ef7eb2e8f9f7 189 // now use the default one, until some new is set by 'spi_slave_write'.
AnnaBridge 165:e614a9f1c9e2 190 p_spi_info->tx_buf = SPIS_DEFAULT_ORC;
<> 144:ef7eb2e8f9f7 191 nrf_drv_spis_buffers_set(&m_instances[spi_idx].slave,
<> 144:ef7eb2e8f9f7 192 (uint8_t const *)&p_spi_info->tx_buf, 1,
<> 144:ef7eb2e8f9f7 193 (uint8_t *)&p_spi_info->rx_buf, 1);
<> 144:ef7eb2e8f9f7 194 }
<> 144:ef7eb2e8f9f7 195 }
<> 144:ef7eb2e8f9f7 196 #define SLAVE_EVENT_HANDLER(idx) \
<> 144:ef7eb2e8f9f7 197 static void slave_event_handler_##idx(nrf_drv_spis_event_t event) { \
<> 144:ef7eb2e8f9f7 198 slave_event_handler(SPIS##idx##_INSTANCE_INDEX, event); \
<> 144:ef7eb2e8f9f7 199 }
<> 144:ef7eb2e8f9f7 200 #if SPIS0_ENABLED
<> 144:ef7eb2e8f9f7 201 SLAVE_EVENT_HANDLER(0)
<> 144:ef7eb2e8f9f7 202 #endif
<> 144:ef7eb2e8f9f7 203 #if SPIS1_ENABLED
<> 144:ef7eb2e8f9f7 204 SLAVE_EVENT_HANDLER(1)
<> 144:ef7eb2e8f9f7 205 #endif
<> 144:ef7eb2e8f9f7 206 #if SPIS2_ENABLED
<> 144:ef7eb2e8f9f7 207 SLAVE_EVENT_HANDLER(2)
<> 144:ef7eb2e8f9f7 208 #endif
<> 144:ef7eb2e8f9f7 209
<> 144:ef7eb2e8f9f7 210 static nrf_drv_spis_event_handler_t const m_slave_event_handlers[SPIS_COUNT] = {
<> 144:ef7eb2e8f9f7 211 #if SPIS0_ENABLED
<> 144:ef7eb2e8f9f7 212 slave_event_handler_0,
<> 144:ef7eb2e8f9f7 213 #endif
<> 144:ef7eb2e8f9f7 214 #if SPIS1_ENABLED
<> 144:ef7eb2e8f9f7 215 slave_event_handler_1,
<> 144:ef7eb2e8f9f7 216 #endif
<> 144:ef7eb2e8f9f7 217 #if SPIS2_ENABLED
<> 144:ef7eb2e8f9f7 218 slave_event_handler_2,
<> 144:ef7eb2e8f9f7 219 #endif
<> 144:ef7eb2e8f9f7 220 };
<> 144:ef7eb2e8f9f7 221
<> 144:ef7eb2e8f9f7 222 static void prepare_master_config(nrf_drv_spi_config_t *p_config,
<> 144:ef7eb2e8f9f7 223 spi_info_t const *p_spi_info)
<> 144:ef7eb2e8f9f7 224 {
<> 144:ef7eb2e8f9f7 225 p_config->sck_pin = p_spi_info->sck_pin;
<> 144:ef7eb2e8f9f7 226 p_config->mosi_pin = p_spi_info->mosi_pin;
<> 144:ef7eb2e8f9f7 227 p_config->miso_pin = p_spi_info->miso_pin;
<> 144:ef7eb2e8f9f7 228 p_config->ss_pin = p_spi_info->ss_pin;
<> 144:ef7eb2e8f9f7 229 p_config->frequency = p_spi_info->frequency;
<> 144:ef7eb2e8f9f7 230 p_config->mode = (nrf_drv_spi_mode_t)p_spi_info->spi_mode;
<> 144:ef7eb2e8f9f7 231
AnnaBridge 165:e614a9f1c9e2 232 p_config->irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY;
<> 144:ef7eb2e8f9f7 233 p_config->orc = 0xFF;
<> 144:ef7eb2e8f9f7 234 p_config->bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
<> 144:ef7eb2e8f9f7 235 }
<> 144:ef7eb2e8f9f7 236
<> 144:ef7eb2e8f9f7 237 static void prepare_slave_config(nrf_drv_spis_config_t *p_config,
<> 144:ef7eb2e8f9f7 238 spi_info_t const *p_spi_info)
<> 144:ef7eb2e8f9f7 239 {
<> 144:ef7eb2e8f9f7 240 p_config->sck_pin = p_spi_info->sck_pin;
<> 144:ef7eb2e8f9f7 241 p_config->mosi_pin = p_spi_info->mosi_pin;
<> 144:ef7eb2e8f9f7 242 p_config->miso_pin = p_spi_info->miso_pin;
<> 144:ef7eb2e8f9f7 243 p_config->csn_pin = p_spi_info->ss_pin;
<> 144:ef7eb2e8f9f7 244 p_config->mode = (nrf_drv_spis_mode_t)p_spi_info->spi_mode;
<> 144:ef7eb2e8f9f7 245
AnnaBridge 165:e614a9f1c9e2 246 p_config->irq_priority = SPIS_DEFAULT_CONFIG_IRQ_PRIORITY;
AnnaBridge 165:e614a9f1c9e2 247 p_config->orc = SPIS_DEFAULT_ORC;
AnnaBridge 165:e614a9f1c9e2 248 p_config->def = SPIS_DEFAULT_DEF;
<> 144:ef7eb2e8f9f7 249 p_config->bit_order = NRF_DRV_SPIS_BIT_ORDER_MSB_FIRST;
<> 144:ef7eb2e8f9f7 250 p_config->csn_pullup = NRF_DRV_SPIS_DEFAULT_CSN_PULLUP;
<> 144:ef7eb2e8f9f7 251 p_config->miso_drive = NRF_DRV_SPIS_DEFAULT_MISO_DRIVE;
<> 144:ef7eb2e8f9f7 252 }
<> 144:ef7eb2e8f9f7 253
<> 144:ef7eb2e8f9f7 254 void spi_init(spi_t *obj,
<> 144:ef7eb2e8f9f7 255 PinName mosi, PinName miso, PinName sclk, PinName ssel)
<> 144:ef7eb2e8f9f7 256 {
<> 144:ef7eb2e8f9f7 257 int i;
<> 160:d5399cc887bb 258
<> 160:d5399cc887bb 259 // This block is only a workaround that allows to create SPI object several
<> 160:d5399cc887bb 260 // times, what would be otherwise impossible in the current implementation
<> 160:d5399cc887bb 261 // of mbed driver that does not call spi_free() from SPI destructor.
<> 160:d5399cc887bb 262 // Once this mbed's imperfection is corrected, this block should be removed.
<> 160:d5399cc887bb 263 for (i = 0; i < SPI_COUNT; ++i) {
<> 160:d5399cc887bb 264 spi_info_t *p_spi_info = &m_spi_info[i];
<> 160:d5399cc887bb 265 if (p_spi_info->initialized &&
<> 160:d5399cc887bb 266 p_spi_info->mosi_pin == (uint8_t)mosi &&
<> 160:d5399cc887bb 267 p_spi_info->miso_pin == (uint8_t)miso &&
<> 160:d5399cc887bb 268 p_spi_info->sck_pin == (uint8_t)sclk &&
<> 160:d5399cc887bb 269 p_spi_info->ss_pin == (uint8_t)ssel) {
<> 160:d5399cc887bb 270 // Reuse the already allocated SPI instance (instead of allocating
<> 160:d5399cc887bb 271 // a new one), if it appears to be initialized with exactly the same
<> 160:d5399cc887bb 272 // pin assignments.
<> 160:d5399cc887bb 273 SPI_IDX(obj) = i;
<> 160:d5399cc887bb 274 return;
<> 160:d5399cc887bb 275 }
<> 160:d5399cc887bb 276 }
<> 160:d5399cc887bb 277
<> 144:ef7eb2e8f9f7 278 for (i = 0; i < SPI_COUNT; ++i) {
<> 144:ef7eb2e8f9f7 279 spi_info_t *p_spi_info = &m_spi_info[i];
<> 144:ef7eb2e8f9f7 280 if (!p_spi_info->initialized) {
<> 144:ef7eb2e8f9f7 281 p_spi_info->sck_pin = (uint8_t)sclk;
<> 144:ef7eb2e8f9f7 282 p_spi_info->mosi_pin = (mosi != NC) ?
<> 144:ef7eb2e8f9f7 283 (uint8_t)mosi : NRF_DRV_SPI_PIN_NOT_USED;
<> 144:ef7eb2e8f9f7 284 p_spi_info->miso_pin = (miso != NC) ?
<> 144:ef7eb2e8f9f7 285 (uint8_t)miso : NRF_DRV_SPI_PIN_NOT_USED;
<> 144:ef7eb2e8f9f7 286 p_spi_info->ss_pin = (ssel != NC) ?
<> 144:ef7eb2e8f9f7 287 (uint8_t)ssel : NRF_DRV_SPI_PIN_NOT_USED;
<> 144:ef7eb2e8f9f7 288 p_spi_info->spi_mode = (uint8_t)NRF_DRV_SPI_MODE_0;
<> 144:ef7eb2e8f9f7 289 p_spi_info->frequency = NRF_DRV_SPI_FREQ_1M;
<> 144:ef7eb2e8f9f7 290
<> 160:d5399cc887bb 291 NVIC_SetVector(spi_handler_desc[i].IRQn, spi_handler_desc[i].vector);
<> 160:d5399cc887bb 292
<> 144:ef7eb2e8f9f7 293 // By default each SPI instance is initialized to work as a master.
<> 144:ef7eb2e8f9f7 294 // Should the slave mode be used, the instance will be reconfigured
<> 144:ef7eb2e8f9f7 295 // appropriately in 'spi_format'.
<> 144:ef7eb2e8f9f7 296 nrf_drv_spi_config_t config;
<> 144:ef7eb2e8f9f7 297 prepare_master_config(&config, p_spi_info);
<> 144:ef7eb2e8f9f7 298
<> 144:ef7eb2e8f9f7 299 nrf_drv_spi_t const *p_spi = &m_instances[i].master;
<> 144:ef7eb2e8f9f7 300 ret_code_t ret_code = nrf_drv_spi_init(p_spi,
<> 144:ef7eb2e8f9f7 301 &config, m_master_event_handlers[i]);
<> 144:ef7eb2e8f9f7 302 if (ret_code == NRF_SUCCESS) {
<> 144:ef7eb2e8f9f7 303 p_spi_info->initialized = true;
<> 144:ef7eb2e8f9f7 304 p_spi_info->master = true;
<> 144:ef7eb2e8f9f7 305 p_spi_info->flag.busy = false;
<> 144:ef7eb2e8f9f7 306 #if DEVICE_SPI_ASYNCH
<> 144:ef7eb2e8f9f7 307 p_spi_info->handler = 0;
<> 144:ef7eb2e8f9f7 308 #endif
<> 144:ef7eb2e8f9f7 309 SPI_IDX(obj) = i;
<> 144:ef7eb2e8f9f7 310
<> 144:ef7eb2e8f9f7 311 return;
<> 144:ef7eb2e8f9f7 312 }
<> 144:ef7eb2e8f9f7 313 }
<> 144:ef7eb2e8f9f7 314 }
<> 144:ef7eb2e8f9f7 315
<> 144:ef7eb2e8f9f7 316 // No available peripheral
<> 144:ef7eb2e8f9f7 317 error("No available SPI peripheral\r\n");
<> 144:ef7eb2e8f9f7 318 }
<> 144:ef7eb2e8f9f7 319
<> 144:ef7eb2e8f9f7 320 void spi_free(spi_t *obj)
<> 144:ef7eb2e8f9f7 321 {
<> 144:ef7eb2e8f9f7 322 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 323 if (p_spi_info->master) {
<> 144:ef7eb2e8f9f7 324 nrf_drv_spi_uninit(MASTER_INST(obj));
<> 144:ef7eb2e8f9f7 325 }
<> 144:ef7eb2e8f9f7 326 else {
<> 144:ef7eb2e8f9f7 327 nrf_drv_spis_uninit(SLAVE_INST(obj));
<> 144:ef7eb2e8f9f7 328 }
<> 144:ef7eb2e8f9f7 329 p_spi_info->initialized = false;
<> 144:ef7eb2e8f9f7 330 }
<> 144:ef7eb2e8f9f7 331
<> 144:ef7eb2e8f9f7 332 int spi_busy(spi_t *obj)
<> 144:ef7eb2e8f9f7 333 {
<> 144:ef7eb2e8f9f7 334 return (int)(SPI_INFO(obj)->flag.busy);
<> 144:ef7eb2e8f9f7 335 }
<> 144:ef7eb2e8f9f7 336
<> 144:ef7eb2e8f9f7 337 void spi_format(spi_t *obj, int bits, int mode, int slave)
<> 144:ef7eb2e8f9f7 338 {
<> 144:ef7eb2e8f9f7 339 if (bits != 8) {
<> 144:ef7eb2e8f9f7 340 error("Only 8-bits SPI is supported\r\n");
<> 144:ef7eb2e8f9f7 341 }
<> 144:ef7eb2e8f9f7 342 if (mode > 3) {
<> 144:ef7eb2e8f9f7 343 error("SPI format error\r\n");
<> 144:ef7eb2e8f9f7 344 }
<> 144:ef7eb2e8f9f7 345
<> 144:ef7eb2e8f9f7 346 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 347
<> 144:ef7eb2e8f9f7 348 if (slave)
<> 144:ef7eb2e8f9f7 349 {
<> 144:ef7eb2e8f9f7 350 nrf_drv_spis_mode_t spi_modes[4] = {
<> 144:ef7eb2e8f9f7 351 NRF_DRV_SPIS_MODE_0,
<> 144:ef7eb2e8f9f7 352 NRF_DRV_SPIS_MODE_1,
<> 144:ef7eb2e8f9f7 353 NRF_DRV_SPIS_MODE_2,
<> 144:ef7eb2e8f9f7 354 NRF_DRV_SPIS_MODE_3,
<> 144:ef7eb2e8f9f7 355 };
<> 144:ef7eb2e8f9f7 356 nrf_drv_spis_mode_t new_mode = spi_modes[mode];
<> 144:ef7eb2e8f9f7 357
<> 144:ef7eb2e8f9f7 358 // If the peripheral is currently working as a master, the SDK driver
<> 144:ef7eb2e8f9f7 359 // it uses needs to be switched from SPI to SPIS.
<> 144:ef7eb2e8f9f7 360 if (p_spi_info->master) {
<> 144:ef7eb2e8f9f7 361 nrf_drv_spi_uninit(MASTER_INST(obj));
<> 144:ef7eb2e8f9f7 362 }
<> 144:ef7eb2e8f9f7 363 // I the SPI mode has to be changed, the SDK's SPIS driver needs to be
<> 144:ef7eb2e8f9f7 364 // re-initialized (there is no other way to change its configuration).
<> 144:ef7eb2e8f9f7 365 else if (p_spi_info->spi_mode != (uint8_t)new_mode) {
<> 144:ef7eb2e8f9f7 366 nrf_drv_spis_uninit(SLAVE_INST(obj));
<> 144:ef7eb2e8f9f7 367 }
<> 144:ef7eb2e8f9f7 368 else {
<> 144:ef7eb2e8f9f7 369 return;
<> 144:ef7eb2e8f9f7 370 }
<> 144:ef7eb2e8f9f7 371
<> 144:ef7eb2e8f9f7 372 p_spi_info->spi_mode = (uint8_t)new_mode;
<> 144:ef7eb2e8f9f7 373 p_spi_info->master = false;
<> 144:ef7eb2e8f9f7 374 p_spi_info->flag.readable = false;
<> 144:ef7eb2e8f9f7 375
<> 144:ef7eb2e8f9f7 376 // Initialize SDK's SPIS driver with the new configuration.
<> 144:ef7eb2e8f9f7 377 nrf_drv_spis_config_t config;
<> 144:ef7eb2e8f9f7 378 prepare_slave_config(&config, p_spi_info);
<> 144:ef7eb2e8f9f7 379 (void)nrf_drv_spis_init(SLAVE_INST(obj), &config,
<> 144:ef7eb2e8f9f7 380 m_slave_event_handlers[SPI_IDX(obj)]);
<> 144:ef7eb2e8f9f7 381
<> 144:ef7eb2e8f9f7 382 // Prepare the slave for transfer.
AnnaBridge 165:e614a9f1c9e2 383 p_spi_info->tx_buf = SPIS_DEFAULT_ORC;
<> 144:ef7eb2e8f9f7 384 nrf_drv_spis_buffers_set(SLAVE_INST(obj),
<> 144:ef7eb2e8f9f7 385 (uint8_t const *)&p_spi_info->tx_buf, 1,
<> 144:ef7eb2e8f9f7 386 (uint8_t *)&p_spi_info->rx_buf, 1);
<> 144:ef7eb2e8f9f7 387 }
<> 144:ef7eb2e8f9f7 388 else // master
<> 144:ef7eb2e8f9f7 389 {
<> 144:ef7eb2e8f9f7 390 nrf_drv_spi_mode_t spi_modes[4] = {
<> 144:ef7eb2e8f9f7 391 NRF_DRV_SPI_MODE_0,
<> 144:ef7eb2e8f9f7 392 NRF_DRV_SPI_MODE_1,
<> 144:ef7eb2e8f9f7 393 NRF_DRV_SPI_MODE_2,
<> 144:ef7eb2e8f9f7 394 NRF_DRV_SPI_MODE_3,
<> 144:ef7eb2e8f9f7 395 };
<> 144:ef7eb2e8f9f7 396 nrf_drv_spi_mode_t new_mode = spi_modes[mode];
<> 144:ef7eb2e8f9f7 397
<> 144:ef7eb2e8f9f7 398 // If the peripheral is currently working as a slave, the SDK driver
<> 144:ef7eb2e8f9f7 399 // it uses needs to be switched from SPIS to SPI.
<> 144:ef7eb2e8f9f7 400 if (!p_spi_info->master) {
<> 144:ef7eb2e8f9f7 401 nrf_drv_spis_uninit(SLAVE_INST(obj));
<> 144:ef7eb2e8f9f7 402 }
<> 144:ef7eb2e8f9f7 403 // I the SPI mode has to be changed, the SDK's SPI driver needs to be
<> 144:ef7eb2e8f9f7 404 // re-initialized (there is no other way to change its configuration).
<> 144:ef7eb2e8f9f7 405 else if (p_spi_info->spi_mode != (uint8_t)new_mode) {
<> 144:ef7eb2e8f9f7 406 nrf_drv_spi_uninit(MASTER_INST(obj));
<> 144:ef7eb2e8f9f7 407 }
<> 144:ef7eb2e8f9f7 408 else {
<> 144:ef7eb2e8f9f7 409 return;
<> 144:ef7eb2e8f9f7 410 }
<> 144:ef7eb2e8f9f7 411
<> 144:ef7eb2e8f9f7 412 p_spi_info->spi_mode = (uint8_t)new_mode;
<> 144:ef7eb2e8f9f7 413 p_spi_info->master = true;
<> 144:ef7eb2e8f9f7 414 p_spi_info->flag.busy = false;
<> 144:ef7eb2e8f9f7 415
<> 144:ef7eb2e8f9f7 416 // Initialize SDK's SPI driver with the new configuration.
<> 144:ef7eb2e8f9f7 417 nrf_drv_spi_config_t config;
<> 144:ef7eb2e8f9f7 418 prepare_master_config(&config, p_spi_info);
<> 144:ef7eb2e8f9f7 419 (void)nrf_drv_spi_init(MASTER_INST(obj), &config,
<> 144:ef7eb2e8f9f7 420 m_master_event_handlers[SPI_IDX(obj)]);
<> 144:ef7eb2e8f9f7 421 }
<> 144:ef7eb2e8f9f7 422 }
<> 144:ef7eb2e8f9f7 423
<> 144:ef7eb2e8f9f7 424 static nrf_drv_spi_frequency_t freq_translate(int hz)
<> 144:ef7eb2e8f9f7 425 {
<> 144:ef7eb2e8f9f7 426 nrf_drv_spi_frequency_t frequency;
<> 144:ef7eb2e8f9f7 427 if (hz<250000) { //125Kbps
<> 144:ef7eb2e8f9f7 428 frequency = NRF_DRV_SPI_FREQ_125K;
<> 144:ef7eb2e8f9f7 429 } else if (hz<500000) { //250Kbps
<> 144:ef7eb2e8f9f7 430 frequency = NRF_DRV_SPI_FREQ_250K;
<> 144:ef7eb2e8f9f7 431 } else if (hz<1000000) { //500Kbps
<> 144:ef7eb2e8f9f7 432 frequency = NRF_DRV_SPI_FREQ_500K;
<> 144:ef7eb2e8f9f7 433 } else if (hz<2000000) { //1Mbps
<> 144:ef7eb2e8f9f7 434 frequency = NRF_DRV_SPI_FREQ_1M;
<> 144:ef7eb2e8f9f7 435 } else if (hz<4000000) { //2Mbps
<> 144:ef7eb2e8f9f7 436 frequency = NRF_DRV_SPI_FREQ_2M;
<> 144:ef7eb2e8f9f7 437 } else if (hz<8000000) { //4Mbps
<> 144:ef7eb2e8f9f7 438 frequency = NRF_DRV_SPI_FREQ_4M;
<> 144:ef7eb2e8f9f7 439 } else { //8Mbps
<> 144:ef7eb2e8f9f7 440 frequency = NRF_DRV_SPI_FREQ_8M;
<> 144:ef7eb2e8f9f7 441 }
<> 144:ef7eb2e8f9f7 442 return frequency;
<> 144:ef7eb2e8f9f7 443 }
<> 144:ef7eb2e8f9f7 444
<> 144:ef7eb2e8f9f7 445 void spi_frequency(spi_t *obj, int hz)
<> 144:ef7eb2e8f9f7 446 {
<> 144:ef7eb2e8f9f7 447 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 448 nrf_drv_spi_frequency_t new_frequency = freq_translate(hz);
<> 144:ef7eb2e8f9f7 449
<> 144:ef7eb2e8f9f7 450 if (p_spi_info->master)
<> 144:ef7eb2e8f9f7 451 {
<> 144:ef7eb2e8f9f7 452 if (p_spi_info->frequency != new_frequency) {
<> 144:ef7eb2e8f9f7 453 p_spi_info->frequency = new_frequency;
<> 144:ef7eb2e8f9f7 454
<> 144:ef7eb2e8f9f7 455 nrf_drv_spi_config_t config;
<> 144:ef7eb2e8f9f7 456 prepare_master_config(&config, p_spi_info);
<> 144:ef7eb2e8f9f7 457
<> 144:ef7eb2e8f9f7 458 nrf_drv_spi_t const *p_spi = MASTER_INST(obj);
<> 144:ef7eb2e8f9f7 459 nrf_drv_spi_uninit(p_spi);
<> 144:ef7eb2e8f9f7 460 (void)nrf_drv_spi_init(p_spi, &config,
<> 144:ef7eb2e8f9f7 461 m_master_event_handlers[SPI_IDX(obj)]);
<> 144:ef7eb2e8f9f7 462 }
<> 144:ef7eb2e8f9f7 463 }
<> 144:ef7eb2e8f9f7 464 // There is no need to set anything in slaves when it comes to frequency,
<> 144:ef7eb2e8f9f7 465 // since slaves just synchronize with the clock provided by a master.
<> 144:ef7eb2e8f9f7 466 }
<> 144:ef7eb2e8f9f7 467
<> 144:ef7eb2e8f9f7 468 int spi_master_write(spi_t *obj, int value)
<> 144:ef7eb2e8f9f7 469 {
<> 144:ef7eb2e8f9f7 470 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 471
<> 144:ef7eb2e8f9f7 472 #if DEVICE_SPI_ASYNCH
<> 144:ef7eb2e8f9f7 473 while (p_spi_info->flag.busy) {
<> 144:ef7eb2e8f9f7 474 }
<> 144:ef7eb2e8f9f7 475 #endif
<> 144:ef7eb2e8f9f7 476
<> 144:ef7eb2e8f9f7 477 p_spi_info->tx_buf = value;
<> 144:ef7eb2e8f9f7 478 p_spi_info->flag.busy = true;
<> 144:ef7eb2e8f9f7 479 (void)nrf_drv_spi_transfer(MASTER_INST(obj),
<> 144:ef7eb2e8f9f7 480 (uint8_t const *)&p_spi_info->tx_buf, 1,
<> 144:ef7eb2e8f9f7 481 (uint8_t *)&p_spi_info->rx_buf, 1);
<> 144:ef7eb2e8f9f7 482 while (p_spi_info->flag.busy) {
<> 144:ef7eb2e8f9f7 483 }
<> 144:ef7eb2e8f9f7 484
<> 144:ef7eb2e8f9f7 485 return p_spi_info->rx_buf;
<> 144:ef7eb2e8f9f7 486 }
<> 144:ef7eb2e8f9f7 487
<> 144:ef7eb2e8f9f7 488 int spi_slave_receive(spi_t *obj)
<> 144:ef7eb2e8f9f7 489 {
<> 144:ef7eb2e8f9f7 490 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 491 MBED_ASSERT(!p_spi_info->master);
<> 144:ef7eb2e8f9f7 492 return p_spi_info->flag.readable;
<> 144:ef7eb2e8f9f7 493 ;
<> 144:ef7eb2e8f9f7 494 }
<> 144:ef7eb2e8f9f7 495
<> 144:ef7eb2e8f9f7 496 int spi_slave_read(spi_t *obj)
<> 144:ef7eb2e8f9f7 497 {
<> 144:ef7eb2e8f9f7 498 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 499 MBED_ASSERT(!p_spi_info->master);
<> 144:ef7eb2e8f9f7 500 while (!p_spi_info->flag.readable) {
<> 144:ef7eb2e8f9f7 501 }
<> 144:ef7eb2e8f9f7 502 p_spi_info->flag.readable = false;
<> 144:ef7eb2e8f9f7 503 return p_spi_info->rx_buf;
<> 144:ef7eb2e8f9f7 504 }
<> 144:ef7eb2e8f9f7 505
<> 144:ef7eb2e8f9f7 506 void spi_slave_write(spi_t *obj, int value)
<> 144:ef7eb2e8f9f7 507 {
<> 144:ef7eb2e8f9f7 508 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 509 MBED_ASSERT(!p_spi_info->master);
<> 144:ef7eb2e8f9f7 510
<> 144:ef7eb2e8f9f7 511 p_spi_info->tx_buf = (uint8_t)value;
<> 144:ef7eb2e8f9f7 512 }
<> 144:ef7eb2e8f9f7 513
<> 144:ef7eb2e8f9f7 514 #if DEVICE_SPI_ASYNCH
<> 144:ef7eb2e8f9f7 515
<> 144:ef7eb2e8f9f7 516 void spi_master_transfer(spi_t *obj,
<> 144:ef7eb2e8f9f7 517 const void *tx, size_t tx_length,
<> 144:ef7eb2e8f9f7 518 void *rx, size_t rx_length, uint8_t bit_width,
<> 144:ef7eb2e8f9f7 519 uint32_t handler, uint32_t event, DMAUsage hint)
<> 144:ef7eb2e8f9f7 520 {
<> 144:ef7eb2e8f9f7 521 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 522 MBED_ASSERT(p_spi_info->master);
<> 144:ef7eb2e8f9f7 523 (void)hint;
<> 144:ef7eb2e8f9f7 524 (void)bit_width;
<> 144:ef7eb2e8f9f7 525
<> 144:ef7eb2e8f9f7 526 p_spi_info->handler = handler;
<> 144:ef7eb2e8f9f7 527 p_spi_info->event = event;
<> 144:ef7eb2e8f9f7 528
<> 144:ef7eb2e8f9f7 529 p_spi_info->flag.busy = true;
<> 144:ef7eb2e8f9f7 530 (void)nrf_drv_spi_transfer(MASTER_INST(obj),
<> 144:ef7eb2e8f9f7 531 (uint8_t const *)tx, tx_length,
<> 144:ef7eb2e8f9f7 532 (uint8_t *)rx, rx_length);
<> 144:ef7eb2e8f9f7 533 }
<> 144:ef7eb2e8f9f7 534
<> 144:ef7eb2e8f9f7 535 uint32_t spi_irq_handler_asynch(spi_t *obj)
<> 144:ef7eb2e8f9f7 536 {
<> 144:ef7eb2e8f9f7 537 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 538 MBED_ASSERT(p_spi_info->master);
<> 144:ef7eb2e8f9f7 539 return p_spi_info->event & SPI_EVENT_COMPLETE;
<> 144:ef7eb2e8f9f7 540 }
<> 144:ef7eb2e8f9f7 541
<> 144:ef7eb2e8f9f7 542 uint8_t spi_active(spi_t *obj)
<> 144:ef7eb2e8f9f7 543 {
<> 144:ef7eb2e8f9f7 544 spi_info_t *p_spi_info = SPI_INFO(obj);
<> 144:ef7eb2e8f9f7 545 MBED_ASSERT(p_spi_info->master);
<> 144:ef7eb2e8f9f7 546 return p_spi_info->flag.busy;
<> 144:ef7eb2e8f9f7 547 }
<> 144:ef7eb2e8f9f7 548
<> 144:ef7eb2e8f9f7 549 void spi_abort_asynch(spi_t *obj)
<> 144:ef7eb2e8f9f7 550 {
<> 144:ef7eb2e8f9f7 551 MBED_ASSERT(SPI_INFO(obj)->master);
<> 144:ef7eb2e8f9f7 552 nrf_drv_spi_abort(MASTER_INST(obj));
<> 144:ef7eb2e8f9f7 553 }
<> 144:ef7eb2e8f9f7 554
<> 144:ef7eb2e8f9f7 555 #endif // DEVICE_SPI_ASYNCH
<> 144:ef7eb2e8f9f7 556
<> 144:ef7eb2e8f9f7 557 #endif // DEVICE_SPI