Tool/software:
I've been working on the AM263x and had discovered an issue with multi-channel mode for the MCSPI module:
- When sending a single 8-bit byte or 16-bit word in the TX buffer, everything would work
- When sending multiple bytes/words in the TX buffer, we would see CS toggle repeatedly during the transaction, causing it to fail
This was an issue because we have two IMU peripherals that are along this one SPI bus. After some digging in the MCSPI driver as well as the documentation, I discovered that
in single-channel mode, the CS pin is manually toggled at the beginning and end of every transaction, but this was not the case for multi-channel mode. From mcspi_v0_lld.c:
if(MCSPI_CH_MODE_SINGLE == hMcspiInit->chMode)
{
/* 3/4 pin mode applicable only in single channel mode.
* For multi-ch mode, CS is always controlled by HW during transfer */
As a workaround, I made changes to the mcspi driver to essentially treat multi-channel mode and single-channel mode as the same, as the only differences I could find between single and
multi-channel mode in the driver code was this manual CS toggle and a single register value.
Can someone let me know if this change is safe? From the testing I've done so far, I've seen no issues collecting data from both IMU peripherals at 800Hz using this workaround, but I'm still unsure
if this is something that can be changed safely or not.
Full diff of the change I made are below:
diff --git a/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/cslr_mcspi.h b/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/cslr_mcspi.h
index c2aaab84..809ce3c0 100644
--- a/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/cslr_mcspi.h
+++ b/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/cslr_mcspi.h
@@ -700,7 +700,7 @@ typedef struct {
#define CSL_MCSPI_MODULCTRL_SINGLE_MASK (0x00000001U)
#define CSL_MCSPI_MODULCTRL_SINGLE_SHIFT (0U)
#define CSL_MCSPI_MODULCTRL_SINGLE_RESETVAL (0x00000000U)
-#define CSL_MCSPI_MODULCTRL_SINGLE_MULTI (0x00000000U)
+#define CSL_MCSPI_MODULCTRL_SINGLE_MULTI (0x00000001U)
#define CSL_MCSPI_MODULCTRL_SINGLE_SINGLE (0x00000001U)
#define CSL_MCSPI_MODULCTRL_PIN34_MASK (0x00000002U)
diff --git a/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/lld/mcspi_v0_lld.c b/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/lld/mcspi_v0_lld.c
index 1a16e798..9ba140b7 100644
--- a/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/lld/mcspi_v0_lld.c
+++ b/mcu_plus_sdk_am263x_09_02_00_56/source/drivers/mcspi/v0/lld/mcspi_v0_lld.c
@@ -1694,7 +1694,7 @@ static int32_t MCSPI_transferControllerPoll(MCSPILLD_Handle hMcspi,
timeout = transaction->timeout;
/* Manual CS assert */
- if(MCSPI_CH_MODE_SINGLE == hMcspi->hMcspiInit->chMode)
+ if(MCSPI_CH_MODE_SINGLE == hMcspi->hMcspiInit->chMode || MCSPI_CH_MODE_MULTI == hMcspi->hMcspiInit->chMode)
{
if (chObj->csEnable == TRUE)
{
@@ -1821,7 +1821,6 @@ static int32_t MCSPI_transferControllerPoll(MCSPILLD_Handle hMcspi,
}
}
}
-
/* Check for Rx overflow or Tx underflow.
* Cancel the current transfer and return error.
*/
@@ -1853,7 +1852,7 @@ static void MCSPI_transferControllerIntr(MCSPILLD_Handle hMcspi,
CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQENABLE, chObj->intrMask);
/* Manual CS assert */
- if(MCSPI_CH_MODE_SINGLE == hMcspi->hMcspiInit->chMode)
+ if(MCSPI_CH_MODE_SINGLE == hMcspi->hMcspiInit->chMode || MCSPI_CH_MODE_MULTI == hMcspi->hMcspiInit->chMode)
{
if (chObj->csEnable == TRUE)
{
@@ -2218,7 +2217,7 @@ static void MCSPI_configInstance(MCSPILLD_Handle hMcspi)
{
regVal |= (hMcspiInit->chMode << CSL_MCSPI_MODULCTRL_SINGLE_SHIFT);
}
- if(MCSPI_CH_MODE_SINGLE == hMcspiInit->chMode)
+ if(MCSPI_CH_MODE_SINGLE == hMcspiInit->chMode || MCSPI_CH_MODE_MULTI == hMcspiInit->chMode)
{
/* 3/4 pin mode applicable only in single channel mode.
* For multi-ch mode, CS is always controlled by HW during transfer */
@@ -2806,7 +2805,7 @@ void MCSPI_stop(MCSPILLD_Handle hMcspi, MCSPI_ChObject *chObj, uint32_t chNum)
if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
{
/* Manual CS de-assert */
- if(MCSPI_CH_MODE_SINGLE == hMcspiInit->chMode)
+ if(MCSPI_CH_MODE_SINGLE == hMcspiInit->chMode || MCSPI_CH_MODE_MULTI == hMcspi->hMcspiInit->chMode)
{
if (chObj->csDisable == TRUE)
{