summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 2603e88)
raw | patch | inline | side by side (parent: 2603e88)
author | Hao Zhang <hzhang@ti.com> | |
Thu, 7 Mar 2019 15:47:18 +0000 (10:47 -0500) | ||
committer | Hao Zhang <hzhang@ti.com> | |
Thu, 7 Mar 2019 15:47:18 +0000 (10:47 -0500) |
Signed-off-by: Hao Zhang <hzhang@ti.com>
example/mcspi_slavemode/src/main_mcspi_slave_mode.c | patch | blob | history | |
src/v0/SPI_v0.c | patch | blob | history | |
src/v0/SPI_v0.h | patch | blob | history | |
src/v1/SPI_v1.c | patch | blob | history |
diff --git a/example/mcspi_slavemode/src/main_mcspi_slave_mode.c b/example/mcspi_slavemode/src/main_mcspi_slave_mode.c
index 25f63bdccc546e01e73972d3761b8e6678fc9170..72b49970dbf10ddf9a3afabacd0d05a332f089dc 100644 (file)
*/
/*
- * Copyright (C) 2016 - 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2016 - 2019 Texas Instruments Incorporated - http://www.ti.com/
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#define SPI_TEST_ID_RX_ONLY 11 /* Multi-channel RX only test */
#define SPI_TEST_ID_XFER_ERR 12 /* Single-channel transfer error test */
#define SPI_TEST_ID_PHA_POL 13 /* Single-channel phase/polarity test */
-#define SPI_TEST_ID_TIMEOUT 14 /* Single-channel Timeout test */
+#define SPI_TEST_ID_TIMEOUT 14 /* Single-channel Timeout test with interrupt enabled */
+#define SPI_TEST_ID_TIMEOUT_POLL 15 /* Single-channel Timeout test with polling enabled */
/* Loopback tests */
#define SPI_TEST_ID_LOOPBACK 20
@@ -675,11 +676,10 @@ static void SPI_initConfig(uint32_t instance, SPI_Tests *test, uint32_t chn, boo
{
/* polling mode */
spi_cfg.enableIntr = false;
-#if defined(SOC_DRA78x) || defined(SOC_TDA3XX) || defined(SOC_TDA2XX) || defined(SOC_TDA2PX) || defined(SOC_TDA2EX) || defined (SOC_DRA75x) || defined (SOC_AM572x) || defined (SOC_AM571x) || defined(SOC_AM574x) || defined (SOC_AM437x) || defined (SOC_AM335x) || defined (SOC_AM65XX) || defined(SOC_J721E)
- /* SPI DMA mode is not supported in Keystone devices */
+
+ /* SPI DMA mode is not supported in polling mode */
spi_cfg.edmaHandle = NULL;
spi_cfg.dmaMode = FALSE;
-#endif
}
else
{
}
else
{
- if (testId == SPI_TEST_ID_TIMEOUT)
+ if ((testId == SPI_TEST_ID_TIMEOUT) || (testId == SPI_TEST_ID_TIMEOUT_POLL))
{
if (transaction.status == SPI_TRANSFER_TIMEOUT)
{
#endif
/* NOTE: Timeout Test case should be executed as the final test, as this test requires no transaction on the data lines
* for the timeout to happen */
- {SPI_test_single_channel, SPI_TEST_ID_TIMEOUT, false, false, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI Timeout Test", },
+ {SPI_test_single_channel, SPI_TEST_ID_TIMEOUT, false, false, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in interrupt mode", },
+ {SPI_test_single_channel, SPI_TEST_ID_TIMEOUT_POLL, false, true, false, false, SPI_TIMEOUT_VALUE, "\r\n SPI timeout test in polling mode", },
{NULL, },
};
break;
#if defined (SOC_AM65XX) || defined(SOC_J721E)
- if (test->testId < SPI_TEST_ID_LOOPBACK)
+ if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
+ (test->testId != SPI_TEST_ID_TIMEOUT) &&
+ (test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
#endif
if (evmAM570x == true)
{
/* Only loopback test supported on AM570x EVM */
- if (test->testId < SPI_TEST_ID_LOOPBACK)
+ if ((test->testId < SPI_TEST_ID_LOOPBACK) &&
+ (test->testId != SPI_TEST_ID_TIMEOUT) &&
+ (test->testId != SPI_TEST_ID_TIMEOUT_POLL))
continue;
}
SPI_test_print_test_desc(test);
diff --git a/src/v0/SPI_v0.c b/src/v0/SPI_v0.c
index 74d3d37d2266b44ac1270d08d9f121f5d8fa80fc..b45e597ce6bf9f9550153fd1eee04ee5f3cd563a 100644 (file)
--- a/src/v0/SPI_v0.c
+++ b/src/v0/SPI_v0.c
*/
/*
- * Copyright (c) 2015 - 2018, Texas Instruments Incorporated
+ * Copyright (c) 2015 - 2019, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include <ti/csl/src/ip/mcspi/V1/spi.h>
#include <ti/drv/spi/src/SPI_osal.h>
+#define SPI_POLLING_TIMEOUT_LOOP (1000U)
+
/* SPITiva functions */
static void SPI_close_v0(SPI_Handle handle);
static void SPI_init_v0(SPI_Handle handle);
@@ -165,6 +167,35 @@ void *SPI_transmitData_v0 (uint32_t baseAddr, uint32_t csHold, SPI_v0_FrameSize
return (dataPtr);
}
+static bool SPI_pollingXferTimeout_v0(uint32_t *timeout, uint32_t *timeoutLoop, uint32_t timeoutVal);
+static bool SPI_pollingXferTimeout_v0(uint32_t *timeout, uint32_t *timeoutLoop, uint32_t timeoutVal)
+{
+ bool timeoutFlag = (bool)false;
+
+ if (*timeout > 0)
+ {
+ *timeout -= 1U;
+ if (*timeout == 0U)
+ {
+ if (*timeoutLoop > 0U)
+ {
+ *timeoutLoop -= 1U;
+ *timeout = timeoutVal;
+ }
+ }
+ }
+ else
+ {
+ if (*timeoutLoop == 0U)
+ {
+ /* Polling transfer timed out */
+ timeoutFlag = (bool)true;
+ }
+ }
+
+ return (timeoutFlag);
+}
+
/*
* ======== SPI_primeTransfer_v0 ========
* This functions configures the transmit and receive channels for a given
uint32_t csHold = SPI_CSHOLD_ON;
uint32_t terminateXfer;
uint32_t intCode;
+ uint32_t timeout;
+ uint32_t timeoutLoop;
+ bool timeoutFlag = (bool)false;
/* Get the pointer to the object and hwAttrs */
hwAttrs = (const SPI_v0_HWAttrs *)handle->hwAttrs;
}
else
{
+ /* Initialize the timeout value and loop count in polling mode */
+ timeout = object->waitTimeout;
+ timeoutLoop = SPI_POLLING_TIMEOUT_LOOP;
+
/* Polling mode transfer */
- while (0 != object->writeCountIdx)
+ while ((0 != object->writeCountIdx) && (timeoutFlag == (bool)false))
{
intCode = SPIIntStatusGet(hwAttrs->baseAddr);
/* Wait until TX buffer is empty */
while (SPITxEmpty(hwAttrs->baseAddr) == false)
- {}
-
- /* Write data to TX buffer, if no write data, write 0 */
- if (object->writeBufIdx)
{
- object->writeBufIdx = (uint8_t *)SPI_transmitData_v0 (hwAttrs->baseAddr,
- csHold,
- object->frameSize,
- object->writeBufIdx);
+ timeoutFlag = SPI_pollingXferTimeout_v0(&timeout,
+ &timeoutLoop,
+ object->waitTimeout);
+ if (timeoutFlag == (bool)true)
+ {
+ break;
+ }
}
- else
+
+ /* Write data to TX buffer, if no write data, write 0 */
+ if (timeoutFlag == (bool)false)
{
- SPITransmitData(hwAttrs->baseAddr, csHold, 0);
+ if (object->writeBufIdx)
+ {
+ object->writeBufIdx = (uint8_t *)SPI_transmitData_v0 (hwAttrs->baseAddr,
+ csHold,
+ object->frameSize,
+ object->writeBufIdx);
+ }
+ else
+ {
+ SPITransmitData(hwAttrs->baseAddr, csHold, 0);
+ }
+ object->writeCountIdx--;
}
- object->writeCountIdx--;
/* Wait until RX buffer is full */
while(SPIRxFull(hwAttrs->baseAddr) == false)
- {}
+ {
+ timeoutFlag = SPI_pollingXferTimeout_v0(&timeout,
+ &timeoutLoop,
+ object->waitTimeout);
+ if (timeoutFlag == (bool)true)
+ {
+ break;
+ }
+ }
if (intCode & SPI_INT_RX_OVERRUN)
{
object->transferErr = SPI_XFER_ERR_RXOR;
}
- if (object->readCountIdx)
+ if ((object->readCountIdx) && (timeoutFlag == (bool)false))
{
if (object->readBufIdx)
{
object->readCountIdx--;
}
+ timeoutFlag = SPI_pollingXferTimeout_v0(&timeout,
+ &timeoutLoop,
+ object->waitTimeout);
+
+ if ((object->readCountIdx != 0U) || (object->writeCountIdx != 0U))
+ {
+ if (timeoutFlag == (bool)true)
+ {
+ object->transferErr = SPI_XFER_ERR_TIMEOUT;
+ }
+ }
}
if (object->transferErr == SPI_XFER_ERR_NONE)
{
- transaction->status=SPI_TRANSFER_COMPLETED;
+ transaction->status = SPI_TRANSFER_COMPLETED;
+ }
+ else if (object->transferErr == SPI_XFER_ERR_TIMEOUT)
+ {
+ transaction->status = SPI_TRANSFER_TIMEOUT;
}
else
{
- transaction->status=SPI_TRANSFER_FAILED;
+ transaction->status = SPI_TRANSFER_FAILED;
}
}
}
/* store the SPI transfer mode (master or slave */
object->spiMode = params->mode;
- if(object->operMode == SPI_OPER_MODE_BLOCKING)
- {
- object->waitTimeout = params->transferTimeout;
- }
+ object->waitTimeout = params->transferTimeout;
if(ret_flag == 0U)
{
if (semStatus == SemaphoreP_TIMEOUT)
{
#ifdef SPI_DMA_ENABLE
- if (hwAttrs->dmaMode == TRUE)
- {
- SPIIntDisable(hwAttrs->baseAddr, SPI_INT_RX_OVERRUN |
- SPI_INT_TX_BITERR);
- }
- else
+ if (hwAttrs->dmaMode == TRUE)
+ {
+ SPIIntDisable(hwAttrs->baseAddr, SPI_INT_RX_OVERRUN |
+ SPI_INT_TX_BITERR);
+ }
+ else
#endif
- {
- SPIIntDisable(hwAttrs->baseAddr, SPI_INT_TX_EMPTY |
- SPI_INT_RX_FULL | SPI_INT_RX_OVERRUN | SPI_INT_TX_BITERR);
- }
- SPIIntStatusClear(hwAttrs->baseAddr, SPI_INT_RX_FULL | SPI_INT_DMA_ENABLE |
- SPI_INT_RX_OVERRUN | SPI_INT_TX_BITERR);
+ {
+ SPIIntDisable(hwAttrs->baseAddr, SPI_INT_TX_EMPTY |
+ SPI_INT_RX_FULL | SPI_INT_RX_OVERRUN | SPI_INT_TX_BITERR);
+ }
+ SPIIntStatusClear(hwAttrs->baseAddr,
+ SPI_INT_RX_FULL | SPI_INT_DMA_ENABLE |
+ SPI_INT_RX_OVERRUN | SPI_INT_TX_BITERR);
+
/* Transaction timed out */
- transaction->status=SPI_TRANSFER_TIMEOUT;
+ transaction->status = SPI_TRANSFER_TIMEOUT;
+ object->transferErr = SPI_XFER_ERR_TIMEOUT;
+
ret = (bool)false;
}
else
{
- ret = (bool)true;
+ if (object->operMode == SPI_OPER_MODE_POLLING)
+ {
+ /*
+ * Polling transaction status is set in SPI_primeTransfer_v0
+ */
+ if (transaction->status == SPI_TRANSFER_COMPLETED)
+ {
+ ret = (bool)true;
+ }
+ else
+ {
+ ret = (bool)false;
+ }
+ }
+ else
+ {
+ /* Callback transaction or interrupt/dma (no timeout) transaction */
+ ret = (bool)true;
+ }
}
}
} else {
diff --git a/src/v0/SPI_v0.h b/src/v0/SPI_v0.h
index 7e4bbf37aa70642e354b88a3d055c42274b47e7b..4d87dbc0cc3f05c4f2edaf5b0e69a6ca3046449c 100644 (file)
--- a/src/v0/SPI_v0.h
+++ b/src/v0/SPI_v0.h
/*
- * Copyright (c) 2015 - 2017, Texas Instruments Incorporated
+ * Copyright (c) 2015 - 2019, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
typedef enum spiXferErr_e {
SPI_XFER_ERR_NONE, /* No transfer error */
SPI_XFER_ERR_RXOR, /* Receiver overrun error */
- SPI_XFER_ERR_BE /* Bit error */
+ SPI_XFER_ERR_BE, /* Bit error */
+ SPI_XFER_ERR_TIMEOUT /* Transfer timeout error */
} spiXferErr;
/*!
diff --git a/src/v1/SPI_v1.c b/src/v1/SPI_v1.c
index af9cf83b4c006ac66b848b59aece0d7e680a659b..b9c2f2112305ff9b14893a77b1129a3dfe506780 100644 (file)
--- a/src/v1/SPI_v1.c
+++ b/src/v1/SPI_v1.c
*/
/*
- * Copyright (c) 2014-2017, Texas Instruments Incorporated
+ * Copyright (c) 2014-2019, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define MCSPI_TX_RX_FIFO_OFFSET (4U)
+#define MCSPI_POLLING_TIMEOUT_LOOP (1000U)
+
/* SPI functions */
static void SPI_close_v1(SPI_Handle handle);
static void SPI_init_v1(SPI_Handle handle);
@@ -695,6 +697,9 @@ static void MCSPI_primeTransfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *trans
SPI_v1_ChnCfg const *chnCfg;
uint32_t channelStatus = 0;
uint32_t intStatus;
+ uint32_t timeout;
+ uint32_t timeoutLoop;
+ bool xferFlag = true;
/* Get the pointer to the object and hwAttrs */
handle = mcHandle->handle;
@@ -753,36 +758,36 @@ static void MCSPI_primeTransfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *trans
McSPICSAssert(hwAttrs->baseAddr, chNum);
}
+ /* Initialize the timeout value and loop count in polling mode */
+ timeout = chObj->spiParams.transferTimeout;
+ timeoutLoop = MCSPI_POLLING_TIMEOUT_LOOP;
+
/* Polling mode transfer */
- while ((chObj->readCountIdx != 0) || (chObj->writeCountIdx != 0))
+ while (xferFlag)
{
channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
if ((SPI_MASTER == chObj->spiParams.mode) && (chObj->writeCountIdx != 0))
{
- while (0U == (channelStatus & CSL_MCSPI_CH0STAT_TXS_MASK))
+ if (0U != (channelStatus & CSL_MCSPI_CH0STAT_TXS_MASK))
{
- channelStatus = 0;
- channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
+ chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
+ chObj->spiParams.dataSize,
+ chObj->writeBufIdx,
+ chNum);
+ chObj->writeCountIdx--;
}
- chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
- chObj->spiParams.dataSize,
- chObj->writeBufIdx,
- chNum);
- chObj->writeCountIdx--;
}
if (chObj->readCountIdx != 0)
{
- while (0U == (channelStatus & CSL_MCSPI_CH0STAT_RXS_MASK))
+ if (0U != (channelStatus & CSL_MCSPI_CH0STAT_RXS_MASK))
{
- channelStatus = 0;
- channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
+ chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
+ chObj->spiParams.dataSize,
+ chObj->readBufIdx,
+ chNum);
+ chObj->readCountIdx--;
}
- chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
- chObj->spiParams.dataSize,
- chObj->readBufIdx,
- chNum);
- chObj->readCountIdx--;
}
if ((SPI_SLAVE == chObj->spiParams.mode) && (chObj->writeCountIdx != 0))
@@ -794,6 +799,34 @@ static void MCSPI_primeTransfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *trans
chObj->writeCountIdx--;
}
+
+ if ((chObj->readCountIdx != 0) || (chObj->writeCountIdx != 0))
+ {
+ if (timeout > 0U)
+ {
+ timeout--;
+ }
+ else
+ {
+ if (timeoutLoop == 0U)
+ {
+ /* Transfer timeout */
+ xferFlag = false;
+ transaction->status=SPI_TRANSFER_TIMEOUT;
+ }
+ else
+ {
+ timeoutLoop--;
+ timeout = chObj->spiParams.transferTimeout;
+ }
+ }
+ }
+ else
+ {
+ /* Transfer completed successfully */
+ xferFlag = false;
+ transaction->status=SPI_TRANSFER_COMPLETED;
+ }
}
if ((SPI_MASTER == chObj->spiParams.mode) &&
@@ -1429,15 +1462,40 @@ static bool MCSPI_transfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transactio
{
McSPICSDeAssert(hwAttrs->baseAddr, chNum);
}
- /* Transaction timed out */
+
+ /*
+ * Interrupt/dma (timeout) transaction
+ * returns timeout status
+ */
transaction->status=SPI_TRANSFER_TIMEOUT;
chObj->transaction = NULL;
ret_val = (bool)false;
}
else
{
- transaction->status = SPI_TRANSFER_COMPLETED;
- ret_val = (bool)true;
+ if (chObj->operMode == SPI_OPER_MODE_POLLING)
+ {
+ /*
+ * Polling transaction status is set in MCSPI_primeTransfer_v1
+ */
+ if (transaction->status == SPI_TRANSFER_COMPLETED)
+ {
+ ret_val = (bool)true;
+ }
+ else
+ {
+ ret_val = (bool)false;
+ }
+ }
+ else
+ {
+ /*
+ * Callback transaction or interrupt/dma (no timeout) transaction
+ * returns completed status
+ */
+ transaction->status = SPI_TRANSFER_COMPLETED;
+ ret_val = (bool)true;
+ }
}
}
}