mbed

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Fri Feb 16 16:09:33 2018 +0000
Revision:
182:57724642e740
Parent:
171:19eb464bc2be
mbed-dev library. Release version 159.

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