Manh Pham / Mbed OS Nucleo_rtos_basic_ir_controller
Committer:
manhpham
Date:
Sat Apr 07 09:22:54 2018 +0000
Revision:
0:c8673aa96267
Nucleo_rtos_basic_ir_controller

Who changed what in which revision?

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