mbed library sources. Supersedes mbed-src.
Fork of mbed-dev by
targets/TARGET_Maxim/TARGET_MAX32625/mxc/spis.c@165:2dd56e6daeec, 2017-05-23 (annotated)
- Committer:
- ranaumarnaeem
- Date:
- Tue May 23 12:54:50 2017 +0000
- Revision:
- 165:2dd56e6daeec
- Parent:
- 150:02e0a0aed4ec
jhjg
Who changed what in which revision?
User | Revision | Line number | New 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-08-03 16:00:49 -0500 (Wed, 03 Aug 2016) $ |
<> | 150:02e0a0aed4ec | 33 | * $Revision: 23914 $ |
<> | 150:02e0a0aed4ec | 34 | * |
<> | 150:02e0a0aed4ec | 35 | ******************************************************************************/ |
<> | 150:02e0a0aed4ec | 36 | |
<> | 150:02e0a0aed4ec | 37 | /** |
<> | 150:02e0a0aed4ec | 38 | * @file spis.c |
<> | 150:02e0a0aed4ec | 39 | * @brief SPI Slave 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 "spis.h" |
<> | 150:02e0a0aed4ec | 49 | |
<> | 150:02e0a0aed4ec | 50 | /***** Definitions *****/ |
<> | 150:02e0a0aed4ec | 51 | #define SPIS_FIFO_BUFFER 6 |
<> | 150:02e0a0aed4ec | 52 | |
<> | 150:02e0a0aed4ec | 53 | /***** Globals *****/ |
<> | 150:02e0a0aed4ec | 54 | |
<> | 150:02e0a0aed4ec | 55 | static spis_req_t *states[MXC_CFG_SPIS_INSTANCES]; |
<> | 150:02e0a0aed4ec | 56 | |
<> | 150:02e0a0aed4ec | 57 | /***** Functions *****/ |
<> | 150:02e0a0aed4ec | 58 | |
<> | 150:02e0a0aed4ec | 59 | static uint32_t SPIS_TransHandler(mxc_spis_regs_t *spis, spis_req_t *req, int spis_num); |
<> | 150:02e0a0aed4ec | 60 | |
<> | 150:02e0a0aed4ec | 61 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 62 | int SPIS_Init(mxc_spis_regs_t *spis, uint8_t mode, const sys_cfg_spis_t *sys_cfg) |
<> | 150:02e0a0aed4ec | 63 | { |
<> | 150:02e0a0aed4ec | 64 | int err, spis_num; |
<> | 150:02e0a0aed4ec | 65 | |
<> | 150:02e0a0aed4ec | 66 | spis_num = MXC_SPIS_GET_IDX(spis); |
<> | 150:02e0a0aed4ec | 67 | MXC_ASSERT(spis_num >= 0); |
<> | 150:02e0a0aed4ec | 68 | |
<> | 150:02e0a0aed4ec | 69 | // Set system level configurations |
<> | 150:02e0a0aed4ec | 70 | if ((err = SYS_SPIS_Init(sys_cfg)) != E_NO_ERROR) { |
<> | 150:02e0a0aed4ec | 71 | return err; |
<> | 150:02e0a0aed4ec | 72 | } |
<> | 150:02e0a0aed4ec | 73 | |
<> | 150:02e0a0aed4ec | 74 | // Initialize state pointers |
<> | 150:02e0a0aed4ec | 75 | states[spis_num] = NULL; |
<> | 150:02e0a0aed4ec | 76 | |
<> | 150:02e0a0aed4ec | 77 | // Drain the FIFOs, enable SPIS |
<> | 150:02e0a0aed4ec | 78 | spis->gen_ctrl = 0; |
<> | 150:02e0a0aed4ec | 79 | spis->gen_ctrl = (MXC_F_SPIS_GEN_CTRL_SPI_SLAVE_EN | MXC_F_SPIS_GEN_CTRL_TX_FIFO_EN | |
<> | 150:02e0a0aed4ec | 80 | MXC_F_SPIS_GEN_CTRL_RX_FIFO_EN); |
<> | 150:02e0a0aed4ec | 81 | |
<> | 150:02e0a0aed4ec | 82 | // Set the TX FIFO almost empty level |
<> | 150:02e0a0aed4ec | 83 | spis->fifo_ctrl = ((spis->fifo_ctrl & ~MXC_F_SPIS_FIFO_CTRL_TX_FIFO_AE_LVL) | |
<> | 150:02e0a0aed4ec | 84 | ((MXC_CFG_SPIS_FIFO_DEPTH - SPIS_FIFO_BUFFER) << MXC_F_SPIS_FIFO_CTRL_TX_FIFO_AE_LVL_POS)); |
<> | 150:02e0a0aed4ec | 85 | |
<> | 150:02e0a0aed4ec | 86 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 87 | } |
<> | 150:02e0a0aed4ec | 88 | |
<> | 150:02e0a0aed4ec | 89 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 90 | int SPIS_Shutdown(mxc_spis_regs_t *spis) |
<> | 150:02e0a0aed4ec | 91 | { |
<> | 150:02e0a0aed4ec | 92 | int spis_num, err; |
<> | 150:02e0a0aed4ec | 93 | spis_req_t *temp_req; |
<> | 150:02e0a0aed4ec | 94 | |
<> | 150:02e0a0aed4ec | 95 | // Disable and clear interrupts |
<> | 150:02e0a0aed4ec | 96 | spis->inten = 0; |
<> | 150:02e0a0aed4ec | 97 | spis->intfl = spis->intfl; |
<> | 150:02e0a0aed4ec | 98 | |
<> | 150:02e0a0aed4ec | 99 | // Disable SPIS and FIFOS |
<> | 150:02e0a0aed4ec | 100 | spis->gen_ctrl &= ~(MXC_F_SPIS_GEN_CTRL_SPI_SLAVE_EN | MXC_F_SPIS_GEN_CTRL_TX_FIFO_EN | |
<> | 150:02e0a0aed4ec | 101 | MXC_F_SPIS_GEN_CTRL_RX_FIFO_EN); |
<> | 150:02e0a0aed4ec | 102 | |
<> | 150:02e0a0aed4ec | 103 | // Call all of the pending callbacks for this SPIS |
<> | 150:02e0a0aed4ec | 104 | spis_num = MXC_SPIS_GET_IDX(spis); |
<> | 150:02e0a0aed4ec | 105 | if(states[spis_num] != NULL) { |
<> | 150:02e0a0aed4ec | 106 | |
<> | 150:02e0a0aed4ec | 107 | // Save the request |
<> | 150:02e0a0aed4ec | 108 | temp_req = states[spis_num]; |
<> | 150:02e0a0aed4ec | 109 | |
<> | 150:02e0a0aed4ec | 110 | // Unlock this SPIS |
<> | 150:02e0a0aed4ec | 111 | mxc_free_lock((uint32_t*)&states[spis_num]); |
<> | 150:02e0a0aed4ec | 112 | |
<> | 150:02e0a0aed4ec | 113 | // Callback if not NULL |
<> | 150:02e0a0aed4ec | 114 | if(temp_req->callback != NULL) { |
<> | 150:02e0a0aed4ec | 115 | temp_req->callback(temp_req, E_SHUTDOWN); |
<> | 150:02e0a0aed4ec | 116 | } |
<> | 150:02e0a0aed4ec | 117 | } |
<> | 150:02e0a0aed4ec | 118 | |
<> | 150:02e0a0aed4ec | 119 | // Clear system level configurations |
<> | 150:02e0a0aed4ec | 120 | if ((err = SYS_SPIS_Shutdown(spis)) != E_NO_ERROR) { |
<> | 150:02e0a0aed4ec | 121 | return err; |
<> | 150:02e0a0aed4ec | 122 | } |
<> | 150:02e0a0aed4ec | 123 | |
<> | 150:02e0a0aed4ec | 124 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 125 | } |
<> | 150:02e0a0aed4ec | 126 | |
<> | 150:02e0a0aed4ec | 127 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 128 | int SPIS_Trans(mxc_spis_regs_t *spis, spis_req_t *req) |
<> | 150:02e0a0aed4ec | 129 | { |
<> | 150:02e0a0aed4ec | 130 | int spis_num; |
<> | 150:02e0a0aed4ec | 131 | |
<> | 150:02e0a0aed4ec | 132 | // Make sure the SPIS has been initialized |
<> | 150:02e0a0aed4ec | 133 | if((spis->gen_ctrl & MXC_F_SPIS_GEN_CTRL_SPI_SLAVE_EN) == 0) |
<> | 150:02e0a0aed4ec | 134 | return E_UNINITIALIZED; |
<> | 150:02e0a0aed4ec | 135 | |
<> | 150:02e0a0aed4ec | 136 | // Check the input parameters |
<> | 150:02e0a0aed4ec | 137 | if(req == NULL) |
<> | 150:02e0a0aed4ec | 138 | return E_NULL_PTR; |
<> | 150:02e0a0aed4ec | 139 | |
<> | 150:02e0a0aed4ec | 140 | if((req->rx_data == NULL) && (req->tx_data == NULL)) |
<> | 150:02e0a0aed4ec | 141 | return E_NULL_PTR; |
<> | 150:02e0a0aed4ec | 142 | |
<> | 150:02e0a0aed4ec | 143 | if(!(req->len > 0)) { |
<> | 150:02e0a0aed4ec | 144 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 145 | } |
<> | 150:02e0a0aed4ec | 146 | |
<> | 150:02e0a0aed4ec | 147 | // Attempt to register this write request |
<> | 150:02e0a0aed4ec | 148 | spis_num = MXC_SPIS_GET_IDX(spis); |
<> | 150:02e0a0aed4ec | 149 | if(mxc_get_lock((uint32_t*)&states[spis_num], (uint32_t)req) != E_NO_ERROR) { |
<> | 150:02e0a0aed4ec | 150 | return E_BUSY; |
<> | 150:02e0a0aed4ec | 151 | } |
<> | 150:02e0a0aed4ec | 152 | |
<> | 150:02e0a0aed4ec | 153 | //force deass to a 1 or 0 |
<> | 150:02e0a0aed4ec | 154 | req->deass = !!req->deass; |
<> | 150:02e0a0aed4ec | 155 | |
<> | 150:02e0a0aed4ec | 156 | // Clear the number of bytes counter |
<> | 150:02e0a0aed4ec | 157 | req->read_num = 0; |
<> | 150:02e0a0aed4ec | 158 | req->write_num = 0; |
<> | 150:02e0a0aed4ec | 159 | req->callback = NULL; |
<> | 150:02e0a0aed4ec | 160 | |
<> | 150:02e0a0aed4ec | 161 | // Start the transaction, keep calling the handler until complete |
<> | 150:02e0a0aed4ec | 162 | spis->intfl = (MXC_F_SPIS_INTFL_SS_DEASSERTED | MXC_F_SPIS_INTFL_TX_UNDERFLOW); |
<> | 150:02e0a0aed4ec | 163 | while(SPIS_TransHandler(spis, req, spis_num) & (MXC_F_SPIS_INTEN_RX_FIFO_AF | |
<> | 150:02e0a0aed4ec | 164 | MXC_F_SPIS_INTEN_TX_FIFO_AE)) { |
<> | 150:02e0a0aed4ec | 165 | |
<> | 150:02e0a0aed4ec | 166 | if((req->tx_data != NULL) && (spis->intfl & MXC_F_SPIS_INTFL_TX_UNDERFLOW)) { |
<> | 150:02e0a0aed4ec | 167 | return E_UNDERFLOW; |
<> | 150:02e0a0aed4ec | 168 | } |
<> | 150:02e0a0aed4ec | 169 | |
<> | 150:02e0a0aed4ec | 170 | if((req->rx_data != NULL) && (spis->intfl & MXC_F_SPIS_INTFL_RX_LOST_DATA)) { |
<> | 150:02e0a0aed4ec | 171 | return E_OVERFLOW; |
<> | 150:02e0a0aed4ec | 172 | } |
<> | 150:02e0a0aed4ec | 173 | |
<> | 150:02e0a0aed4ec | 174 | if((req->deass) && (spis->intfl & MXC_F_SPIS_INTFL_SS_DEASSERTED)) { |
<> | 150:02e0a0aed4ec | 175 | if(((req->rx_data != NULL) && ((req->read_num + SPIS_NumReadAvail(spis)) < req->len)) || |
<> | 150:02e0a0aed4ec | 176 | ((req->tx_data != NULL) && (req->write_num < req->len))) { |
<> | 150:02e0a0aed4ec | 177 | |
<> | 150:02e0a0aed4ec | 178 | return E_COMM_ERR; |
<> | 150:02e0a0aed4ec | 179 | } |
<> | 150:02e0a0aed4ec | 180 | } |
<> | 150:02e0a0aed4ec | 181 | } |
<> | 150:02e0a0aed4ec | 182 | |
<> | 150:02e0a0aed4ec | 183 | if(req->tx_data == NULL) { |
<> | 150:02e0a0aed4ec | 184 | return req->read_num; |
<> | 150:02e0a0aed4ec | 185 | } |
<> | 150:02e0a0aed4ec | 186 | return req->write_num; |
<> | 150:02e0a0aed4ec | 187 | } |
<> | 150:02e0a0aed4ec | 188 | |
<> | 150:02e0a0aed4ec | 189 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 190 | int SPIS_TransAsync(mxc_spis_regs_t *spis, spis_req_t *req) |
<> | 150:02e0a0aed4ec | 191 | { |
<> | 150:02e0a0aed4ec | 192 | int spis_num; |
<> | 150:02e0a0aed4ec | 193 | |
<> | 150:02e0a0aed4ec | 194 | // Make sure the SPIS has been initialized |
<> | 150:02e0a0aed4ec | 195 | if((spis->gen_ctrl & MXC_F_SPIS_GEN_CTRL_SPI_SLAVE_EN) == 0) |
<> | 150:02e0a0aed4ec | 196 | return E_UNINITIALIZED; |
<> | 150:02e0a0aed4ec | 197 | |
<> | 150:02e0a0aed4ec | 198 | // Check the input parameters |
<> | 150:02e0a0aed4ec | 199 | if(req == NULL) |
<> | 150:02e0a0aed4ec | 200 | return E_NULL_PTR; |
<> | 150:02e0a0aed4ec | 201 | |
<> | 150:02e0a0aed4ec | 202 | if((req->rx_data == NULL) && (req->tx_data == NULL)) |
<> | 150:02e0a0aed4ec | 203 | return E_NULL_PTR; |
<> | 150:02e0a0aed4ec | 204 | |
<> | 150:02e0a0aed4ec | 205 | if(!(req->len > 0)) { |
<> | 150:02e0a0aed4ec | 206 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 207 | } |
<> | 150:02e0a0aed4ec | 208 | |
<> | 150:02e0a0aed4ec | 209 | // Attempt to register this write request |
<> | 150:02e0a0aed4ec | 210 | spis_num = MXC_SPIS_GET_IDX(spis); |
<> | 150:02e0a0aed4ec | 211 | if(mxc_get_lock((uint32_t*)&states[spis_num], (uint32_t)req) != E_NO_ERROR) { |
<> | 150:02e0a0aed4ec | 212 | return E_BUSY; |
<> | 150:02e0a0aed4ec | 213 | } |
<> | 150:02e0a0aed4ec | 214 | |
<> | 150:02e0a0aed4ec | 215 | //force deass to a 1 or 0 |
<> | 150:02e0a0aed4ec | 216 | req->deass = !!req->deass; |
<> | 150:02e0a0aed4ec | 217 | |
<> | 150:02e0a0aed4ec | 218 | // Clear the number of bytes counter |
<> | 150:02e0a0aed4ec | 219 | req->read_num = 0; |
<> | 150:02e0a0aed4ec | 220 | req->write_num = 0; |
<> | 150:02e0a0aed4ec | 221 | |
<> | 150:02e0a0aed4ec | 222 | // Start the transaction, enable the interrupts |
<> | 150:02e0a0aed4ec | 223 | spis->intfl = MXC_F_SPIS_INTFL_SS_DEASSERTED; |
<> | 150:02e0a0aed4ec | 224 | spis->inten = SPIS_TransHandler(spis, req, spis_num); |
<> | 150:02e0a0aed4ec | 225 | |
<> | 150:02e0a0aed4ec | 226 | if(spis->intfl & MXC_F_SPIS_INTFL_SS_DEASSERTED) { |
<> | 150:02e0a0aed4ec | 227 | return E_COMM_ERR; |
<> | 150:02e0a0aed4ec | 228 | } |
<> | 150:02e0a0aed4ec | 229 | |
<> | 150:02e0a0aed4ec | 230 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 231 | } |
<> | 150:02e0a0aed4ec | 232 | |
<> | 150:02e0a0aed4ec | 233 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 234 | int SPIS_AbortAsync(spis_req_t *req) |
<> | 150:02e0a0aed4ec | 235 | { |
<> | 150:02e0a0aed4ec | 236 | int spis_num; |
<> | 150:02e0a0aed4ec | 237 | |
<> | 150:02e0a0aed4ec | 238 | // Check the input parameters |
<> | 150:02e0a0aed4ec | 239 | if(req == NULL) { |
<> | 150:02e0a0aed4ec | 240 | return E_BAD_PARAM; |
<> | 150:02e0a0aed4ec | 241 | } |
<> | 150:02e0a0aed4ec | 242 | |
<> | 150:02e0a0aed4ec | 243 | // Find the request, set to NULL |
<> | 150:02e0a0aed4ec | 244 | for(spis_num = 0; spis_num < MXC_CFG_SPIS_INSTANCES; spis_num++) { |
<> | 150:02e0a0aed4ec | 245 | if(req == states[spis_num]) { |
<> | 150:02e0a0aed4ec | 246 | |
<> | 150:02e0a0aed4ec | 247 | // Disable interrupts, clear the flags |
<> | 150:02e0a0aed4ec | 248 | MXC_SPIS_GET_SPIS(spis_num)->inten = 0; |
<> | 150:02e0a0aed4ec | 249 | MXC_SPIS_GET_SPIS(spis_num)->intfl = MXC_SPIS_GET_SPIS(spis_num)->intfl; |
<> | 150:02e0a0aed4ec | 250 | |
<> | 150:02e0a0aed4ec | 251 | // Unlock this SPIS |
<> | 150:02e0a0aed4ec | 252 | mxc_free_lock((uint32_t*)&states[spis_num]); |
<> | 150:02e0a0aed4ec | 253 | |
<> | 150:02e0a0aed4ec | 254 | // Callback if not NULL |
<> | 150:02e0a0aed4ec | 255 | if(req->callback != NULL) { |
<> | 150:02e0a0aed4ec | 256 | req->callback(req, E_ABORT); |
<> | 150:02e0a0aed4ec | 257 | } |
<> | 150:02e0a0aed4ec | 258 | |
<> | 150:02e0a0aed4ec | 259 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 260 | } |
<> | 150:02e0a0aed4ec | 261 | } |
<> | 150:02e0a0aed4ec | 262 | |
<> | 150:02e0a0aed4ec | 263 | return E_BAD_PARAM; |
<> | 150:02e0a0aed4ec | 264 | } |
<> | 150:02e0a0aed4ec | 265 | |
<> | 150:02e0a0aed4ec | 266 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 267 | void SPIS_Handler(mxc_spis_regs_t *spis) |
<> | 150:02e0a0aed4ec | 268 | { |
<> | 150:02e0a0aed4ec | 269 | int spis_num; |
<> | 150:02e0a0aed4ec | 270 | uint32_t flags; |
<> | 150:02e0a0aed4ec | 271 | spis_req_t *req; |
<> | 150:02e0a0aed4ec | 272 | |
<> | 150:02e0a0aed4ec | 273 | // Clear the interrupt flags |
<> | 150:02e0a0aed4ec | 274 | spis->inten = 0; |
<> | 150:02e0a0aed4ec | 275 | flags = spis->intfl; |
<> | 150:02e0a0aed4ec | 276 | spis->intfl = flags; |
<> | 150:02e0a0aed4ec | 277 | |
<> | 150:02e0a0aed4ec | 278 | spis_num = MXC_SPIS_GET_IDX(spis); |
<> | 150:02e0a0aed4ec | 279 | req = states[spis_num]; |
<> | 150:02e0a0aed4ec | 280 | |
<> | 150:02e0a0aed4ec | 281 | // Check for errors |
<> | 150:02e0a0aed4ec | 282 | if((flags & MXC_F_SPIS_INTFL_TX_UNDERFLOW) && (req->tx_data != NULL)) { |
<> | 150:02e0a0aed4ec | 283 | // Unlock this SPIS |
<> | 150:02e0a0aed4ec | 284 | mxc_free_lock((uint32_t*)&states[spis_num]); |
<> | 150:02e0a0aed4ec | 285 | |
<> | 150:02e0a0aed4ec | 286 | // Callback if not NULL |
<> | 150:02e0a0aed4ec | 287 | if(req->callback != NULL) { |
<> | 150:02e0a0aed4ec | 288 | req->callback(req, E_UNDERFLOW); |
<> | 150:02e0a0aed4ec | 289 | } |
<> | 150:02e0a0aed4ec | 290 | return; |
<> | 150:02e0a0aed4ec | 291 | } |
<> | 150:02e0a0aed4ec | 292 | if((flags & MXC_F_SPIS_INTFL_RX_LOST_DATA) && (req->rx_data != NULL)) { |
<> | 150:02e0a0aed4ec | 293 | // Unlock this SPIS |
<> | 150:02e0a0aed4ec | 294 | mxc_free_lock((uint32_t*)&states[spis_num]); |
<> | 150:02e0a0aed4ec | 295 | |
<> | 150:02e0a0aed4ec | 296 | // Callback if not NULL |
<> | 150:02e0a0aed4ec | 297 | if(req->callback != NULL) { |
<> | 150:02e0a0aed4ec | 298 | req->callback(req, E_OVERFLOW); |
<> | 150:02e0a0aed4ec | 299 | } |
<> | 150:02e0a0aed4ec | 300 | return; |
<> | 150:02e0a0aed4ec | 301 | } |
<> | 150:02e0a0aed4ec | 302 | |
<> | 150:02e0a0aed4ec | 303 | // Check for deassert |
<> | 150:02e0a0aed4ec | 304 | if((flags & MXC_F_SPIS_INTFL_SS_DEASSERTED) && (req != NULL) && |
<> | 150:02e0a0aed4ec | 305 | (req->deass)) { |
<> | 150:02e0a0aed4ec | 306 | |
<> | 150:02e0a0aed4ec | 307 | if(((req->rx_data != NULL) && ((req->read_num + SPIS_NumReadAvail(spis)) < req->len)) || |
<> | 150:02e0a0aed4ec | 308 | ((req->tx_data != NULL) && (req->write_num < req->len))) { |
<> | 150:02e0a0aed4ec | 309 | |
<> | 150:02e0a0aed4ec | 310 | // Unlock this SPIS |
<> | 150:02e0a0aed4ec | 311 | mxc_free_lock((uint32_t*)&states[spis_num]); |
<> | 150:02e0a0aed4ec | 312 | |
<> | 150:02e0a0aed4ec | 313 | // Callback if not NULL |
<> | 150:02e0a0aed4ec | 314 | if(req->callback != NULL) { |
<> | 150:02e0a0aed4ec | 315 | req->callback(states[spis_num], E_COMM_ERR); |
<> | 150:02e0a0aed4ec | 316 | } |
<> | 150:02e0a0aed4ec | 317 | |
<> | 150:02e0a0aed4ec | 318 | return; |
<> | 150:02e0a0aed4ec | 319 | } |
<> | 150:02e0a0aed4ec | 320 | } |
<> | 150:02e0a0aed4ec | 321 | |
<> | 150:02e0a0aed4ec | 322 | // Figure out if this SPIS has an active request |
<> | 150:02e0a0aed4ec | 323 | if(flags && (req != NULL)) { |
<> | 150:02e0a0aed4ec | 324 | |
<> | 150:02e0a0aed4ec | 325 | spis->inten = SPIS_TransHandler(spis, req, spis_num); |
<> | 150:02e0a0aed4ec | 326 | } |
<> | 150:02e0a0aed4ec | 327 | } |
<> | 150:02e0a0aed4ec | 328 | |
<> | 150:02e0a0aed4ec | 329 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 330 | int SPIS_Busy(mxc_spis_regs_t *spis) |
<> | 150:02e0a0aed4ec | 331 | { |
<> | 150:02e0a0aed4ec | 332 | // Check to see if there are any ongoing transactions |
<> | 150:02e0a0aed4ec | 333 | if(states[MXC_SPIS_GET_IDX(spis)] == NULL) { |
<> | 150:02e0a0aed4ec | 334 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 335 | } |
<> | 150:02e0a0aed4ec | 336 | |
<> | 150:02e0a0aed4ec | 337 | return E_BUSY; |
<> | 150:02e0a0aed4ec | 338 | } |
<> | 150:02e0a0aed4ec | 339 | |
<> | 150:02e0a0aed4ec | 340 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 341 | int SPIS_PrepForSleep(mxc_spis_regs_t *spis) |
<> | 150:02e0a0aed4ec | 342 | { |
<> | 150:02e0a0aed4ec | 343 | if(SPIS_Busy(spis) != E_NO_ERROR) { |
<> | 150:02e0a0aed4ec | 344 | return E_BUSY; |
<> | 150:02e0a0aed4ec | 345 | } |
<> | 150:02e0a0aed4ec | 346 | |
<> | 150:02e0a0aed4ec | 347 | // Disable interrupts |
<> | 150:02e0a0aed4ec | 348 | spis->inten = 0; |
<> | 150:02e0a0aed4ec | 349 | return E_NO_ERROR; |
<> | 150:02e0a0aed4ec | 350 | } |
<> | 150:02e0a0aed4ec | 351 | |
<> | 150:02e0a0aed4ec | 352 | /******************************************************************************/ |
<> | 150:02e0a0aed4ec | 353 | static uint32_t SPIS_TransHandler(mxc_spis_regs_t *spis, spis_req_t *req, int spis_num) |
<> | 150:02e0a0aed4ec | 354 | { |
<> | 150:02e0a0aed4ec | 355 | uint8_t read, write; |
<> | 150:02e0a0aed4ec | 356 | uint32_t inten; |
<> | 150:02e0a0aed4ec | 357 | unsigned remain, avail, temp_len; |
<> | 150:02e0a0aed4ec | 358 | mxc_spis_fifo_regs_t *fifo; |
<> | 150:02e0a0aed4ec | 359 | |
<> | 150:02e0a0aed4ec | 360 | inten = 0; |
<> | 150:02e0a0aed4ec | 361 | |
<> | 150:02e0a0aed4ec | 362 | // Get the FIFOS for this UART |
<> | 150:02e0a0aed4ec | 363 | fifo = MXC_SPIS_GET_SPIS_FIFO(spis_num); |
<> | 150:02e0a0aed4ec | 364 | |
<> | 150:02e0a0aed4ec | 365 | // Figure out if we're reading |
<> | 150:02e0a0aed4ec | 366 | if(req->rx_data != NULL) { |
<> | 150:02e0a0aed4ec | 367 | read = 1; |
<> | 150:02e0a0aed4ec | 368 | } else { |
<> | 150:02e0a0aed4ec | 369 | read = 0; |
<> | 150:02e0a0aed4ec | 370 | } |
<> | 150:02e0a0aed4ec | 371 | |
<> | 150:02e0a0aed4ec | 372 | // Figure out if we're writing |
<> | 150:02e0a0aed4ec | 373 | if(req->tx_data != NULL) { |
<> | 150:02e0a0aed4ec | 374 | write = 1; |
<> | 150:02e0a0aed4ec | 375 | } else { |
<> | 150:02e0a0aed4ec | 376 | write = 0; |
<> | 150:02e0a0aed4ec | 377 | } |
<> | 150:02e0a0aed4ec | 378 | |
<> | 150:02e0a0aed4ec | 379 | // Put data into the FIFO if we are writing |
<> | 150:02e0a0aed4ec | 380 | if(write) { |
<> | 150:02e0a0aed4ec | 381 | |
<> | 150:02e0a0aed4ec | 382 | avail = SPIS_NumWriteAvail(spis); |
<> | 150:02e0a0aed4ec | 383 | remain = req->len - req->write_num; |
<> | 150:02e0a0aed4ec | 384 | |
<> | 150:02e0a0aed4ec | 385 | if(remain > avail) { |
<> | 150:02e0a0aed4ec | 386 | temp_len = avail; |
<> | 150:02e0a0aed4ec | 387 | } else { |
<> | 150:02e0a0aed4ec | 388 | temp_len = remain; |
<> | 150:02e0a0aed4ec | 389 | } |
<> | 150:02e0a0aed4ec | 390 | |
<> | 150:02e0a0aed4ec | 391 | memcpy((void*)fifo->tx_32, &(req->tx_data[req->write_num]), temp_len); |
<> | 150:02e0a0aed4ec | 392 | spis->intfl = MXC_F_SPIS_INTFL_TX_FIFO_AE; |
<> | 150:02e0a0aed4ec | 393 | req->write_num += temp_len; |
<> | 150:02e0a0aed4ec | 394 | remain = req->len - req->write_num; |
<> | 150:02e0a0aed4ec | 395 | |
<> | 150:02e0a0aed4ec | 396 | // Set the TX interrupts |
<> | 150:02e0a0aed4ec | 397 | if(remain) { |
<> | 150:02e0a0aed4ec | 398 | inten |= (MXC_F_SPIS_INTEN_TX_FIFO_AE | MXC_F_SPIS_INTFL_TX_UNDERFLOW); |
<> | 150:02e0a0aed4ec | 399 | } |
<> | 150:02e0a0aed4ec | 400 | } |
<> | 150:02e0a0aed4ec | 401 | |
<> | 150:02e0a0aed4ec | 402 | // Read from the FIFO if we are reading |
<> | 150:02e0a0aed4ec | 403 | if(read) { |
<> | 150:02e0a0aed4ec | 404 | |
<> | 150:02e0a0aed4ec | 405 | avail = SPIS_NumReadAvail(MXC_SPIS); |
<> | 150:02e0a0aed4ec | 406 | remain = req->len - req->read_num; |
<> | 150:02e0a0aed4ec | 407 | |
<> | 150:02e0a0aed4ec | 408 | if(remain > avail) { |
<> | 150:02e0a0aed4ec | 409 | temp_len = avail; |
<> | 150:02e0a0aed4ec | 410 | } else { |
<> | 150:02e0a0aed4ec | 411 | temp_len = remain; |
<> | 150:02e0a0aed4ec | 412 | } |
<> | 150:02e0a0aed4ec | 413 | |
<> | 150:02e0a0aed4ec | 414 | memcpy((void*)&req->rx_data[req->read_num], (void*)&(fifo->rx_8[0]), temp_len); |
<> | 150:02e0a0aed4ec | 415 | spis->intfl = MXC_F_SPIS_INTFL_RX_FIFO_AF; |
<> | 150:02e0a0aed4ec | 416 | req->read_num += temp_len; |
<> | 150:02e0a0aed4ec | 417 | remain = req->len - req->read_num; |
<> | 150:02e0a0aed4ec | 418 | |
<> | 150:02e0a0aed4ec | 419 | // Set the RX interrupts |
<> | 150:02e0a0aed4ec | 420 | if(remain) { |
<> | 150:02e0a0aed4ec | 421 | |
<> | 150:02e0a0aed4ec | 422 | // Adjust the almost full threshold |
<> | 150:02e0a0aed4ec | 423 | if (remain > (MXC_CFG_SPIS_FIFO_DEPTH - SPIS_FIFO_BUFFER)) { |
<> | 150:02e0a0aed4ec | 424 | spis->fifo_ctrl = ((spis->fifo_ctrl & ~MXC_F_SPIS_FIFO_CTRL_RX_FIFO_AF_LVL) | |
<> | 150:02e0a0aed4ec | 425 | ((MXC_CFG_SPIS_FIFO_DEPTH - SPIS_FIFO_BUFFER) << MXC_F_SPIS_FIFO_CTRL_RX_FIFO_AF_LVL_POS)); |
<> | 150:02e0a0aed4ec | 426 | |
<> | 150:02e0a0aed4ec | 427 | } else { |
<> | 150:02e0a0aed4ec | 428 | spis->fifo_ctrl = ((spis->fifo_ctrl & ~MXC_F_SPIS_FIFO_CTRL_RX_FIFO_AF_LVL) | |
<> | 150:02e0a0aed4ec | 429 | ((remain-1) << MXC_F_SPIS_FIFO_CTRL_RX_FIFO_AF_LVL_POS)); |
<> | 150:02e0a0aed4ec | 430 | } |
<> | 150:02e0a0aed4ec | 431 | |
<> | 150:02e0a0aed4ec | 432 | inten |= (MXC_F_SPIS_INTEN_RX_FIFO_AF | MXC_F_SPIS_INTFL_RX_LOST_DATA); |
<> | 150:02e0a0aed4ec | 433 | } |
<> | 150:02e0a0aed4ec | 434 | } |
<> | 150:02e0a0aed4ec | 435 | |
<> | 150:02e0a0aed4ec | 436 | // Check to see if we've finished reading and writing |
<> | 150:02e0a0aed4ec | 437 | if(((read && (req->read_num == req->len)) || !read) && |
<> | 150:02e0a0aed4ec | 438 | ((req->write_num == req->len) || !write)) { |
<> | 150:02e0a0aed4ec | 439 | |
<> | 150:02e0a0aed4ec | 440 | // Unlock this SPIS |
<> | 150:02e0a0aed4ec | 441 | mxc_free_lock((uint32_t*)&states[spis_num]); |
<> | 150:02e0a0aed4ec | 442 | |
<> | 150:02e0a0aed4ec | 443 | // Callback if not NULL |
<> | 150:02e0a0aed4ec | 444 | if(req->callback != NULL) { |
<> | 150:02e0a0aed4ec | 445 | req->callback(req, E_NO_ERROR); |
<> | 150:02e0a0aed4ec | 446 | } |
<> | 150:02e0a0aed4ec | 447 | |
<> | 150:02e0a0aed4ec | 448 | return 0; |
<> | 150:02e0a0aed4ec | 449 | } |
<> | 150:02e0a0aed4ec | 450 | |
<> | 150:02e0a0aed4ec | 451 | // Enable deassert interrupt |
<> | 150:02e0a0aed4ec | 452 | if(req->deass) { |
<> | 150:02e0a0aed4ec | 453 | inten |= MXC_F_SPIS_INTEN_SS_DEASSERTED; |
<> | 150:02e0a0aed4ec | 454 | } |
<> | 150:02e0a0aed4ec | 455 | |
<> | 150:02e0a0aed4ec | 456 | return inten; |
<> | 150:02e0a0aed4ec | 457 | } |