mbed

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Tue Mar 14 16:40:56 2017 +0000
Revision:
160:d5399cc887bb
Parent:
150:02e0a0aed4ec
Child:
165:e614a9f1c9e2
This updates the lib to the mbed lib v138

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