mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
170:19eb464bc2be
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 15:a81a8d6c1dfe 1 /* mbed Microcontroller Library
mbed_official 15:a81a8d6c1dfe 2 * Copyright (c) 2006-2015 ARM Limited
mbed_official 15:a81a8d6c1dfe 3 *
mbed_official 15:a81a8d6c1dfe 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 15:a81a8d6c1dfe 5 * you may not use this file except in compliance with the License.
mbed_official 15:a81a8d6c1dfe 6 * You may obtain a copy of the License at
mbed_official 15:a81a8d6c1dfe 7 *
mbed_official 15:a81a8d6c1dfe 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 15:a81a8d6c1dfe 9 *
mbed_official 15:a81a8d6c1dfe 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 15:a81a8d6c1dfe 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 15:a81a8d6c1dfe 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 15:a81a8d6c1dfe 13 * See the License for the specific language governing permissions and
mbed_official 15:a81a8d6c1dfe 14 * limitations under the License.
mbed_official 15:a81a8d6c1dfe 15 */
mbed_official 15:a81a8d6c1dfe 16 #include "mbed_assert.h"
mbed_official 15:a81a8d6c1dfe 17 #include "spi_api.h"
mbed_official 15:a81a8d6c1dfe 18
mbed_official 15:a81a8d6c1dfe 19 #include "cmsis.h"
mbed_official 15:a81a8d6c1dfe 20 #include "pinmap.h"
mbed_official 15:a81a8d6c1dfe 21 #include "sercom.h"
mbed_official 15:a81a8d6c1dfe 22
mbed_official 15:a81a8d6c1dfe 23 #include "pinmap_function.h"
mbed_official 15:a81a8d6c1dfe 24
mbed_official 18:da299f395b9e 25 #define SERCOM_SPI_STATUS_SYNCBUSY_Pos 15
mbed_official 18:da299f395b9e 26 #define SERCOM_SPI_STATUS_SYNCBUSY (0x1u << SERCOM_SPI_STATUS_SYNCBUSY_Pos)
mbed_official 18:da299f395b9e 27
mbed_official 15:a81a8d6c1dfe 28 #define SPI_MOSI_INDEX 0
mbed_official 15:a81a8d6c1dfe 29 #define SPI_MISO_INDEX 1
mbed_official 15:a81a8d6c1dfe 30 #define SPI_SCLK_INDEX 2
mbed_official 15:a81a8d6c1dfe 31 #define SPI_SSEL_INDEX 3
mbed_official 15:a81a8d6c1dfe 32
mbed_official 15:a81a8d6c1dfe 33 /**
mbed_official 15:a81a8d6c1dfe 34 * \brief SPI modes enum
mbed_official 15:a81a8d6c1dfe 35 *
mbed_official 15:a81a8d6c1dfe 36 * SPI mode selection.
mbed_official 15:a81a8d6c1dfe 37 */
mbed_official 15:a81a8d6c1dfe 38 enum spi_mode {
mbed_official 15:a81a8d6c1dfe 39 /** Master mode. */
mbed_official 15:a81a8d6c1dfe 40 SPI_MODE_MASTER = 1,
mbed_official 15:a81a8d6c1dfe 41 /** Slave mode. */
mbed_official 15:a81a8d6c1dfe 42 SPI_MODE_SLAVE = 0,
mbed_official 15:a81a8d6c1dfe 43 };
mbed_official 15:a81a8d6c1dfe 44
mbed_official 15:a81a8d6c1dfe 45 #if DEVICE_SPI_ASYNCH
mbed_official 15:a81a8d6c1dfe 46 #define pSPI_S(obj) (&obj->spi)
mbed_official 15:a81a8d6c1dfe 47 #define pSPI_SERCOM(obj) obj->spi.spi
mbed_official 15:a81a8d6c1dfe 48 #else
mbed_official 15:a81a8d6c1dfe 49 #define pSPI_S(obj) (obj)
mbed_official 15:a81a8d6c1dfe 50 #define pSPI_SERCOM(obj) (obj->spi)
mbed_official 15:a81a8d6c1dfe 51 #endif
mbed_official 15:a81a8d6c1dfe 52 #define _SPI(obj) pSPI_SERCOM(obj)->SPI
mbed_official 15:a81a8d6c1dfe 53
mbed_official 15:a81a8d6c1dfe 54 /** SPI default baud rate. */
mbed_official 15:a81a8d6c1dfe 55 #define SPI_DEFAULT_BAUD 100000
mbed_official 15:a81a8d6c1dfe 56
mbed_official 15:a81a8d6c1dfe 57
mbed_official 15:a81a8d6c1dfe 58 /** SPI timeout value. */
mbed_official 15:a81a8d6c1dfe 59 # define SPI_TIMEOUT 10000
mbed_official 15:a81a8d6c1dfe 60
mbed_official 15:a81a8d6c1dfe 61 extern uint8_t g_sys_init;
mbed_official 15:a81a8d6c1dfe 62 uint16_t dummy_fill_word = 0xFFFF;
mbed_official 15:a81a8d6c1dfe 63
mbed_official 15:a81a8d6c1dfe 64
mbed_official 15:a81a8d6c1dfe 65 static inline bool spi_is_syncing(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 66 {
mbed_official 15:a81a8d6c1dfe 67 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 68 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 69
mbed_official 18:da299f395b9e 70 # ifdef FEATURE_SPI_SYNC_SCHEME_VERSION_2
mbed_official 15:a81a8d6c1dfe 71 /* Return synchronization status */
mbed_official 15:a81a8d6c1dfe 72 return (_SPI(obj).SYNCBUSY.reg);
mbed_official 18:da299f395b9e 73 # else
mbed_official 18:da299f395b9e 74 /* Return synchronization status */
mbed_official 18:da299f395b9e 75 return (_SPI(obj).STATUS.reg & SERCOM_SPI_STATUS_SYNCBUSY);
mbed_official 18:da299f395b9e 76 # endif
mbed_official 15:a81a8d6c1dfe 77 }
mbed_official 15:a81a8d6c1dfe 78
mbed_official 15:a81a8d6c1dfe 79 static inline void spi_enable(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 80 {
mbed_official 15:a81a8d6c1dfe 81 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 82 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 83
mbed_official 15:a81a8d6c1dfe 84 /* Wait until the synchronization is complete */
mbed_official 15:a81a8d6c1dfe 85 while (spi_is_syncing(obj));
mbed_official 15:a81a8d6c1dfe 86
mbed_official 15:a81a8d6c1dfe 87 /* Enable SPI */
mbed_official 15:a81a8d6c1dfe 88 _SPI(obj).CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
mbed_official 15:a81a8d6c1dfe 89 }
mbed_official 15:a81a8d6c1dfe 90
mbed_official 15:a81a8d6c1dfe 91 static inline void spi_disable(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 92 {
mbed_official 15:a81a8d6c1dfe 93 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 94 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 95
mbed_official 15:a81a8d6c1dfe 96 /* Wait until the synchronization is complete */
mbed_official 15:a81a8d6c1dfe 97 while (spi_is_syncing(obj));
mbed_official 15:a81a8d6c1dfe 98
mbed_official 15:a81a8d6c1dfe 99 /* Disable SPI */
mbed_official 15:a81a8d6c1dfe 100 _SPI(obj).CTRLA.reg &= ~SERCOM_SPI_CTRLA_ENABLE;
mbed_official 15:a81a8d6c1dfe 101 }
mbed_official 15:a81a8d6c1dfe 102
mbed_official 15:a81a8d6c1dfe 103 static inline bool spi_is_write_complete(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 104 {
mbed_official 15:a81a8d6c1dfe 105 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 106 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 107
mbed_official 15:a81a8d6c1dfe 108 /* Check interrupt flag */
mbed_official 15:a81a8d6c1dfe 109 return (_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC);
mbed_official 15:a81a8d6c1dfe 110 }
mbed_official 15:a81a8d6c1dfe 111
mbed_official 15:a81a8d6c1dfe 112 static inline bool spi_is_ready_to_write(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 113 {
mbed_official 15:a81a8d6c1dfe 114 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 115 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 116
mbed_official 15:a81a8d6c1dfe 117 /* Check interrupt flag */
mbed_official 15:a81a8d6c1dfe 118 return (_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_DRE);
mbed_official 15:a81a8d6c1dfe 119 }
mbed_official 15:a81a8d6c1dfe 120
mbed_official 15:a81a8d6c1dfe 121 static inline bool spi_is_ready_to_read(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 122 {
mbed_official 15:a81a8d6c1dfe 123 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 124 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 125
mbed_official 15:a81a8d6c1dfe 126 /* Check interrupt flag */
mbed_official 15:a81a8d6c1dfe 127 return (_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_RXC);
mbed_official 15:a81a8d6c1dfe 128 }
mbed_official 15:a81a8d6c1dfe 129
mbed_official 15:a81a8d6c1dfe 130 static inline bool spi_write(spi_t *obj, uint16_t tx_data)
mbed_official 15:a81a8d6c1dfe 131 {
mbed_official 15:a81a8d6c1dfe 132 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 133 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 134
mbed_official 15:a81a8d6c1dfe 135 /* Check if the data register has been copied to the shift register */
mbed_official 15:a81a8d6c1dfe 136 if (!spi_is_ready_to_write(obj)) {
mbed_official 15:a81a8d6c1dfe 137 /* Data register has not been copied to the shift register, return */
mbed_official 15:a81a8d6c1dfe 138 return false;
mbed_official 15:a81a8d6c1dfe 139 }
mbed_official 15:a81a8d6c1dfe 140
mbed_official 15:a81a8d6c1dfe 141 /* Write the character to the DATA register */
mbed_official 15:a81a8d6c1dfe 142 _SPI(obj).DATA.reg = tx_data & SERCOM_SPI_DATA_MASK;
mbed_official 15:a81a8d6c1dfe 143
mbed_official 15:a81a8d6c1dfe 144 return true;
mbed_official 15:a81a8d6c1dfe 145 }
mbed_official 15:a81a8d6c1dfe 146
mbed_official 15:a81a8d6c1dfe 147 static inline bool spi_read(spi_t *obj, uint16_t *rx_data)
mbed_official 15:a81a8d6c1dfe 148 {
mbed_official 15:a81a8d6c1dfe 149 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 150 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 151
mbed_official 15:a81a8d6c1dfe 152 /* Check if data is ready to be read */
mbed_official 15:a81a8d6c1dfe 153 if (!spi_is_ready_to_read(obj)) {
mbed_official 15:a81a8d6c1dfe 154 /* No data has been received, return */
mbed_official 15:a81a8d6c1dfe 155 return false;
mbed_official 15:a81a8d6c1dfe 156 }
mbed_official 15:a81a8d6c1dfe 157
mbed_official 15:a81a8d6c1dfe 158 /* Check if data is overflown */
mbed_official 15:a81a8d6c1dfe 159 if (_SPI(obj).STATUS.reg & SERCOM_SPI_STATUS_BUFOVF) {
mbed_official 15:a81a8d6c1dfe 160 /* Clear overflow flag */
mbed_official 15:a81a8d6c1dfe 161 _SPI(obj).STATUS.reg |= SERCOM_SPI_STATUS_BUFOVF;
mbed_official 15:a81a8d6c1dfe 162 }
mbed_official 15:a81a8d6c1dfe 163
mbed_official 15:a81a8d6c1dfe 164 /* Read the character from the DATA register */
mbed_official 15:a81a8d6c1dfe 165 if (_SPI(obj).CTRLB.bit.CHSIZE == 1) {
mbed_official 15:a81a8d6c1dfe 166 *rx_data = (_SPI(obj).DATA.reg & SERCOM_SPI_DATA_MASK);
mbed_official 15:a81a8d6c1dfe 167 } else {
mbed_official 15:a81a8d6c1dfe 168 *rx_data = (uint8_t)_SPI(obj).DATA.reg;
mbed_official 15:a81a8d6c1dfe 169 }
mbed_official 15:a81a8d6c1dfe 170
mbed_official 15:a81a8d6c1dfe 171 return true;
mbed_official 15:a81a8d6c1dfe 172 }
mbed_official 15:a81a8d6c1dfe 173
mbed_official 15:a81a8d6c1dfe 174 static uint32_t spi_find_mux_settings(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 175 {
mbed_official 15:a81a8d6c1dfe 176 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 177 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 178 uint8_t i_dipo;
mbed_official 15:a81a8d6c1dfe 179 uint8_t i_dopo;
mbed_official 15:a81a8d6c1dfe 180 uint32_t dipo = 0;
mbed_official 15:a81a8d6c1dfe 181 uint32_t dopo = 0;
mbed_official 15:a81a8d6c1dfe 182 uint32_t mux_pad;
mbed_official 15:a81a8d6c1dfe 183
mbed_official 15:a81a8d6c1dfe 184 uint32_t mux_settings = 0;
mbed_official 15:a81a8d6c1dfe 185
mbed_official 15:a81a8d6c1dfe 186 uint32_t sercom_index = _sercom_get_sercom_inst_index(pSPI_SERCOM(obj));
mbed_official 15:a81a8d6c1dfe 187
mbed_official 15:a81a8d6c1dfe 188 if (pSPI_S(obj)->mode == SPI_MODE_MASTER) {
mbed_official 15:a81a8d6c1dfe 189 i_dipo = SPI_MISO_INDEX;
mbed_official 15:a81a8d6c1dfe 190 i_dopo = SPI_MOSI_INDEX;
mbed_official 15:a81a8d6c1dfe 191 } else {
mbed_official 15:a81a8d6c1dfe 192 i_dipo = SPI_MOSI_INDEX;
mbed_official 15:a81a8d6c1dfe 193 i_dopo = SPI_MISO_INDEX;
mbed_official 15:a81a8d6c1dfe 194 }
mbed_official 15:a81a8d6c1dfe 195
mbed_official 15:a81a8d6c1dfe 196 /* Find MUX setting */
mbed_official 15:a81a8d6c1dfe 197 if (pSPI_S(obj)->pins[i_dipo] != NC) {
mbed_official 15:a81a8d6c1dfe 198 /* Set Data input MUX padding for master */
mbed_official 15:a81a8d6c1dfe 199 mux_pad = pinmap_pad_sercom(pSPI_S(obj)->pins[i_dipo], sercom_index);
mbed_official 64:41a834223ea3 200 if (mux_pad != (uint32_t)NC) {
mbed_official 15:a81a8d6c1dfe 201 /* MUX pad value is same as DIPO value */
mbed_official 15:a81a8d6c1dfe 202 dipo = mux_pad;
mbed_official 15:a81a8d6c1dfe 203 mux_settings |= ((dipo << SERCOM_SPI_CTRLA_DIPO_Pos) & SERCOM_SPI_CTRLA_DIPO_Msk);
mbed_official 15:a81a8d6c1dfe 204 }
mbed_official 15:a81a8d6c1dfe 205 }
mbed_official 15:a81a8d6c1dfe 206
mbed_official 15:a81a8d6c1dfe 207 if (pSPI_S(obj)->pins[i_dopo] != NC) {
mbed_official 15:a81a8d6c1dfe 208 /* Set Data output MUX padding for master */
mbed_official 15:a81a8d6c1dfe 209 mux_pad = pinmap_pad_sercom(pSPI_S(obj)->pins[i_dopo], sercom_index);
mbed_official 64:41a834223ea3 210 if (mux_pad != (uint32_t)NC) {
mbed_official 15:a81a8d6c1dfe 211 if (mux_pad != 0) {
mbed_official 15:a81a8d6c1dfe 212 dopo = mux_pad - 1;
mbed_official 15:a81a8d6c1dfe 213 } else {
mbed_official 15:a81a8d6c1dfe 214 if (3 == pinmap_pad_sercom(pSPI_S(obj)->pins[SPI_SCLK_INDEX], sercom_index)) {
mbed_official 15:a81a8d6c1dfe 215 dopo = 3;
mbed_official 15:a81a8d6c1dfe 216 } else {
mbed_official 15:a81a8d6c1dfe 217 dopo = 0;
mbed_official 15:a81a8d6c1dfe 218 }
mbed_official 15:a81a8d6c1dfe 219 }
mbed_official 15:a81a8d6c1dfe 220 mux_settings |= ((dopo << SERCOM_SPI_CTRLA_DOPO_Pos) & SERCOM_SPI_CTRLA_DOPO_Msk);
mbed_official 15:a81a8d6c1dfe 221 }
mbed_official 15:a81a8d6c1dfe 222 }
mbed_official 15:a81a8d6c1dfe 223
mbed_official 15:a81a8d6c1dfe 224 return mux_settings;
mbed_official 15:a81a8d6c1dfe 225 }
mbed_official 15:a81a8d6c1dfe 226
mbed_official 15:a81a8d6c1dfe 227 /**
mbed_official 15:a81a8d6c1dfe 228 * \defgroup GeneralSPI SPI Configuration Functions
mbed_official 15:a81a8d6c1dfe 229 * @{
mbed_official 15:a81a8d6c1dfe 230 */
mbed_official 15:a81a8d6c1dfe 231
mbed_official 15:a81a8d6c1dfe 232 /** Initialize the SPI peripheral
mbed_official 15:a81a8d6c1dfe 233 *
mbed_official 15:a81a8d6c1dfe 234 * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
mbed_official 15:a81a8d6c1dfe 235 * @param[out] obj The SPI object to initialize
mbed_official 15:a81a8d6c1dfe 236 * @param[in] mosi The pin to use for MOSI
mbed_official 15:a81a8d6c1dfe 237 * @param[in] miso The pin to use for MISO
mbed_official 15:a81a8d6c1dfe 238 * @param[in] sclk The pin to use for SCLK
mbed_official 15:a81a8d6c1dfe 239 * @param[in] ssel The pin to use for SSEL
mbed_official 15:a81a8d6c1dfe 240 */
mbed_official 15:a81a8d6c1dfe 241 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
mbed_official 15:a81a8d6c1dfe 242 {
mbed_official 15:a81a8d6c1dfe 243 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 244 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 245 MBED_ASSERT(sclk != NC);
mbed_official 15:a81a8d6c1dfe 246
mbed_official 15:a81a8d6c1dfe 247 uint16_t baud = 0;
mbed_official 15:a81a8d6c1dfe 248 uint32_t ctrla = 0;
mbed_official 15:a81a8d6c1dfe 249 uint32_t ctrlb = 0;
mbed_official 15:a81a8d6c1dfe 250 enum status_code error_code;
mbed_official 15:a81a8d6c1dfe 251
mbed_official 15:a81a8d6c1dfe 252 if (g_sys_init == 0) {
mbed_official 15:a81a8d6c1dfe 253 system_init();
mbed_official 15:a81a8d6c1dfe 254 g_sys_init = 1;
mbed_official 15:a81a8d6c1dfe 255 }
mbed_official 15:a81a8d6c1dfe 256
mbed_official 15:a81a8d6c1dfe 257 /* Calculate SERCOM instance from pins */
mbed_official 15:a81a8d6c1dfe 258 uint32_t sercom_index = pinmap_find_sercom(mosi, miso, sclk, ssel);
mbed_official 15:a81a8d6c1dfe 259 pSPI_SERCOM(obj) = (Sercom*)pinmap_peripheral_sercom(NC, sercom_index);
mbed_official 15:a81a8d6c1dfe 260
mbed_official 15:a81a8d6c1dfe 261 /* Disable SPI */
mbed_official 15:a81a8d6c1dfe 262 spi_disable(obj);
mbed_official 15:a81a8d6c1dfe 263
mbed_official 15:a81a8d6c1dfe 264 /* Check if reset is in progress. */
mbed_official 15:a81a8d6c1dfe 265 if (_SPI(obj).CTRLA.reg & SERCOM_SPI_CTRLA_SWRST) {
mbed_official 15:a81a8d6c1dfe 266 return;
mbed_official 15:a81a8d6c1dfe 267 }
mbed_official 15:a81a8d6c1dfe 268
mbed_official 15:a81a8d6c1dfe 269 uint32_t pm_index, gclk_index;
mbed_official 15:a81a8d6c1dfe 270 #if (SAML21)
mbed_official 15:a81a8d6c1dfe 271 if (sercom_index == 5) {
mbed_official 18:da299f395b9e 272 # ifdef ID_SERCOM5
mbed_official 15:a81a8d6c1dfe 273 pm_index = MCLK_APBDMASK_SERCOM5_Pos;
mbed_official 15:a81a8d6c1dfe 274 gclk_index = SERCOM5_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 275 # else
mbed_official 18:da299f395b9e 276 return STATUS_ERR_INVALID_ARG;
mbed_official 18:da299f395b9e 277 # endif
mbed_official 15:a81a8d6c1dfe 278 } else {
mbed_official 15:a81a8d6c1dfe 279 pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
mbed_official 15:a81a8d6c1dfe 280 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 15:a81a8d6c1dfe 281 }
mbed_official 18:da299f395b9e 282 #elif (SAMC21)
mbed_official 18:da299f395b9e 283 if (sercom_index == 5) {
mbed_official 18:da299f395b9e 284 # ifdef ID_SERCOM5
mbed_official 18:da299f395b9e 285 pm_index = MCLK_APBCMASK_SERCOM5_Pos;
mbed_official 18:da299f395b9e 286 gclk_index = SERCOM5_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 287 # else
mbed_official 18:da299f395b9e 288 return STATUS_ERR_INVALID_ARG;
mbed_official 18:da299f395b9e 289 # endif
mbed_official 18:da299f395b9e 290 } else {
mbed_official 18:da299f395b9e 291 pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
mbed_official 18:da299f395b9e 292 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 293 }
mbed_official 18:da299f395b9e 294 #elif (SAMC20)
mbed_official 18:da299f395b9e 295 pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
mbed_official 18:da299f395b9e 296 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 15:a81a8d6c1dfe 297 #else
mbed_official 15:a81a8d6c1dfe 298 pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
mbed_official 15:a81a8d6c1dfe 299 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 15:a81a8d6c1dfe 300 #endif
mbed_official 15:a81a8d6c1dfe 301
mbed_official 15:a81a8d6c1dfe 302 /* Turn on module in PM */
mbed_official 15:a81a8d6c1dfe 303 #if (SAML21)
mbed_official 15:a81a8d6c1dfe 304 if (sercom_index == 5) {
mbed_official 18:da299f395b9e 305 # ifdef ID_SERCOM5
mbed_official 15:a81a8d6c1dfe 306 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBD, 1 << pm_index);
mbed_official 18:da299f395b9e 307 # else
mbed_official 18:da299f395b9e 308 return STATUS_ERR_INVALID_ARG;
mbed_official 18:da299f395b9e 309 # endif
mbed_official 15:a81a8d6c1dfe 310 } else {
mbed_official 15:a81a8d6c1dfe 311 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
mbed_official 15:a81a8d6c1dfe 312 }
mbed_official 15:a81a8d6c1dfe 313 #else
mbed_official 15:a81a8d6c1dfe 314 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
mbed_official 15:a81a8d6c1dfe 315 #endif
mbed_official 15:a81a8d6c1dfe 316
mbed_official 15:a81a8d6c1dfe 317 /* Set up the GCLK for the module */
mbed_official 15:a81a8d6c1dfe 318 struct system_gclk_chan_config gclk_chan_conf;
mbed_official 15:a81a8d6c1dfe 319 system_gclk_chan_get_config_defaults(&gclk_chan_conf);
mbed_official 15:a81a8d6c1dfe 320 gclk_chan_conf.source_generator = GCLK_GENERATOR_0;
mbed_official 15:a81a8d6c1dfe 321 system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
mbed_official 15:a81a8d6c1dfe 322 system_gclk_chan_enable(gclk_index);
mbed_official 15:a81a8d6c1dfe 323 sercom_set_gclk_generator(GCLK_GENERATOR_0, false);
mbed_official 15:a81a8d6c1dfe 324
mbed_official 15:a81a8d6c1dfe 325 /* Set the SERCOM in SPI master mode */
mbed_official 15:a81a8d6c1dfe 326 _SPI(obj).CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x3);
mbed_official 15:a81a8d6c1dfe 327 pSPI_S(obj)->mode = SPI_MODE_MASTER;
mbed_official 15:a81a8d6c1dfe 328
mbed_official 15:a81a8d6c1dfe 329 /* TODO: Do pin muxing here */
mbed_official 15:a81a8d6c1dfe 330 struct system_pinmux_config pin_conf;
mbed_official 15:a81a8d6c1dfe 331 system_pinmux_get_config_defaults(&pin_conf);
mbed_official 15:a81a8d6c1dfe 332 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
mbed_official 15:a81a8d6c1dfe 333
mbed_official 15:a81a8d6c1dfe 334 pSPI_S(obj)->pins[SPI_MOSI_INDEX] = mosi;
mbed_official 15:a81a8d6c1dfe 335 pSPI_S(obj)->pins[SPI_MISO_INDEX] = miso;
mbed_official 15:a81a8d6c1dfe 336 pSPI_S(obj)->pins[SPI_SCLK_INDEX] = sclk;
mbed_official 15:a81a8d6c1dfe 337 pSPI_S(obj)->pins[SPI_SSEL_INDEX] = ssel;
mbed_official 15:a81a8d6c1dfe 338 /* Configure the SERCOM pins according to the user configuration */
mbed_official 15:a81a8d6c1dfe 339 for (uint8_t pad = 0; pad < 4; pad++) {
mbed_official 15:a81a8d6c1dfe 340 uint32_t current_pin = pSPI_S(obj)->pins[pad];
mbed_official 64:41a834223ea3 341 if (current_pin != (uint32_t)NC) {
mbed_official 64:41a834223ea3 342 pin_conf.mux_position = pinmap_function_sercom((PinName)current_pin, sercom_index);
mbed_official 15:a81a8d6c1dfe 343 if ((uint8_t)NC != pin_conf.mux_position) {
mbed_official 15:a81a8d6c1dfe 344 system_pinmux_pin_set_config(current_pin, &pin_conf);
mbed_official 15:a81a8d6c1dfe 345 }
mbed_official 15:a81a8d6c1dfe 346 }
mbed_official 15:a81a8d6c1dfe 347 }
mbed_official 15:a81a8d6c1dfe 348
mbed_official 15:a81a8d6c1dfe 349 /* Get baud value, based on baudrate and the internal clock frequency */
mbed_official 15:a81a8d6c1dfe 350 uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);
mbed_official 15:a81a8d6c1dfe 351 //internal_clock = 8000000;
mbed_official 15:a81a8d6c1dfe 352 error_code = _sercom_get_sync_baud_val(SPI_DEFAULT_BAUD, internal_clock, &baud);
mbed_official 15:a81a8d6c1dfe 353 if (error_code != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 354 /* Baud rate calculation error */
mbed_official 15:a81a8d6c1dfe 355 return;
mbed_official 15:a81a8d6c1dfe 356 }
mbed_official 15:a81a8d6c1dfe 357 _SPI(obj).BAUD.reg = (uint8_t)baud;
mbed_official 15:a81a8d6c1dfe 358
mbed_official 15:a81a8d6c1dfe 359 /* TODO: Find MUX settings */
mbed_official 15:a81a8d6c1dfe 360 ctrla |= spi_find_mux_settings(obj);
mbed_official 15:a81a8d6c1dfe 361
mbed_official 15:a81a8d6c1dfe 362 /* Set SPI character size */
mbed_official 15:a81a8d6c1dfe 363 ctrlb |= SERCOM_SPI_CTRLB_CHSIZE(0);
mbed_official 15:a81a8d6c1dfe 364
mbed_official 15:a81a8d6c1dfe 365 /* Enable receiver */
mbed_official 15:a81a8d6c1dfe 366 ctrlb |= SERCOM_SPI_CTRLB_RXEN;
mbed_official 15:a81a8d6c1dfe 367
mbed_official 15:a81a8d6c1dfe 368 /* Write CTRLA register */
mbed_official 15:a81a8d6c1dfe 369 _SPI(obj).CTRLA.reg |= ctrla;
mbed_official 15:a81a8d6c1dfe 370
mbed_official 15:a81a8d6c1dfe 371 /* Write CTRLB register */
mbed_official 15:a81a8d6c1dfe 372 _SPI(obj).CTRLB.reg |= ctrlb;
mbed_official 15:a81a8d6c1dfe 373
mbed_official 15:a81a8d6c1dfe 374 /* Enable SPI */
mbed_official 15:a81a8d6c1dfe 375 spi_enable(obj);
mbed_official 15:a81a8d6c1dfe 376 }
mbed_official 15:a81a8d6c1dfe 377
mbed_official 15:a81a8d6c1dfe 378 /** Release a SPI object
mbed_official 15:a81a8d6c1dfe 379 *
mbed_official 15:a81a8d6c1dfe 380 * TODO: spi_free is currently unimplemented
mbed_official 15:a81a8d6c1dfe 381 * This will require reference counting at the C++ level to be safe
mbed_official 15:a81a8d6c1dfe 382 *
mbed_official 15:a81a8d6c1dfe 383 * Return the pins owned by the SPI object to their reset state
mbed_official 15:a81a8d6c1dfe 384 * Disable the SPI peripheral
mbed_official 15:a81a8d6c1dfe 385 * Disable the SPI clock
mbed_official 15:a81a8d6c1dfe 386 * @param[in] obj The SPI object to deinitialize
mbed_official 15:a81a8d6c1dfe 387 */
mbed_official 15:a81a8d6c1dfe 388 void spi_free(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 389 {
mbed_official 15:a81a8d6c1dfe 390 // [TODO]
mbed_official 15:a81a8d6c1dfe 391 }
mbed_official 15:a81a8d6c1dfe 392
mbed_official 15:a81a8d6c1dfe 393 /** Configure the SPI format
mbed_official 15:a81a8d6c1dfe 394 *
mbed_official 15:a81a8d6c1dfe 395 * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode
mbed_official 15:a81a8d6c1dfe 396 * @param[in,out] obj The SPI object to configure
mbed_official 15:a81a8d6c1dfe 397 * @param[in] bits The number of bits per frame
mbed_official 15:a81a8d6c1dfe 398 * @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
mbed_official 15:a81a8d6c1dfe 399 * @param[in] slave Zero for master mode or non-zero for slave mode
mbed_official 15:a81a8d6c1dfe 400 */
mbed_official 15:a81a8d6c1dfe 401 void spi_format(spi_t *obj, int bits, int mode, int slave)
mbed_official 15:a81a8d6c1dfe 402 {
mbed_official 15:a81a8d6c1dfe 403 PinMode pull_mode;
mbed_official 15:a81a8d6c1dfe 404 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 405 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 406
mbed_official 15:a81a8d6c1dfe 407 /* Disable SPI */
mbed_official 15:a81a8d6c1dfe 408 spi_disable(obj);
mbed_official 15:a81a8d6c1dfe 409
mbed_official 15:a81a8d6c1dfe 410
mbed_official 15:a81a8d6c1dfe 411 if (slave) {
mbed_official 15:a81a8d6c1dfe 412 /* Set the SERCOM in SPI mode */
mbed_official 15:a81a8d6c1dfe 413 _SPI(obj).CTRLA.bit.MODE = 0x2;
mbed_official 15:a81a8d6c1dfe 414 pSPI_S(obj)->mode = SPI_MODE_SLAVE;
mbed_official 15:a81a8d6c1dfe 415 pull_mode = PullNone;
mbed_official 15:a81a8d6c1dfe 416 /* Enable PLOADEN to avoid sending dummy character by slave */
mbed_official 15:a81a8d6c1dfe 417 _SPI(obj).CTRLB.bit.PLOADEN = 1;
mbed_official 15:a81a8d6c1dfe 418 } else {
mbed_official 15:a81a8d6c1dfe 419 /* Set the SERCOM in SPI mode */
mbed_official 15:a81a8d6c1dfe 420 _SPI(obj).CTRLA.bit.MODE = 0x3;
mbed_official 15:a81a8d6c1dfe 421 pSPI_S(obj)->mode = SPI_MODE_MASTER;
mbed_official 15:a81a8d6c1dfe 422 pull_mode = PullUp;
mbed_official 15:a81a8d6c1dfe 423 }
mbed_official 15:a81a8d6c1dfe 424
mbed_official 15:a81a8d6c1dfe 425 /* Change pull mode of pins */
mbed_official 15:a81a8d6c1dfe 426 for (uint8_t pad = 0; pad < 4; pad++) {
mbed_official 15:a81a8d6c1dfe 427 if (pSPI_S(obj)->pins[pad] != NC) {
mbed_official 15:a81a8d6c1dfe 428 pin_mode(pSPI_S(obj)->pins[pad], pull_mode);
mbed_official 15:a81a8d6c1dfe 429 }
mbed_official 15:a81a8d6c1dfe 430 }
mbed_official 15:a81a8d6c1dfe 431
mbed_official 15:a81a8d6c1dfe 432 /* Change MUX settings */
mbed_official 15:a81a8d6c1dfe 433 uint32_t ctrla = _SPI(obj).CTRLA.reg;
mbed_official 15:a81a8d6c1dfe 434 ctrla &= ~(SERCOM_SPI_CTRLA_DIPO_Msk | SERCOM_SPI_CTRLA_DOPO_Msk);
mbed_official 15:a81a8d6c1dfe 435 ctrla |= spi_find_mux_settings(obj);
mbed_official 15:a81a8d6c1dfe 436 _SPI(obj).CTRLA.reg = ctrla;
mbed_official 15:a81a8d6c1dfe 437
mbed_official 15:a81a8d6c1dfe 438 /* Set SPI Frame size - only 8-bit and 9-bit supported now */
mbed_official 15:a81a8d6c1dfe 439 _SPI(obj).CTRLB.bit.CHSIZE = (bits > 8)? 1 : 0;
mbed_official 15:a81a8d6c1dfe 440
mbed_official 15:a81a8d6c1dfe 441 /* Set SPI Clock Phase */
mbed_official 15:a81a8d6c1dfe 442 _SPI(obj).CTRLA.bit.CPHA = (mode & 0x01)? 1 : 0;
mbed_official 15:a81a8d6c1dfe 443
mbed_official 15:a81a8d6c1dfe 444 /* Set SPI Clock Polarity */
mbed_official 15:a81a8d6c1dfe 445 _SPI(obj).CTRLA.bit.CPOL = (mode & 0x02)? 1 : 0;
mbed_official 15:a81a8d6c1dfe 446
mbed_official 15:a81a8d6c1dfe 447 /* Enable SPI */
mbed_official 15:a81a8d6c1dfe 448 spi_enable(obj);
mbed_official 15:a81a8d6c1dfe 449 }
mbed_official 15:a81a8d6c1dfe 450
mbed_official 15:a81a8d6c1dfe 451 /** Set the SPI baud rate
mbed_official 15:a81a8d6c1dfe 452 *
mbed_official 15:a81a8d6c1dfe 453 * Actual frequency may differ from the desired frequency due to available dividers and bus clock
mbed_official 15:a81a8d6c1dfe 454 * Configures the SPI peripheral's baud rate
mbed_official 15:a81a8d6c1dfe 455 * @param[in,out] obj The SPI object to configure
mbed_official 15:a81a8d6c1dfe 456 * @param[in] hz The baud rate in Hz
mbed_official 15:a81a8d6c1dfe 457 */
mbed_official 15:a81a8d6c1dfe 458 void spi_frequency(spi_t *obj, int hz)
mbed_official 15:a81a8d6c1dfe 459 {
mbed_official 15:a81a8d6c1dfe 460 uint16_t baud = 0;
mbed_official 18:da299f395b9e 461 uint32_t gclk_index = 0;
mbed_official 15:a81a8d6c1dfe 462 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 463 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 464
mbed_official 15:a81a8d6c1dfe 465 /* Disable SPI */
mbed_official 15:a81a8d6c1dfe 466 spi_disable(obj);
mbed_official 15:a81a8d6c1dfe 467
mbed_official 15:a81a8d6c1dfe 468 /* Find frequency of the internal SERCOMi_GCLK_ID_CORE */
mbed_official 15:a81a8d6c1dfe 469 uint32_t sercom_index = _sercom_get_sercom_inst_index(pSPI_SERCOM(obj));
mbed_official 18:da299f395b9e 470 #if (SAML21)
mbed_official 18:da299f395b9e 471 if (sercom_index == 5) {
mbed_official 18:da299f395b9e 472 # ifdef ID_SERCOM5
mbed_official 18:da299f395b9e 473 gclk_index = SERCOM5_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 474 # else
mbed_official 18:da299f395b9e 475 return STATUS_ERR_INVALID_ARG;
mbed_official 18:da299f395b9e 476 # endif
mbed_official 18:da299f395b9e 477 } else {
mbed_official 18:da299f395b9e 478 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 479 }
mbed_official 18:da299f395b9e 480 #elif (SAMC21)
mbed_official 18:da299f395b9e 481 if (sercom_index == 5) {
mbed_official 18:da299f395b9e 482 # ifdef ID_SERCOM5
mbed_official 18:da299f395b9e 483 gclk_index = SERCOM5_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 484 # else
mbed_official 18:da299f395b9e 485 return STATUS_ERR_INVALID_ARG;
mbed_official 18:da299f395b9e 486 # endif
mbed_official 18:da299f395b9e 487 } else {
mbed_official 18:da299f395b9e 488 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 489 }
mbed_official 18:da299f395b9e 490 #elif (SAMC20)
mbed_official 18:da299f395b9e 491 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 492 #else
mbed_official 18:da299f395b9e 493 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
mbed_official 18:da299f395b9e 494 #endif
mbed_official 15:a81a8d6c1dfe 495 uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);
mbed_official 15:a81a8d6c1dfe 496
mbed_official 15:a81a8d6c1dfe 497 /* Get baud value, based on baudrate and the internal clock frequency */
mbed_official 15:a81a8d6c1dfe 498 enum status_code error_code = _sercom_get_sync_baud_val(hz, internal_clock, &baud);
mbed_official 15:a81a8d6c1dfe 499
mbed_official 15:a81a8d6c1dfe 500 if (error_code != STATUS_OK) {
mbed_official 15:a81a8d6c1dfe 501 /* Baud rate calculation error, return status code */
mbed_official 15:a81a8d6c1dfe 502 /* Enable SPI */
mbed_official 15:a81a8d6c1dfe 503 spi_enable(obj);
mbed_official 15:a81a8d6c1dfe 504 return;
mbed_official 15:a81a8d6c1dfe 505 }
mbed_official 15:a81a8d6c1dfe 506
mbed_official 15:a81a8d6c1dfe 507 _SPI(obj).BAUD.reg = (uint8_t)baud;
mbed_official 15:a81a8d6c1dfe 508
mbed_official 15:a81a8d6c1dfe 509 /* Enable SPI */
mbed_official 15:a81a8d6c1dfe 510 spi_enable(obj);
mbed_official 15:a81a8d6c1dfe 511 }
mbed_official 15:a81a8d6c1dfe 512
mbed_official 15:a81a8d6c1dfe 513 /**@}*/
mbed_official 15:a81a8d6c1dfe 514 /**
mbed_official 15:a81a8d6c1dfe 515 * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer
mbed_official 15:a81a8d6c1dfe 516 * @{
mbed_official 15:a81a8d6c1dfe 517 */
mbed_official 15:a81a8d6c1dfe 518
mbed_official 15:a81a8d6c1dfe 519 /** Write a byte out in master mode and receive a value
mbed_official 15:a81a8d6c1dfe 520 *
mbed_official 15:a81a8d6c1dfe 521 * @param[in] obj The SPI peripheral to use for sending
mbed_official 15:a81a8d6c1dfe 522 * @param[in] value The value to send
mbed_official 15:a81a8d6c1dfe 523 * @return Returns the value received during send
mbed_official 15:a81a8d6c1dfe 524 */
mbed_official 15:a81a8d6c1dfe 525 int spi_master_write(spi_t *obj, int value)
mbed_official 15:a81a8d6c1dfe 526 {
mbed_official 15:a81a8d6c1dfe 527 uint16_t rx_data = 0;
mbed_official 15:a81a8d6c1dfe 528
mbed_official 15:a81a8d6c1dfe 529 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 530 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 531
mbed_official 15:a81a8d6c1dfe 532 #if DEVICE_SPI_ASYNCH
mbed_official 15:a81a8d6c1dfe 533 if (obj->spi.status == STATUS_BUSY) {
mbed_official 15:a81a8d6c1dfe 534 /* Check if the SPI module is busy with a job */
mbed_official 15:a81a8d6c1dfe 535 return 0;
mbed_official 15:a81a8d6c1dfe 536 }
mbed_official 15:a81a8d6c1dfe 537 #endif
mbed_official 15:a81a8d6c1dfe 538
mbed_official 15:a81a8d6c1dfe 539 /* Wait until the module is ready to write the character */
mbed_official 15:a81a8d6c1dfe 540 while (!spi_is_ready_to_write(obj));
mbed_official 15:a81a8d6c1dfe 541
mbed_official 15:a81a8d6c1dfe 542 /* Write data */
mbed_official 15:a81a8d6c1dfe 543 spi_write(obj, value);
mbed_official 15:a81a8d6c1dfe 544
mbed_official 15:a81a8d6c1dfe 545 if (!(_SPI(obj).CTRLB.bit.RXEN)) {
mbed_official 15:a81a8d6c1dfe 546 return 0;
mbed_official 15:a81a8d6c1dfe 547 }
mbed_official 15:a81a8d6c1dfe 548
mbed_official 15:a81a8d6c1dfe 549 /* Wait until the module is ready to read the character */
mbed_official 15:a81a8d6c1dfe 550 while (!spi_is_ready_to_read(obj));
mbed_official 15:a81a8d6c1dfe 551
mbed_official 15:a81a8d6c1dfe 552 /* Read data */
mbed_official 15:a81a8d6c1dfe 553 spi_read(obj, &rx_data);
mbed_official 15:a81a8d6c1dfe 554
mbed_official 15:a81a8d6c1dfe 555 return rx_data;
mbed_official 15:a81a8d6c1dfe 556 }
mbed_official 15:a81a8d6c1dfe 557
Kojto 170:19eb464bc2be 558 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
Kojto 170:19eb464bc2be 559 char *rx_buffer, int rx_length, char write_fill) {
AnnaBridge 167:e84263d55307 560 int total = (tx_length > rx_length) ? tx_length : rx_length;
AnnaBridge 167:e84263d55307 561
AnnaBridge 167:e84263d55307 562 for (int i = 0; i < total; i++) {
Kojto 170:19eb464bc2be 563 char out = (i < tx_length) ? tx_buffer[i] : write_fill;
AnnaBridge 167:e84263d55307 564 char in = spi_master_write(obj, out);
AnnaBridge 167:e84263d55307 565 if (i < rx_length) {
AnnaBridge 167:e84263d55307 566 rx_buffer[i] = in;
AnnaBridge 167:e84263d55307 567 }
AnnaBridge 167:e84263d55307 568 }
AnnaBridge 167:e84263d55307 569
AnnaBridge 167:e84263d55307 570 return total;
AnnaBridge 167:e84263d55307 571 }
AnnaBridge 167:e84263d55307 572
mbed_official 15:a81a8d6c1dfe 573 /** Check if a value is available to read
mbed_official 15:a81a8d6c1dfe 574 *
mbed_official 15:a81a8d6c1dfe 575 * @param[in] obj The SPI peripheral to check
mbed_official 15:a81a8d6c1dfe 576 * @return non-zero if a value is available
mbed_official 15:a81a8d6c1dfe 577 */
mbed_official 15:a81a8d6c1dfe 578 int spi_slave_receive(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 579 {
mbed_official 15:a81a8d6c1dfe 580 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 581 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 582
mbed_official 15:a81a8d6c1dfe 583 return spi_is_ready_to_read(obj);
mbed_official 15:a81a8d6c1dfe 584 }
mbed_official 15:a81a8d6c1dfe 585
mbed_official 15:a81a8d6c1dfe 586 /** Get a received value out of the SPI receive buffer in slave mode
mbed_official 15:a81a8d6c1dfe 587 *
mbed_official 15:a81a8d6c1dfe 588 * Blocks until a value is available
mbed_official 15:a81a8d6c1dfe 589 * @param[in] obj The SPI peripheral to read
mbed_official 15:a81a8d6c1dfe 590 * @return The value received
mbed_official 15:a81a8d6c1dfe 591 */
mbed_official 15:a81a8d6c1dfe 592 int spi_slave_read(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 593 {
mbed_official 15:a81a8d6c1dfe 594 int i;
mbed_official 15:a81a8d6c1dfe 595 uint16_t rx_data = 0;
mbed_official 15:a81a8d6c1dfe 596
mbed_official 15:a81a8d6c1dfe 597 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 598 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 599
mbed_official 15:a81a8d6c1dfe 600 /* Check for timeout period */
mbed_official 15:a81a8d6c1dfe 601 for (i = 0; i < SPI_TIMEOUT; i++) {
mbed_official 15:a81a8d6c1dfe 602 if (spi_is_ready_to_read(obj)) {
mbed_official 15:a81a8d6c1dfe 603 break;
mbed_official 15:a81a8d6c1dfe 604 }
mbed_official 15:a81a8d6c1dfe 605 }
mbed_official 15:a81a8d6c1dfe 606 if (i == SPI_TIMEOUT) {
mbed_official 15:a81a8d6c1dfe 607 /* Not ready to read data within timeout period */
mbed_official 15:a81a8d6c1dfe 608 return 0;
mbed_official 15:a81a8d6c1dfe 609 }
mbed_official 15:a81a8d6c1dfe 610
mbed_official 15:a81a8d6c1dfe 611 /* Read data */
mbed_official 15:a81a8d6c1dfe 612 spi_read(obj, &rx_data);
mbed_official 15:a81a8d6c1dfe 613
mbed_official 15:a81a8d6c1dfe 614 return rx_data;
mbed_official 15:a81a8d6c1dfe 615 }
mbed_official 15:a81a8d6c1dfe 616
mbed_official 15:a81a8d6c1dfe 617 /** Write a value to the SPI peripheral in slave mode
mbed_official 15:a81a8d6c1dfe 618 *
mbed_official 15:a81a8d6c1dfe 619 * Blocks until the SPI peripheral can be written to
mbed_official 15:a81a8d6c1dfe 620 * @param[in] obj The SPI peripheral to write
mbed_official 15:a81a8d6c1dfe 621 * @param[in] value The value to write
mbed_official 15:a81a8d6c1dfe 622 */
mbed_official 15:a81a8d6c1dfe 623 void spi_slave_write(spi_t *obj, int value)
mbed_official 15:a81a8d6c1dfe 624 {
mbed_official 15:a81a8d6c1dfe 625 int i;
mbed_official 15:a81a8d6c1dfe 626
mbed_official 15:a81a8d6c1dfe 627 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 628 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 629
mbed_official 15:a81a8d6c1dfe 630 /* Check for timeout period */
mbed_official 15:a81a8d6c1dfe 631 for (i = 0; i < SPI_TIMEOUT; i++) {
mbed_official 15:a81a8d6c1dfe 632 if (spi_is_ready_to_write(obj)) {
mbed_official 15:a81a8d6c1dfe 633 break;
mbed_official 15:a81a8d6c1dfe 634 }
mbed_official 15:a81a8d6c1dfe 635 }
mbed_official 15:a81a8d6c1dfe 636 if (i == SPI_TIMEOUT) {
mbed_official 15:a81a8d6c1dfe 637 /* Not ready to write data within timeout period */
mbed_official 15:a81a8d6c1dfe 638 return;
mbed_official 15:a81a8d6c1dfe 639 }
mbed_official 15:a81a8d6c1dfe 640
mbed_official 15:a81a8d6c1dfe 641 /* Write data */
mbed_official 15:a81a8d6c1dfe 642 spi_write(obj, value);
mbed_official 15:a81a8d6c1dfe 643 }
mbed_official 15:a81a8d6c1dfe 644
mbed_official 15:a81a8d6c1dfe 645 /** Checks if the specified SPI peripheral is in use
mbed_official 15:a81a8d6c1dfe 646 *
mbed_official 15:a81a8d6c1dfe 647 * @param[in] obj The SPI peripheral to check
mbed_official 15:a81a8d6c1dfe 648 * @return non-zero if the peripheral is currently transmitting
mbed_official 15:a81a8d6c1dfe 649 */
mbed_official 15:a81a8d6c1dfe 650 int spi_busy(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 651 {
mbed_official 15:a81a8d6c1dfe 652 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 653 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 654
mbed_official 15:a81a8d6c1dfe 655 return spi_is_write_complete(obj);
mbed_official 15:a81a8d6c1dfe 656 }
mbed_official 15:a81a8d6c1dfe 657
mbed_official 15:a81a8d6c1dfe 658 /** Get the module number
mbed_official 15:a81a8d6c1dfe 659 *
mbed_official 15:a81a8d6c1dfe 660 * @param[in] obj The SPI peripheral to check
mbed_official 15:a81a8d6c1dfe 661 * @return The module number
mbed_official 15:a81a8d6c1dfe 662 */
mbed_official 15:a81a8d6c1dfe 663 uint8_t spi_get_module(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 664 {
mbed_official 15:a81a8d6c1dfe 665 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 666 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 667 return _sercom_get_sercom_inst_index(pSPI_SERCOM(obj));
mbed_official 15:a81a8d6c1dfe 668 }
mbed_official 15:a81a8d6c1dfe 669
mbed_official 15:a81a8d6c1dfe 670
mbed_official 15:a81a8d6c1dfe 671 #if DEVICE_SPI_ASYNCH
mbed_official 15:a81a8d6c1dfe 672 /**
mbed_official 15:a81a8d6c1dfe 673 * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
mbed_official 15:a81a8d6c1dfe 674 * @{
mbed_official 15:a81a8d6c1dfe 675 */
mbed_official 15:a81a8d6c1dfe 676
mbed_official 15:a81a8d6c1dfe 677
mbed_official 15:a81a8d6c1dfe 678 /**
mbed_official 15:a81a8d6c1dfe 679 * \internal
mbed_official 15:a81a8d6c1dfe 680 * Writes a character from the TX buffer to the Data register.
mbed_official 15:a81a8d6c1dfe 681 *
mbed_official 15:a81a8d6c1dfe 682 * \param[in,out] module Pointer to SPI software instance struct
mbed_official 15:a81a8d6c1dfe 683 */
mbed_official 15:a81a8d6c1dfe 684 static void _spi_write_async(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 685 {
mbed_official 15:a81a8d6c1dfe 686 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 687 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 688
mbed_official 15:a81a8d6c1dfe 689 uint16_t data_to_send;
mbed_official 15:a81a8d6c1dfe 690 uint8_t *tx_buffer = obj->tx_buff.buffer;
mbed_official 15:a81a8d6c1dfe 691
mbed_official 15:a81a8d6c1dfe 692 /* Do nothing if we are at the end of buffer */
mbed_official 15:a81a8d6c1dfe 693 if (obj->tx_buff.pos < obj->tx_buff.length) {
mbed_official 15:a81a8d6c1dfe 694 /* Write value will be at least 8-bits long */
mbed_official 15:a81a8d6c1dfe 695 if (tx_buffer) {
mbed_official 15:a81a8d6c1dfe 696 data_to_send = tx_buffer[obj->tx_buff.pos];
mbed_official 15:a81a8d6c1dfe 697 } else {
mbed_official 15:a81a8d6c1dfe 698 data_to_send = dummy_fill_word;
mbed_official 15:a81a8d6c1dfe 699 }
mbed_official 15:a81a8d6c1dfe 700 /* Increment 8-bit index */
mbed_official 15:a81a8d6c1dfe 701 obj->tx_buff.pos++;
mbed_official 15:a81a8d6c1dfe 702
mbed_official 15:a81a8d6c1dfe 703 if (_SPI(obj).CTRLB.bit.CHSIZE == 1) {
mbed_official 15:a81a8d6c1dfe 704 if (tx_buffer)
mbed_official 15:a81a8d6c1dfe 705 data_to_send |= (tx_buffer[obj->tx_buff.pos] << 8);
mbed_official 15:a81a8d6c1dfe 706 /* Increment 8-bit index */
mbed_official 15:a81a8d6c1dfe 707 obj->tx_buff.pos++;
mbed_official 15:a81a8d6c1dfe 708 }
mbed_official 15:a81a8d6c1dfe 709 } else {
mbed_official 15:a81a8d6c1dfe 710 /* Write a dummy packet */
mbed_official 15:a81a8d6c1dfe 711 /* TODO: Current implementation do not enter this condition, remove if not needed */
mbed_official 15:a81a8d6c1dfe 712 data_to_send = dummy_fill_word;
mbed_official 15:a81a8d6c1dfe 713 }
mbed_official 15:a81a8d6c1dfe 714
mbed_official 15:a81a8d6c1dfe 715 /* Write the data to send*/
mbed_official 15:a81a8d6c1dfe 716 _SPI(obj).DATA.reg = data_to_send & SERCOM_SPI_DATA_MASK;
mbed_official 15:a81a8d6c1dfe 717
mbed_official 15:a81a8d6c1dfe 718 /* Check for error */
mbed_official 15:a81a8d6c1dfe 719 if ((_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_ERROR) && (obj->spi.mask & SPI_EVENT_ERROR)) {
mbed_official 15:a81a8d6c1dfe 720 obj->spi.event |= SPI_EVENT_ERROR;
mbed_official 15:a81a8d6c1dfe 721 }
mbed_official 15:a81a8d6c1dfe 722 }
mbed_official 15:a81a8d6c1dfe 723
mbed_official 15:a81a8d6c1dfe 724 /**
mbed_official 15:a81a8d6c1dfe 725 * \internal
mbed_official 15:a81a8d6c1dfe 726 * Reads a character from the Data register to the RX buffer.
mbed_official 15:a81a8d6c1dfe 727 *
mbed_official 15:a81a8d6c1dfe 728 * \param[in,out] module Pointer to SPI software instance struct
mbed_official 15:a81a8d6c1dfe 729 */
mbed_official 15:a81a8d6c1dfe 730 static void _spi_read_async(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 731 {
mbed_official 15:a81a8d6c1dfe 732 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 733 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 734
mbed_official 15:a81a8d6c1dfe 735 uint8_t *rx_buffer = obj->rx_buff.buffer;
mbed_official 15:a81a8d6c1dfe 736
mbed_official 15:a81a8d6c1dfe 737 /* Check if data is overflown */
mbed_official 15:a81a8d6c1dfe 738 if (_SPI(obj).STATUS.reg & SERCOM_SPI_STATUS_BUFOVF) {
mbed_official 15:a81a8d6c1dfe 739 /* Clear overflow flag */
mbed_official 15:a81a8d6c1dfe 740 _SPI(obj).STATUS.reg |= SERCOM_SPI_STATUS_BUFOVF;
mbed_official 15:a81a8d6c1dfe 741 if (obj->spi.mask & SPI_EVENT_RX_OVERFLOW) {
mbed_official 15:a81a8d6c1dfe 742 /* Set overflow error */
mbed_official 15:a81a8d6c1dfe 743 obj->spi.event |= SPI_EVENT_RX_OVERFLOW;
mbed_official 15:a81a8d6c1dfe 744 return;
mbed_official 15:a81a8d6c1dfe 745 }
mbed_official 15:a81a8d6c1dfe 746 }
mbed_official 15:a81a8d6c1dfe 747
mbed_official 15:a81a8d6c1dfe 748 /* Read data, either valid, or dummy */
mbed_official 15:a81a8d6c1dfe 749 uint16_t received_data = (_SPI(obj).DATA.reg & SERCOM_SPI_DATA_MASK);
mbed_official 15:a81a8d6c1dfe 750
mbed_official 15:a81a8d6c1dfe 751 /* Do nothing if we are at the end of buffer */
mbed_official 15:a81a8d6c1dfe 752 if ((obj->rx_buff.pos >= obj->rx_buff.length) && rx_buffer) {
mbed_official 15:a81a8d6c1dfe 753 return;
mbed_official 15:a81a8d6c1dfe 754 }
mbed_official 15:a81a8d6c1dfe 755
mbed_official 15:a81a8d6c1dfe 756 /* Read value will be at least 8-bits long */
mbed_official 15:a81a8d6c1dfe 757 rx_buffer[obj->rx_buff.pos] = received_data;
mbed_official 15:a81a8d6c1dfe 758 /* Increment 8-bit index */
mbed_official 15:a81a8d6c1dfe 759 obj->rx_buff.pos++;
mbed_official 15:a81a8d6c1dfe 760
mbed_official 15:a81a8d6c1dfe 761 if (_SPI(obj).CTRLB.bit.CHSIZE == 1) {
mbed_official 15:a81a8d6c1dfe 762 /* 9-bit data, write next received byte to the buffer */
mbed_official 15:a81a8d6c1dfe 763 rx_buffer[obj->rx_buff.pos] = (received_data >> 8);
mbed_official 15:a81a8d6c1dfe 764 /* Increment 8-bit index */
mbed_official 15:a81a8d6c1dfe 765 obj->rx_buff.pos++;
mbed_official 15:a81a8d6c1dfe 766 }
mbed_official 15:a81a8d6c1dfe 767
mbed_official 15:a81a8d6c1dfe 768 /* Check for error */
mbed_official 15:a81a8d6c1dfe 769 if ((_SPI(obj).INTFLAG.reg & SERCOM_SPI_INTFLAG_ERROR) && (obj->spi.mask & SPI_EVENT_ERROR)) {
mbed_official 15:a81a8d6c1dfe 770 obj->spi.event |= SPI_EVENT_ERROR;
mbed_official 15:a81a8d6c1dfe 771 }
mbed_official 15:a81a8d6c1dfe 772 }
mbed_official 15:a81a8d6c1dfe 773
mbed_official 15:a81a8d6c1dfe 774 /**
mbed_official 15:a81a8d6c1dfe 775 * \internal
mbed_official 15:a81a8d6c1dfe 776 * Clears all interrupt flags of SPI
mbed_official 15:a81a8d6c1dfe 777 *
mbed_official 15:a81a8d6c1dfe 778 * \param[in,out] module Pointer to SPI software instance struct
mbed_official 15:a81a8d6c1dfe 779 */
mbed_official 15:a81a8d6c1dfe 780 static void _spi_clear_interrupts(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 781 {
mbed_official 15:a81a8d6c1dfe 782 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 783 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 784
mbed_official 15:a81a8d6c1dfe 785 uint8_t sercom_index = _sercom_get_sercom_inst_index(obj->spi.spi);
mbed_official 15:a81a8d6c1dfe 786
mbed_official 15:a81a8d6c1dfe 787 /* Clear all interrupts */
mbed_official 15:a81a8d6c1dfe 788 _SPI(obj).INTENCLR.reg =
mbed_official 15:a81a8d6c1dfe 789 SERCOM_SPI_INTFLAG_DRE |
mbed_official 15:a81a8d6c1dfe 790 SERCOM_SPI_INTFLAG_TXC |
mbed_official 15:a81a8d6c1dfe 791 SERCOM_SPI_INTFLAG_RXC |
mbed_official 15:a81a8d6c1dfe 792 SERCOM_SPI_INTFLAG_ERROR;
mbed_official 64:41a834223ea3 793 NVIC_DisableIRQ((IRQn_Type)((uint8_t)SERCOM0_IRQn + sercom_index));
mbed_official 64:41a834223ea3 794 NVIC_SetVector((IRQn_Type)((uint8_t)SERCOM0_IRQn + sercom_index), (uint32_t)NULL);
mbed_official 15:a81a8d6c1dfe 795 }
mbed_official 15:a81a8d6c1dfe 796
mbed_official 15:a81a8d6c1dfe 797 /**
mbed_official 15:a81a8d6c1dfe 798 * \internal
mbed_official 15:a81a8d6c1dfe 799 * Starts transceive of buffers with a given length
mbed_official 15:a81a8d6c1dfe 800 *
mbed_official 15:a81a8d6c1dfe 801 * \param[in,out] obj Pointer to SPI software instance struct
mbed_official 15:a81a8d6c1dfe 802 *
mbed_official 15:a81a8d6c1dfe 803 */
mbed_official 15:a81a8d6c1dfe 804 static enum status_code _spi_transceive_buffer(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 805 {
mbed_official 15:a81a8d6c1dfe 806 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 807 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 808
mbed_official 15:a81a8d6c1dfe 809 uint16_t interrupt_status = _SPI(obj).INTFLAG.reg;
mbed_official 15:a81a8d6c1dfe 810 interrupt_status &= _SPI(obj).INTENSET.reg;
mbed_official 15:a81a8d6c1dfe 811
mbed_official 15:a81a8d6c1dfe 812 if (interrupt_status & SERCOM_SPI_INTFLAG_DRE) {
mbed_official 15:a81a8d6c1dfe 813 /* Clear DRE interrupt */
mbed_official 15:a81a8d6c1dfe 814 _SPI(obj).INTENCLR.reg = SERCOM_SPI_INTFLAG_DRE;
mbed_official 15:a81a8d6c1dfe 815 /* Write data */
mbed_official 15:a81a8d6c1dfe 816 _spi_write_async(obj);
mbed_official 15:a81a8d6c1dfe 817 /* Set TXC interrupt */
mbed_official 15:a81a8d6c1dfe 818 _SPI(obj).INTENSET.reg |= SERCOM_SPI_INTFLAG_TXC;
mbed_official 15:a81a8d6c1dfe 819 }
mbed_official 15:a81a8d6c1dfe 820 if (interrupt_status & SERCOM_SPI_INTFLAG_TXC) {
mbed_official 15:a81a8d6c1dfe 821 /* Clear TXC interrupt */
mbed_official 15:a81a8d6c1dfe 822 _SPI(obj).INTENCLR.reg = SERCOM_SPI_INTFLAG_TXC;
mbed_official 15:a81a8d6c1dfe 823 if ((obj->rx_buff.buffer) && (obj->rx_buff.pos < obj->rx_buff.length)) {
mbed_official 15:a81a8d6c1dfe 824 while (!spi_is_ready_to_read(obj));
mbed_official 15:a81a8d6c1dfe 825 _spi_read_async(obj);
mbed_official 15:a81a8d6c1dfe 826 if ((obj->tx_buff.pos >= obj->tx_buff.length) && (obj->tx_buff.length < obj->rx_buff.length)) {
mbed_official 15:a81a8d6c1dfe 827 obj->tx_buff.length = obj->rx_buff.length;
mbed_official 15:a81a8d6c1dfe 828 obj->tx_buff.buffer = 0;
mbed_official 15:a81a8d6c1dfe 829 }
mbed_official 15:a81a8d6c1dfe 830 }
mbed_official 15:a81a8d6c1dfe 831 if (obj->tx_buff.pos < obj->tx_buff.length) {
mbed_official 15:a81a8d6c1dfe 832 /* Set DRE interrupt */
mbed_official 15:a81a8d6c1dfe 833 _SPI(obj).INTENSET.reg |= SERCOM_SPI_INTFLAG_DRE;
mbed_official 15:a81a8d6c1dfe 834 }
mbed_official 15:a81a8d6c1dfe 835 }
mbed_official 15:a81a8d6c1dfe 836
mbed_official 15:a81a8d6c1dfe 837 if (obj->spi.event & (SPI_EVENT_ERROR | SPI_EVENT_RX_OVERFLOW) || (interrupt_status & SERCOM_SPI_INTFLAG_ERROR)) {
mbed_official 15:a81a8d6c1dfe 838 /* Clear all interrupts */
mbed_official 15:a81a8d6c1dfe 839 _spi_clear_interrupts(obj);
mbed_official 15:a81a8d6c1dfe 840
mbed_official 15:a81a8d6c1dfe 841 if (interrupt_status & SERCOM_SPI_INTFLAG_ERROR) {
mbed_official 15:a81a8d6c1dfe 842 obj->spi.event = STATUS_ERR_BAD_DATA;
mbed_official 15:a81a8d6c1dfe 843 }
mbed_official 15:a81a8d6c1dfe 844
mbed_official 15:a81a8d6c1dfe 845 /* Transfer interrupted, invoke the callback function */
mbed_official 15:a81a8d6c1dfe 846 if (obj->spi.event & SPI_EVENT_RX_OVERFLOW) {
mbed_official 15:a81a8d6c1dfe 847 obj->spi.status = STATUS_ERR_OVERFLOW;
mbed_official 15:a81a8d6c1dfe 848 } else {
mbed_official 15:a81a8d6c1dfe 849 obj->spi.status = STATUS_ERR_BAD_DATA;
mbed_official 15:a81a8d6c1dfe 850 }
mbed_official 64:41a834223ea3 851 return (enum status_code)obj->spi.status;
mbed_official 15:a81a8d6c1dfe 852 }
mbed_official 15:a81a8d6c1dfe 853
mbed_official 15:a81a8d6c1dfe 854 if ((obj->tx_buff.pos >= obj->tx_buff.length) && (obj->rx_buff.pos >= obj->rx_buff.length) && (interrupt_status & SERCOM_SPI_INTFLAG_TXC)) {
mbed_official 15:a81a8d6c1dfe 855 /* Clear all interrupts */
mbed_official 15:a81a8d6c1dfe 856 _spi_clear_interrupts(obj);
mbed_official 15:a81a8d6c1dfe 857
mbed_official 15:a81a8d6c1dfe 858 /* Transfer complete, invoke the callback function */
mbed_official 15:a81a8d6c1dfe 859 obj->spi.event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
mbed_official 15:a81a8d6c1dfe 860 obj->spi.status = STATUS_OK;
mbed_official 15:a81a8d6c1dfe 861 }
mbed_official 15:a81a8d6c1dfe 862
mbed_official 64:41a834223ea3 863 return (enum status_code)(obj->spi.status);
mbed_official 15:a81a8d6c1dfe 864 }
mbed_official 15:a81a8d6c1dfe 865
mbed_official 15:a81a8d6c1dfe 866 /** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
mbed_official 15:a81a8d6c1dfe 867 *
mbed_official 15:a81a8d6c1dfe 868 * @param[in] obj The SPI object which holds the transfer information
mbed_official 15:a81a8d6c1dfe 869 * @param[in] tx The buffer to send
mbed_official 15:a81a8d6c1dfe 870 * @param[in] tx_length The number of words to transmit
mbed_official 15:a81a8d6c1dfe 871 * @param[out]rx The buffer to receive
mbed_official 15:a81a8d6c1dfe 872 * @param[in] rx_length The number of words to receive
mbed_official 15:a81a8d6c1dfe 873 * @param[in] bit_width The bit width of buffer words
mbed_official 15:a81a8d6c1dfe 874 * @param[in] event The logical OR of events to be registered
mbed_official 15:a81a8d6c1dfe 875 * @param[in] handler SPI interrupt handler
mbed_official 15:a81a8d6c1dfe 876 * @param[in] hint A suggestion for how to use DMA with this transfer **< DMA currently not implemented >**
mbed_official 15:a81a8d6c1dfe 877 */
mbed_official 15:a81a8d6c1dfe 878 void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
mbed_official 15:a81a8d6c1dfe 879 {
mbed_official 15:a81a8d6c1dfe 880 uint16_t dummy_read;
mbed_official 64:41a834223ea3 881 (void) dummy_read;
mbed_official 15:a81a8d6c1dfe 882 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 883 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 884
mbed_official 15:a81a8d6c1dfe 885 uint8_t sercom_index = _sercom_get_sercom_inst_index(obj->spi.spi);
mbed_official 15:a81a8d6c1dfe 886
mbed_official 64:41a834223ea3 887 obj->spi.tx_buffer = (void *)tx;
mbed_official 64:41a834223ea3 888 obj->tx_buff.buffer =(void *)tx;
mbed_official 15:a81a8d6c1dfe 889 obj->tx_buff.pos = 0;
mbed_official 15:a81a8d6c1dfe 890 if (tx) {
mbed_official 15:a81a8d6c1dfe 891 /* Only two bit rates supported now */
mbed_official 15:a81a8d6c1dfe 892 obj->tx_buff.length = tx_length * ((bit_width > 8)? 2 : 1);
mbed_official 15:a81a8d6c1dfe 893 } else {
mbed_official 15:a81a8d6c1dfe 894 if (rx) {
mbed_official 15:a81a8d6c1dfe 895 obj->tx_buff.length = rx_length * ((bit_width > 8)? 2 : 1);
mbed_official 15:a81a8d6c1dfe 896 } else {
mbed_official 15:a81a8d6c1dfe 897 /* Nothing to transfer */
mbed_official 15:a81a8d6c1dfe 898 return;
mbed_official 15:a81a8d6c1dfe 899 }
mbed_official 15:a81a8d6c1dfe 900 }
mbed_official 15:a81a8d6c1dfe 901
mbed_official 15:a81a8d6c1dfe 902 obj->spi.rx_buffer = rx;
mbed_official 15:a81a8d6c1dfe 903 obj->rx_buff.buffer = rx;
mbed_official 15:a81a8d6c1dfe 904 obj->rx_buff.pos = 0;
mbed_official 15:a81a8d6c1dfe 905 if (rx) {
mbed_official 15:a81a8d6c1dfe 906 /* Only two bit rates supported now */
mbed_official 15:a81a8d6c1dfe 907 obj->rx_buff.length = rx_length * ((bit_width > 8)? 2 : 1);
mbed_official 15:a81a8d6c1dfe 908 } else {
mbed_official 15:a81a8d6c1dfe 909 /* Disable RXEN */
mbed_official 15:a81a8d6c1dfe 910 spi_disable(obj);
mbed_official 15:a81a8d6c1dfe 911 _SPI(obj).CTRLB.bit.RXEN = 0;
mbed_official 15:a81a8d6c1dfe 912 spi_enable(obj);
mbed_official 15:a81a8d6c1dfe 913 obj->rx_buff.length = 0;
mbed_official 15:a81a8d6c1dfe 914 }
mbed_official 15:a81a8d6c1dfe 915
mbed_official 15:a81a8d6c1dfe 916 /* Clear data buffer if there is anything pending to read */
mbed_official 15:a81a8d6c1dfe 917 while (spi_is_ready_to_read(obj)) {
mbed_official 15:a81a8d6c1dfe 918 dummy_read = _SPI(obj).DATA.reg;
mbed_official 15:a81a8d6c1dfe 919 }
mbed_official 15:a81a8d6c1dfe 920
mbed_official 15:a81a8d6c1dfe 921 obj->spi.mask = event;
mbed_official 15:a81a8d6c1dfe 922
mbed_official 15:a81a8d6c1dfe 923 obj->spi.dma_usage = hint;
mbed_official 15:a81a8d6c1dfe 924
mbed_official 15:a81a8d6c1dfe 925 /*if (hint == DMA_USAGE_NEVER) {** TEMP: Commented as DMA is not implemented now */
mbed_official 15:a81a8d6c1dfe 926 /* Use irq method */
mbed_official 15:a81a8d6c1dfe 927 uint16_t irq_mask = 0;
mbed_official 15:a81a8d6c1dfe 928 obj->spi.status = STATUS_BUSY;
mbed_official 15:a81a8d6c1dfe 929
mbed_official 15:a81a8d6c1dfe 930 /* Enable interrupt */
mbed_official 64:41a834223ea3 931 NVIC_SetVector((IRQn_Type)((uint8_t)SERCOM0_IRQn + sercom_index), handler);
mbed_official 64:41a834223ea3 932 NVIC_EnableIRQ((IRQn_Type)((uint8_t)SERCOM0_IRQn + sercom_index));
mbed_official 15:a81a8d6c1dfe 933
mbed_official 15:a81a8d6c1dfe 934 /* Clear all interrupts */
mbed_official 15:a81a8d6c1dfe 935 _SPI(obj).INTENCLR.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_ERROR;
mbed_official 15:a81a8d6c1dfe 936 _SPI(obj).INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_ERROR;
mbed_official 15:a81a8d6c1dfe 937 _SPI(obj).STATUS.reg |= SERCOM_SPI_STATUS_BUFOVF;
mbed_official 15:a81a8d6c1dfe 938
mbed_official 15:a81a8d6c1dfe 939 /* Set SPI interrupts */
mbed_official 15:a81a8d6c1dfe 940 /* Set DRE flag to kick start transmission */
mbed_official 15:a81a8d6c1dfe 941 irq_mask |= SERCOM_SPI_INTFLAG_DRE;
mbed_official 15:a81a8d6c1dfe 942
mbed_official 15:a81a8d6c1dfe 943 if (event & SPI_EVENT_ERROR) {
mbed_official 15:a81a8d6c1dfe 944 irq_mask |= SERCOM_SPI_INTFLAG_ERROR;
mbed_official 15:a81a8d6c1dfe 945 }
mbed_official 15:a81a8d6c1dfe 946 _SPI(obj).INTENSET.reg = irq_mask;
mbed_official 15:a81a8d6c1dfe 947 /*} ** TEMP: Commented as DMA is not implemented now */
mbed_official 15:a81a8d6c1dfe 948 }
mbed_official 15:a81a8d6c1dfe 949
mbed_official 15:a81a8d6c1dfe 950 /** The asynchronous IRQ handler
mbed_official 15:a81a8d6c1dfe 951 *
mbed_official 15:a81a8d6c1dfe 952 * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
mbed_official 15:a81a8d6c1dfe 953 * conditions, such as buffer overflows or transfer complete.
mbed_official 15:a81a8d6c1dfe 954 * @param[in] obj The SPI object which holds the transfer information
mbed_official 15:a81a8d6c1dfe 955 * @return event flags if a transfer termination condition was met or 0 otherwise.
mbed_official 15:a81a8d6c1dfe 956 */
mbed_official 15:a81a8d6c1dfe 957 uint32_t spi_irq_handler_asynch(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 958 {
mbed_official 15:a81a8d6c1dfe 959 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 960 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 961 enum status_code tmp_status;
mbed_official 15:a81a8d6c1dfe 962
mbed_official 15:a81a8d6c1dfe 963 uint32_t transfer_event = 0;
mbed_official 15:a81a8d6c1dfe 964
mbed_official 15:a81a8d6c1dfe 965 /*if (obj->spi.dma_usage == DMA_USAGE_NEVER) {** TEMP: Commented as DMA is not implemented now */
mbed_official 15:a81a8d6c1dfe 966 /* IRQ method */
mbed_official 15:a81a8d6c1dfe 967 tmp_status = _spi_transceive_buffer(obj);
mbed_official 15:a81a8d6c1dfe 968 if (STATUS_BUSY != tmp_status) {
mbed_official 15:a81a8d6c1dfe 969 if ((obj->spi.event & SPI_EVENT_INTERNAL_TRANSFER_COMPLETE) && (tmp_status == STATUS_OK)) {
mbed_official 15:a81a8d6c1dfe 970 obj->spi.event |= SPI_EVENT_COMPLETE;
mbed_official 15:a81a8d6c1dfe 971 }
mbed_official 15:a81a8d6c1dfe 972 transfer_event = obj->spi.event & (obj->spi.mask | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE);
mbed_official 15:a81a8d6c1dfe 973 }
mbed_official 15:a81a8d6c1dfe 974 /*}** TEMP: Commented as DMA is not implemented now */
mbed_official 15:a81a8d6c1dfe 975 return transfer_event;
mbed_official 15:a81a8d6c1dfe 976 }
mbed_official 15:a81a8d6c1dfe 977
mbed_official 15:a81a8d6c1dfe 978 /** Attempts to determine if the SPI peripheral is already in use.
mbed_official 15:a81a8d6c1dfe 979 * @param[in] obj The SPI object to check for activity
mbed_official 15:a81a8d6c1dfe 980 * @return non-zero if the SPI port is active or zero if it is not.
mbed_official 15:a81a8d6c1dfe 981 */
mbed_official 15:a81a8d6c1dfe 982 uint8_t spi_active(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 983 {
mbed_official 15:a81a8d6c1dfe 984 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 985 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 986
mbed_official 15:a81a8d6c1dfe 987 /* Check if the SPI module is busy with a job */
mbed_official 15:a81a8d6c1dfe 988 return (obj->spi.status == STATUS_BUSY);
mbed_official 15:a81a8d6c1dfe 989 }
mbed_official 15:a81a8d6c1dfe 990
mbed_official 15:a81a8d6c1dfe 991 /** Abort an SPI transfer
mbed_official 15:a81a8d6c1dfe 992 *
mbed_official 15:a81a8d6c1dfe 993 * @param obj The SPI peripheral to stop
mbed_official 15:a81a8d6c1dfe 994 */
mbed_official 15:a81a8d6c1dfe 995 void spi_abort_asynch(spi_t *obj)
mbed_official 15:a81a8d6c1dfe 996 {
mbed_official 15:a81a8d6c1dfe 997 /* Sanity check arguments */
mbed_official 15:a81a8d6c1dfe 998 MBED_ASSERT(obj);
mbed_official 15:a81a8d6c1dfe 999
mbed_official 15:a81a8d6c1dfe 1000 uint8_t sercom_index = _sercom_get_sercom_inst_index(obj->spi.spi);
mbed_official 15:a81a8d6c1dfe 1001
mbed_official 15:a81a8d6c1dfe 1002 /* Clear all interrupts */
mbed_official 15:a81a8d6c1dfe 1003 _SPI(obj).INTENCLR.reg =
mbed_official 15:a81a8d6c1dfe 1004 SERCOM_SPI_INTFLAG_DRE |
mbed_official 15:a81a8d6c1dfe 1005 SERCOM_SPI_INTFLAG_TXC |
mbed_official 15:a81a8d6c1dfe 1006 SERCOM_SPI_INTFLAG_RXC |
mbed_official 15:a81a8d6c1dfe 1007 SERCOM_SPI_INTFLAG_ERROR;
mbed_official 15:a81a8d6c1dfe 1008
mbed_official 15:a81a8d6c1dfe 1009 // TODO: Disable and remove irq handler
mbed_official 64:41a834223ea3 1010 NVIC_DisableIRQ((IRQn_Type)((uint8_t)SERCOM0_IRQn + sercom_index));
mbed_official 64:41a834223ea3 1011 NVIC_SetVector((IRQn_Type)((uint8_t)SERCOM0_IRQn + sercom_index), (uint32_t)NULL);
mbed_official 15:a81a8d6c1dfe 1012
mbed_official 15:a81a8d6c1dfe 1013 obj->spi.status = STATUS_ABORTED;
mbed_official 15:a81a8d6c1dfe 1014 }
mbed_official 15:a81a8d6c1dfe 1015
mbed_official 15:a81a8d6c1dfe 1016 #endif /* DEVICE_SPI_ASYNCH */