Rigado / mbed-src-bmd-200

Dependents:   mbed_blinky-bmd-200 bmd-200_accel_demo firstRig

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Wed Jul 01 09:45:11 2015 +0100
Revision:
583:53297373a894
Synchronized with git revision d5b4d2ab9c47edb4dc5776e7177b0c2263459081

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

Initial version of drivers for SAMR21

Who changed what in which revision?

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