AM263x MCU+ SDK  09.01.00
MCSPI Low Level Driver

Features Supported

  • Controller and Peripheral mode of operation
  • Per transfer selection of different channels/chip select
  • Non-blocking (Callback) transfers

Features NOT Supported

  • Default TX data feature is not supported in DMA mode.
  • In DMA mode, FIFO is not enabled.

Usage Overview

API Sequence

To use the MCSPI driver to send data over the SPI bus, the application calls the following APIs:

Initializing the MCSPI Driver

MCSPI_lld_init() must be called before any other MCSPI APIs. This function iterates till the channel count. This function uses mcspi handle to initialize each instance. Calling MCSPI_lld_init() a second time with the same handle previously passed to MCSPI_lld_init() will result in an error. You can, though, re-use the handle if the instance is closed via MCSPI_lld_deInit(). In DMA mode, MCSPI_lld_initDma() needs to be called instead of MCSPI_lld_init() to acquire and initialize mcspi instance. Please note that initializing MCSPI driver is taken care by the SysConfig generated code.

MCSPI Transfer Mode

The MCSPI driver supports three transfer modes of operation: Interrupt, Polling and DMA Mode. Interrupt and DMA mode, it supports only callback mode. Once a MCSPI driver is opened, the only way to change the operation mode is to close and re-open the MCSPI instance with the new transfer mode.

In callback mode, a MCSPI transaction functions asynchronously, which means that it does not block code execution. After a MCSPI transaction has been completed, the MCSPI driver calls a user-provided hook function. Callback mode is supported in the execution context of tasks and hardware interrupt routines.

In multichannel mode connected to multiple external devices, the MCSPI exchanges data with one MCSPI device at a time and FIFO is enabled per each channel at a time.

Important Usage Guidelines

  • The MCSPI protocol does not account for a built-in handshaking mechanism and neither does this driver. Therefore, when operating in MCSPI_MS_MODE_PERIPHERAL mode, the application must provide such a mechanism to ensure that the MCSPI peripheral is ready for the MCSPI controller. The MCSPI peripheral must call MCSPI_lld_readWrite() / MCSPI_lld_readWriteIntr() / MCSPI_lld_readWriteDma() before the controller starts transmitting. Some example application mechanisms could include:
    • Timed delays on the MCSPI controller to guarantee the MCSPI peripheral is ready for a MCSPI transaction.
    • A form of GPIO flow control from the peripheral to the MCSPI controller to notify the controller when ready.
  • In case of DMA mode, as R5F core is not Cache Coherent, Cache Writeback is required if R5F writes to the buffers. And before reading the buffers, application needs to invalidate those. Please refer MCSPI Loopback DMA LLD.

Example Usage

Include the below file to access the APIs

#include <kernel/dpl/MutexArmP.h>
#include <kernel/nortos/dpl/r5/HwiP_armv7r_vim.h>

Instance Open Example

int32_t status = MCSPI_STATUS_SUCCESS;
gMcspiHandle0 = &gMcspiObject[CONFIG_MCSPI0];
status = MCSPI_lld_init(gMcspiHandle0);

Instance Close Example

int32_t status = MCSPI_STATUS_SUCCESS;
status = MCSPI_lld_deInit(gMcspiHandle0);

Non-Blocking Transfer Example

