mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
186:707f6e361f3e
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anna Bridge 186:707f6e361f3e 1 /**
Anna Bridge 186:707f6e361f3e 2 * @file
Anna Bridge 186:707f6e361f3e 3 * @brief Serial Peripheral Interface Master (SPIM) Function Implementations.
Anna Bridge 186:707f6e361f3e 4 */
Anna Bridge 186:707f6e361f3e 5 /* *****************************************************************************
Anna Bridge 186:707f6e361f3e 6 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
Anna Bridge 186:707f6e361f3e 7 *
Anna Bridge 186:707f6e361f3e 8 * Permission is hereby granted, free of charge, to any person obtaining a
Anna Bridge 186:707f6e361f3e 9 * copy of this software and associated documentation files (the "Software"),
Anna Bridge 186:707f6e361f3e 10 * to deal in the Software without restriction, including without limitation
Anna Bridge 186:707f6e361f3e 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Anna Bridge 186:707f6e361f3e 12 * and/or sell copies of the Software, and to permit persons to whom the
Anna Bridge 186:707f6e361f3e 13 * Software is furnished to do so, subject to the following conditions:
Anna Bridge 186:707f6e361f3e 14 *
Anna Bridge 186:707f6e361f3e 15 * The above copyright notice and this permission notice shall be included
Anna Bridge 186:707f6e361f3e 16 * in all copies or substantial portions of the Software.
Anna Bridge 186:707f6e361f3e 17 *
Anna Bridge 186:707f6e361f3e 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Anna Bridge 186:707f6e361f3e 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Anna Bridge 186:707f6e361f3e 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Anna Bridge 186:707f6e361f3e 21 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
Anna Bridge 186:707f6e361f3e 22 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
Anna Bridge 186:707f6e361f3e 23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Anna Bridge 186:707f6e361f3e 24 * OTHER DEALINGS IN THE SOFTWARE.
Anna Bridge 186:707f6e361f3e 25 *
Anna Bridge 186:707f6e361f3e 26 * Except as contained in this notice, the name of Maxim Integrated
Anna Bridge 186:707f6e361f3e 27 * Products, Inc. shall not be used except as stated in the Maxim Integrated
Anna Bridge 186:707f6e361f3e 28 * Products, Inc. Branding Policy.
Anna Bridge 186:707f6e361f3e 29 *
Anna Bridge 186:707f6e361f3e 30 * The mere transfer of this software does not imply any licenses
Anna Bridge 186:707f6e361f3e 31 * of trade secrets, proprietary technology, copyrights, patents,
Anna Bridge 186:707f6e361f3e 32 * trademarks, maskwork rights, or any other form of intellectual
Anna Bridge 186:707f6e361f3e 33 * property whatsoever. Maxim Integrated Products, Inc. retains all
Anna Bridge 186:707f6e361f3e 34 * ownership rights.
Anna Bridge 186:707f6e361f3e 35 *
Anna Bridge 186:707f6e361f3e 36 * $Date: 2016-09-08 17:32:38 -0500 (Thu, 08 Sep 2016) $
Anna Bridge 186:707f6e361f3e 37 * $Revision: 24324 $
Anna Bridge 186:707f6e361f3e 38 *
Anna Bridge 186:707f6e361f3e 39 **************************************************************************** */
Anna Bridge 186:707f6e361f3e 40
Anna Bridge 186:707f6e361f3e 41 /* **** Includes **** */
Anna Bridge 186:707f6e361f3e 42 #include <stddef.h>
Anna Bridge 186:707f6e361f3e 43 #include <string.h>
Anna Bridge 186:707f6e361f3e 44 #include "mxc_config.h"
Anna Bridge 186:707f6e361f3e 45 #include "mxc_assert.h"
Anna Bridge 186:707f6e361f3e 46 #include "mxc_sys.h"
Anna Bridge 186:707f6e361f3e 47 #include "mxc_lock.h"
Anna Bridge 186:707f6e361f3e 48 #include "spim.h"
Anna Bridge 186:707f6e361f3e 49
Anna Bridge 186:707f6e361f3e 50 /**
Anna Bridge 186:707f6e361f3e 51 * @ingroup spim
Anna Bridge 186:707f6e361f3e 52 * @{
Anna Bridge 186:707f6e361f3e 53 */
Anna Bridge 186:707f6e361f3e 54 /* **** Definitions **** */
Anna Bridge 186:707f6e361f3e 55 #define SPIM_MAX_BYTE_LEN 32
Anna Bridge 186:707f6e361f3e 56 #define SPIM_MAX_PAGE_LEN 32
Anna Bridge 186:707f6e361f3e 57
Anna Bridge 186:707f6e361f3e 58 /* **** Globals **** */
Anna Bridge 186:707f6e361f3e 59
Anna Bridge 186:707f6e361f3e 60 // Saves the state of the non-blocking requests
Anna Bridge 186:707f6e361f3e 61 typedef struct {
Anna Bridge 186:707f6e361f3e 62 spim_req_t *req;
Anna Bridge 186:707f6e361f3e 63 unsigned head_rem;
Anna Bridge 186:707f6e361f3e 64 } spim_req_head_t;
Anna Bridge 186:707f6e361f3e 65
Anna Bridge 186:707f6e361f3e 66 static spim_req_head_t states[MXC_CFG_SPIM_INSTANCES];
Anna Bridge 186:707f6e361f3e 67
Anna Bridge 186:707f6e361f3e 68 /* **** Local Function Prototypes **** */
Anna Bridge 186:707f6e361f3e 69
Anna Bridge 186:707f6e361f3e 70 static unsigned SPIM_ReadRXFIFO(mxc_spim_regs_t *spim, mxc_spim_fifo_regs_t *fifo,
Anna Bridge 186:707f6e361f3e 71 uint8_t *data, unsigned len);
Anna Bridge 186:707f6e361f3e 72
Anna Bridge 186:707f6e361f3e 73 static uint32_t SPIM_TransHandler(mxc_spim_regs_t *spim, spim_req_t *req, int spim_num);
Anna Bridge 186:707f6e361f3e 74
Anna Bridge 186:707f6e361f3e 75 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 76 int SPIM_Init(mxc_spim_regs_t *spim, const spim_cfg_t *cfg, const sys_cfg_spim_t *sys_cfg)
Anna Bridge 186:707f6e361f3e 77 {
Anna Bridge 186:707f6e361f3e 78 int err, spim_num;
Anna Bridge 186:707f6e361f3e 79 uint32_t spim_clk, clocks;
Anna Bridge 186:707f6e361f3e 80
Anna Bridge 186:707f6e361f3e 81 spim_num = MXC_SPIM_GET_IDX(spim);
Anna Bridge 186:707f6e361f3e 82 MXC_ASSERT(spim_num >= 0);
Anna Bridge 186:707f6e361f3e 83
Anna Bridge 186:707f6e361f3e 84 // Check the input parameters
Anna Bridge 186:707f6e361f3e 85 if(cfg == NULL)
Anna Bridge 186:707f6e361f3e 86 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 87
Anna Bridge 186:707f6e361f3e 88 if(cfg->baud == 0)
Anna Bridge 186:707f6e361f3e 89 return E_BAD_PARAM;
Anna Bridge 186:707f6e361f3e 90
Anna Bridge 186:707f6e361f3e 91 // Set system level configurations
Anna Bridge 186:707f6e361f3e 92 if ((err = SYS_SPIM_Init(spim, cfg, sys_cfg)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 93 return err;
Anna Bridge 186:707f6e361f3e 94 }
Anna Bridge 186:707f6e361f3e 95
Anna Bridge 186:707f6e361f3e 96 /* Configure the baud, make sure the SPIM clk is enabled and the baud
Anna Bridge 186:707f6e361f3e 97 is less than the maximum */
Anna Bridge 186:707f6e361f3e 98 spim_clk = SYS_SPIM_GetFreq(spim);
Anna Bridge 186:707f6e361f3e 99 if((spim_clk == 0) || ((spim_clk == SystemCoreClock) && ((spim_clk/2) < cfg->baud))) {
Anna Bridge 186:707f6e361f3e 100 return E_BAD_PARAM;
Anna Bridge 186:707f6e361f3e 101 }
Anna Bridge 186:707f6e361f3e 102
Anna Bridge 186:707f6e361f3e 103 // Initialize state pointers
Anna Bridge 186:707f6e361f3e 104 states[spim_num].req = NULL;
Anna Bridge 186:707f6e361f3e 105 states[spim_num].head_rem = 0;
Anna Bridge 186:707f6e361f3e 106
Anna Bridge 186:707f6e361f3e 107 // Drain the FIFOs, enable SPIM, enable SCK Feedback
Anna Bridge 186:707f6e361f3e 108 spim->gen_ctrl = 0;
Anna Bridge 186:707f6e361f3e 109 spim->gen_ctrl = (MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN | MXC_F_SPIM_GEN_CTRL_TX_FIFO_EN |
Anna Bridge 186:707f6e361f3e 110 MXC_F_SPIM_GEN_CTRL_RX_FIFO_EN | MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE);
Anna Bridge 186:707f6e361f3e 111
Anna Bridge 186:707f6e361f3e 112 // Set mode and page size
Anna Bridge 186:707f6e361f3e 113 spim->mstr_cfg = (((cfg->mode << MXC_F_SPIM_MSTR_CFG_SPI_MODE_POS) & MXC_F_SPIM_MSTR_CFG_SPI_MODE) |
Anna Bridge 186:707f6e361f3e 114 MXC_S_SPIM_MSTR_CFG_PAGE_32B | (0x2 << MXC_F_SPIM_MSTR_CFG_ACT_DELAY_POS));
Anna Bridge 186:707f6e361f3e 115
Anna Bridge 186:707f6e361f3e 116 // Configure the SSEL polarity
Anna Bridge 186:707f6e361f3e 117 spim->ss_sr_polarity = ((cfg->ssel_pol << MXC_F_SPIM_SS_SR_POLARITY_SS_POLARITY_POS) &
Anna Bridge 186:707f6e361f3e 118 MXC_F_SPIM_SS_SR_POLARITY_SS_POLARITY);
Anna Bridge 186:707f6e361f3e 119
Anna Bridge 186:707f6e361f3e 120 #if(MXC_SPIM_REV == 0)
Anna Bridge 186:707f6e361f3e 121 // Disable the feedback clock in modes 1 and 2
Anna Bridge 186:707f6e361f3e 122 if((cfg->mode == 1) || (cfg->mode == 2)) {
Anna Bridge 186:707f6e361f3e 123 spim->gen_ctrl &= ~MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE;
Anna Bridge 186:707f6e361f3e 124 spim->mstr_cfg |= (0x1 << MXC_F_SPIM_MSTR_CFG_SDIO_SAMPLE_POINT_POS);
Anna Bridge 186:707f6e361f3e 125 }
Anna Bridge 186:707f6e361f3e 126 #else
Anna Bridge 186:707f6e361f3e 127 // Increase the RX FIFO margin
Anna Bridge 186:707f6e361f3e 128 MXC_SPIM1->spcl_ctrl = ((MXC_SPIM1->spcl_ctrl & ~(MXC_F_SPIM_SPCL_CTRL_RX_FIFO_MARGIN)) |
Anna Bridge 186:707f6e361f3e 129 (0x3 << MXC_F_SPIM_SPCL_CTRL_RX_FIFO_MARGIN_POS));
Anna Bridge 186:707f6e361f3e 130 #endif
Anna Bridge 186:707f6e361f3e 131
Anna Bridge 186:707f6e361f3e 132 // Calculate the hi/lo clock setting
Anna Bridge 186:707f6e361f3e 133 if(spim_clk/2 > cfg->baud) {
Anna Bridge 186:707f6e361f3e 134
Anna Bridge 186:707f6e361f3e 135 /* Disable the feedback mode and use the sample mode with an appropriate hi/lo clk
Anna Bridge 186:707f6e361f3e 136 to achieve the lower baud rate */
Anna Bridge 186:707f6e361f3e 137 spim->gen_ctrl &= ~MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE;
Anna Bridge 186:707f6e361f3e 138
Anna Bridge 186:707f6e361f3e 139 clocks = (spim_clk / (2*cfg->baud));
Anna Bridge 186:707f6e361f3e 140
Anna Bridge 186:707f6e361f3e 141 if(clocks == 0 || clocks > 0x10) {
Anna Bridge 186:707f6e361f3e 142 return E_BAD_PARAM;
Anna Bridge 186:707f6e361f3e 143 }
Anna Bridge 186:707f6e361f3e 144
Anna Bridge 186:707f6e361f3e 145 // 0 => 16 in the 4 bit field for HI_CLK and LO_CLK
Anna Bridge 186:707f6e361f3e 146 if(clocks == 0x10) {
Anna Bridge 186:707f6e361f3e 147 clocks = 0;
Anna Bridge 186:707f6e361f3e 148 }
Anna Bridge 186:707f6e361f3e 149
Anna Bridge 186:707f6e361f3e 150 } else {
Anna Bridge 186:707f6e361f3e 151 // Continue to use feedback mode and set hi/lo clk to 1
Anna Bridge 186:707f6e361f3e 152 clocks = 1;
Anna Bridge 186:707f6e361f3e 153 }
Anna Bridge 186:707f6e361f3e 154
Anna Bridge 186:707f6e361f3e 155 spim->mstr_cfg |= (((clocks << MXC_F_SPIM_MSTR_CFG_SCK_HI_CLK_POS) & MXC_F_SPIM_MSTR_CFG_SCK_HI_CLK) |
Anna Bridge 186:707f6e361f3e 156 ((clocks << MXC_F_SPIM_MSTR_CFG_SCK_LO_CLK_POS) & MXC_F_SPIM_MSTR_CFG_SCK_LO_CLK));
Anna Bridge 186:707f6e361f3e 157
Anna Bridge 186:707f6e361f3e 158 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 159 }
Anna Bridge 186:707f6e361f3e 160
Anna Bridge 186:707f6e361f3e 161 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 162 int SPIM_Shutdown(mxc_spim_regs_t *spim)
Anna Bridge 186:707f6e361f3e 163 {
Anna Bridge 186:707f6e361f3e 164 int spim_num, err;
Anna Bridge 186:707f6e361f3e 165 spim_req_t *temp_req;
Anna Bridge 186:707f6e361f3e 166
Anna Bridge 186:707f6e361f3e 167 // Disable and clear interrupts
Anna Bridge 186:707f6e361f3e 168 spim->inten = 0;
Anna Bridge 186:707f6e361f3e 169 spim->intfl = spim->intfl;
Anna Bridge 186:707f6e361f3e 170
Anna Bridge 186:707f6e361f3e 171 // Disable SPIM and FIFOS
Anna Bridge 186:707f6e361f3e 172 spim->gen_ctrl &= ~(MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN | MXC_F_SPIM_GEN_CTRL_TX_FIFO_EN |
Anna Bridge 186:707f6e361f3e 173 MXC_F_SPIM_GEN_CTRL_RX_FIFO_EN);
Anna Bridge 186:707f6e361f3e 174
Anna Bridge 186:707f6e361f3e 175 // Call all of the pending callbacks for this SPIM
Anna Bridge 186:707f6e361f3e 176 spim_num = MXC_SPIM_GET_IDX(spim);
Anna Bridge 186:707f6e361f3e 177 if(states[spim_num].req != NULL) {
Anna Bridge 186:707f6e361f3e 178
Anna Bridge 186:707f6e361f3e 179 // Save the request
Anna Bridge 186:707f6e361f3e 180 temp_req = states[spim_num].req;
Anna Bridge 186:707f6e361f3e 181
Anna Bridge 186:707f6e361f3e 182 // Unlock this SPIM
Anna Bridge 186:707f6e361f3e 183 mxc_free_lock((uint32_t*)&states[spim_num].req);
Anna Bridge 186:707f6e361f3e 184
Anna Bridge 186:707f6e361f3e 185 // Callback if not NULL
Anna Bridge 186:707f6e361f3e 186 if(temp_req->callback != NULL) {
Anna Bridge 186:707f6e361f3e 187 temp_req->callback(temp_req, E_SHUTDOWN);
Anna Bridge 186:707f6e361f3e 188 }
Anna Bridge 186:707f6e361f3e 189 }
Anna Bridge 186:707f6e361f3e 190
Anna Bridge 186:707f6e361f3e 191 // Clear system level configurations
Anna Bridge 186:707f6e361f3e 192 if ((err = SYS_SPIM_Shutdown(spim)) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 193 return err;
Anna Bridge 186:707f6e361f3e 194 }
Anna Bridge 186:707f6e361f3e 195
Anna Bridge 186:707f6e361f3e 196 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 197 }
Anna Bridge 186:707f6e361f3e 198
Anna Bridge 186:707f6e361f3e 199 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 200 int SPIM_Clocks(mxc_spim_regs_t *spim, uint32_t len, uint8_t ssel, uint8_t deass)
Anna Bridge 186:707f6e361f3e 201 {
Anna Bridge 186:707f6e361f3e 202 int spim_num;
Anna Bridge 186:707f6e361f3e 203 mxc_spim_fifo_regs_t *fifo;
Anna Bridge 186:707f6e361f3e 204 uint16_t header = 0x1;
Anna Bridge 186:707f6e361f3e 205 uint32_t num = len;
Anna Bridge 186:707f6e361f3e 206
Anna Bridge 186:707f6e361f3e 207 // Make sure the SPIM has been initialized
Anna Bridge 186:707f6e361f3e 208 if((spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN) == 0)
Anna Bridge 186:707f6e361f3e 209 return E_UNINITIALIZED;
Anna Bridge 186:707f6e361f3e 210
Anna Bridge 186:707f6e361f3e 211 if(!(len > 0)) {
Anna Bridge 186:707f6e361f3e 212 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 213 }
Anna Bridge 186:707f6e361f3e 214
Anna Bridge 186:707f6e361f3e 215 // Check the previous transaction if we're switching the slave select
Anna Bridge 186:707f6e361f3e 216 if((ssel != ((spim->mstr_cfg & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) >>
Anna Bridge 186:707f6e361f3e 217 MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS)) && (spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_BB_SS_IN_OUT)) {
Anna Bridge 186:707f6e361f3e 218
Anna Bridge 186:707f6e361f3e 219 // Return E_BUSY if the slave select is still asserted
Anna Bridge 186:707f6e361f3e 220 return E_BUSY;
Anna Bridge 186:707f6e361f3e 221 }
Anna Bridge 186:707f6e361f3e 222
Anna Bridge 186:707f6e361f3e 223 // Attempt to lock this SPIM
Anna Bridge 186:707f6e361f3e 224 spim_num = MXC_SPIM_GET_IDX(spim);
Anna Bridge 186:707f6e361f3e 225 if(mxc_get_lock((uint32_t*)&states[spim_num].req, 1) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 226 return E_BUSY;
Anna Bridge 186:707f6e361f3e 227 }
Anna Bridge 186:707f6e361f3e 228
Anna Bridge 186:707f6e361f3e 229 // Set which slave select we are using
Anna Bridge 186:707f6e361f3e 230 spim->mstr_cfg = ((spim->mstr_cfg & ~MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) |
Anna Bridge 186:707f6e361f3e 231 ((ssel << MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS) & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL));
Anna Bridge 186:707f6e361f3e 232
Anna Bridge 186:707f6e361f3e 233 //force deass to a 1 or 0
Anna Bridge 186:707f6e361f3e 234 deass = !!deass;
Anna Bridge 186:707f6e361f3e 235
Anna Bridge 186:707f6e361f3e 236 #if(MXC_SPIM_REV == 0)
Anna Bridge 186:707f6e361f3e 237 // Wait for all of the data to transmit
Anna Bridge 186:707f6e361f3e 238 while(spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) {}
Anna Bridge 186:707f6e361f3e 239
Anna Bridge 186:707f6e361f3e 240 // Disable the feedback clock, save state
Anna Bridge 186:707f6e361f3e 241 uint32_t gen_ctrl = spim->gen_ctrl;
Anna Bridge 186:707f6e361f3e 242 spim->gen_ctrl &= ~MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE;
Anna Bridge 186:707f6e361f3e 243 #endif
Anna Bridge 186:707f6e361f3e 244
Anna Bridge 186:707f6e361f3e 245 // Get the TX and RX FIFO for this SPIM
Anna Bridge 186:707f6e361f3e 246 fifo = MXC_SPIM_GET_SPIM_FIFO(spim_num);
Anna Bridge 186:707f6e361f3e 247
Anna Bridge 186:707f6e361f3e 248 // Send the headers to transmit the clocks
Anna Bridge 186:707f6e361f3e 249 while(len > 32) {
Anna Bridge 186:707f6e361f3e 250 fifo->trans_16[0] = header;
Anna Bridge 186:707f6e361f3e 251 fifo->trans_16[0] = 0xF000;
Anna Bridge 186:707f6e361f3e 252 fifo->trans_16[0] = 0xF000;
Anna Bridge 186:707f6e361f3e 253 len -= 32;
Anna Bridge 186:707f6e361f3e 254 }
Anna Bridge 186:707f6e361f3e 255
Anna Bridge 186:707f6e361f3e 256 if(len) {
Anna Bridge 186:707f6e361f3e 257 if(len < 32) {
Anna Bridge 186:707f6e361f3e 258 header |= (len << 4);
Anna Bridge 186:707f6e361f3e 259 }
Anna Bridge 186:707f6e361f3e 260 header |= (deass << 13);
Anna Bridge 186:707f6e361f3e 261
Anna Bridge 186:707f6e361f3e 262 fifo->trans_16[0] = header;
Anna Bridge 186:707f6e361f3e 263
Anna Bridge 186:707f6e361f3e 264 if(len > 16) {
Anna Bridge 186:707f6e361f3e 265 fifo->trans_16[0] = 0xF000;
Anna Bridge 186:707f6e361f3e 266 }
Anna Bridge 186:707f6e361f3e 267 fifo->trans_16[0] = 0xF000;
Anna Bridge 186:707f6e361f3e 268 }
Anna Bridge 186:707f6e361f3e 269
Anna Bridge 186:707f6e361f3e 270 #if(MXC_SPIM_REV == 0)
Anna Bridge 186:707f6e361f3e 271 // Wait for all of the data to transmit
Anna Bridge 186:707f6e361f3e 272 while(spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) {}
Anna Bridge 186:707f6e361f3e 273
Anna Bridge 186:707f6e361f3e 274 // Restore feedback clock setting
Anna Bridge 186:707f6e361f3e 275 spim->gen_ctrl |= (gen_ctrl & MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE);
Anna Bridge 186:707f6e361f3e 276 #endif
Anna Bridge 186:707f6e361f3e 277
Anna Bridge 186:707f6e361f3e 278 // Unlock this SPIM
Anna Bridge 186:707f6e361f3e 279 mxc_free_lock((uint32_t*)&states[spim_num].req);
Anna Bridge 186:707f6e361f3e 280
Anna Bridge 186:707f6e361f3e 281 return num;
Anna Bridge 186:707f6e361f3e 282 }
Anna Bridge 186:707f6e361f3e 283
Anna Bridge 186:707f6e361f3e 284
Anna Bridge 186:707f6e361f3e 285 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 286 int SPIM_Trans(mxc_spim_regs_t *spim, spim_req_t *req)
Anna Bridge 186:707f6e361f3e 287 {
Anna Bridge 186:707f6e361f3e 288 int spim_num;
Anna Bridge 186:707f6e361f3e 289
Anna Bridge 186:707f6e361f3e 290 // Make sure the SPIM has been initialized
Anna Bridge 186:707f6e361f3e 291 if((spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN) == 0)
Anna Bridge 186:707f6e361f3e 292 return E_UNINITIALIZED;
Anna Bridge 186:707f6e361f3e 293
Anna Bridge 186:707f6e361f3e 294 // Check the input parameters
Anna Bridge 186:707f6e361f3e 295 if(req == NULL)
Anna Bridge 186:707f6e361f3e 296 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 297
Anna Bridge 186:707f6e361f3e 298 if((req->rx_data == NULL) && (req->tx_data == NULL))
Anna Bridge 186:707f6e361f3e 299 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 300
Anna Bridge 186:707f6e361f3e 301 if(!(req->len > 0)) {
Anna Bridge 186:707f6e361f3e 302 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 303 }
Anna Bridge 186:707f6e361f3e 304
Anna Bridge 186:707f6e361f3e 305 // Check the previous transaction if we're switching the slave select
Anna Bridge 186:707f6e361f3e 306 if((req->ssel != ((spim->mstr_cfg & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) >>
Anna Bridge 186:707f6e361f3e 307 MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS)) && (spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_BB_SS_IN_OUT)) {
Anna Bridge 186:707f6e361f3e 308
Anna Bridge 186:707f6e361f3e 309 // Return E_BUSY if the slave select is still asserted
Anna Bridge 186:707f6e361f3e 310 return E_BUSY;
Anna Bridge 186:707f6e361f3e 311 }
Anna Bridge 186:707f6e361f3e 312
Anna Bridge 186:707f6e361f3e 313 // Attempt to register this write request
Anna Bridge 186:707f6e361f3e 314 spim_num = MXC_SPIM_GET_IDX(spim);
Anna Bridge 186:707f6e361f3e 315 if(mxc_get_lock((uint32_t*)&states[spim_num].req, (uint32_t)req) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 316 return E_BUSY;
Anna Bridge 186:707f6e361f3e 317 }
Anna Bridge 186:707f6e361f3e 318
Anna Bridge 186:707f6e361f3e 319 // Set which slave select we are using
Anna Bridge 186:707f6e361f3e 320 spim->mstr_cfg = ((spim->mstr_cfg & ~MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) |
Anna Bridge 186:707f6e361f3e 321 ((req->ssel << MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS) & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL));
Anna Bridge 186:707f6e361f3e 322
Anna Bridge 186:707f6e361f3e 323 //force deass to a 1 or 0
Anna Bridge 186:707f6e361f3e 324 req->deass = !!req->deass;
Anna Bridge 186:707f6e361f3e 325
Anna Bridge 186:707f6e361f3e 326 // Clear the number of bytes counter
Anna Bridge 186:707f6e361f3e 327 req->read_num = 0;
Anna Bridge 186:707f6e361f3e 328 req->write_num = 0;
Anna Bridge 186:707f6e361f3e 329 req->callback = NULL;
Anna Bridge 186:707f6e361f3e 330 states[spim_num].head_rem = 0;
Anna Bridge 186:707f6e361f3e 331
Anna Bridge 186:707f6e361f3e 332 // Start the transaction, keep calling the handler until complete
Anna Bridge 186:707f6e361f3e 333 while(SPIM_TransHandler(spim, req, spim_num) != 0);
Anna Bridge 186:707f6e361f3e 334
Anna Bridge 186:707f6e361f3e 335 if(req->tx_data == NULL) {
Anna Bridge 186:707f6e361f3e 336 return req->read_num;
Anna Bridge 186:707f6e361f3e 337 }
Anna Bridge 186:707f6e361f3e 338 return req->write_num;
Anna Bridge 186:707f6e361f3e 339 }
Anna Bridge 186:707f6e361f3e 340
Anna Bridge 186:707f6e361f3e 341 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 342 int SPIM_TransAsync(mxc_spim_regs_t *spim, spim_req_t *req)
Anna Bridge 186:707f6e361f3e 343 {
Anna Bridge 186:707f6e361f3e 344 int spim_num;
Anna Bridge 186:707f6e361f3e 345
Anna Bridge 186:707f6e361f3e 346 // Make sure the SPIM has been initialized
Anna Bridge 186:707f6e361f3e 347 if((spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN) == 0)
Anna Bridge 186:707f6e361f3e 348 return E_UNINITIALIZED;
Anna Bridge 186:707f6e361f3e 349
Anna Bridge 186:707f6e361f3e 350 // Check the input parameters
Anna Bridge 186:707f6e361f3e 351 if(req == NULL)
Anna Bridge 186:707f6e361f3e 352 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 353
Anna Bridge 186:707f6e361f3e 354 if((req->rx_data == NULL) && (req->tx_data == NULL))
Anna Bridge 186:707f6e361f3e 355 return E_NULL_PTR;
Anna Bridge 186:707f6e361f3e 356
Anna Bridge 186:707f6e361f3e 357 if(!(req->len > 0)) {
Anna Bridge 186:707f6e361f3e 358 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 359 }
Anna Bridge 186:707f6e361f3e 360
Anna Bridge 186:707f6e361f3e 361
Anna Bridge 186:707f6e361f3e 362 // Check the previous transaction if we're switching the slave select
Anna Bridge 186:707f6e361f3e 363 if((req->ssel != ((spim->mstr_cfg & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) >>
Anna Bridge 186:707f6e361f3e 364 MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS)) && (spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_BB_SS_IN_OUT)) {
Anna Bridge 186:707f6e361f3e 365
Anna Bridge 186:707f6e361f3e 366 // Return E_BUSY if the slave select is still asserted
Anna Bridge 186:707f6e361f3e 367 return E_BUSY;
Anna Bridge 186:707f6e361f3e 368 }
Anna Bridge 186:707f6e361f3e 369
Anna Bridge 186:707f6e361f3e 370 // Attempt to register this write request
Anna Bridge 186:707f6e361f3e 371 spim_num = MXC_SPIM_GET_IDX(spim);
Anna Bridge 186:707f6e361f3e 372 if(mxc_get_lock((uint32_t*)&states[spim_num].req, (uint32_t)req) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 373 return E_BUSY;
Anna Bridge 186:707f6e361f3e 374 }
Anna Bridge 186:707f6e361f3e 375
Anna Bridge 186:707f6e361f3e 376 // Set which slave select we are using
Anna Bridge 186:707f6e361f3e 377 spim->mstr_cfg = ((spim->mstr_cfg & ~MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) |
Anna Bridge 186:707f6e361f3e 378 ((req->ssel << MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS) & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL));
Anna Bridge 186:707f6e361f3e 379
Anna Bridge 186:707f6e361f3e 380 //force deass to a 1 or 0
Anna Bridge 186:707f6e361f3e 381 req->deass = !!req->deass;
Anna Bridge 186:707f6e361f3e 382
Anna Bridge 186:707f6e361f3e 383 // Clear the number of bytes counter
Anna Bridge 186:707f6e361f3e 384 req->read_num = 0;
Anna Bridge 186:707f6e361f3e 385 req->write_num = 0;
Anna Bridge 186:707f6e361f3e 386 states[spim_num].head_rem = 0;
Anna Bridge 186:707f6e361f3e 387
Anna Bridge 186:707f6e361f3e 388 // Start the transaction, enable the interrupts
Anna Bridge 186:707f6e361f3e 389 spim->inten = SPIM_TransHandler(spim, req, spim_num);
Anna Bridge 186:707f6e361f3e 390
Anna Bridge 186:707f6e361f3e 391 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 392 }
Anna Bridge 186:707f6e361f3e 393
Anna Bridge 186:707f6e361f3e 394 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 395 int SPIM_AbortAsync(spim_req_t *req)
Anna Bridge 186:707f6e361f3e 396 {
Anna Bridge 186:707f6e361f3e 397 int spim_num;
Anna Bridge 186:707f6e361f3e 398 mxc_spim_regs_t *spim;
Anna Bridge 186:707f6e361f3e 399
Anna Bridge 186:707f6e361f3e 400 // Check the input parameters
Anna Bridge 186:707f6e361f3e 401 if(req == NULL) {
Anna Bridge 186:707f6e361f3e 402 return E_BAD_PARAM;
Anna Bridge 186:707f6e361f3e 403 }
Anna Bridge 186:707f6e361f3e 404
Anna Bridge 186:707f6e361f3e 405 // Find the request, set to NULL
Anna Bridge 186:707f6e361f3e 406 for(spim_num = 0; spim_num < MXC_CFG_SPIM_INSTANCES; spim_num++) {
Anna Bridge 186:707f6e361f3e 407 if(req == states[spim_num].req) {
Anna Bridge 186:707f6e361f3e 408
Anna Bridge 186:707f6e361f3e 409 spim = MXC_SPIM_GET_SPIM(spim_num);
Anna Bridge 186:707f6e361f3e 410
Anna Bridge 186:707f6e361f3e 411 // Disable interrupts, clear the flags
Anna Bridge 186:707f6e361f3e 412 spim->inten = 0;
Anna Bridge 186:707f6e361f3e 413 spim->intfl = spim->intfl;
Anna Bridge 186:707f6e361f3e 414
Anna Bridge 186:707f6e361f3e 415 // Reset the SPIM to cancel the on ongoing transaction
Anna Bridge 186:707f6e361f3e 416 spim->gen_ctrl &= ~(MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN);
Anna Bridge 186:707f6e361f3e 417 spim->gen_ctrl |= (MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN);
Anna Bridge 186:707f6e361f3e 418
Anna Bridge 186:707f6e361f3e 419 // Unlock this SPIM
Anna Bridge 186:707f6e361f3e 420 mxc_free_lock((uint32_t*)&states[spim_num].req);
Anna Bridge 186:707f6e361f3e 421
Anna Bridge 186:707f6e361f3e 422 // Callback if not NULL
Anna Bridge 186:707f6e361f3e 423 if(req->callback != NULL) {
Anna Bridge 186:707f6e361f3e 424 req->callback(req, E_ABORT);
Anna Bridge 186:707f6e361f3e 425 }
Anna Bridge 186:707f6e361f3e 426
Anna Bridge 186:707f6e361f3e 427 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 428 }
Anna Bridge 186:707f6e361f3e 429 }
Anna Bridge 186:707f6e361f3e 430
Anna Bridge 186:707f6e361f3e 431 return E_BAD_PARAM;
Anna Bridge 186:707f6e361f3e 432 }
Anna Bridge 186:707f6e361f3e 433
Anna Bridge 186:707f6e361f3e 434 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 435 void SPIM_Handler(mxc_spim_regs_t *spim)
Anna Bridge 186:707f6e361f3e 436 {
Anna Bridge 186:707f6e361f3e 437 int spim_num;
Anna Bridge 186:707f6e361f3e 438 uint32_t flags;
Anna Bridge 186:707f6e361f3e 439
Anna Bridge 186:707f6e361f3e 440 // Clear the interrupt flags
Anna Bridge 186:707f6e361f3e 441 spim->inten = 0;
Anna Bridge 186:707f6e361f3e 442 flags = spim->intfl;
Anna Bridge 186:707f6e361f3e 443 spim->intfl = flags;
Anna Bridge 186:707f6e361f3e 444
Anna Bridge 186:707f6e361f3e 445 spim_num = MXC_SPIM_GET_IDX(spim);
Anna Bridge 186:707f6e361f3e 446
Anna Bridge 186:707f6e361f3e 447 // Figure out if this SPIM has an active request
Anna Bridge 186:707f6e361f3e 448 if((states[spim_num].req != NULL) && (flags)) {
Anna Bridge 186:707f6e361f3e 449 spim->inten = SPIM_TransHandler(spim, states[spim_num].req, spim_num);
Anna Bridge 186:707f6e361f3e 450 }
Anna Bridge 186:707f6e361f3e 451 }
Anna Bridge 186:707f6e361f3e 452
Anna Bridge 186:707f6e361f3e 453 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 454 int SPIM_Busy(mxc_spim_regs_t *spim)
Anna Bridge 186:707f6e361f3e 455 {
Anna Bridge 186:707f6e361f3e 456 // Check to see if there are any ongoing transactions
Anna Bridge 186:707f6e361f3e 457 if((states[MXC_SPIM_GET_IDX(spim)].req == NULL) &&
Anna Bridge 186:707f6e361f3e 458 !(spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED)) {
Anna Bridge 186:707f6e361f3e 459
Anna Bridge 186:707f6e361f3e 460 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 461 }
Anna Bridge 186:707f6e361f3e 462
Anna Bridge 186:707f6e361f3e 463 return E_BUSY;
Anna Bridge 186:707f6e361f3e 464 }
Anna Bridge 186:707f6e361f3e 465
Anna Bridge 186:707f6e361f3e 466 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 467 int SPIM_PrepForSleep(mxc_spim_regs_t *spim)
Anna Bridge 186:707f6e361f3e 468 {
Anna Bridge 186:707f6e361f3e 469 if(SPIM_Busy(spim) != E_NO_ERROR) {
Anna Bridge 186:707f6e361f3e 470 return E_BUSY;
Anna Bridge 186:707f6e361f3e 471 }
Anna Bridge 186:707f6e361f3e 472
Anna Bridge 186:707f6e361f3e 473 // Disable interrupts
Anna Bridge 186:707f6e361f3e 474 spim->inten = 0;
Anna Bridge 186:707f6e361f3e 475 return E_NO_ERROR;
Anna Bridge 186:707f6e361f3e 476 }
Anna Bridge 186:707f6e361f3e 477
Anna Bridge 186:707f6e361f3e 478 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 479 static unsigned SPIM_ReadRXFIFO(mxc_spim_regs_t *spim, mxc_spim_fifo_regs_t *fifo,
Anna Bridge 186:707f6e361f3e 480 uint8_t *data, unsigned len)
Anna Bridge 186:707f6e361f3e 481 {
Anna Bridge 186:707f6e361f3e 482 unsigned num = 0;
Anna Bridge 186:707f6e361f3e 483 unsigned avail = ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED) >>
Anna Bridge 186:707f6e361f3e 484 MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED_POS);
Anna Bridge 186:707f6e361f3e 485
Anna Bridge 186:707f6e361f3e 486 // Get data from the RXFIFO
Anna Bridge 186:707f6e361f3e 487 while(avail && (len - num)) {
Anna Bridge 186:707f6e361f3e 488
Anna Bridge 186:707f6e361f3e 489 if((avail >= 4) && ((len-num) >= 4)) {
Anna Bridge 186:707f6e361f3e 490 // Save data from the RXFIFO
Anna Bridge 186:707f6e361f3e 491 uint32_t temp = fifo->rslts_32[0];
Anna Bridge 186:707f6e361f3e 492 data[num+0] = ((temp & 0x000000FF) >> 0);
Anna Bridge 186:707f6e361f3e 493 data[num+1] = ((temp & 0x0000FF00) >> 8);
Anna Bridge 186:707f6e361f3e 494 data[num+2] = ((temp & 0x00FF0000) >> 16);
Anna Bridge 186:707f6e361f3e 495 data[num+3] = ((temp & 0xFF000000) >> 24);
Anna Bridge 186:707f6e361f3e 496 num+=4;
Anna Bridge 186:707f6e361f3e 497 avail-=4;
Anna Bridge 186:707f6e361f3e 498 } else if ((avail >= 2) && ((len-num) >= 2)) {
Anna Bridge 186:707f6e361f3e 499 // Save data from the RXFIFO
Anna Bridge 186:707f6e361f3e 500 uint16_t temp = fifo->rslts_16[0];
Anna Bridge 186:707f6e361f3e 501 data[num+0] = ((temp & 0x00FF) >> 0);
Anna Bridge 186:707f6e361f3e 502 data[num+1] = ((temp & 0xFF00) >> 8);
Anna Bridge 186:707f6e361f3e 503 num+=2;
Anna Bridge 186:707f6e361f3e 504 avail-=2;
Anna Bridge 186:707f6e361f3e 505 } else {
Anna Bridge 186:707f6e361f3e 506 // Save data from the RXFIFO
Anna Bridge 186:707f6e361f3e 507 data[num] = fifo->rslts_8[0];
Anna Bridge 186:707f6e361f3e 508 num+=1;
Anna Bridge 186:707f6e361f3e 509 avail-=1;
Anna Bridge 186:707f6e361f3e 510 }
Anna Bridge 186:707f6e361f3e 511
Anna Bridge 186:707f6e361f3e 512 // Check to see if there is more data in the FIFO
Anna Bridge 186:707f6e361f3e 513 if(avail == 0) {
Anna Bridge 186:707f6e361f3e 514 avail = ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED) >>
Anna Bridge 186:707f6e361f3e 515 MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED_POS);
Anna Bridge 186:707f6e361f3e 516 }
Anna Bridge 186:707f6e361f3e 517 }
Anna Bridge 186:707f6e361f3e 518
Anna Bridge 186:707f6e361f3e 519 return num;
Anna Bridge 186:707f6e361f3e 520 }
Anna Bridge 186:707f6e361f3e 521
Anna Bridge 186:707f6e361f3e 522 uint16_t header_save;
Anna Bridge 186:707f6e361f3e 523
Anna Bridge 186:707f6e361f3e 524
Anna Bridge 186:707f6e361f3e 525 /* ************************************************************************* */
Anna Bridge 186:707f6e361f3e 526 static uint32_t SPIM_TransHandler(mxc_spim_regs_t *spim, spim_req_t *req, int spim_num)
Anna Bridge 186:707f6e361f3e 527 {
Anna Bridge 186:707f6e361f3e 528 uint8_t read, write;
Anna Bridge 186:707f6e361f3e 529 uint16_t header;
Anna Bridge 186:707f6e361f3e 530 uint32_t pages, bytes, inten;
Anna Bridge 186:707f6e361f3e 531 unsigned remain, bytes_read, head_rem_temp, avail;
Anna Bridge 186:707f6e361f3e 532 mxc_spim_fifo_regs_t *fifo;
Anna Bridge 186:707f6e361f3e 533
Anna Bridge 186:707f6e361f3e 534 inten = 0;
Anna Bridge 186:707f6e361f3e 535
Anna Bridge 186:707f6e361f3e 536 // Get the FIFOS for this SPIM
Anna Bridge 186:707f6e361f3e 537 fifo = MXC_SPIM_GET_SPIM_FIFO(spim_num);
Anna Bridge 186:707f6e361f3e 538
Anna Bridge 186:707f6e361f3e 539 // Figure out if we're reading
Anna Bridge 186:707f6e361f3e 540 if(req->rx_data != NULL) {
Anna Bridge 186:707f6e361f3e 541 read = 1;
Anna Bridge 186:707f6e361f3e 542 } else {
Anna Bridge 186:707f6e361f3e 543 read = 0;
Anna Bridge 186:707f6e361f3e 544 }
Anna Bridge 186:707f6e361f3e 545
Anna Bridge 186:707f6e361f3e 546 // Figure out if we're writing
Anna Bridge 186:707f6e361f3e 547 if(req->tx_data != NULL) {
Anna Bridge 186:707f6e361f3e 548 write = 1;
Anna Bridge 186:707f6e361f3e 549 } else {
Anna Bridge 186:707f6e361f3e 550 write = 0;
Anna Bridge 186:707f6e361f3e 551 }
Anna Bridge 186:707f6e361f3e 552
Anna Bridge 186:707f6e361f3e 553 // Read byte from the FIFO if we are reading
Anna Bridge 186:707f6e361f3e 554 if(read) {
Anna Bridge 186:707f6e361f3e 555
Anna Bridge 186:707f6e361f3e 556 // Read all of the data in the RXFIFO, or until we don't need anymore
Anna Bridge 186:707f6e361f3e 557 bytes_read = SPIM_ReadRXFIFO(spim, fifo, &req->rx_data[req->read_num],
Anna Bridge 186:707f6e361f3e 558 (req->len - req->read_num));
Anna Bridge 186:707f6e361f3e 559
Anna Bridge 186:707f6e361f3e 560 req->read_num += bytes_read;
Anna Bridge 186:707f6e361f3e 561
Anna Bridge 186:707f6e361f3e 562 // Adjust head_rem if we are only reading
Anna Bridge 186:707f6e361f3e 563 if(!write && (states[spim_num].head_rem > 0)) {
Anna Bridge 186:707f6e361f3e 564 states[spim_num].head_rem -= bytes_read;
Anna Bridge 186:707f6e361f3e 565 }
Anna Bridge 186:707f6e361f3e 566
Anna Bridge 186:707f6e361f3e 567 // Figure out how many byte we have left to read
Anna Bridge 186:707f6e361f3e 568 if(states[spim_num].head_rem > 0) {
Anna Bridge 186:707f6e361f3e 569 remain = states[spim_num].head_rem;
Anna Bridge 186:707f6e361f3e 570 } else {
Anna Bridge 186:707f6e361f3e 571 remain = req->len - req->read_num;
Anna Bridge 186:707f6e361f3e 572 }
Anna Bridge 186:707f6e361f3e 573
Anna Bridge 186:707f6e361f3e 574 if(remain) {
Anna Bridge 186:707f6e361f3e 575
Anna Bridge 186:707f6e361f3e 576 // Set the RX interrupts
Anna Bridge 186:707f6e361f3e 577 if (remain > MXC_CFG_SPIM_FIFO_DEPTH) {
Anna Bridge 186:707f6e361f3e 578 spim->fifo_ctrl = ((spim->fifo_ctrl & ~MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL) |
Anna Bridge 186:707f6e361f3e 579 ((MXC_CFG_SPIM_FIFO_DEPTH - 2) <<
Anna Bridge 186:707f6e361f3e 580 MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL_POS));
Anna Bridge 186:707f6e361f3e 581
Anna Bridge 186:707f6e361f3e 582 } else {
Anna Bridge 186:707f6e361f3e 583 spim->fifo_ctrl = ((spim->fifo_ctrl & ~MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL) |
Anna Bridge 186:707f6e361f3e 584 ((remain - 1) << MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL_POS));
Anna Bridge 186:707f6e361f3e 585 }
Anna Bridge 186:707f6e361f3e 586
Anna Bridge 186:707f6e361f3e 587 inten |= MXC_F_SPIM_INTEN_RX_FIFO_AF;
Anna Bridge 186:707f6e361f3e 588 }
Anna Bridge 186:707f6e361f3e 589 }
Anna Bridge 186:707f6e361f3e 590
Anna Bridge 186:707f6e361f3e 591 // Figure out how many bytes we have left to send headers for
Anna Bridge 186:707f6e361f3e 592 if(write) {
Anna Bridge 186:707f6e361f3e 593 remain = req->len - req->write_num;
Anna Bridge 186:707f6e361f3e 594 } else {
Anna Bridge 186:707f6e361f3e 595 remain = req->len - req->read_num;
Anna Bridge 186:707f6e361f3e 596 }
Anna Bridge 186:707f6e361f3e 597
Anna Bridge 186:707f6e361f3e 598 // See if we need to send a new header
Anna Bridge 186:707f6e361f3e 599 if(states[spim_num].head_rem <= 0 && remain) {
Anna Bridge 186:707f6e361f3e 600
Anna Bridge 186:707f6e361f3e 601 // Set the transaction configuration in the header
Anna Bridge 186:707f6e361f3e 602 header = ((write << 0) | (read << 1) | (req->width << 9));
Anna Bridge 186:707f6e361f3e 603
Anna Bridge 186:707f6e361f3e 604 if(remain >= SPIM_MAX_BYTE_LEN) {
Anna Bridge 186:707f6e361f3e 605
Anna Bridge 186:707f6e361f3e 606 // Send a 32 byte header
Anna Bridge 186:707f6e361f3e 607 if(remain == SPIM_MAX_BYTE_LEN) {
Anna Bridge 186:707f6e361f3e 608
Anna Bridge 186:707f6e361f3e 609 header |= ((0x1 << 2) | (req->deass << 13));
Anna Bridge 186:707f6e361f3e 610
Anna Bridge 186:707f6e361f3e 611 // Save the number of bytes we need to write to the FIFO
Anna Bridge 186:707f6e361f3e 612 bytes = SPIM_MAX_BYTE_LEN;
Anna Bridge 186:707f6e361f3e 613
Anna Bridge 186:707f6e361f3e 614 } else {
Anna Bridge 186:707f6e361f3e 615 // Send in increments of 32 byte pages
Anna Bridge 186:707f6e361f3e 616 header |= (0x2 << 2);
Anna Bridge 186:707f6e361f3e 617 pages = remain / SPIM_MAX_PAGE_LEN;
Anna Bridge 186:707f6e361f3e 618
Anna Bridge 186:707f6e361f3e 619 if(pages >= 32) {
Anna Bridge 186:707f6e361f3e 620 // 0 maps to 32 in the header
Anna Bridge 186:707f6e361f3e 621 bytes = 32 * SPIM_MAX_PAGE_LEN;
Anna Bridge 186:707f6e361f3e 622 } else {
Anna Bridge 186:707f6e361f3e 623 header |= (pages << 4);
Anna Bridge 186:707f6e361f3e 624 bytes = pages * SPIM_MAX_PAGE_LEN;
Anna Bridge 186:707f6e361f3e 625 }
Anna Bridge 186:707f6e361f3e 626
Anna Bridge 186:707f6e361f3e 627 // Check if this is the last header we will send
Anna Bridge 186:707f6e361f3e 628 if((remain - bytes) == 0) {
Anna Bridge 186:707f6e361f3e 629 header |= (req->deass << 13);
Anna Bridge 186:707f6e361f3e 630 }
Anna Bridge 186:707f6e361f3e 631 }
Anna Bridge 186:707f6e361f3e 632
Anna Bridge 186:707f6e361f3e 633 header_save = header;
Anna Bridge 186:707f6e361f3e 634 fifo->trans_16[0] = header;
Anna Bridge 186:707f6e361f3e 635
Anna Bridge 186:707f6e361f3e 636 // Save the number of bytes we need to write to the FIFO
Anna Bridge 186:707f6e361f3e 637 states[spim_num].head_rem = bytes;
Anna Bridge 186:707f6e361f3e 638
Anna Bridge 186:707f6e361f3e 639 } else {
Anna Bridge 186:707f6e361f3e 640
Anna Bridge 186:707f6e361f3e 641 // Send final header with the number of bytes remaining and if
Anna Bridge 186:707f6e361f3e 642 // we want to de-assert the SS at the end of the transaction
Anna Bridge 186:707f6e361f3e 643 header |= ((0x1 << 2) | (remain << 4) | (req->deass << 13));
Anna Bridge 186:707f6e361f3e 644 fifo->trans_16[0] = header;
Anna Bridge 186:707f6e361f3e 645 states[spim_num].head_rem = remain;
Anna Bridge 186:707f6e361f3e 646 }
Anna Bridge 186:707f6e361f3e 647 }
Anna Bridge 186:707f6e361f3e 648
Anna Bridge 186:707f6e361f3e 649 // Put data into the FIFO if we are writing
Anna Bridge 186:707f6e361f3e 650 remain = req->len - req->write_num;
Anna Bridge 186:707f6e361f3e 651 head_rem_temp = states[spim_num].head_rem;
Anna Bridge 186:707f6e361f3e 652 if(write && head_rem_temp) {
Anna Bridge 186:707f6e361f3e 653
Anna Bridge 186:707f6e361f3e 654 // Fill the FIFO
Anna Bridge 186:707f6e361f3e 655 avail = (MXC_CFG_SPIM_FIFO_DEPTH - ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) >>
Anna Bridge 186:707f6e361f3e 656 MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED_POS));
Anna Bridge 186:707f6e361f3e 657
Anna Bridge 186:707f6e361f3e 658 // Use memcpy for everything except the last byte in odd length transactions
Anna Bridge 186:707f6e361f3e 659 while((avail >= 2) && (head_rem_temp >= 2)) {
Anna Bridge 186:707f6e361f3e 660
Anna Bridge 186:707f6e361f3e 661 unsigned length;
Anna Bridge 186:707f6e361f3e 662 if(head_rem_temp < avail) {
Anna Bridge 186:707f6e361f3e 663 length = head_rem_temp;
Anna Bridge 186:707f6e361f3e 664 } else {
Anna Bridge 186:707f6e361f3e 665 length = avail;
Anna Bridge 186:707f6e361f3e 666 }
Anna Bridge 186:707f6e361f3e 667
Anna Bridge 186:707f6e361f3e 668 // Only memcpy even numbers
Anna Bridge 186:707f6e361f3e 669 length = ((length / 2) * 2);
Anna Bridge 186:707f6e361f3e 670
Anna Bridge 186:707f6e361f3e 671 memcpy((void*)fifo->trans_32, &(req->tx_data[req->write_num]), length);
Anna Bridge 186:707f6e361f3e 672
Anna Bridge 186:707f6e361f3e 673 head_rem_temp -= length;
Anna Bridge 186:707f6e361f3e 674 req->write_num += length;
Anna Bridge 186:707f6e361f3e 675
Anna Bridge 186:707f6e361f3e 676 avail = (MXC_CFG_SPIM_FIFO_DEPTH - ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) >>
Anna Bridge 186:707f6e361f3e 677 MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED_POS));
Anna Bridge 186:707f6e361f3e 678 }
Anna Bridge 186:707f6e361f3e 679
Anna Bridge 186:707f6e361f3e 680 // Copy the last byte and pad with 0xF0 to not get confused as header
Anna Bridge 186:707f6e361f3e 681 if((avail >= 1) && (head_rem_temp == 1)) {
Anna Bridge 186:707f6e361f3e 682
Anna Bridge 186:707f6e361f3e 683 // Write the last byte
Anna Bridge 186:707f6e361f3e 684 fifo->trans_16[0] = (0xF000 | req->tx_data[req->write_num]);
Anna Bridge 186:707f6e361f3e 685
Anna Bridge 186:707f6e361f3e 686 avail -= 1;
Anna Bridge 186:707f6e361f3e 687 req->write_num += 1;
Anna Bridge 186:707f6e361f3e 688 head_rem_temp -= 1;
Anna Bridge 186:707f6e361f3e 689 }
Anna Bridge 186:707f6e361f3e 690
Anna Bridge 186:707f6e361f3e 691 states[spim_num].head_rem = head_rem_temp;
Anna Bridge 186:707f6e361f3e 692 remain = req->len - req->write_num;
Anna Bridge 186:707f6e361f3e 693
Anna Bridge 186:707f6e361f3e 694 // Set the TX interrupts
Anna Bridge 186:707f6e361f3e 695 if(remain) {
Anna Bridge 186:707f6e361f3e 696
Anna Bridge 186:707f6e361f3e 697 // Set the TX FIFO almost empty interrupt if we have to refill
Anna Bridge 186:707f6e361f3e 698 spim->fifo_ctrl = ((spim->fifo_ctrl & ~MXC_F_SPIM_FIFO_CTRL_TX_FIFO_AE_LVL) |
Anna Bridge 186:707f6e361f3e 699 ((MXC_CFG_SPIM_FIFO_DEPTH - 2) << MXC_F_SPIM_FIFO_CTRL_TX_FIFO_AE_LVL_POS));
Anna Bridge 186:707f6e361f3e 700
Anna Bridge 186:707f6e361f3e 701 inten |= MXC_F_SPIM_INTEN_TX_FIFO_AE;
Anna Bridge 186:707f6e361f3e 702
Anna Bridge 186:707f6e361f3e 703 }
Anna Bridge 186:707f6e361f3e 704 }
Anna Bridge 186:707f6e361f3e 705
Anna Bridge 186:707f6e361f3e 706 // Check to see if we've finished reading and writing
Anna Bridge 186:707f6e361f3e 707 if(((read && (req->read_num == req->len)) || !read) &&
Anna Bridge 186:707f6e361f3e 708 ((req->write_num == req->len) || !write)) {
Anna Bridge 186:707f6e361f3e 709
Anna Bridge 186:707f6e361f3e 710 // Disable interrupts
Anna Bridge 186:707f6e361f3e 711 spim->inten = 0;
Anna Bridge 186:707f6e361f3e 712
Anna Bridge 186:707f6e361f3e 713 // Unlock this SPIM
Anna Bridge 186:707f6e361f3e 714 mxc_free_lock((uint32_t*)&states[spim_num].req);
Anna Bridge 186:707f6e361f3e 715
Anna Bridge 186:707f6e361f3e 716 // Callback if not NULL
Anna Bridge 186:707f6e361f3e 717 if(req->callback != NULL) {
Anna Bridge 186:707f6e361f3e 718 req->callback(req, E_NO_ERROR);
Anna Bridge 186:707f6e361f3e 719 }
Anna Bridge 186:707f6e361f3e 720 }
Anna Bridge 186:707f6e361f3e 721
Anna Bridge 186:707f6e361f3e 722 // Enable the SPIM interrupts
Anna Bridge 186:707f6e361f3e 723 return inten;
Anna Bridge 186:707f6e361f3e 724 }
Anna Bridge 186:707f6e361f3e 725 /**@} end of ingroup spim */