added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
mbed_official
Date:
Wed Nov 04 16:30:11 2015 +0000
Revision:
15:a81a8d6c1dfe
Child:
18:da299f395b9e
Synchronized with git revision 46af745ef4405614c3fa49abbd9a706a362ea514

Full URL: https://github.com/mbedmicro/mbed/commit/46af745ef4405614c3fa49abbd9a706a362ea514/

Renamed TARGET_SAM_CortexM0+ to TARGET_SAM_CortexM0P for compatiblity with online compiler

Who changed what in which revision?

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