mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by Umar Naeem

Committer:
<>
Date:
Tue Nov 08 17:45:16 2016 +0000
Revision:
150:02e0a0aed4ec
This updates the lib to the mbed lib v129

Who changed what in which revision?

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