uint32_t bufIndex;
uint32_t count;
uint32_t timeout = MCSPI_WAIT_FOREVER;
int32_t status = MCSPI_STATUS_SUCCESS;
MCSPI_ExtendedParams extendedParams;
/* Interrupt configuration and registration*/
intrNum = gConfigMcspi0InitObject[CONFIG_MCSPI0].intrNum;
gMcspiVimStsAddr = gVimBaseAddr + (0x404u + (((intrNum)>> 5) & 0xFu) * 0x20u);
gMcspiVimStsClrMask = 0x1u << ((intrNum) & 0x1Fu);
HwiP_setVecAddr(intrNum, (uintptr_t)&App_MCSPI_ISR);
HwiP_setPri(intrNum, gConfigMcspi0InitObject[CONFIG_MCSPI0].intrPriority);
HwiP_enableInt(intrNum);
if(status == MCSPI_STATUS_SUCCESS)
{
DebugP_log("\n[MCSPI] Loopback example started ...\r\n");
/* Memfill buffers */
for(bufIndex = 0U; bufIndex < APP_MCSPI_MSGSIZE; bufIndex++)
{
gMcspiTxBuffer[bufIndex] = bufIndex;
gMcspiRxBuffer[bufIndex] = 0U;
}
gMcspiObject[CONFIG_MCSPI0].transferMutex = &gMutexLockUnlock;
/* populate extended parameters */
extendedParams.channel = 0;
extendedParams.csDisable = TRUE;
extendedParams.dataSize = 32;
count = APP_MCSPI_MSGSIZE / (extendedParams.dataSize/8);
status = MCSPI_lld_readWriteIntr(gMcspiHandle0, \
gMcspiTxBuffer, \
&gMcspiRxBuffer, \
count, \
timeout, \
&extendedParams);
while(try_lock_mutex(gMcspiObject[CONFIG_MCSPI0].transferMutex) == MUTEX_ARM_LOCKED);
{
DebugP_assert(FALSE); /* MCSPI transfer failed!! */
}
else
{
/* Compare data */
for(bufIndex = 0U; bufIndex < APP_MCSPI_MSGSIZE; bufIndex++)
{
if(gMcspiTxBuffer[bufIndex] != gMcspiRxBuffer[bufIndex])
{
status = MCSPI_STATUS_FAILURE; /* Data mismatch */
DebugP_log("Data Mismatch at offset %d\r\n", bufIndex);
break;
}
}
}
}
/* Deregister IRQ */
HwiP_setVecAddr(intrNum, 0);
HwiP_setPri(intrNum, 15);
if(MCSPI_STATUS_SUCCESS == status)
{
DebugP_log("All tests have passed!!\r\n");
}
else
{
DebugP_log("Some tests have failed!!\r\n");
}

Non-Blocking Example transfer callback

void MCSPI_lld_transferCallback(void *args, uint32_t transferStatus)
{
unlock_mutex(gMcspiObject[CONFIG_MCSPI0].transferMutex);
}

Non-Blocking Example ISR CALL callback

static __attribute__((__section__(".text.hwi"), noinline, naked, target("arm"), aligned(4))) void App_MCSPI_ISR(void)
{
ISR_CALL_LEVEL_NONFLOAT_REENTRANT(MCSPI_lld_controllerIsr, \
gMcspiHandle0, \
intrNum, \
gMcspiVimStsAddr, \
gMcspiVimStsClrMask,
gVimBaseAddr);
}

API

APIs for MCSPI LLD

args
void * args
Definition: hsmclient_msg.h:4
MCSPI_WAIT_FOREVER
#define MCSPI_WAIT_FOREVER
Value to use when needing a timeout of infinity or wait forver until resource is available.
Definition: mcspi_lld.h:125
SystemP.h
MCSPI_lld_controllerIsr
void MCSPI_lld_controllerIsr(void *args)
This is the McSPI Controller ISR and can be used as IRQ handler in Controller mode.
MCSPI_STATUS_SUCCESS
#define MCSPI_STATUS_SUCCESS
Return status when the API execution was successful.
Definition: mcspi_lld.h:85
MCSPI_lld_readWriteIntr
int32_t MCSPI_lld_readWriteIntr(MCSPILLD_Handle hMcspi, void *txBuf, void *rxBuf, uint32_t count, uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
This API reads writes data from the McSPI instance in Interrupt mode.
SemaphoreP.h
MCSPI_TRANSFER_COMPLETED
#define MCSPI_TRANSFER_COMPLETED
Definition: mcspi_lld.h:191
DebugP_log
#define DebugP_log(format,...)
Function to log a string to the enabled console.
Definition: DebugP.h:225
MCSPI_lld_init
int32_t MCSPI_lld_init(MCSPILLD_Handle hMcspi)
This API Initializes the McSPI instance.
HwiP.h
HwiP_enableInt
void HwiP_enableInt(uint32_t intNum)
Enable a specific interrupt.
MCSPI_ExtendedParams
Data structure used with MCSPI_lld_read(), MCSPI_lld_readIntr(), MCSPI_lld_readDma(),...
Definition: mcspi_lld.h:535
mcspi_lld.h
MCSPI LLD Driver API/interface file.
MCSPI_lld_deInit
int32_t MCSPI_lld_deInit(MCSPILLD_Handle hMcspi)
This API De-Initializes the McSPI instance.
DebugP.h
DebugP_assert
#define DebugP_assert(expression)
Function to call for assert check.
Definition: DebugP.h:177
__attribute__
struct sockaddr __attribute__
HSM client / server message format struct.
MCSPI_STATUS_FAILURE
#define MCSPI_STATUS_FAILURE
Return status when the API execution was not successful due to a failure.
Definition: mcspi_lld.h:90