mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Fri Jul 17 09:15:10 2015 +0100
Revision:
592:a274ee790e56
Parent:
579:53297373a894
Synchronized with git revision e7144f83a8d75df80c4877936b6ffe552b0be9e6

Full URL: https://github.com/mbedmicro/mbed/commit/e7144f83a8d75df80c4877936b6ffe552b0be9e6/

More API implementation for SAMR21

Who changed what in which revision?

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