1 /* 2 * Copyright (c) 2015-2019, Texas Instruments Incorporated 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of Texas Instruments Incorporated nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /*!***************************************************************************** 33 * @file SPICC32XXDMA.h 34 * 35 * @brief SPI driver implementation for a CC32XX SPI controller using the 36 * micro DMA controller. 37 * 38 * The SPI header file should be included in an application as follows: 39 * @code 40 * #include <ti/drivers/SPI.h> 41 * #include <ti/drivers/spi/SPICC32XXDMA.h> 42 * @endcode 43 * 44 * Refer to @ref SPI.h for a complete description of APIs & example of use. 45 * 46 * This SPI driver implementation is designed to operate on a CC32XX SPI 47 * controller using a micro DMA controller. 48 * 49 * @warning This driver does not support queueing multiple SPI transactions. 50 * 51 * ## Frame Formats # 52 * This SPI controller supports 4 phase & polarity formats. Refer to the device 53 * specific data sheets & technical reference manuals for specifics on each 54 * format. 55 * 56 * ## SPI Chip Select # 57 * This SPI controller supports a hardware chip select pin. Refer to the 58 * device's user manual on how this hardware chip select pin behaves in regards 59 * to the SPI frame format. 60 * 61 * <table> 62 * <tr> 63 * <th>Chip select type</th> 64 * <th>SPI_MASTER mode</th> 65 * <th>SPI_SLAVE mode</th> 66 * </tr> 67 * <tr> 68 * <td>Hardware chip select</td> 69 * <td>No action is needed by the application to select the peripheral.</td> 70 * <td>See the device documentation on it's chip select requirements.</td> 71 * </tr> 72 * <tr> 73 * <td>Software chip select</td> 74 * <td>The application is responsible to ensure that correct SPI slave is 75 * selected before performing a SPI_transfer().</td> 76 * <td>See the device documentation on it's chip select requirements.</td> 77 * </tr> 78 * </table> 79 * 80 * ## SPI data frames # 81 * SPI data frames can be any size from 4-bits to 32-bits. The SPI data 82 * frame size is set in #SPI_Params.dataSize passed to SPI_open. 83 * The SPICC32XXDMA driver implementation makes assumptions on the element 84 * size of the #SPI_Transaction txBuf and rxBuf arrays, based on the data 85 * frame size. If the data frame size is less than or equal to 8 bits, 86 * txBuf and rxBuf are assumed to be arrays of 8-bit uint8_t elements. 87 * If the data frame size is greater than 8 bits, but less than or equal 88 * to 16 bits, txBuf and rxBuf are assumed to be arrays of 16-bit uint16_t 89 * elements. Otherwise, txBuf and rxBuf are assumed to point to 32-bit 90 * uint32_t elements. 91 * 92 * data frame size | buffer element size | 93 * -------------- | ------------------- | 94 * 4-8 bits | uint8_t | 95 * 9-16 bits | uint16_t | 96 * 17-32 bits | uint32_t | 97 * 98 * Data buffers in transactions (rxBuf & txBuf) must be address aligned 99 * according to the data frame size. For example, if data frame is 9-bit 100 * (driver assumes buffers are uint16_t) rxBuf & txBuf must be aligned 101 * on a 16-bit address boundary, if data frame is 20-bit (driver assumes 102 * buffers are uint32_t) rxBuf & txBuf must be aligned on a 32-bit address 103 * boundary. 104 * 105 * ## DMA Interrupts # 106 * This driver is designed to operate with the micro DMA. The micro DMA 107 * generates an interrupt on the perpheral's interrupt vector. This 108 * implementation automatically installs a DMA aware hardware ISR to service 109 * the assigned micro DMA channels. 110 * 111 * ## DMA and Queueing 112 * This driver utilizes DMA channels in ping pong mode (see device TRM) in 113 * order to overcome the 1024 item DMA channel limit. This means the driver 114 * can execute multi kilo-item transactions without pausing to reconfigure the 115 * DMA and causing gaps in transmission. In addition, the driver also allows 116 * the user to queue up transfers when opened in #SPI_MODE_CALLBACK by calling 117 * SPI_transfer() multiple times. Note that each transaction's 118 * #SPI_Transaction struct must still be persistent and unmodified until that 119 * transaction is complete. 120 * 121 * @anchor ti_drivers_spi_SPICC32XXDMA_example_queueing 122 * Below is an example of queueing three transactions 123 * @code 124 * // SPI already opened in callback mode 125 * SPI_Transaction t0, t1, t2; 126 * 127 * t0.txBuf = txBuff0; 128 * t0.rxBuf = rxBuff0; 129 * t0.count = 2000; 130 * 131 * t1.txBuf = txBuff1; 132 * t1.rxBuf = rxBuff1; 133 * t1.count = 1000; 134 * 135 * t2.txBuf = txBuff2; 136 * t2.rxBuf = NULL; 137 * t2.count = 1000; 138 * 139 * bool transferOk = false; 140 * 141 * if (SPI_transfer(spiHandle, &t0)) { 142 * if (SPI_transfer(spiHandle, &t1)) { 143 * transferOk = SPI_transfer(spiHandle, &t2); 144 * } 145 * } 146 * } 147 * @endcode 148 * 149 * ## DMA accessible memory # 150 * As this driver uses uDMA to transfer data/from data buffers, it is the 151 * responsibility of the application to ensure that these buffers reside in 152 * memory that is accessible by the DMA. 153 * 154 * ## Scratch Buffers # 155 * A uint32_t scratch buffer is used to allow SPI_transfers where txBuf or 156 * rxBuf are NULL. Rather than requiring txBuf or rxBuf to have a dummy buffer 157 * of size of the transfer count, a single DMA accessible uint32_t scratch 158 * buffer is used. When rxBuf is NULL, the uDMA will transfer all the SPI data 159 * receives into the scratch buffer as a "bit-bucket". When txBuf is NULL, the 160 * scratch buffer is initialized to defaultTxBufValue so the uDMA will send 161 * some known value. Each SPI driver instance must have its own scratch buffer. 162 * 163 * ## Polling SPI transfers # 164 * When used in blocking mode small SPI transfers are can be done by polling 165 * the peripheral & sending data frame-by-frame. This will not block the task 166 * which requested the transfer, but instead immediately perform the transfer 167 * & return. The minDmaTransferSize field in the hardware attributes is 168 * the threshold; if the transaction count is below the threshold a polling 169 * transfer is performed; otherwise a DMA transfer is done. This is intended 170 * to reduce the overhead of setting up a DMA transfer to only send a few 171 * data frames. Keep in mind that during polling transfers the current task 172 * is still being executed; there is no context switch to another task. 173 ******************************************************************************* 174 */ 175 176 #ifndef ti_drivers_spi_SPICC32XXDMA__include 177 #define ti_drivers_spi_SPICC32XXDMA__include 178 179 #include <ti/drivers/dpl/HwiP.h> 180 #include <ti/drivers/dpl/SemaphoreP.h> 181 #include <ti/drivers/Power.h> 182 #include <ti/drivers/SPI.h> 183 #include <ti/drivers/dma/UDMACC32XX.h> 184 185 #ifdef __cplusplus 186 extern "C" { 187 #endif 188 189 /** 190 * @addtogroup SPI_STATUS 191 * SPICC32XXDMA_STATUS_* macros are command codes only defined in the 192 * SPICC32XXDMA.h driver implementation and need to: 193 * @code 194 * #include <ti/drivers/sdspi/SPICC32XXDMA.h> 195 * @endcode 196 * @{ 197 */ 198 199 /* Add SPICC32XXDMA_STATUS_* macros here */ 200 201 /** @}*/ 202 203 /** 204 * @addtogroup SPI_CMD 205 * SPICC32XXDMA_CMD_* macros are command codes only defined in the 206 * SPICC32XXDMA.h driver implementation and need to: 207 * @code 208 * #include <ti/drivers/sdspi/SPICC32XXDMA.h> 209 * @endcode 210 * @{ 211 */ 212 213 /* Add SPICC32XXDMA_CMD_* macros here */ 214 215 216 /** @}*/ 217 218 /* 219 * Macros defining possible SPI signal pin mux options 220 * 221 * The lower 8 bits of the macro refer to the pin, offset by 1, to match 222 * driverlib pin defines. For example, SPICC32XXDMA_PIN_05_CLK & 0xff = 4, 223 * which equals PIN_05 in driverlib pin.h. By matching the PIN_xx defines in 224 * driverlib pin.h, we can pass the pin directly to the driverlib functions. 225 * The upper 8 bits of the macro correspond to the pin mux confg mode 226 * value for the pin to operate in the SPI mode. 227 * 228 * PIN_62 is special for the SDSPI driver when using an SD BoosterPack, 229 * as PIN_62 doesn't have an assigned SPI function yet the SD BoosterPack 230 * has it tied to the CS signal. 231 */ 232 /*! @cond HIDDEN_DEFINES */ 233 #define SPICC32XXDMA_PIN_05_CLK 0x0704 /*!< PIN 5 is used for SPI CLK */ 234 #define SPICC32XXDMA_PIN_06_MISO 0x0705 /*!< PIN 6 is used for MISO */ 235 #define SPICC32XXDMA_PIN_07_MOSI 0x0706 /*!< PIN 7 is used for MOSI */ 236 #define SPICC32XXDMA_PIN_08_CS 0x0707 /*!< PIN 8 is used for CS */ 237 #define SPICC32XXDMA_PIN_45_CLK 0x072C /*!< PIN 45 is used for SPI CLK */ 238 #define SPICC32XXDMA_PIN_50_CS 0x0931 /*!< PIN 50 is used for CS */ 239 #define SPICC32XXDMA_PIN_52_MOSI 0x0833 /*!< PIN 52 is used for MOSI */ 240 #define SPICC32XXDMA_PIN_53_MISO 0x0734 /*!< PIN 53 is used for MISO */ 241 242 /*! @endcond*/ 243 244 /*! 245 * @brief Indicates a pin is not to be configured by the SPICC32XXDMA driver. 246 */ 247 #define SPICC32XXDMA_PIN_NO_CONFIG 0xFFFF 248 249 /* SPI function table pointer */ 250 extern const SPI_FxnTable SPICC32XXDMA_fxnTable; 251 252 /*! 253 * @brief SPICC32XXDMA Hardware attributes 254 * 255 * These fields, with the exception of intPriority, 256 * are used by driverlib APIs and therefore must be populated by 257 * driverlib macro definitions. For CCWare these definitions are found in: 258 * - driverlib/prcm.h 259 * - driverlib/spi.h 260 * - driverlib/udma.h 261 * - inc/hw_memmap.h 262 * - inc/hw_ints.h 263 * 264 * intPriority is the SPI peripheral's interrupt priority, as defined by the 265 * underlying OS. It is passed unmodified to the underlying OS's interrupt 266 * handler creation code, so you need to refer to the OS documentation 267 * for usage. For example, for SYS/BIOS applications, refer to the 268 * ti.sysbios.family.arm.m3.Hwi documentation for SYS/BIOS usage of 269 * interrupt priorities. If the driver uses the ti.dpl interface 270 * instead of making OS calls directly, then the HwiP port handles the 271 * interrupt priority in an OS specific way. In the case of the SYS/BIOS 272 * port, intPriority is passed unmodified to Hwi_create(). 273 * 274 * A sample structure is shown below: 275 * @code 276 * #if defined(__TI_COMPILER_VERSION__) 277 * #pragma DATA_ALIGN(scratchBuf, 32) 278 * #elif defined(__IAR_SYSTEMS_ICC__) 279 * #pragma data_alignment=32 280 * #elif defined(__GNUC__) 281 * __attribute__ ((aligned (32))) 282 * #endif 283 * uint32_t scratchBuf; 284 * 285 * const SPICC32XXDMA_HWAttrsV1 SPICC32XXDMAHWAttrs[] = { 286 * { 287 * .baseAddr = GSPI_BASE, 288 * .intNum = INT_GSPI, 289 * .intPriority = (~0), 290 * .spiPRCM = PRCM_GSPI, 291 * .csControl = SPI_HW_CTRL_CS, 292 * .csPolarity = SPI_CS_ACTIVELOW, 293 * .pinMode = SPI_4PIN_MODE, 294 * .turboMode = SPI_TURBO_OFF, 295 * .scratchBufPtr = &scratchBuf, 296 * .defaultTxBufValue = 0, 297 * .rxChannelIndex = UDMA_CH6_GSPI_RX, 298 * .txChannelIndex = UDMA_CH7_GSPI_TX, 299 * .minDmaTransferSize = 100, 300 * .mosiPin = SPICC32XXDMA_PIN_07_MOSI, 301 * .misoPin = SPICC32XXDMA_PIN_06_MISO, 302 * .clkPin = SPICC32XXDMA_PIN_05_CLK, 303 * .csPin = SPICC32XXDMA_PIN_08_CS, 304 * }, 305 * ... 306 * }; 307 * @endcode 308 */ 309 typedef struct { 310 /*! SPICC32XXDMA Peripheral's base address */ 311 uint32_t baseAddr; 312 313 314 /*! SPICC32XXDMA Peripheral's interrupt vector */ 315 uint32_t intNum; 316 317 /*! SPICC32XXDMA Peripheral's interrupt priority */ 318 uint32_t intPriority; 319 320 /*! SPI PRCM peripheral number */ 321 uint32_t spiPRCM; 322 323 /*! Specify if chip select line will be controlled by SW or HW */ 324 uint32_t csControl; 325 326 uint32_t csPolarity; 327 328 /*! Set peripheral to work in 3-pin or 4-pin mode */ 329 uint32_t pinMode; 330 331 /*! Enable or disable SPI TURBO mode */ 332 uint32_t turboMode; 333 334 /*! Address of a scratch buffer of size uint32_t */ 335 uint32_t *scratchBufPtr; 336 337 /*! Default TX value if txBuf == NULL */ 338 uint32_t defaultTxBufValue; 339 340 /*! uDMA RX channel index */ 341 uint32_t rxChannelIndex; 342 343 /*! uDMA TX channel index */ 344 uint32_t txChannelIndex; 345 346 /*! Minimum amout of data to start a uDMA transfer */ 347 uint32_t minDmaTransferSize; 348 349 /*! GSPI MOSI pin assignment */ 350 uint16_t mosiPin; 351 352 /*! GSPI MISO pin assignment */ 353 uint16_t misoPin; 354 355 /*! GSPI CLK pin assignment */ 356 uint16_t clkPin; 357 358 /*! GSPI CS pin assignment */ 359 uint16_t csPin; 360 } SPICC32XXDMA_HWAttrsV1; 361 362 /*! 363 * @brief SPICC32XXDMA Object 364 * 365 * The application must not access any member variables of this structure! 366 */ 367 typedef struct { 368 HwiP_Handle hwiHandle; 369 Power_NotifyObj notifyObj; 370 SemaphoreP_Handle transferComplete; 371 SPI_CallbackFxn transferCallbackFxn; 372 SPI_Transaction *transaction; 373 UDMACC32XX_Handle dmaHandle; 374 375 size_t amtDataXferred; 376 size_t currentXferAmt; 377 uint32_t bitRate; 378 uint32_t dataSize; 379 uint32_t transferTimeout; 380 381 SPI_Mode spiMode; 382 SPI_TransferMode transferMode; 383 SPI_FrameFormat frameFormat; 384 385 bool cancelInProgress; 386 bool isOpen; 387 uint8_t rxFifoTrigger; 388 uint8_t txFifoTrigger; 389 } SPICC32XXDMA_Object, *SPICC32XXDMA_Handle; 390 391 #ifdef __cplusplus 392 } 393 #endif 394 395 #endif /* ti_drivers_spi_SPICC32XXDMA__include */ 396