Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sat Jun 03 00:22:44 2017 +0000
Revision:
46:b156ef445742
Parent:
18:6a4db94011d3
Final code for internal battlebot competition.

Who changed what in which revision?

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