added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
64:41a834223ea3
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

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