123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- /*
- * @brief SPI master ROM API declarations and functions
- *
- * @note
- * Copyright(C) NXP Semiconductors, 2014
- * All rights reserved.
- *
- * @par
- * Software that is described herein is for illustrative purposes only
- * which provides customers with programming information regarding the
- * LPC products. This software is supplied "AS IS" without any warranties of
- * any kind, and NXP Semiconductors and its licensor disclaim any and
- * all warranties, express or implied, including all implied warranties of
- * merchantability, fitness for a particular purpose and non-infringement of
- * intellectual property rights. NXP Semiconductors assumes no responsibility
- * or liability for the use of the software, conveys no license or rights under any
- * patent, copyright, mask work right, or any other intellectual property rights in
- * or to any products. NXP Semiconductors reserves the right to make changes
- * in the software without notification. NXP Semiconductors also makes no
- * representation or warranty that such application will be suitable for the
- * specified use without further testing or modification.
- *
- * @par
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, under NXP Semiconductors' and its
- * licensor's relevant copyrights in the software, without fee, provided that it
- * is used in conjunction with NXP Semiconductors microcontrollers. This
- * copyright, permission, and disclaimer notice must appear in all copies of
- * this code.
- */
- #include <stdint.h>
- #include <string.h>
- #include "hw_spimd.h"
- #define DRVVERSION 0x0100
- /* Private callback for FIFO push and pop functions. This privately maps
- to the VFIFO for the SPI master, but can be overriden if needed. The driver will
- automatically pick the right implementation at run-time based on the transfer
- size in the transfer descriptor. */
- typedef uint16_t (*spiMasterFifoPushFN)(LPC_SPI_T *pSPI, void *data, uint32_t sendBytes, uint32_t curIndex);
- typedef uint16_t (*spiMasterFifoPopFN)(LPC_SPI_T *pSPI, void *data, uint32_t bytes, uint32_t curIndex);
- /* Private data structure used for the SPI master driver, holds the driver and
- peripheral context */
- typedef struct {
- void *pUserData; /*!< Pointer to user data used by driver instance, use NULL if not used */
- LPC_SPI_T *base; /*!< Base address of SPI peripheral to use */
- uint32_t baseClockRate; /*!< SPI base clock rate in Hz, call Init() again if this rate changes */
- spiMasterXferCSAssertCB pAssertCb; /*!< SSEL assertion callback */
- spiMasterTransmitCB pTranCb; /*!< Transmit data start callback */
- spiMasterReceiveCB pRecvCb; /*!< Receive data start callback */
- spiMMasterXferCSDeAssertCB pDeassertCb; /*!< SSEL deassertion callback */
- spiMasterFifoPushFN pPushFN; /*!< Pointer to current FIFO push function */
- spiMasterFifoPopFN pPopFN; /*!< Pointer to current FIFO pop function */
- ROM_SPIM_XFER_T *pXfer; /*!< Pointer to current transfer descriptor */
- uint32_t sendIdx; /*!< Current transmit buffer index */
- uint32_t recvIdx; /*!< Current receive buffer index */
- ErrorCode_t pendingStatus; /*!< Pending transfer status */
- uint8_t xmitOn; /*!< Transfer in progress flag */
- uint8_t terminate; /*!< Terminate transfer flag */
- uint8_t reserved[2];
- } SPIM_DATACONTEXT_T;
- /* Maps config registers bits for SPI mode to the transfer descriptor */
- static const uint32_t spiModeBits[4] = {
- (SPI_CFG_CPOL_LO | SPI_CFG_CPHA_FIRST),
- (SPI_CFG_CPOL_LO | SPI_CFG_CPHA_SECOND),
- (SPI_CFG_CPOL_HI | SPI_CFG_CPHA_FIRST),
- (SPI_CFG_CPOL_HI | SPI_CFG_CPHA_SECOND)
- };
- void spim_close_pending_transfer(ROM_SPIM_HANDLE_T pHandle);
- /* FIFO push function using standard SPI FIFO for datum >8 bits */
- static uint16_t _rom_spimMasterFifoPush16(LPC_SPI_T *pSPI, void *data, uint32_t numData, uint32_t curIndex)
- {
- uint16_t pushed = 0, *p16 = (uint16_t *) data;
- /* Push as 16-bit value */
- while ((numData > 0) && ((pSPI->STAT & SPI_STAT_TXRDY) != 0)) {
- pSPI->TXDAT = (uint32_t) p16[curIndex];
- numData--;
- curIndex++;
- pushed++;
- }
- return pushed;
- }
- /* FIFO pop function using standard SPI FIFO for datum >8 bits */
- static uint16_t _rom_spimMasterFifoPop16(LPC_SPI_T *pSPI, void *data, uint32_t numData, uint32_t curIndex)
- {
- uint16_t popped = 0, *p16 = (uint16_t *) data;
- /* Pop as 16-bit value */
- while ((numData > 0) && ((pSPI->STAT & SPI_STAT_RXRDY) != 0)) {
- p16[curIndex] = (uint16_t) pSPI->RXDAT;
- numData--;
- curIndex++;
- popped++;
- }
- return popped;
- }
- /* FIFO push function using standard SPI FIFO for datum <=8 bits */
- static uint16_t _rom_spimMasterFifoPush8(LPC_SPI_T *pSPI, void *data, uint32_t numData, uint32_t curIndex)
- {
- uint16_t pushed = 0;
- uint8_t *p8 = (uint8_t *) data;
- /* Push as 8-bit value */
- while ((numData > 0) && ((pSPI->STAT & SPI_STAT_TXRDY) != 0)) {
- pSPI->TXDAT = (uint32_t) p8[curIndex];
- numData--;
- curIndex++;
- pushed++;
- }
- return pushed;
- }
- /* FIFO pop function using standard SPI FIFO for datum <=8 bits */
- static uint16_t _rom_spimMasterFifoPop8(LPC_SPI_T *pSPI, void *data, uint32_t numData, uint32_t curIndex)
- {
- uint16_t popped = 0;
- uint8_t *p8 = (uint8_t *) data;
- /* Pop as 16-bit value */
- while ((numData > 0) && ((pSPI->STAT & SPI_STAT_RXRDY) != 0)) {
- p8[curIndex] = (uint8_t) pSPI->RXDAT;
- numData--;
- curIndex++;
- popped++;
- }
- return popped;
- }
- /* Assert a SPI select */
- static void _rom_spimAssertSSEL(LPC_SPI_T *pSPI, uint8_t sselNum)
- {
- /* Assert a SSEL line by driving it low */
- pSPI->TXCTRL &= ~SPI_TXDATCTL_DEASSERTNUM_SSEL(sselNum);
- }
- static void _rom_spimCloseTransfer(SPIM_DATACONTEXT_T *pDrv)
- {
- /* Transfer terminates after this byte */
- pDrv->xmitOn = 0;
- pDrv->base->INTENCLR = SPI_INTENSET_TXDYEN;
- }
- static void _rom_spimTransmitHandler(ROM_SPIM_HANDLE_T pHandle, ROM_SPIM_XFER_T *pXfer)
- {
- SPIM_DATACONTEXT_T *pDrv = (SPIM_DATACONTEXT_T *) pHandle;
- /* Is DMA being used? */
- if ((pXfer->flags & ROM_SPIM_FLAG_DMATX) != 0) {
- /* Call transmit callback, callback is pre-validated by setup */
- if (pDrv->pTranCb) {
- pDrv->pTranCb(pHandle, pXfer);
- pDrv->base->INTENCLR = SPI_INTENSET_TXDYEN;
- }
- }
- else { /* Transfer without using DMA */
- if ((pXfer->flags & ROM_SPIM_FLAG_TXIGNORE) != 0) {
- /* ROM_SPIM_FLAG_TXIGNORE flag is set. Will send 0xFF and decrement txSz,
- transfer terminates on last data */
- static const uint16_t sb = 0xFFFF;
- if (pDrv->sendIdx >= pXfer->txSz) {
- /* Transferring last datum, end transfer */
- spim_close_pending_transfer(pHandle);
- }
- else {
- if (pDrv->sendIdx >= (pXfer->txSz - 1)) {
- pDrv->base->TXCTRL |= SPI_TXCTL_EOT;
- }
- pDrv->sendIdx += pDrv->pPushFN(pDrv->base, (void *) &sb, 1, 0);
- }
- }
- else {
- /* Normal data transfer */
- if (pDrv->sendIdx >= pXfer->txSz) {
- /* Ran out of data, so stop */
- spim_close_pending_transfer(pHandle);
- }
- else {
- pDrv->sendIdx += pDrv->pPushFN(pDrv->base, (void *) pXfer->txBuff, 1, pDrv->sendIdx);
- /* Call callback for more data */
- if (pDrv->sendIdx >= pXfer->txSz) {
- if (pDrv->pTranCb) {
- pDrv->pTranCb(pHandle, pXfer);
- pDrv->sendIdx = 0;
- }
- else {
- /* No transmit callback, close transfer */
- spim_close_pending_transfer(pHandle);
- }
- }
- }
- }
- }
- }
- static void _rom_spimReceiveHandler(ROM_SPIM_HANDLE_T pHandle, ROM_SPIM_XFER_T *pXfer)
- {
- SPIM_DATACONTEXT_T *pDrv = (SPIM_DATACONTEXT_T *) pHandle;
- /* Is DMA being used? */
- if ((pXfer->flags & ROM_SPIM_FLAG_DMARX) != 0) {
- /* Call receive callback, callback is pre-validated by setup */
- if (pDrv->pRecvCb) {
- pDrv->pRecvCb(pHandle, pXfer);
- pDrv->base->INTENCLR = SPI_INTENSET_RXDYEN;
- }
- }
- else { /* Transfer without using DMA */
- /* Normal data transfer */
- if (pDrv->recvIdx >= pXfer->rxSz) {
- uint16_t temp;
- /* Ran out of data, overflowing */
- pDrv->pendingStatus = ERR_SPI_RXOVERRUN;
- pDrv->recvIdx += pDrv->pPopFN(pDrv->base, (void *) &temp, 1, 0); /* Flush data */
- }
- else {
- pDrv->recvIdx += pDrv->pPopFN(pDrv->base, (void *) pXfer->rxBuff, 1, pDrv->recvIdx);
- /* Call callback for more data */
- if ((pDrv->recvIdx >= pXfer->rxSz) && (pDrv->pRecvCb)) {
- pDrv->pRecvCb(pHandle, pXfer);
- pDrv->recvIdx = 0;
- }
- }
- }
- }
- // **********************************************************
- uint32_t spim_get_mem_size(void)
- {
- return sizeof(SPIM_DATACONTEXT_T);
- }
- ROM_SPIM_HANDLE_T spim_init(void *mem, const ROM_SPIM_INIT_T *pInit)
- {
- SPIM_DATACONTEXT_T *pDrv;
- int i;
- /* Verify alignment is at least 4 bytes and clock rate is not 0 */
- if ((((uint32_t) mem & 0x3) != 0) || (pInit->baseClockRate == 0)) {
- return NULL;
- }
- pDrv = (SPIM_DATACONTEXT_T *) mem;
- memset(pDrv, 0, sizeof(SPIM_DATACONTEXT_T));
- /* Save base of peripheral and pointer to user data */
- pDrv->pUserData = pInit->pUserData;
- pDrv->base = (LPC_SPI_T *) pInit->base;
- pDrv->baseClockRate = pInit->baseClockRate;
- /* Enable SPI master interface, deassert all chip selects */
- pDrv->base->CFG = 0;/* Forces state machine reset */
- pDrv->base->CFG = SPI_CFG_SPI_EN | SPI_CFG_MASTER_EN;
- /* Set SPI slave select (SSEL) polarity for each slave signal */
- for (i = 0; i <= 3; i++) {
- if (pInit->spiPol[i] == 0) {
- /* Active low select, high during idle */
- pDrv->base->CFG &= ~(1 << (8 + i));
- }
- else {
- /* Active high, low during idle */
- pDrv->base->CFG |= (1 << (8 + i));
- }
- }
- /* Deassert all chip selects */
- pDrv->base->TXCTRL = SPI_TXDATCTL_DEASSERT_ALL;
- /* Clear pending master statuses - RXOV, TXUR, SSA, SSD, EOT */
- pDrv->base->STAT = (SPI_STAT_RXOV | SPI_STAT_TXUR | SPI_STAT_SSA |
- SPI_STAT_SSD | SPI_STAT_EOT);
- return (ROM_SPIM_HANDLE_T) pDrv;
- }
- void spim_register_callback(ROM_SPIM_HANDLE_T pHandle, uint32_t cbIndex, void *pCB)
- {
- SPIM_DATACONTEXT_T *pDrv = (SPIM_DATACONTEXT_T *) pHandle;
- switch (cbIndex) {
- case ROM_SPIM_ASSERTSSEL_CB:
- pDrv->pAssertCb = (spiMasterXferCSAssertCB) pCB;
- break;
- case ROM_SPIM_DATATRANSMIT_CB:
- pDrv->pTranCb = (spiMasterTransmitCB) pCB;
- break;
- case ROM_SPIM_DATATRECEIVE_CB:
- pDrv->pRecvCb = (spiMasterReceiveCB) pCB;
- break;
- case ROM_SPIM_DEASSERTSSEL_CB:
- pDrv->pDeassertCb = (spiMMasterXferCSDeAssertCB) pCB;
- break;
- }
- }
- ErrorCode_t spim_setup_transfer(ROM_SPIM_HANDLE_T pHandle, ROM_SPIM_XFER_CONFIG_T *pCfg)
- {
- SPIM_DATACONTEXT_T *pDrv = (SPIM_DATACONTEXT_T *) pHandle;
- uint32_t reg;
- /* Verify config is valid */
- if (pCfg == NULL) {
- return ERR_SPI_PARAM;
- }
- /* Verify data parameters area valid */
- if ((pCfg->dataBits == 0) || (pCfg->dataBits > 16) || (pCfg->dXferBitRate == 0)) {
- return ERR_SPI_PARAM;
- }
- /* Verify mode */
- if (pCfg->mode > ROM_SPI_CLOCK_MODE3) {
- return ERR_SPI_PARAM;
- }
- /* Transfer timing is valid? */
- if ((pCfg->PreDelay > 15) || (pCfg->PostDelay > 15) || (pCfg->FrameDelay > 15) ||
- (pCfg->TransferDelay > 16)) {
- return ERR_SPI_PARAM;
- }
- /* Compute real clock rate from desired clock rate */
- reg = pDrv->baseClockRate / pCfg->dXferBitRate;
- if ((pDrv->baseClockRate % pCfg->dXferBitRate) != 0) {
- reg++;
- }
- if (reg > 0x10000) {
- reg = 0x10000;
- }
- else if (reg == 0) {
- reg = 1;
- }
- /* Save pre-computed divider and set real SPI master bit rate for app */
- pDrv->base->DIV = (reg - 1);
- pCfg->rXferBitRate = pDrv->baseClockRate / reg;
- /* Setup transfer timing */
- if (pCfg->TransferDelay == 0) {
- pCfg->TransferDelay = 1;
- }
- pDrv->base->DLY = (
- SPI_DLY_PRE_DELAY(pCfg->PreDelay) |
- SPI_DLY_POST_DELAY(pCfg->PostDelay) |
- SPI_DLY_FRAME_DELAY(pCfg->FrameDelay) |
- SPI_DLY_TRANSFER_DELAY(pCfg->TransferDelay - 1));
- /* Setup transfer mode and LSB/MSB first */
- reg = pDrv->base->CFG;
- reg &= ~(SPI_CFG_LSB_FIRST_EN | SPI_CFG_CPHA_SECOND |
- SPI_CFG_CPOL_HI);
- /* Setup SPI transfer configuration (CFG register) */
- reg |= spiModeBits[(int) pCfg->mode];
- if (pCfg->lsbFirst) {
- reg |= SPI_CFG_LSB_FIRST_EN;
- }
- pDrv->base->CFG = reg;
- /* Setup SPI transfer configuration (TXCTRL) for data size, don't alter SPI SSEL states */
- reg = pDrv->base->TXCTRL & ~SPI_TXCTL_FLEN(16);
- if (pCfg->FrameDelay > 0) {
- reg |= SPI_TXCTL_EOF;
- }
- pDrv->base->TXCTRL = reg | SPI_TXCTL_FLEN(pCfg->dataBits);
- /* Setup FIFO callbacks based on the data transfer width */
- if (pCfg->dataBits > 8) {
- pDrv->pPushFN = &_rom_spimMasterFifoPush16;
- pDrv->pPopFN = &_rom_spimMasterFifoPop16;
- }
- else {
- pDrv->pPushFN = &_rom_spimMasterFifoPush8;
- pDrv->pPopFN = &_rom_spimMasterFifoPop8;
- }
- return LPC_OK;
- }
- ErrorCode_t spim_transfer(ROM_SPIM_HANDLE_T pHandle, ROM_SPIM_XFER_T *pXfer)
- {
- SPIM_DATACONTEXT_T *pDrv = (SPIM_DATACONTEXT_T *) pHandle;
- uint32_t reg;
- uint8_t flen;
- /* Get length of a receive value */
- flen = 1 + (uint8_t) ((pDrv->base->TXCTRL >> 24) & 0xF);
- /* Is transfer descriptor valid? */
- if (pXfer == NULL) {
- return ERR_SPI_PARAM;
- }
- /* Is slave select valid? */
- if (pXfer->sselNum >= ROM_SPIM_MAXSELECTS) {
- pXfer->status = ERR_SPI_PARAM;
- return ERR_SPI_PARAM;
- }
- /* Verify transmit size, must have at least 1 byte */
- if (pXfer->txSz == 0) {
- pXfer->status = ERR_SPI_INVALID_LENGTH;
- return ERR_SPI_INVALID_LENGTH;
- }
- /* No need to check RX buffer alignment if ROM_SPIM_FLAG_RXIGNORE flag is set */
- if ((pXfer->flags & ROM_SPIM_FLAG_RXIGNORE) == 0) {
- if ((pXfer->rxSz == 0) || (pXfer->rxBuff == NULL)) {
- pXfer->status = ERR_SPI_PARAM;
- return ERR_SPI_PARAM;
- }
- if ((flen > 8) && ((((uint32_t) pXfer->rxBuff) & 0x1) != 0)) {
- /* Receive buffer not 16-bit aligned or not present */
- pXfer->status = ERR_SPI_PARAM;
- return ERR_SPI_PARAM;
- }
- /* Is DMA being used? */
- if ((pXfer->flags & ROM_SPIM_FLAG_DMARX) != 0) {
- if (pDrv->pRecvCb == NULL) {
- pXfer->status = ERR_SPI_PARAM;
- return ERR_SPI_PARAM;
- }
- }
- }
- /* Check transmit buffer alignment */
- if ((pXfer->flags & ROM_SPIM_FLAG_TXIGNORE) == 0) {
- if ((pXfer->txSz == 0) || (pXfer->txBuff == NULL)) {
- pXfer->status = ERR_SPI_PARAM;
- return ERR_SPI_PARAM;
- }
- if ((flen > 8) && ((((uint32_t) pXfer->txBuff) & 0x1) != 0)) {
- pXfer->status = ERR_SPI_PARAM;
- return ERR_SPI_PARAM;
- }
- /* Is DMA being used? */
- if ((pXfer->flags & ROM_SPIM_FLAG_DMATX) != 0) {
- if (pDrv->pTranCb == NULL) {
- pXfer->status = ERR_SPI_PARAM;
- return ERR_SPI_PARAM;
- }
- }
- }
- /* If in loopback mode, set loopback enable */
- reg = pDrv->base->CFG;
- if ((pXfer->flags & ROM_SPIM_FLAG_LOOPBACK) != 0) {
- reg |= SPI_CFG_LBM_EN;
- }
- else {
- reg &= ~SPI_CFG_LBM_EN;
- }
- pDrv->base->CFG = reg;
- /* ROM_SPIM_FLAG_RXIGNORE flag */
- reg = pDrv->base->TXCTRL & ~SPI_TXCTL_EOT;
- if ((pXfer->flags & ROM_SPIM_FLAG_RXIGNORE) != 0) {
- reg |= SPI_TXCTL_RXIGNORE;
- }
- else {
- reg &= ~SPI_TXCTL_RXIGNORE;
- }
- pDrv->base->TXCTRL = reg;
- /* Save pointer to transfer descriptor and initial status */
- pDrv->pXfer = pXfer;
- pXfer->status = ERR_SPI_BUSY;
- pDrv->pendingStatus = LPC_OK;
- pDrv->sendIdx = pDrv->recvIdx = 0;
- /* Transmit start, no terminate */
- pDrv->xmitOn = 1;
- pDrv->terminate = 0;
- /* Start transfer by asserting selected slave */
- _rom_spimAssertSSEL(pDrv->base, pXfer->sselNum);
- /* Enable SPI interrupts for master */
- pDrv->base->INTENSET = SPI_INTENSET_RXDYEN | SPI_INTENSET_TXDYEN |
- SPI_INTENSET_SSAEN | SPI_INTENSET_SSDEN;
- /* Is transfer blocking? */
- if ((pXfer->flags & ROM_SPIM_FLAG_BLOCKING) != 0) {
- while (pXfer->status == ERR_SPI_BUSY) {
- spim_transfer_handler(pHandle);
- }
- }
- return pXfer->status;
- }
- // Otime = "optimize for speed of code execution"
- // ...add this pragma 1 line above the interrupt service routine function.
- void spim_transfer_handler(ROM_SPIM_HANDLE_T pHandle)
- {
- SPIM_DATACONTEXT_T *pDrv = (SPIM_DATACONTEXT_T *) pHandle;
- ROM_SPIM_XFER_T *pXfer = pDrv->pXfer;
- uint32_t status = pDrv->base->STAT;
- /* Master asserts slave */
- if ((status & SPI_STAT_SSA) != 0) {
- pDrv->base->STAT = SPI_STAT_SSA;
- pDrv->base->INTENCLR = SPI_INTENSET_SSAEN;
- /* Master SSEL assertion callback */
- if (pDrv->pAssertCb != NULL) {
- pDrv->pAssertCb(pHandle, pXfer);
- }
- }
- /* Transmit data handler */
- if (((status & SPI_STAT_TXRDY) != 0) && (pDrv->xmitOn == 1)) {
- /* Handle transmit */
- _rom_spimTransmitHandler(pHandle, pXfer);
- }
- /* Receive data handler */
- if ((status & SPI_STAT_RXRDY) != 0) {
- /* Handle receive */
- _rom_spimReceiveHandler(pHandle, pXfer);
- }
- /* If the controller is stalled and the transmit is finished, close the transfer
- or be stuck in a stalled condition indefinitely. */
- if (((status & SPI_STAT_STALLED) != 0) && (pDrv->xmitOn == 0)) {
- spim_close_pending_transfer(pHandle);
- }
- /* Master SSEL de-assertion callback */
- if ((status & SPI_STAT_SSD) != 0) {
- pDrv->base->STAT = SPI_STAT_SSD;
- pDrv->base->INTENCLR = SPI_INTENSET_SSAEN | SPI_INTENSET_SSDEN |
- SPI_INTENSET_RXDYEN | SPI_INTENSET_TXDYEN;
- pXfer->status = pDrv->pendingStatus;
- /* De-assetion event */
- if (pDrv->pDeassertCb != NULL) {
- pDrv->pDeassertCb(pHandle, pXfer);
- }
- }
- }
- void spim_close_pending_transfer(ROM_SPIM_HANDLE_T pHandle)
- {
- SPIM_DATACONTEXT_T *pDrv = (SPIM_DATACONTEXT_T *) pHandle;
- /* If stalled, force an EOT */
- if ((pDrv->base->STAT & SPI_STAT_STALLED) != 0) {
- pDrv->base->STAT = SPI_STAT_EOT;
- }
- pDrv->base->TXCTRL |= SPI_TXCTL_EOT;
- _rom_spimCloseTransfer(pDrv);
- }
- uint32_t spim_get_driver_version(void)
- {
- return DRVVERSION;
- }
- // *********************************************************
|