This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

PROCESSOR-SDK-AM64X: Bug in MCSPI_transferCallback

Part Number: PROCESSOR-SDK-AM64X

Hello, 

I can not ask questions anymore in this post: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1343348/processor-sdk-am64x-bug-in-mcspi_transfercallback/5125260#5125260

Do you have any news? Is it a bug? Do you plan to fix it?

Best regards,

Andrean

  • Hi Andrean,

    Thanks for your question.

    Yes the bug was identified and a commit was made internally.

    You can expect this fix to come in the next SDK release.

    Apart from this, I can share with you the files which have changed.

    They are shown in the attached image.


    mcspi_lld.h

    /*
     *  Copyright (C) 2023-24 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \defgroup DRV_MCSPI_LLD_MODULE APIs for MCSPI LLD
     *  \ingroup  DRV_MODULE
     *
     *  This module contains APIs to program and use the MCSPI LLD module. The APIs
     *  can be used by other drivers to get access to MCSPI and also by
     *  application to initiate data transfer operation.
     *
     *  @{
     */
    
    /**
     *  \file v0/lld/mcspi_lld.h
     *
     *  \brief MCSPI LLD Driver API/interface file.
     */
    
    #ifndef MCSPI_LLD_H_
    #define MCSPI_LLD_H_
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    #include <stdint.h>
    #include <stdbool.h>
    #include <drivers/hw_include/csl_types.h>
    #include <drivers/hw_include/cslr_mcspi.h>
    #include <drivers/hw_include/cslr.h>
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /*  pointer for DMA Handle  */
    typedef void *MCSPI_DmaHandle;
    /*  pointer for DMA Channel Config */
    typedef void *MCSPI_DmaChConfig;
    
    /* function pointer to get clock ticks */
    typedef uint32_t (*MCSPI_clockGet) (void);
    
    
    /** @name Return status
     */
    /**@{*/
    /**
     * \brief Return status when the API execution was successful
     */
    #define MCSPI_STATUS_SUCCESS         ((int32_t)0)
    
    /**
     * \brief Return status when the API execution was not successful due to a failure
     */
    #define MCSPI_STATUS_FAILURE         ((int32_t)-1)
    
    /**
     * \brief Return status when the API execution was not successful due to a time out
     */
    #define MCSPI_TIMEOUT                ((int32_t)-2)
    
    /**
     * \brief Return status when the API execution failed due invalid parameters
     */
    #define MCSPI_INVALID_PARAM          ((int32_t)-3)
    
    /**
     * \brief Return status when the API execution failed due to driver busy
     */
    #define MCSPI_STATUS_BUSY            ((int32_t)-4)
    
    /**
     * \brief Return status when the API execution failed due to invalid state
     */
    #define MCSPI_INVALID_STATE          ((int32_t)-5)
    
    /**@}*/
    
    /** @name Timeout values
     */
    /**@{*/
    /**
     * \brief Value to use when needing a timeout of zero or NO timeout, return immediately on resource not available.
     */
    #define MCSPI_NO_WAIT                ((uint32_t)0)
    
    /**
     * \brief Value to use when needing a timeout of infinity or wait forver until resource is available
     */
    #define MCSPI_WAIT_FOREVER           ((uint32_t)-1)
    /**@}*/
    
    /**@{*/
    /** @name MCSPI Driver states
     */
    /**
     * \brief MCSPI driver is in Reset State prior to driver init and post driver deinit
     */
    #define MCSPI_STATE_RESET            ((uint32_t)0U)
    
    /**
     * \brief MCSPI driver accepts runtime APIs only Ready State, otherwise return error
     */
    #define MCSPI_STATE_READY            ((uint32_t)1U)
    
    /**
     * \brief MCSPI driver is busy performing operation with peripherals, return error when APIs are invoked
     */
    #define MCSPI_STATE_BUSY             ((uint32_t)2U)
    
    /**
     * \brief MCSPI driver ran into error, returns error for all APIs other than deinit in this state
     */
    #define MCSPI_STATE_ERROR            ((uint32_t)3U)
    /**@}*/
    
    /**
     *  \anchor MCSPI_ChannelId
     *  \name Channel Id
     *
     *  Values used to determine the channel number used for McSPI
     *  communication. This determines which Chip Select (CS) line to use
     *
     *  @{
     */
    #define MCSPI_CHANNEL_0                 (0U)
    #define MCSPI_CHANNEL_1                 (1U)
    #define MCSPI_CHANNEL_2                 (2U)
    #define MCSPI_CHANNEL_3                 (3U)
    /** @} */
    
    /**
     *  \anchor MCSPI_OperatingMode
     *  \name Operating Mode
     *
     *  Values used to determine the McSPI driver operation.
     *
     *  @{
     */
    #define MCSPI_OPER_MODE_POLLED                 (0U)
    #define MCSPI_OPER_MODE_INTERRUPT              (1U)
    #define MCSPI_OPER_MODE_DMA                    (2U)
    /** @} */
    
    /** \brief Max number of channels/Chip Select (CS) supported */
    #define MCSPI_MAX_NUM_CHANNELS          (4U)
    
    /**
     *  \anchor MCSPI_TransferStatus
     *  \name Transfer Status Code
     *
     *  Status codes that are set by the MCSPI driver
     *
     *  @{
     */
    #define MCSPI_TRANSFER_COMPLETED        ((int32_t)0U)
    #define MCSPI_TRANSFER_STARTED          ((int32_t)1U)
    #define MCSPI_TRANSFER_CANCELLED        ((int32_t)2U)
    #define MCSPI_TRANSFER_FAILED           ((int32_t)3U)
    #define MCSPI_TRANSFER_CSN_DEASSERT     ((int32_t)4U)
    #define MCSPI_TRANSFER_TIMEOUT          ((int32_t)5U)
    /** @} */
    
    /**
     *  \anchor MCSPI_MsMode
     *  \name Modes of Operation
     *
     *  Definitions for various MCSPI modes of operation
     *
     *  The MCSPI driver operates in both controller and SPI peripheral modes.
     *  Logically, the implementation is identical, however the difference
     *  between these two modes is driven by hardware. The default mode is
     *  #MCSPI_MS_MODE_CONTROLLER, but can be set to peripheral mode by setting
     *  #MCSPI_OpenParams.msMode to #MCSPI_MS_MODE_PERIPHERAL in the parameters passed to
     *  #MCSPI_open().
     *
     *  @{
     */
    /** \brief The module generates the clock and CS */
    #define MCSPI_MS_MODE_CONTROLLER        (CSL_MCSPI_MODULCTRL_MS_MASTER)
    /** \brief The module receives the clock and CS */
    #define MCSPI_MS_MODE_PERIPHERAL        (CSL_MCSPI_MODULCTRL_MS_SLAVE)
    /** @} */
    
    /**
     *  \anchor MCSPI_FrameFormat
     *  \name Frame Format
     *
     *  Definitions for various SPI data frame formats
     *
     *  POL0 = SPICLK is held low during the INACTIVE state
     *  POL1 = SPICLK is held high during the INACTIVE state
     *
     *  PHA0 = Data are latched on odd-numbered edges of SPICLK
     *  PHA1 = Data are latched on even-numbered edges of SPICLK
     *
     *  @{
     */
    #define MCSPI_FF_POL0_PHA0              (0U)
    #define MCSPI_FF_POL0_PHA1              (1U)
    #define MCSPI_FF_POL1_PHA0              (2U)
    #define MCSPI_FF_POL1_PHA1              (3U)
    /** @} */
    
    
    /**
     *  \anchor MCSPI_CsPolarity
     *  \name Chip-select Polarity
     *  Type for SPI Chip Select Polarity and Clock Idle Level
     *
     *  @{
     */
    /** \brief SPIEN (CS) is held high during the ACTIVE state */
    #define MCSPI_CS_POL_HIGH               (CSL_MCSPI_CH0CONF_EPOL_ACTIVEHIGH)
    /** \brief SPIEN (CS) is held low during the ACTIVE state */
    #define MCSPI_CS_POL_LOW                (CSL_MCSPI_CH0CONF_EPOL_ACTIVELOW)
    /** @} */
    
    /**
     *  \anchor MCSPI_TrMode
     *  \name Transmit-Receive Modes
     *
     *  @{
     */
    #define MCSPI_TR_MODE_TX_RX             (CSL_MCSPI_CH0CONF_TRM_TRANSRECEI)
    #define MCSPI_TR_MODE_RX_ONLY           (CSL_MCSPI_CH0CONF_TRM_RECEIVONLY)
    #define MCSPI_TR_MODE_TX_ONLY           (CSL_MCSPI_CH0CONF_TRM_TRANSONLY)
    /** @} */
    
    /**
     *  \anchor MCSPI_InputSelect
     *  \name Input Select
     *
     *  @{
     */
    /** \brief Data line 0 (SPIDAT[0]) selected for reception */
    #define MCSPI_IS_D0                     (CSL_MCSPI_CH0CONF_IS_LINE0)
    /** \brief Data line 1 (SPIDAT[1]) selected for reception */
    #define MCSPI_IS_D1                     (CSL_MCSPI_CH0CONF_IS_LINE1)
    /** @} */
    
    /**
     *  \anchor MCSPI_TxEnable
     *  \name Transmission Enable for Data Line
     *
     *  @{
     */
    /** \brief Data line selected for transmission */
    #define MCSPI_DPE_ENABLE                (CSL_MCSPI_CH0CONF_DPE0_ENABLED)
    /** \brief No transmission on Data Line */
    #define MCSPI_DPE_DISABLE               (CSL_MCSPI_CH0CONF_DPE0_DISABLED)
    /** @} */
    
    /**
     *  \anchor MCSPI_SlvCsSelect
     *  \name Peripheral Chip-select Signal Select
     *
     *  @{
     */
    #define MCSPI_SLV_CS_SELECT_0           (CSL_MCSPI_CH0CONF_SPIENSLV_SPIEN0)
    #define MCSPI_SLV_CS_SELECT_1           (CSL_MCSPI_CH0CONF_SPIENSLV_SPIEN1)
    #define MCSPI_SLV_CS_SELECT_2           (CSL_MCSPI_CH0CONF_SPIENSLV_SPIEN2)
    #define MCSPI_SLV_CS_SELECT_3           (CSL_MCSPI_CH0CONF_SPIENSLV_SPIEN3)
    /** @} */
    
    /**
     *  \anchor MCSPI_SbPolarity
     *  \name Start-bit Polarity
     *
     *  @{
     */
    /** \brief SStart-bit polarity is held to 1 during MCSPI transfer */
    #define MCSPI_SB_POL_HIGH               (CSL_MCSPI_CH0CONF_SBPOL_HIGHLEVEL)
    /** \brief Start-bit polarity is held to 0 during MCSPI transfer */
    #define MCSPI_SB_POL_LOW                (CSL_MCSPI_CH0CONF_SBPOL_LOWLEVEL)
    /** @} */
    
    /**
     *  \anchor MCSPI_CsIdleTime
     *  \name Chip-select Idle Time
     *
     *  Values used to configure the chip select time control (TCS)
     *
     *  @{
     */
    /** \brief 0.5 clock cycles delay */
    #define MCSPI_TCS0_0_CLK                (CSL_MCSPI_CH0CONF_TCS0_ZEROCYCLEDLY)
    /** \brief 1.5 clock cycles delay */
    #define MCSPI_TCS0_1_CLK                (CSL_MCSPI_CH0CONF_TCS0_ONECYCLEDLY)
    /** \brief 2.5 clock cycles delay */
    #define MCSPI_TCS0_2_CLK                (CSL_MCSPI_CH0CONF_TCS0_TWOCYCLEDLY)
    /** \brief 3.5 clock cycles delay */
    #define MCSPI_TCS0_3_CLK                (CSL_MCSPI_CH0CONF_TCS0_THREECYCLEDLY)
    /** @} */
    
    /**
     *  \anchor MCSPI_ChMode
     *  \name Channel Mode
     *
     *  @{
     */
    /**
     *  \brief Only one channel will be used in controller mode. This should be used
     *  when CS is used in forced enable mode.
     */
    #define MCSPI_CH_MODE_SINGLE            (CSL_MCSPI_MODULCTRL_SINGLE_SINGLE)
    /** \brief More than one channel will be used in controller mode */
    #define MCSPI_CH_MODE_MULTI             (CSL_MCSPI_MODULCTRL_SINGLE_MULTI)
    /** @} */
    
    /**
     *  \anchor MCSPI_PinMode
     *  \name Pin Mode
     *
     *  @{
     */
    /**
     *  \brief SPIEN (CS) is not used. In this mode all related options to
     *  chip-select have no meaning.
     */
    #define MCSPI_PINMODE_3PIN              (CSL_MCSPI_MODULCTRL_PIN34_3PINMODE)
    #define MCSPI_PINMODE_4PIN              (CSL_MCSPI_MODULCTRL_PIN34_4PINMODE)
    /** @} */
    
    /**
     *  \anchor MCSPI_InitDelay
     *  \name Init Delay
     *
     *  Values used to enable initial delay for first transfer
     *
     *  @{
     */
    /** \brief No delay */
    #define MCSPI_INITDLY_0                 (CSL_MCSPI_MODULCTRL_INITDLY_NODELAY)
    /** \brief 4 SPI bus clock delays */
    #define MCSPI_INITDLY_4                 (CSL_MCSPI_MODULCTRL_INITDLY_4CLKDLY)
    /** \brief 8 SPI bus clock delays */
    #define MCSPI_INITDLY_8                 (CSL_MCSPI_MODULCTRL_INITDLY_8CLKDLY)
    /** \brief 16 SPI bus clock delays */
    #define MCSPI_INITDLY_16                (CSL_MCSPI_MODULCTRL_INITDLY_16CLKDLY)
    /** \brief 32 SPI bus clock delays */
    #define MCSPI_INITDLY_32                (CSL_MCSPI_MODULCTRL_INITDLY_32CLKDLY)
    /** @} */
    
    /** \brief McSPI error macro's*/
    #define MCSPI_ERROR_TX_UNDERFLOW    (0x00000001U)
    #define MCSPI_ERROR_RX_OVERFLOW     (0x00000002U)
    
    /** Maximuum Clock Divider supported */
    #define MCSPI_MAX_CLK_DIVIDER_SUPPORTED   (4096U)
    
    /* ========================================================================== */
    /*                       Advanced Macros & Typedefs                           */
    /* ========================================================================== */
    
    /** \brief Total length of FIFO for both TX/RX */
    #define MCSPI_FIFO_LENGTH           (64U)
    /**
     * \brief McSPI peripheral Rx FIFO is enabled
     */
    #define MCSPI_RX_FIFO_ENABLE         ((uint32_t) CSL_MCSPI_CH0CONF_FFER_FFENABLED \
                                          <<                                      \
                                          CSL_MCSPI_CH0CONF_FFER_SHIFT)
    
    /**
     * \brief McSPI peripheral Rx FIFO is disabled
     */
    #define MCSPI_RX_FIFO_DISABLE        ((uint32_t) CSL_MCSPI_CH0CONF_FFER_FFDISABLED \
                                          << CSL_MCSPI_CH0CONF_FFER_SHIFT)
    
    /**
     * \brief McSPI peripheral Tx FIFO is enabled
     */
    #define MCSPI_TX_FIFO_ENABLE         ((uint32_t) CSL_MCSPI_CH0CONF_FFEW_FFENABLED \
                                          << CSL_MCSPI_CH0CONF_FFEW_SHIFT)
    
    /**
     * \brief McSPI peripheral Tx FIFO is disabled
     */
    #define MCSPI_TX_FIFO_DISABLE        ((uint32_t) CSL_MCSPI_CH0CONF_FFEW_FFDISABLED \
                                          << CSL_MCSPI_CH0CONF_FFEW_SHIFT)
    /**
     *  \brief McSPI Register Offset for MCSPI_CHxCONF, MCSPI_CHxSTAT,
     *  MCSPI_CHxCTRL, MCSPI_TXx and MCSPI_RXx register set.
     */
    #define MCSPI_REG_OFFSET            (0x14U)
    /** \brief Base address of McSPI_CHCONF(x) */
    #define MCSPI_CHCONF(x)             ((uint32_t) CSL_MCSPI_CH0CONF +            \
                                         (uint32_t) ((uint32_t) MCSPI_REG_OFFSET * \
                                                     (uint32_t) (x)))
    /** \brief Base address of McSPI_CHSTAT(x) */
    #define MCSPI_CHSTAT(x)             ((uint32_t) CSL_MCSPI_CH0STAT +            \
                                         (uint32_t) ((uint32_t) MCSPI_REG_OFFSET * \
                                                     (uint32_t) (x)))
    /** \brief Base address of McSPI_CHCTRL(x) */
    #define MCSPI_CHCTRL(x)             ((uint32_t) CSL_MCSPI_CH0CTRL +            \
                                         (uint32_t) ((uint32_t) MCSPI_REG_OFFSET * \
                                                     (uint32_t) (x)))
    /** \brief Base address of McSPI_CHTX(x) */
    #define MCSPI_CHTX(x)               ((uint32_t) CSL_MCSPI_TX0 +                \
                                         (uint32_t) ((uint32_t) MCSPI_REG_OFFSET * \
                                                     (uint32_t) (x)))
    /** \brief Base address of McSPI_CHRX(x) */
    #define MCSPI_CHRX(x)               ((uint32_t) CSL_MCSPI_RX0 +                \
                                         (uint32_t) ((uint32_t) MCSPI_REG_OFFSET * \
                                                     (uint32_t) (x)))
    
    #define MCSPI_CLKD_MASK             (0x0FU)
    
    /** \brief Bit mask to clear all status bits */
    #define MCSPI_IRQSTATUS_CLEAR_ALL   (CSL_MCSPI_IRQSTATUS_EOW_MASK |            \
                                         CSL_MCSPI_IRQSTATUS_WKS_MASK |            \
                                         CSL_MCSPI_IRQSTATUS_RX3_FULL_MASK |       \
                                         CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK |  \
                                         CSL_MCSPI_IRQSTATUS_TX3_EMPTY_MASK |      \
                                         CSL_MCSPI_IRQSTATUS_RX2_FULL_MASK |       \
                                         CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK |  \
                                         CSL_MCSPI_IRQSTATUS_TX2_EMPTY_MASK |      \
                                         CSL_MCSPI_IRQSTATUS_RX1_FULL_MASK |       \
                                         CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK |  \
                                         CSL_MCSPI_IRQSTATUS_TX1_EMPTY_MASK |      \
                                         CSL_MCSPI_IRQSTATUS_RX0_OVERFLOW_MASK |   \
                                         CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK |       \
                                         CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK |  \
                                         CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK)
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    /**
     *  \brief Data structure used with #MCSPI_transfer()
     *
     *  It indicates how many \ref MCSPI_FrameFormat frames are sent and received
     *  from the buffers pointed to txBuf and rxBuf.
     *  The args variable is an user-definable argument which gets passed to the
     *  #MCSPI_CallbackFxn when the SPI driver is in #MCSPI_TRANSFER_MODE_CALLBACK.
     */
    typedef struct
    {
        uint32_t                channel;
        /**< [IN] Channel number (chip select) to use.
          *  Valid value from 0 to (#MCSPI_MAX_NUM_CHANNELS - 1) */
        uint32_t                csDisable;
        /**< [IN] TRUE/FALSE to disable CS(chip select)
          * If it is set to TRUE, CS is de-asseted automatically at the end of the
          * transfer. If user wants to chain more transfers under one CS pulse,
          * user needs to set it to FALSE for each transfer and for the last
          * transfer, user needs to set to TRUE to de-assert CS */
        uint32_t                dataSize;
        /**< [IN] MCSPI data frame size in bits - valid values: 4 bits to 32 bits
         *
         *   The dataSize value determines the element types of txBuf and rxBuf.
         *   If the dataSize is from 4 to 8 bits, the driver assumes the
         *   data buffers are of type uint8_t (unsigned char).
         *   If the dataSize is from 8 to 16 bits, the driver assumes the
         *   data buffers are of type uint16_t (unsigned short).
         *   If the dataSize is greater than 16 bits, the driver assumes the
         *   data buffers are uint32_t (unsigned long).
         */
        uint32_t                count;
        /**< [IN] Number of frames for this transaction. This should in word size
         *   length and not in bytes */
        void                   *txBuf;
        /**< [IN] void * to a buffer with data to be transmitted.
         *
         *   If txBuf is NULL, the driver sends MCSPI frames with all data set to
         *   the default value specified by #MCSPI_ChConfig.defaultTxData.
         *
         *   The size of the buffer should be count * #MCSPI_Transaction.dataSize
         *   in bytes rounded to nearest byte boundary.
         *   For example if #MCSPI_Transaction.dataSize is 12 bits, then size of
         *   buffers should be count * 2 bytes.
         */
        void                   *rxBuf;
        /**< [IN] void * to a buffer to receive data.
         *
         *   If rxBuf is NULL, the driver discards all MCSPI frames received.
         *
         *   The size of the buffer is similar to txBuf as explained above.
         */
        void                   *args;
        /**< [IN] Argument to be passed to the callback function */
        uint32_t                timeout;
        /**< Timeout for this transaction in units of system ticks */
        uint32_t                status;
        /**< [OUT] \ref MCSPI_TransferStatus code set by #MCSPI_transfer() */
    } MCSPI_Transaction;
    
    /**
     *  \brief Data structure used with #MCSPI_lld_read(), #MCSPI_lld_readIntr(),
     *         #MCSPI_lld_readDma(), #MCSPI_lld_write(), #MCSPI_lld_writeIntr,
     *         #MCSPI_lld_writeDma, #MCSPI_lld_readWrite(), #MCSPI_lld_readWriteIntr(),
     *         #MCSPI_lld_readWriteDma().
     *         MCSPI ExtendedParams to be used in case, one's don't want to use
     *         default parameters, else pass NULL.
     *
     */
    typedef struct MCSPI_ExtendedParams_s
    {
        uint32_t                channel;
        /**< [IN] Channel number (chip select) to use.
          *  Valid value from 0 to (#MCSPI_MAX_NUM_CHANNELS - 1) */
        uint32_t                csDisable;
        /**< [IN] TRUE/FALSE to disable CS(chip select)
          * If it is set to TRUE, CS is de-asseted automatically at the end of the
          * transfer. If user wants to chain more transfers under one CS pulse,
          * user needs to set it to FALSE for each transfer and for the last
          * transfer, user needs to set to TRUE to de-assert CS */
        uint32_t               dataSize;
        /**< [IN] MCSPI data frame size in bits - valid values: 4 bits to 32 bits
         *
         *   The dataSize value determines the element types of txBuf and rxBuf.
         *   If the dataSize is from 4 to 8 bits, the driver assumes the
         *   data buffers are of type uint8_t (unsigned char).
         *   If the dataSize is from 8 to 16 bits, the driver assumes the
         *   data buffers are of type uint16_t (unsigned short).
         *   If the dataSize is greater than 16 bits, the driver assumes the
         *   data buffers are uint32_t (unsigned long).
         */
        void                   *args;
        /**< [IN] Argument to be passed to the callback function */
    } MCSPI_ExtendedParams;
    
    /**
     *  \brief MCSPI configuration parameters for the channel
     *
     *  MCSPI channel parameters used with the #MCSPI_chConfig() call.
     *  Default values for these parameters are set using MCSPI_ChConfig_init().
     *
     *  If NULL is passed for the parameters, #MCSPI_chConfig() uses default
     *  parameters.
     *
     *  \sa #MCSPI_ChConfig_init()
     */
    typedef struct
    {
        uint32_t                chNum;
        /**< Channel number. Refer \ref MCSPI_ChannelId */
        uint32_t                frameFormat;
        /**< MCSPI frame format. Refer \ref MCSPI_FrameFormat */
        uint32_t                bitRate;
        /**< MCSPI bit rate in Hz */
        uint32_t                csPolarity;
        /**< Polarity of the chip select signal. Refer \ref MCSPI_CsPolarity */
        uint32_t                trMode;
        /**< Channel transmit/receive mode. Refer \ref MCSPI_TrMode */
        uint32_t                inputSelect;
        /**< Input Select - D0 or D1. Refer \ref MCSPI_InputSelect */
        uint32_t                dpe0;
        /**< Transmission enable/disable for D0. Refer \ref MCSPI_TxEnable */
        uint32_t                dpe1;
        /**< Transmission enable/disable for D1. Refer \ref MCSPI_TxEnable */
        uint32_t                slvCsSelect;
        /**< MCSPI peripheral select signal detection. Applicable for Channel 0 and
         *   in peripheral mode only. Refer \ref MCSPI_SlvCsSelect */
        uint32_t                startBitEnable;
        /**< Start bit D/CX added before SPI transfer. Polarity is defined by
         *   start bit level (below) */
        uint32_t                startBitPolarity;
        /**< Start-bit polarity used when startBitEnable is TRUE
         *   Refer \ref MCSPI_SbPolarity */
        uint32_t                turboEnable;
        /**< Enable Turbo Mode */
        uint32_t                csIdleTime;
        /**< Chip select time control. Refer \ref MCSPI_CsIdleTime.
         *   This is applicable only in controller mode */
        uint32_t                defaultTxData;
        /**< Default TX data to use when NULL pointer is provided for TX buffer.
         *   The actual data that is transmitted depends on the dataSize field */
        uint32_t                txFifoTrigLvl;
        /**< TX FIFO trigger level in bytes */
        uint32_t                rxFifoTrigLvl;
        /**< RX FIFO trigger level in bytes */
    } MCSPI_ChConfig;
    
    /* ========================================================================== */
    /*                      Function pointers Declarations                        */
    /* ========================================================================== */
    
    /**
     *  \brief  The definition of a transfer completion callback function used by
     *  the SPI driver when used in #MCSPI_TRANSFER_MODE_CALLBACK
     *
     *  \param void*          void pointer
     *  \param transferStatus transfer Status
     */
    typedef void (*MCSPI_transferCallbackFxn) (void *args, uint32_t transferStatus);
    
    /**
     *  \brief  The definition of a error callback function used by the SPI driver
     *  when used in #MCSPI_TRANSFER_MODE_CALLBACK
     *
     *  \param void*          void pointer
     *  \param transferStatus transfer Status
     */
    typedef void (*MCSPI_errorCallbackFxn) (void *args, uint32_t transferStatus);
    
    /* ========================================================================== */
    /*                  Internal/Private Structure Declarations                   */
    /* ========================================================================== */
    
    /**
     *  \brief MCSPI channel object
     */
    typedef struct
    {
        /*
         * User parameters
         */
        MCSPI_ChConfig  *chCfg;
        /**< Channel configuration as provided by user */
        uint32_t        dmaChConfigNum;
        /**< Index of dmaChConfig in DMA Config Array */
    
        /*
         * State variables
         */
        uint32_t                isOpen;
        /**< Flag to indicate whether the instance is opened already */
        uint32_t                csDisable;
        /**< Flag to indicate disable chip select */
        uint32_t                csEnable;
        /**< Flag to indicate enable chip select */
        uint8_t                *curTxBufPtr;
        /**< Current TX buffer pointer */
        uint8_t                *curRxBufPtr;
        /**< Current RX buffer pointer */
        uint32_t                curTxWords;
        /**< Number of words transmitted. We need seperate counters for TX/RX
         *   because when FIFO in enabled, TX writes happen in advance where as
         *   RX will happen on actual received data. */
        uint32_t                curRxWords;
        /**< Number of words received */
    
        /*
         * MCSPI derived variables
         */
        uint8_t                 bufWidthShift;
        /**< Width of buffer in bytes - used for accessing the TX/RX buffer.
         *   When dataWidth <= 8,           bufWidth = uint8_t  (1 byte - 0 shift)
         *   When dataWidth > 8  && <= 16,  bufWidth = uint16_t (2 bytes - 1 shift)
         *   When dataWidth > 16 && <= 32,  bufWidth = uint32_t (4 bytes - 2 shift)
         */
        uint32_t                dataWidthBitMask;
        /**< Data width mask depending on SPI word size */
        uint32_t                effTxFifoDepth;
        /**< Effective TX FIFO depth in words - depends on dataWidth */
        uint32_t                effRxFifoDepth;
        /**< Effective RX FIFO depth in words - depends on dataWidth */
        uint32_t                intrMask;
        /**< Interrupt mask to be used for enabling / checking interrupts. */
        MCSPI_DmaChConfig       dmaChCfg;
        /**< DMA Configuration for each channel. */
        uint32_t                chConfRegVal;
        /**< Channel Control Register Value. */
        uint32_t                chCtrlRegVal;
        /**< SYST Register Value. */
        uint32_t                systRegVal;
    } MCSPI_ChObject;
    
    /**
     *  \brief MCSPI driver initialization object
     */
    typedef struct
    {
        uint32_t                            inputClkFreq;
        /**< Module input clock frequency */
        uint32_t                            intrNum;
        /**< Peripheral interrupt number */
        uint32_t                            operMode;
        /**< Driver operating mode */
        uint8_t                             intrPriority;
        /**< Interrupt priority */
        uint32_t                            chMode;
        /**< Channel mode: Single or multi channel. Refer \ref MCSPI_ChMode  */
        uint32_t                            pinMode;
        /**< Pin mode. Refer \ref MCSPI_PinMode */
        uint32_t                            initDelay;
        /**< Initial SPI delay for first transfer. Refer \ref MCSPI_InitDelay */
        uint32_t                            multiWordAccess;
        /**< Flag to enable/disable multi word access */
        uint32_t                            msMode;
        /**< Controller or Peripheral mode. Refer \ref MCSPI_MsMode */
        uint32_t                            chEnabled[MCSPI_MAX_NUM_CHANNELS];
        /**< Enable/Disable Flag for all McSPI channels */
        MCSPI_ChObject                      chObj[MCSPI_MAX_NUM_CHANNELS];
        /**< Channel object */
        MCSPI_DmaHandle                     mcspiDmaHandle;
        /**< DMA Handle */
        MCSPI_clockGet                      clockP_get;
        /* clock usec to tick */
        MCSPI_transferCallbackFxn           transferCallbackFxn;
        /**< Callback function pointer */
        MCSPI_errorCallbackFxn              errorCallbackFxn;
        /**< Callback function pointer */
    } MCSPILLD_InitObject, *MCSPILLD_InitHandle;
    
    /**
     *  \brief MCSPI driver object
     */
    typedef struct
    {
        uint32_t                baseAddr;
        /**< Peripheral base address */
    
        /*
         * User parameters
         */
        uint32_t                 state;
        /**< Driver state variable */
        void                    *transferMutex;
        /**< Transfer Sync Sempahore - to signal transfer completion */
        MCSPILLD_InitHandle      hMcspiInit;
        /**< [IN] Initialization parameters of McSPI instance */
        uint32_t                 errorFlag;
        /**< Variable to store different McSPI errors */
    
        /*
         * Transfer parameters
         */
        uint32_t                transferChannel;
        /**< [IN] Channel number (chip select) to use for transfers */
        uint32_t                transferCsDisable;
        /**< [IN] TRUE/FALSE to disable CS(chip select) for transfers */
        uint32_t                transferDataSize;
        /**< [IN] MCSPI data frame size in bits - valid values: 4 bits to 32 bits */
        MCSPI_Transaction       transaction;
        /**< Pointer to current transaction */
        void*                   args;
        /**< Pointer to be used by application to store miscellaneous data.*/
    } MCSPILLD_Object, *MCSPILLD_Handle;
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    /* Low level HW functions */
    void MCSPI_reset(uint32_t baseAddr);
    void MCSPI_clearAllIrqStatus(uint32_t baseAddr);
    void MCSPI_stop(MCSPILLD_Handle hMcspi, MCSPI_ChObject *chObj, uint32_t chNum);
    void MCSPI_setChDataSize(uint32_t baseAddr, MCSPI_ChObject *chObj,
                             uint32_t dataSize, uint32_t csDisable);
    
    static inline void MCSPI_intrStatusClear(const MCSPI_ChObject *chObj,
                                             uint32_t baseAddr, uint32_t intFlags)
    {
        /* Clear the SSB bit in the MCSPI_SYST register. */
        CSL_REG32_WR(baseAddr + CSL_MCSPI_SYST, chObj->systRegVal);
        /* Clear the interrupt status. */
        CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQSTATUS, intFlags);
    }
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    /**
     *  \brief  This API Initializes the McSPI instance
     *
     *  \param  hMcspi      Handle to the McSPI instance used
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_init(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  This API Initializes the McSPI instance in DMA Mode
     *
     *  \param  hMcspi      Handle to the McSPI instance used
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_initDma(MCSPILLD_Handle hMcspi);
    /**
     *  \brief  This API De-Initializes the McSPI instance
     *
     *  \param  hMcspi      Handle to the McSPI instance used
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_deInit(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  This API De-Initializes the McSPI instance in DMA mode
     *
     *  \param  hMcspi      Handle to the McSPI instance used
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_deInitDma(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  This API writes data to the McSPI instance in Polling mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  txBuf            Pointer to write data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          Write timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_write(MCSPILLD_Handle hMcspi, void *txBuf, uint32_t count, uint32_t timeout,
                            const MCSPI_ExtendedParams *extendedParams);
    
    /**
     *  \brief  This API writes data to the McSPI instance in Interrupt mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  txBuf            Pointer to write data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          write timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_writeIntr(MCSPILLD_Handle hMcspi, void *txBuf, uint32_t count, uint32_t timeout,
                                const MCSPI_ExtendedParams *extendedParams);
    
    /**
     *  \brief  This API writes data to the McSPI instance in DMA mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  txBuf            Pointer to write data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          write timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_writeDma(MCSPILLD_Handle hMcspi, void * txBuf, uint32_t count,
                               uint32_t timeout, const MCSPI_ExtendedParams *extendedParams);
    
    /**
     *  \brief  This API reads data from the McSPI instance in Polling mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  rxBuf            Pointer to Read data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          Read timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_read(MCSPILLD_Handle hMcspi, void * rxBuf, uint32_t count, uint32_t timeout,
                           const MCSPI_ExtendedParams *extendedParams);
    
    /**
     *  \brief  This API reads data from the McSPI instance in Interrupt mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  rxBuf            Pointer to Read data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          Read timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_readIntr(MCSPILLD_Handle hMcspi, void * rxBuf, uint32_t count, uint32_t timeout,
                               const MCSPI_ExtendedParams *extendedParams);
    
    /**
     *  \brief  This API reads data from the McSPI instance in DMA mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  rxBuf            Pointer to Read data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          Read timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     * extendedParams
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_readDma(MCSPILLD_Handle hMcspi, void * rxBuf, uint32_t count,
                              uint32_t timeout, const MCSPI_ExtendedParams *extendedParams);
    /**
     *  \brief  This API reads writes data from the McSPI instance in polling mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  txBuf            Pointer to write data buffer
     *  \param  rxBuf            Pointer to Read data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          Read write timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     */
    int32_t MCSPI_lld_readWrite(MCSPILLD_Handle hMcspi, void *txBuf, void *rxBuf, uint32_t count,
                                uint32_t timeout, const MCSPI_ExtendedParams *extendedParams);
    /**
     *  \brief  This API reads writes data from the McSPI instance in Interrupt mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  txBuf            Pointer to write data buffer
     *  \param  rxBuf            Pointer to Read data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          Read write timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     */
    int32_t MCSPI_lld_readWriteIntr(MCSPILLD_Handle hMcspi, void *txBuf, void *rxBuf, uint32_t count,
                                    uint32_t timeout, const MCSPI_ExtendedParams *extendedParams);
    /**
     *  \brief  This API reads writes data from the McSPI instance in DMA mode.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *  \param  txBuf            Pointer to write data buffer
     *  \param  rxBuf            Pointer to Read data buffer
     *  \param  count            Number of frames for this transaction
     *  \param  timeout          Read write timeout value
     *  \param  extendedParams   Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     */
    int32_t MCSPI_lld_readWriteDma(MCSPILLD_Handle hMcspi, void *txBuf, void *rxBuf, uint32_t count,
                                   uint32_t timeout, const MCSPI_ExtendedParams *extendedParams);
    
    /**
     *  \brief  This API cancels current McSPI transfer
     *
     *  \param  hMcspi          Handle to the McSPI instance used
     *
     *  \return Mcspi Status    Status of current mcspi transaction
     *
     */
    int32_t MCSPI_lld_readWriteCancel(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  This API cancels current McSPI transfer in DMA mode
     *
     *  \param  hMcspi          Handle to the McSPI instance used
     *
     *  \return Mcspi Status    Status of current mcspi transaction
     *
     */
    int32_t MCSPI_lld_readWriteDmaCancel(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  This API transfers data from the McSPI instance in Polling mode.
     *
     *  \param  hMcspi          Handle to the McSPI instance used
     *  \param  transaction     Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_transfer(MCSPILLD_Handle hMcspi, MCSPI_Transaction *transaction);
    
    /**
     *  \brief  This API reads data from the McSPI instance in Interrupt mode.
     *
     *  \param  hMcspi          Handle to the McSPI instance used
     *  \param  transaction     Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_transferIntr(MCSPILLD_Handle hMcspi, MCSPI_Transaction *transaction);
    
    /**
     *  \brief  This API reads data from the McSPI instance in DMA mode.
     *
     *  \param  hMcspi          Handle to the McSPI instance used
     *  \param  transaction     Pointer to structure that contains the transfer data.
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_transferDma(MCSPILLD_Handle hMcspi, MCSPI_Transaction *transaction);
    
    /**
     *  \brief  This is the McSPI Controller ISR and can be used as IRQ handler in Controller mode.
     *
     *  \param  args      Argument to the ISR.
     *
     */
    void MCSPI_lld_controllerIsr(void* args);
    
    /**
     *  \brief  This is the McSPI Peripheral ISR and can be used as IRQ handler in Peripheral mode.
     *
     *  \param  args      Argument to the ISR.
     *
     */
    void MCSPI_lld_peripheralIsr(void* args);
    
    /**
     *  \brief  This API returns the driver state.
     *
     *  \param  hMcspi           Handle to the McSPI instance used
     *
     */
    int32_t MCSPI_lld_getState(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  This API cancels current McSPI transfer
     *
     *  \param  hMcspi          Handle to the McSPI instance used
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_transferCancel(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  This API cancels current McSPI transfer in DMA mode
     *
     *  \param  hMcspi          Handle to the McSPI instance used
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     */
    int32_t MCSPI_lld_transferDmaCancel(MCSPILLD_Handle hMcspi);
    
    /**
     *  \brief  Function to initialize the #MCSPI_ChConfig struct to its defaults
     *
     *  \param  chConfig    Pointer to #MCSPI_ChConfig structure for
     *                      initialization
     */
    static inline void MCSPI_lld_ChConfig_init(MCSPI_ChConfig *chConfig);
    
    /**
     *  \brief  Function to initialize the #MCSPI_Transaction struct to its defaults
     *
     *  \param  trans       Pointer to #MCSPI_Transaction structure for
     *                      initialization
     */
    static inline void MCSPI_lld_Transaction_init(MCSPI_Transaction *trans);
    
    /**
     *  \brief  Function to get base address of MCSPI instance of a particular
     *          handle.
     *
     *  \param  handle      #MCSPILLD_Handle returned from #MCSPI_open()
     *
     *  \sa     #MCSPI_open
     */
    uint32_t MCSPI_lld_getBaseAddr(MCSPILLD_Handle handle);
    
    /**
     *  \brief  Function to re-configure Effective FIFO Words.
     *
     *  \param  handle          #MCSPILLD_Handle returned from #MCSPI_open()
     *  \param  chNum           Channel used for communication.
     *  \param  numWordsRxTx    Number of words to transfer
     *
     *  \return #MCSPI_STATUS_SUCCESS if successful; else error on failure
     *
     *  \sa     #MCSPI_open
     */
    int32_t MCSPI_lld_reConfigFifo(MCSPILLD_Handle handle,
                                   uint32_t chNum,
                                   uint32_t numWordsRxTx);
    
    /**
     * \brief  This API will return the buffer width in bytes based on dataSize.
     *
     *
     * \param  dataSize         MCSPI data frame size in bits - valid values: 4 bits to 32 bits
     *
     * \return bufWidthShift    Width of buffer in bytes - used for accessing the TX/RX buffer.
     *                          When dataWidth <= 8,          (1 byte - 0 shift)
     *                          When dataWidth > 8  && <= 16, (2 bytes - 1 shift)
     *                          When dataWidth > 16 && <= 32, (4 bytes - 2 shift)
     *
     *
     *  \sa    #MCSPI_open
     **/
    static inline uint8_t MCSPI_getBufWidthShift(uint32_t dataSize);
    
    /**
     * \brief  This API will return the status of the McSPI channel currently in
     *         use.
     *
     * \param  baseAddr        Memory Address of the McSPI instance used.
     * \param  chNum           Channel used for communication.\n
     *
     *         'chNum' can take the following values.\n
     *         MCSPI_CHANNEL_n - Channel n is used for communication.\n
     *
     * \return This API will return the status of the McSPI channel status
     *         register.
     *         User can use the following macros to check the status \n
     *         MCSPI_CH_STAT_RXS_FULL - Receiver register is full \n
     *         MCSPI_CH_STAT_TXS_EMPTY - Transmitter register is full \n
     *         MCSPI_CH_STAT_EOT - End of transfer status \n
     *         MCSPI_CH_TXFFE - FIFO transmit buffer empty status \n
     *         MCSPI_CH_TXFFF - FIFO transmit buffer full status \n
     *         MCSPI_CH_RXFFE - FIFO receive buffer empty status \n
     *         MCSPI_CH_RXFFF - FIFO receive buffer full status \n
     *
     *  \sa    #MCSPI_open
     **/
    static inline uint32_t MCSPI_readChStatusReg(uint32_t baseAddr, uint32_t chNum);
    
    /**
     * \brief This API returns Channel control register value.
     *
     * \param  baseAddr       Memory Address of the McSPI instance used.
     * \param  chNum          Channel number of the McSPI instance used.
     *
     * \return Channel control register value.
     *
     *  \sa    #MCSPI_open
     **/
    static inline uint32_t MCSPI_readChCtrlReg(uint32_t baseAddr, uint32_t chNum);
    
    /**
     * \brief This API sets Channel control register value.
     *
     * \param  baseAddr       Memory Address of the McSPI instance used.
     * \param  chNum          Channel number of the McSPI instance used.
     * \param  regVal         register value to set in channel control register.
     *
     *  \sa    #MCSPI_open
     **/
    static inline void MCSPI_writeChCtrlReg(uint32_t baseAddr, uint32_t chNum,
                           uint32_t regVal);
    
    /**
     * \brief This API returns Channel Config register value.
     *
     * \param  baseAddr       Memory Address of the McSPI instance used.
     * \param  chNum          Channel number of the McSPI instance used.
     *
     * \return Channel Config register value.
     *
     *  \sa    #MCSPI_open
     **/
    static inline uint32_t MCSPI_readChConf(uint32_t baseAddr, uint32_t chNum);
    
    /**
     * \brief This API sets Channel Config register value.
     *
     * \param  baseAddr       Memory Address of the McSPI instance used.
     * \param  chNum          Channel number of the McSPI instance used.
     * \param  regVal         register value to set in channel Config register.
     *
     *  \sa    #MCSPI_open
     **/
    static inline void MCSPI_writeChConfReg(uint32_t baseAddr, uint32_t chNum,
                           uint32_t regVal);
    
    /**
     * \brief  This API will put the data on to the McSPI Channel
     *         transmit register.
     *
     * \param  baseAddr        Memory Address of the McSPI instance used.
     * \param  txData          32 bit data sent by the user which is put on
     *                         to the MCSPI_TX register.
     * \param  chNum           Channel number of the McSPI instance used.\n
     *
     *         'chNum' can take the following values.\n
     *         MCSPI_CHANNEL_n - Channel n is used for communication.\n
     *
     *         For chNum n can range from 0-3.\n
     *
     *  \sa    #MCSPI_open
     **/
    static inline void MCSPI_writeTxDataReg(uint32_t baseAddr,
                                            uint32_t txData,
                                            uint32_t chNum);
    
    /**
     * \brief  This API will enable/disable the Tx FIFOs of McSPI peripheral.
     *
     * \param  baseAddr        Memory Address of the McSPI instance used.
     * \param  chNum           Channel number of the McSPI instance used.\n
     * \param  enableFlag      Flag to enable/diable FIFO transmit mode.
     *
     *         'enableFlag' can take the following values.\n
     *         MCSPI_TX_FIFO_ENABLE - Enables the receiver FIFO of McSPI.\n
     *         MCSPI_TX_FIFO_DISABLE - Disables the receiver FIFO of McSPI.\n
     *
     *         'chNum' can take the following values.\n
     *         MCSPI_CHANNEL_n - Channel n is used for communication.\n
     *
     *         For chNum n can range from 0-3.\n
     *
     * \note:  Enabling FIFO is restricted to only 1 channel.
     *  \sa    #MCSPI_open
     **/
    static inline void MCSPI_enableTxFIFO(uint32_t baseAddr, uint32_t chNum,
                                          uint32_t enableFlag);
    
    /**
     * \brief  This API will enable/disable the Rx FIFOs of McSPI peripheral.
     *
     * \param  baseAddr        Memory Address of the McSPI instance used.
     * \param  chNum           Channel number of the McSPI instance used.\n
     * \param  enableFlag      Flag to enable/diable FIFO receive mode.
     *
     *         'enableFlag' can take the following values.\n
     *         MCSPI_RX_FIFO_ENABLE - Enables the receiver FIFO of McSPI.\n
     *         MCSPI_RX_FIFO_DISABLE - Disables the receiver FIFO of McSPI.\n
     *
     *         'chNum' can take the following values.\n
     *         MCSPI_CHANNEL_n - Channel n is used for communication.\n
     *
     *         For chNum n can range from 0-3.\n
     *
     * \note:  Enabling FIFO is restricted to only 1 channel.
     *  \sa    #MCSPI_open
     **/
    static inline void MCSPI_enableRxFIFO(uint32_t baseAddr, uint32_t chNum,
                                          uint32_t enableFlag);
    
    /**
     * \brief  This API will return the data present in the MCSPI_RX register.
     *
     * \param  baseAddr        Memory Address of the McSPI instance used.
     * \param  chNum           Channel number of the McSPI instance used.
     *
     *         'chNum' can take the following values.\n
     *         MCSPI_CHANNEL_n - Channel n is used for communication.\n
     *
     *         For chNum n can range from 0-3.\n
     *
     *  \sa    #MCSPI_open
     *
     * \return This API will return the data received in the MCSPI_RX register.
     **/
    static inline uint32_t MCSPI_readRxDataReg(uint32_t baseAddr,
                                               uint32_t chNum);
    
    /**
     * \brief  This API will set the data width in the channel config register.
     *
     * \param  baseAddr        Memory Address of the McSPI instance used.
     * \param  chNum           Channel number of the McSPI instance used.
     * \param  dataWidth        MCSPI data frame width in bits.
     *
     *         'chNum' can take the following values.\n
     *         MCSPI_CHANNEL_n - Channel n is used for communication.\n
     *
     *         For chNum n can range from 0-3.\n
     *         For dataWidth valid values: 4 bits to 32 bits
     *
     *  \sa    #MCSPI_open
     *
     **/
    static inline void MCSPI_setDataWidth(uint32_t baseAddr, uint32_t chNum,
                                          uint32_t dataWidth);
    
    /* ========================================================================== */
    /*                       Static Function Definitions                          */
    /* ========================================================================== */
    
    static inline void MCSPI_lld_ChConfig_init(MCSPI_ChConfig *chConfig)
    {
        if(chConfig != NULL)
        {
            chConfig->chNum             = MCSPI_CHANNEL_0;
            chConfig->frameFormat       = MCSPI_FF_POL0_PHA0;
            chConfig->bitRate           = 1000000U;
            chConfig->csPolarity        = MCSPI_CS_POL_LOW;
            chConfig->trMode            = MCSPI_TR_MODE_TX_RX;
            chConfig->inputSelect       = MCSPI_IS_D1;
            chConfig->dpe0              = MCSPI_DPE_ENABLE;
            chConfig->dpe1              = MCSPI_DPE_DISABLE;
            chConfig->slvCsSelect       = MCSPI_SLV_CS_SELECT_0;
            chConfig->startBitEnable    = FALSE;
            chConfig->startBitPolarity  = MCSPI_SB_POL_LOW;
            chConfig->csIdleTime        = MCSPI_TCS0_0_CLK;
            chConfig->defaultTxData     = 0x00000000U;
        }
    }
    
    static inline void MCSPI_lld_Transaction_init(MCSPI_Transaction *trans)
    {
        if(trans != NULL)
        {
            trans->channel   = 0U;
            trans->csDisable = TRUE;
            trans->dataSize  = 8U;
            trans->count     = 0U;
            trans->txBuf     = NULL;
            trans->rxBuf     = NULL;
            trans->args      = NULL;
            trans->timeout   = MCSPI_WAIT_FOREVER;
        }
    }
    
    static inline uint8_t MCSPI_getBufWidthShift(uint32_t dataSize)
    {
        uint8_t bufWidthShift = 0U;
    
        if(dataSize <= 8U)
        {
            bufWidthShift = 0U;
        }
        else if(dataSize <= 16U)
        {
            bufWidthShift = 1U;
        }
        else
        {
            bufWidthShift = 2U;
        }
    
        return bufWidthShift;
    }
    
    static inline uint32_t MCSPI_readChStatusReg(uint32_t baseAddr, uint32_t chNum)
    {
        /* Return the status from MCSPI_CHSTAT register. */
        return (CSL_REG32_RD(baseAddr + MCSPI_CHSTAT(chNum)));
    }
    
    static inline uint32_t MCSPI_readChCtrlReg(uint32_t baseAddr, uint32_t chNum)
    {
        return CSL_REG32_RD(baseAddr + MCSPI_CHCTRL(chNum));
    }
    
    static inline void MCSPI_writeChCtrlReg(uint32_t baseAddr, uint32_t chNum,
                                            uint32_t regVal)
    {
        CSL_REG32_WR(baseAddr + MCSPI_CHCTRL(chNum), regVal);
    }
    
    static inline uint32_t MCSPI_readChConf(uint32_t baseAddr, uint32_t chNum)
    {
        return CSL_REG32_RD(baseAddr + MCSPI_CHCONF(chNum));
    }
    
    static inline void MCSPI_writeChConfReg(uint32_t baseAddr, uint32_t chNum,
                                            uint32_t regVal)
    {
        CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chNum), regVal);
    }
    
    static inline void MCSPI_writeTxDataReg(uint32_t baseAddr,
                                            uint32_t txData,
                                            uint32_t chNum)
    {
        /* Load the MCSPI_TX register with the data to be transmitted */
        CSL_REG32_WR(baseAddr + MCSPI_CHTX(chNum), txData);
    }
    
    static inline void MCSPI_enableTxFIFO(uint32_t baseAddr,
                                          uint32_t chNum,
                                          uint32_t enableFlag)
    {
        /* Set the FFEW field with user sent value. */
        CSL_REG32_FINS(
            baseAddr + MCSPI_CHCONF(chNum),
            MCSPI_CH0CONF_FFEW,
            enableFlag >> CSL_MCSPI_CH0CONF_FFEW_SHIFT);
    }
    
    static inline void MCSPI_enableRxFIFO(uint32_t baseAddr,
                                          uint32_t chNum,
                                          uint32_t enableFlag)
    {
        /* Set the FFER field with the user sent value. */
        CSL_REG32_FINS(
            baseAddr + MCSPI_CHCONF(chNum),
            MCSPI_CH0CONF_FFER,
            enableFlag >> CSL_MCSPI_CH0CONF_FFER_SHIFT);
    }
    
    static inline uint32_t MCSPI_readRxDataReg(uint32_t baseAddr, uint32_t chNum)
    {
        /* Return the data present in the MCSPI_RX register. */
        return (CSL_REG32_RD(baseAddr + MCSPI_CHRX(chNum)));
    }
    
    static inline void MCSPI_setDataWidth(uint32_t baseAddr, uint32_t chNum,
                                          uint32_t dataWidth)
    {
        uint32_t regVal;
    
        regVal = CSL_REG32_RD(baseAddr + MCSPI_CHCONF(chNum));
        CSL_FINS(regVal, MCSPI_CH0CONF_WL, (dataWidth - 1U));
        CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chNum), regVal);
    }
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* #ifndef MCSPI_LLD_H_ */
    
    /** @} */


    mcspi_v0_lld.c

    /*
     *  Copyright (C) 2023-24 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file mcspi_v0_lld.c
     *
     *  \brief File containing MCSPI Driver APIs implementation for version V0.
     *
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    /* This is needed for memset/memcpy */
    #include <string.h>
    #include <drivers/mcspi/v0/lld/mcspi_lld.h>
    #include <drivers/mcspi/v0/lld/dma/mcspi_dma.h>
    #include <drivers/soc.h>
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    /* Driver internal functions */
    static void MCSPI_initiateLastChunkTransfer(MCSPILLD_Handle hMcspi,
                                                MCSPI_ChObject *chObj,
                                                const MCSPI_Transaction *transaction);
    
    static inline void MCSPI_fifoWrite(uint32_t baseAddr,
                                       MCSPI_ChObject *chObj,
                                       uint32_t transferLength);
    
    static inline void MCSPI_fifoRead(uint32_t baseAddr,
                                      MCSPI_ChObject *chObj,
                                      uint32_t transferLength);
    
    static inline void MCSPI_fifoReadMultiWord(uint32_t baseAddr,
                                               MCSPI_ChObject *chObj,
                                               uint32_t transferLength);
    
    static inline void MCSPI_fifoWriteMultiWord(uint32_t baseAddr,
                                               MCSPI_ChObject *chObj,
                                               uint32_t transferLength);
    
    static uint32_t MCSPI_getDataWidthBitMask(uint32_t dataWidth);
    static uint32_t Spi_mcspiGetRxMask(uint32_t csNum);
    static uint32_t Spi_mcspiGetTxMask(uint32_t csNum);
    static void MCSPI_setClkConfig(uint32_t baseAddr,
                                   uint32_t chNum,
                                   uint32_t inputClkFreq,
                                   uint32_t bitRate);
    
    static inline uint8_t *MCSPI_fifoWrite8(uint32_t  baseAddr,
                                            uint32_t  chNum,
                                            uint8_t  *bufPtr,
                                            uint32_t  transferLength);
    
    static inline uint16_t *MCSPI_fifoWrite16(uint32_t  baseAddr,
                                              uint32_t  chNum,
                                              uint16_t *bufPtr,
                                              uint32_t  transferLength);
    
    static inline uint32_t *MCSPI_fifoWrite32(uint32_t  baseAddr,
                                              uint32_t  chNum,
                                              uint32_t *bufPtr,
                                              uint32_t  transferLength);
    
    static inline uint8_t *MCSPI_fifoRead8(uint32_t  baseAddr,
                                           uint32_t  chNum,
                                           uint8_t  *bufPtr,
                                           uint32_t  transferLength,
                                           uint32_t  dataWidthBitMask);
    
    static inline uint16_t *MCSPI_fifoRead16(uint32_t  baseAddr,
                                             uint32_t  chNum,
                                             uint16_t  *bufPtr,
                                             uint32_t  transferLength,
                                             uint32_t  dataWidthBitMask);
    
    static inline uint32_t *MCSPI_fifoRead32(uint32_t  baseAddr,
                                             uint32_t  chNum,
                                             uint32_t  *bufPtr,
                                             uint32_t  transferLength,
                                             uint32_t  dataWidthBitMask);
    
    static inline void MCSPI_fifoWriteDefault(uint32_t baseAddr,
                                              uint32_t chNum,
                                              uint32_t defaultTxData,
                                              uint32_t transferLength);
    
    static inline void MCSPI_fifoReadDiscard(uint32_t baseAddr,
                                             uint32_t chNum,
                                             uint32_t transferLength);
    
    static inline int32_t MCSPI_lld_isOperModeValid(uint32_t operMode);
    static inline int32_t MCSPI_lld_isChModeValid(uint32_t chMode);
    static inline int32_t MCSPI_lld_isPinModeValid(uint32_t pinMode);
    static inline int32_t MCSPI_lld_isInitDelayValid(uint32_t initDelay);
    static inline int32_t MCSPI_lld_isMsModeValid(uint32_t msMode);
    static inline int32_t MCSPI_lld_isDataSizeValid(uint32_t dataSize);
    static inline int32_t MCSPI_lld_isHandleValid(MCSPI_DmaHandle handle);
    static inline int32_t MCSPI_lld_isParameterValid(uint32_t handleParameters);
    static inline int32_t MCSPI_lld_isChannelValid(uint32_t channel);
    static inline int32_t MCSPI_lld_isChCfgValid(const MCSPI_ChConfig *chCfg);
    static int32_t MCSPI_lld_chConfig(MCSPILLD_Handle hMcspi,
                                       const MCSPI_ChConfig *chCfg,
                                       uint32_t chCnt);
    
    static uint32_t MCSPI_continueTxRx(MCSPILLD_Handle hMcspi,
                                       MCSPI_ChObject *chObj,
                                       const MCSPI_Transaction *transaction);
    
    static int32_t MCSPI_transferControllerPoll(MCSPILLD_Handle hMcspi,
                                       MCSPI_ChObject *chObj,
                                       const MCSPI_Transaction *transaction);
    
    static void MCSPI_transferControllerIntr(MCSPILLD_Handle hMcspi,
                                             MCSPI_ChObject *chObj);
    
    static uint32_t MCSPI_continuePeripheralTxRx(MCSPILLD_Handle hMcspi,
                                       MCSPI_ChObject *chObj,
                                       const MCSPI_Transaction *transaction);
    
    static int32_t MCSPI_transferPeripheralPoll(MCSPILLD_Handle hMcspi,
                                       MCSPI_ChObject *chObj,
                                       const MCSPI_Transaction *transaction);
    
    static void MCSPI_transferPeripheralIntr(MCSPILLD_Handle hMcspi,
                                             MCSPI_ChObject *chObj);
    
    static void MCSPI_configInstance(MCSPILLD_Handle hMcspi);
    static void MCSPI_setChConfig(MCSPILLD_Handle hMcspi, MCSPI_ChObject *chObj);
    static int32_t MCSPI_checkChConfig(MCSPILLD_Object *obj,
                                       const MCSPI_ChConfig *chCfg);
    
    static void MCSPI_setFifoConfig(MCSPILLD_Handle hMcspi,
                                    MCSPI_ChObject *chObj,
                                    uint32_t baseAddr,
                                    uint32_t numWordsTxRx);
    
    static void MCSPI_setPeripheralFifoConfig(MCSPI_ChObject *chObj,
                                              uint32_t baseAddr,
                                              uint32_t numWordsTxRx);
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    int32_t MCSPI_lld_init(MCSPILLD_Handle hMcspi)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        uint32_t               chCnt;
        MCSPILLD_InitHandle    hMcspiInit;
        const MCSPI_ChConfig   *chCfg;
    
        if((hMcspi != NULL) && (hMcspi->hMcspiInit != NULL))
        {
            if(hMcspi->state != MCSPI_STATE_RESET)
            {
                status = MCSPI_INVALID_STATE;
            }
        }
        else
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            hMcspi->state = MCSPI_STATE_BUSY;
            hMcspiInit = hMcspi->hMcspiInit;
    
            /* Check the MCSPI Input parameters */
            status =  MCSPI_lld_isBaseAddrValid(hMcspi->baseAddr);
            status += MCSPI_lld_isParameterValid(hMcspiInit->inputClkFreq);
            status += MCSPI_lld_isOperModeValid(hMcspiInit->operMode);
            status += MCSPI_lld_isChModeValid(hMcspiInit->chMode);
            status += MCSPI_lld_isPinModeValid(hMcspiInit->pinMode);
            status += MCSPI_lld_isInitDelayValid(hMcspiInit->initDelay);
            status += MCSPI_lld_isMsModeValid(hMcspiInit->msMode);
    
            if(status != MCSPI_STATUS_SUCCESS)
            {
                status = MCSPI_INVALID_PARAM;
            }
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            /* Configure the MCSPI instance parameters */
            MCSPI_configInstance(hMcspi);
    
            /* Channel configuration */
            for(chCnt = 0U; chCnt < MCSPI_MAX_NUM_CHANNELS; chCnt++)
            {
                if(hMcspiInit->chEnabled[chCnt] == TRUE)
                {
                    chCfg = hMcspiInit->chObj[chCnt].chCfg;
    
                    status =  MCSPI_lld_isChCfgValid(chCfg);
                    status += MCSPI_lld_isChannelValid(chCfg->chNum);
    
                    if(MCSPI_STATUS_SUCCESS == status)
                    {
                        status += MCSPI_lld_chConfig(hMcspi,
                                    hMcspiInit->chObj[chCnt].chCfg,
                                    chCnt);
                    }
                }
            }
            if(status != MCSPI_STATUS_SUCCESS)
            {
                status = MCSPI_INVALID_PARAM;
            }
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            hMcspi->state = MCSPI_STATE_READY;
        }
        else
        {
            /* Free-up resources in case of error */
            (void)MCSPI_lld_deInit(hMcspi);
        }
    
        return status;
    }
    
    int32_t MCSPI_lld_initDma(MCSPILLD_Handle hMcspi)
    {
        uint32_t                   chCnt;
        MCSPILLD_InitHandle        hMcspiInit;
        const MCSPI_ChConfig      *chCfg;
        int32_t  status =          MCSPI_STATUS_SUCCESS;
    
        if((hMcspi != NULL) && (hMcspi->hMcspiInit != NULL))
        {
            if(hMcspi->state != MCSPI_STATE_RESET)
            {
                status = MCSPI_INVALID_STATE;
            }
        }
        else
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            hMcspi->state = MCSPI_STATE_BUSY;
            hMcspiInit = hMcspi->hMcspiInit;
    
            /* Check the MCSPI Input parameters */
            status =  MCSPI_lld_isBaseAddrValid(hMcspi->baseAddr);
            status += MCSPI_lld_isParameterValid(hMcspiInit->inputClkFreq);
            status += MCSPI_lld_isHandleValid(hMcspiInit->mcspiDmaHandle);
            status += MCSPI_lld_isOperModeValid(hMcspiInit->operMode);
            status += MCSPI_lld_isChModeValid(hMcspiInit->chMode);
            status += MCSPI_lld_isPinModeValid(hMcspiInit->pinMode);
            status += MCSPI_lld_isInitDelayValid(hMcspiInit->initDelay);
            status += MCSPI_lld_isMsModeValid(hMcspiInit->msMode);
    
            if(status != MCSPI_STATUS_SUCCESS)
            {
                status = MCSPI_INVALID_PARAM;
            }
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            status = MCSPI_lld_dmaInit(hMcspiInit->mcspiDmaHandle);
            /* Configure the MCSPI instance parameters */
            MCSPI_configInstance(hMcspi);
    
            /* Channel configuration */
            for(chCnt = 0U; chCnt < MCSPI_MAX_NUM_CHANNELS; chCnt++)
            {
                if(hMcspiInit->chEnabled[chCnt] == TRUE)
                {
                    chCfg = hMcspiInit->chObj[chCnt].chCfg;
    
                    status =  MCSPI_lld_isChCfgValid(chCfg);
                    status += MCSPI_lld_isChannelValid(chCfg->chNum);
    
                    if(MCSPI_STATUS_SUCCESS == status)
                    {
                        status += MCSPI_lld_chConfig(hMcspi, chCfg, chCnt);
                        status += MCSPI_lld_dmaChInit(hMcspi, chCnt);
                    }
                }
            }
    
            if(status == MCSPI_STATUS_SUCCESS)
            {
                hMcspi->state = MCSPI_STATE_READY;
            }
            if((status == MCSPI_STATUS_FAILURE) || (status == MCSPI_INVALID_PARAM))
            {
                /* Free-up resources in case of error */
                (void)MCSPI_lld_deInitDma(hMcspi);
            }
        }
    
        return status;
    }
    
    int32_t MCSPI_lld_deInit(MCSPILLD_Handle hMcspi)
    {
        int32_t             status = MCSPI_STATUS_SUCCESS;
        uint32_t            baseAddr;
    
        if(NULL != hMcspi)
        {
            baseAddr      = hMcspi->baseAddr;
            hMcspi->state = MCSPI_STATE_BUSY;
    
            /* Reset MCSPI */
            MCSPI_reset(baseAddr);
    
            hMcspi->state = MCSPI_STATE_RESET;
        }
        else
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        return status;
    }
    
    int32_t MCSPI_lld_deInitDma(MCSPILLD_Handle hMcspi)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        uint32_t               baseAddr;
        uint32_t               chCnt;
        MCSPILLD_InitHandle    hMcspiInit;
    
        if(NULL != hMcspi)
        {
            baseAddr      = hMcspi->baseAddr;
            hMcspi->state = MCSPI_STATE_BUSY;
            hMcspiInit    = hMcspi->hMcspiInit;
    
            /* Reset MCSPI */
            MCSPI_reset(baseAddr);
    
            for(chCnt = 0U; chCnt < MCSPI_MAX_NUM_CHANNELS; chCnt++)
            {
                if(hMcspiInit->chEnabled[chCnt] == TRUE)
                {
                    status += MCSPI_lld_dmaDeInit(hMcspi,
                                                hMcspiInit->chObj[chCnt].chCfg,
                                                chCnt);
                }
            }
    
            hMcspi->state = MCSPI_STATE_RESET;
        }
        else
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        return status;
    }
    
    int32_t MCSPI_lld_write(MCSPILLD_Handle hMcspi, void *txBuf, uint32_t count,
                            uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPILLD_InitHandle    hMcspiInit;
        MCSPI_ChObject        *chObj;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
    
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->count   = count;
                transaction->timeout = timeout;
                transaction->txBuf   = txBuf;
    
                status =  MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if (MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = (uint8_t *) transaction->txBuf;
            chObj->curRxBufPtr = NULL;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
            {
                /* Enable FIFO*/
                MCSPI_setFifoConfig(hMcspi, chObj, baseAddr, transaction->count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
                status = MCSPI_transferControllerPoll(hMcspi, chObj, transaction);
            }
            else
            {
                /* Enable FIFO*/
                MCSPI_setPeripheralFifoConfig(chObj, baseAddr, count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
                status = MCSPI_transferPeripheralPoll(hMcspi, chObj, transaction);
            }
    
            if(status == MCSPI_TIMEOUT)
            {
                status = MCSPI_TRANSFER_TIMEOUT;
            }
            else if ((status == MCSPI_TRANSFER_CANCELLED) && (hMcspi->errorFlag != 0U))
            {
                status = MCSPI_TRANSFER_FAILED;
            }
            else
            {
                /* success case */
                status  = MCSPI_TRANSFER_COMPLETED;
            }
    
            hMcspi->state = MCSPI_STATE_READY;
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_writeIntr(MCSPILLD_Handle hMcspi, void *txBuf, uint32_t count, uint32_t timeout,
                                const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPILLD_InitHandle    hMcspiInit;
        MCSPI_ChObject        *chObj;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->count   = count;
                transaction->timeout = timeout;
                transaction->txBuf   = txBuf;
    
                status =  MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = (uint8_t *) transaction->txBuf;
            chObj->curRxBufPtr = NULL;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
            {
                /* Enable FIFO*/
                MCSPI_setFifoConfig(hMcspi,chObj, baseAddr, transaction->count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
                MCSPI_transferControllerIntr(hMcspi, chObj);
            }
            else
            {
                /* Enable FIFO*/
                MCSPI_setPeripheralFifoConfig(chObj, baseAddr, count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
                MCSPI_transferPeripheralIntr(hMcspi, chObj);
            }
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_writeDma(MCSPILLD_Handle hMcspi, void *txBuf, uint32_t count, uint32_t timeout,
                               const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t status =       MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPI_ChObject        *chObj;
        MCSPILLD_InitHandle    hMcspiInit;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
    
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->count   = count;
                transaction->timeout = timeout;
                transaction->txBuf   = txBuf;
    
                status =  MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if (MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = (uint8_t *) transaction->txBuf;
            chObj->curRxBufPtr = NULL;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            status = MCSPI_lld_dmaTransfer(hMcspi, chObj, transaction);
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_read(MCSPILLD_Handle hMcspi, void *rxBuf, uint32_t count,
                           uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPILLD_InitHandle    hMcspiInit;
        MCSPI_ChObject        *chObj;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
    
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->count   = count;
                transaction->timeout = timeout;
                transaction->rxBuf   = rxBuf;
    
                status  = MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if (MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = NULL;
            chObj->curRxBufPtr = (uint8_t *) transaction->rxBuf;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
            {
                /* Enable FIFO*/
                MCSPI_setFifoConfig(hMcspi,chObj, baseAddr, transaction->count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
                status = MCSPI_transferControllerPoll(hMcspi, chObj, transaction);
            }
            else
            {
                /* Enable FIFO*/
                MCSPI_setPeripheralFifoConfig(chObj, baseAddr, count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
                status = MCSPI_transferPeripheralPoll(hMcspi, chObj, transaction);
            }
    
            if(status == MCSPI_TIMEOUT)
            {
                status = MCSPI_TRANSFER_TIMEOUT;
            }
            else if ((status == MCSPI_TRANSFER_CANCELLED) && (hMcspi->errorFlag != 0U))
            {
                status = MCSPI_TRANSFER_FAILED;
            }
            else
            {
                /* success case */
                status  = MCSPI_TRANSFER_COMPLETED;
            }
    
            hMcspi->state = MCSPI_STATE_READY;
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_readIntr(MCSPILLD_Handle hMcspi, void *rxBuf, uint32_t count,
                               uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPILLD_InitHandle    hMcspiInit;
        MCSPI_ChObject        *chObj;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
    
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->count   = count;
                transaction->timeout = timeout;
                transaction->rxBuf   = rxBuf;
    
                status  = MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if (MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = NULL;
            chObj->curRxBufPtr = (uint8_t *) transaction->rxBuf;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
            {
                /* Enable FIFO*/
                MCSPI_setFifoConfig(hMcspi,chObj, baseAddr, transaction->count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
                MCSPI_transferControllerIntr(hMcspi, chObj);
            }
            else
            {
                /* Enable FIFO*/
                MCSPI_setPeripheralFifoConfig(chObj, baseAddr, count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
                MCSPI_transferPeripheralIntr(hMcspi, chObj);
            }
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_readDma(MCSPILLD_Handle hMcspi, void *rxBuf, uint32_t count,
                              uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t status =       MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPI_ChObject        *chObj;
        MCSPILLD_InitHandle    hMcspiInit;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
    
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->count   = count;
                transaction->timeout = timeout;
                transaction->rxBuf   = rxBuf;
    
                status = MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if (MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = NULL;
            chObj->curRxBufPtr = (uint8_t *) transaction->rxBuf;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            status = MCSPI_lld_dmaTransfer(hMcspi, chObj, transaction);
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_readWrite(MCSPILLD_Handle hMcspi, void *txBuf, void *rxBuf, uint32_t count,
                                uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t status =       MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPILLD_InitHandle    hMcspiInit;
        MCSPI_ChObject        *chObj;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
    
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->timeout = timeout;
                transaction->count   = count;
                transaction->txBuf   = txBuf;
                transaction->rxBuf   = rxBuf;
    
                status = MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = (uint8_t *) transaction->txBuf;
            chObj->curRxBufPtr = (uint8_t *) transaction->rxBuf;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
            {
                /* Enable FIFO*/
                MCSPI_setFifoConfig(hMcspi,chObj, baseAddr, transaction->count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
                status = MCSPI_transferControllerPoll(hMcspi, chObj, transaction);
            }
            else
            {
                /* Enable FIFO*/
                MCSPI_setPeripheralFifoConfig(chObj, baseAddr, count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
                status = MCSPI_transferPeripheralPoll(hMcspi, chObj, transaction);
            }
    
            if(status == MCSPI_TIMEOUT)
            {
                status = MCSPI_TRANSFER_TIMEOUT;
            }
            else if ((status == MCSPI_TRANSFER_CANCELLED) && (hMcspi->errorFlag != 0U))
            {
                status = MCSPI_TRANSFER_FAILED;
            }
            else
            {
                /* success case */
                status  = MCSPI_TRANSFER_COMPLETED;
            }
    
            hMcspi->state = MCSPI_STATE_READY;
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_readWriteIntr(MCSPILLD_Handle hMcspi, void *txBuf, void *rxBuf, uint32_t count,
                                    uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPILLD_InitHandle    hMcspiInit;
        MCSPI_ChObject        *chObj;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->timeout = timeout;
                transaction->count   = count;
                transaction->txBuf   = txBuf;
                transaction->rxBuf   = rxBuf;
    
                status = MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status = MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = (uint8_t *) transaction->txBuf;
            chObj->curRxBufPtr = (uint8_t *) transaction->rxBuf;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
            {
                /* Enable FIFO */
                MCSPI_setFifoConfig(hMcspi,chObj, baseAddr, transaction->count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
                MCSPI_transferControllerIntr(hMcspi, chObj);
            }
            else
            {
                /* Enable FIFO */
                MCSPI_setPeripheralFifoConfig(chObj, baseAddr, count);
                MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
                MCSPI_transferPeripheralIntr(hMcspi, chObj);
            }
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_readWriteDma(MCSPILLD_Handle hMcspi, void *txBuf, void *rxBuf, uint32_t count,
                                   uint32_t timeout, const MCSPI_ExtendedParams *extendedParams)
    {
        int32_t                status = MCSPI_STATUS_SUCCESS;
        MCSPI_Transaction     *transaction;
        uint32_t               baseAddr, chNum;
        MCSPILLD_InitHandle    hMcspiInit;
        MCSPI_ChObject        *chObj;
    
        /* Check parameters */
        if((NULL == hMcspi) || (NULL == hMcspi->hMcspiInit))
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            transaction = &hMcspi->transaction;
    
            /* Check if any transaction is in progress */
            if(hMcspi->state == MCSPI_STATE_READY)
            {
                hMcspi->state = MCSPI_STATE_BUSY;
                /* Initialize transaction with default parameters */
                MCSPI_lld_Transaction_init(transaction);
    
                if(extendedParams != NULL)
                {
                    transaction->channel   = extendedParams->channel;
                    transaction->dataSize  = extendedParams->dataSize;
                    transaction->csDisable = extendedParams->csDisable;
                    transaction->args      = extendedParams->args;
                }
    
                baseAddr             = hMcspi->baseAddr;
                hMcspiInit           = hMcspi->hMcspiInit;
                transaction->timeout = timeout;
                transaction->count   = count;
                transaction->txBuf   = txBuf;
                transaction->rxBuf   = rxBuf;
    
                status = MCSPI_lld_isParameterValid(count);
                status += MCSPI_lld_isParameterValid(timeout);
                status += MCSPI_lld_isChannelValid(transaction->channel);
                status += MCSPI_lld_isDataSizeValid(transaction->dataSize);
                if(status != MCSPI_STATUS_SUCCESS)
                {
                    status = MCSPI_INVALID_PARAM;
                }
    
                /* Check if the channel is configured */
                if(TRUE != hMcspiInit->chObj[transaction->channel].isOpen)
                {
                    /* Channel not configured */
                    status += MCSPI_TRANSFER_FAILED;
                }
            }
            else
            {
                status = MCSPI_STATUS_BUSY;
            }
        }
    
        if (MCSPI_STATUS_SUCCESS == status)
        {
            /* Reset counter and other params */
            chNum = transaction->channel;
            chObj = &hMcspiInit->chObj[chNum];
            chObj->curTxBufPtr = (uint8_t *) transaction->txBuf;
            chObj->curRxBufPtr = (uint8_t *) transaction->rxBuf;
            chObj->curTxWords  = 0U;
            chObj->curRxWords  = 0U;
    
            /* Initialize channel dataSize */
            MCSPI_setChDataSize(baseAddr, chObj, transaction->dataSize,
                                transaction->csDisable);
    
            status = MCSPI_lld_dmaTransfer(hMcspi, chObj, transaction);
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_readWriteCancel(MCSPILLD_Handle hMcspi)
    {
        int32_t             status = MCSPI_STATUS_SUCCESS;
        uint32_t            chNum;
        MCSPI_ChObject     *chObj;
    
        /* Check parameters */
        if (NULL == hMcspi)
        {
            status = MCSPI_INVALID_PARAM;
        }
        else
        {
            /* Check if any transaction is in progress */
            if(MCSPI_STATE_BUSY == hMcspi->state)
            {
                chNum = hMcspi->transaction.channel;
                chObj = &hMcspi->hMcspiInit->chObj[chNum];
    
                /* Stop MCSPI Channel */
                MCSPI_stop(hMcspi, chObj, chNum);
    
                status  = MCSPI_TRANSFER_CANCELLED;
                /* Return the actual number of words transferred */
                hMcspi->transaction.count = chObj->curRxWords;
                if (MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
                {
                    hMcspi->transaction.count = chObj->curTxWords;
                }
    
                hMcspi->state = MCSPI_STATE_READY;
                if(hMcspi->errorFlag != 0U)
                {
                    hMcspi->hMcspiInit->errorCallbackFxn(hMcspi, status);
                }
                else
                {
                    hMcspi->hMcspiInit->transferCallbackFxn(hMcspi, status);
                }
            }
            else
            {
                /* No transaction to cancel. */
                status = MCSPI_STATUS_FAILURE;
            }
        }
    
        return (status);
    }
    
    int32_t MCSPI_lld_readWriteDmaCancel(MCSPILLD_Handle hMcspi)
    {
        int32_t             status = MCSPI_STATUS_SUCCESS;
        uint32_t            chNum;
        MCSPI_ChObject     *chObj;
    
        /* Check parameters */
        if (NULL == hMcspi)
        {
            status = MCSPI_INVALID_PARAM;
        }
        else
        {
            /* Check if any transaction is in progress */
            if(MCSPI_STATE_BUSY == hMcspi->state)
            {
                chNum = hMcspi->transaction.channel;
                chObj = &hMcspi->hMcspiInit->chObj[chNum];
    
                /* Stop MCSPI Channel */
                MCSPI_lld_dmaStop(hMcspi, chObj, chNum);
    
                status  = MCSPI_TRANSFER_CANCELLED;
                /* Return the actual number of words transferred */
                hMcspi->transaction.count = chObj->curRxWords;
                if (MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
                {
                    hMcspi->transaction.count = chObj->curTxWords;
                }
    
                hMcspi->state = MCSPI_STATE_READY;
                if(hMcspi->errorFlag != 0U)
                {
                    hMcspi->hMcspiInit->errorCallbackFxn(hMcspi, status);
    
                }
                else
                {
                    hMcspi->hMcspiInit->transferCallbackFxn(hMcspi, status);
                }
            }
            else
            {
                /* No transaction to cancel. */
                status = MCSPI_STATUS_FAILURE;
            }
        }
        return (status);
    }
    
    void MCSPI_lld_controllerIsr(void* args)
    {
        uint32_t               transferStatus;
        MCSPI_ChObject        *chObj;
        MCSPI_Transaction     *transaction;
        uint32_t               chNum;
        MCSPILLD_Handle        hMcspi = NULL;
    
        /* Check parameters */
        if(NULL != args)
        {
            hMcspi = (MCSPILLD_Handle)args;
            transaction = &hMcspi->transaction;
            chNum = transaction->channel;
            chObj = &hMcspi->hMcspiInit->chObj[chNum];
            transferStatus = MCSPI_continueTxRx(hMcspi, chObj, transaction);
            if (MCSPI_TRANSFER_COMPLETED == (int32_t)transferStatus)
            {
                /* Process the transfer completion. */
                /* Stop MCSPI Channel */
                MCSPI_stop(hMcspi, chObj, chNum);
                /* Return the actual number of words transferred */
                hMcspi->transaction.count = chObj->curRxWords;
                if (MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
                {
                    hMcspi->transaction.count = chObj->curTxWords;
                }
                hMcspi->state = MCSPI_STATE_READY;
                hMcspi->hMcspiInit->transferCallbackFxn(hMcspi, transferStatus);
            }
    
            if((hMcspi->errorFlag != 0U) && (transferStatus == MCSPI_TRANSFER_CANCELLED))
            {
                hMcspi->state = MCSPI_STATE_READY;
                hMcspi->hMcspiInit->errorCallbackFxn(hMcspi, transferStatus);
            }
            /*
            * Else the transfer is still pending.
            * Do nothing, wait for next interrupt.
            */
        }
    
        return;
    }
    
    void MCSPI_lld_peripheralIsr(void* args)
    {
        uint32_t            transferStatus;
        MCSPI_ChObject     *chObj;
        MCSPI_Transaction  *transaction;
        uint32_t            baseAddr, chNum;
        MCSPILLD_Handle     hMcspi = NULL;
    
        /* Check parameters */
        if(NULL != args)
        {
            hMcspi = (MCSPILLD_Handle)args;
            transaction = &hMcspi->transaction;
            baseAddr = hMcspi->baseAddr;
    
            chNum = transaction->channel;
            chObj = &hMcspi->hMcspiInit->chObj[chNum];
            transferStatus = MCSPI_continuePeripheralTxRx(hMcspi, chObj, transaction);
    
            if (MCSPI_TRANSFER_COMPLETED == (int32_t)transferStatus)
            {
                /* Process the transfer completion. */
                /* Stop MCSPI Channel */
                MCSPI_stop(hMcspi, chObj, chNum);
    
                /* Disable TX and RX FIFO */
                chObj->chConfRegVal &= ~(CSL_MCSPI_CH0CONF_FFEW_MASK | CSL_MCSPI_CH0CONF_FFER_MASK);
                CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chObj->chCfg->chNum), chObj->chConfRegVal);
    
                /* Return the actual number of words transferred */
                hMcspi->transaction.count = chObj->curRxWords;
                if (MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
                {
                    hMcspi->transaction.count = chObj->curTxWords;
                }
                hMcspi->state = MCSPI_STATE_READY;
                if(MCSPI_TRANSFER_COMPLETED == (int32_t)transferStatus)
                {
                    hMcspi->hMcspiInit->transferCallbackFxn(hMcspi, transferStatus);
                }
            }
    
            if((hMcspi->errorFlag != 0U) && (transferStatus == MCSPI_TRANSFER_CANCELLED))
            {
                hMcspi->hMcspiInit->errorCallbackFxn(hMcspi, transferStatus);
            }
            /*
            * Else the transfer is still pending.
            * Do nothing, wait for next interrupt.
            */
        }
    
        return;
    }
    
    int32_t MCSPI_lld_getState(MCSPILLD_Handle hMcspi)
    {
        return (int32_t)(hMcspi->state);
    }
    
    /* ========================================================================== */
    /*                       Static Function Definitions                          */
    /* ========================================================================== */
    
    static int32_t MCSPI_lld_chConfig(MCSPILLD_Handle hMcspi,
                           const MCSPI_ChConfig *chCfg, uint32_t chCnt)
    {
        int32_t         status = MCSPI_STATUS_SUCCESS;
        MCSPI_ChObject  *chObj;
    
        /* Check parameters */
        if((NULL == chCfg) || (chCfg->chNum >= MCSPI_MAX_NUM_CHANNELS))
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            /* Check channel parameters */
            status = MCSPI_checkChConfig(hMcspi, chCfg);
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            chObj = &hMcspi->hMcspiInit->chObj[chCnt];
    
            /* Configure the MCSPI channel */
            MCSPI_setChConfig(hMcspi, chObj);
    
            chObj->isOpen = TRUE;
            chObj->csEnable = TRUE;
        }
    
        return (status);
    }
    
    static void MCSPI_initiateLastChunkTransfer(MCSPILLD_Handle hMcspi,
                                                MCSPI_ChObject *chObj,
                                                const MCSPI_Transaction *transaction)
    {
        uint32_t        baseAddr, chNum;
        uint32_t        reminder;
        uint32_t        regVal;
    
        baseAddr = hMcspi->baseAddr;
        chNum = chObj->chCfg->chNum;
    
        /* Disable channel so that new settings takes effect */
        chObj->chCtrlRegVal &= (~CSL_MCSPI_CH0CTRL_EN_MASK);
        CSL_REG32_WR(baseAddr + MCSPI_CHCTRL(chNum), chObj->chCtrlRegVal);
    
        /* Start transferring only multiple of FIFO trigger level */
        if(MCSPI_TR_MODE_RX_ONLY != chObj->chCfg->trMode)
        {
            reminder = (transaction->count & (chObj->effTxFifoDepth - 1U));
        }
        else
        {
            reminder = (transaction->count & (chObj->effRxFifoDepth - 1U));
        }
    
        /* Set FIFO trigger level and word count */
        regVal  = 0;
        if (chObj->chCfg->rxFifoTrigLvl != 1U)
        {
            regVal |= ((((reminder << chObj->bufWidthShift) - 1U) << CSL_MCSPI_XFERLEVEL_AFL_SHIFT) &
                    CSL_MCSPI_XFERLEVEL_AFL_MASK);
        }
        if (chObj->chCfg->txFifoTrigLvl != 1U)
        {
            regVal |= ((((reminder << chObj->bufWidthShift) - 1U) << CSL_MCSPI_XFERLEVEL_AEL_SHIFT) &
                    CSL_MCSPI_XFERLEVEL_AEL_MASK);
        }
        regVal |= ((reminder << CSL_MCSPI_XFERLEVEL_WCNT_SHIFT) &
                   CSL_MCSPI_XFERLEVEL_WCNT_MASK);
    
        CSL_REG32_WR(baseAddr + CSL_MCSPI_XFERLEVEL, regVal);
    
        /* Enable channel */
        chObj->chCtrlRegVal |= CSL_MCSPI_CH0CTRL_EN_MASK;
        CSL_REG32_WR(baseAddr + MCSPI_CHCTRL(chNum), chObj->chCtrlRegVal);
    }
    
    static uint32_t MCSPI_continueTxRx(MCSPILLD_Handle hMcspi,
                                       MCSPI_ChObject *chObj,
                                       const MCSPI_Transaction *transaction)
    {
        uint32_t                 baseAddr, chNum, txEmptyMask, rxFullMask;
        uint32_t                 retVal = MCSPI_TRANSFER_STARTED;
        volatile uint32_t        irqStatus, chStat;
    
        baseAddr = hMcspi->baseAddr;
        chNum    = chObj->chCfg->chNum;
        txEmptyMask = Spi_mcspiGetTxMask(chNum);
        rxFullMask  = Spi_mcspiGetRxMask(chNum);
    
        irqStatus = CSL_REG32_RD(baseAddr + CSL_MCSPI_IRQSTATUS);
    
        if ((irqStatus & chObj->intrMask) != 0U)
        {
            /* Clear the interrupts being serviced. */
            CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQSTATUS, (irqStatus & chObj->intrMask));
    
            /* First read the data from the Rx FIFO. */
            if ((irqStatus & rxFullMask) == rxFullMask)
            {
                /* Perform RX only when enabled */
                if(MCSPI_TR_MODE_TX_ONLY != chObj->chCfg->trMode)
                {
                    uint32_t numWordsToRead = transaction->count - chObj->curRxWords;
                    if (numWordsToRead > chObj->effRxFifoDepth)
                    {
                        numWordsToRead = chObj->effRxFifoDepth;
                    }
                    if(hMcspi->hMcspiInit->multiWordAccess == TRUE)
                    {
                        /* In case of Multi word Access, always read 32 bits of data from RX FIFO. */
                        MCSPI_fifoReadMultiWord(baseAddr, chObj, numWordsToRead);
                    }
                    else
                    {
                        /* Read data from RX FIFO. */
                        MCSPI_fifoRead(baseAddr, chObj, numWordsToRead);
                    }
                }
            }
            if ((irqStatus & txEmptyMask) == txEmptyMask)
            {
                uint32_t numWordsToWrite = transaction->count - chObj->curTxWords;
                if (numWordsToWrite > chObj->effTxFifoDepth)
                {
                    numWordsToWrite = chObj->effTxFifoDepth;
                }
                if(hMcspi->hMcspiInit->multiWordAccess == TRUE)
                {
                    /* Write the data in TX FIFO.Even in RX only mode, dummy data has to
                    be written to receive data from Peripheral */
                    MCSPI_fifoWriteMultiWord(baseAddr, chObj, numWordsToWrite);
                }
                else
                {
                    MCSPI_fifoWrite(baseAddr, chObj, numWordsToWrite);
                }
            }
            if ((irqStatus & CSL_MCSPI_IRQSTATUS_EOW_MASK) == CSL_MCSPI_IRQSTATUS_EOW_MASK)
            {
                if (MCSPI_TR_MODE_RX_ONLY != chObj->chCfg->trMode)
                {
                    if (transaction->count == chObj->curTxWords)
                    {
                        do
                        {
                            /* Wait for end of transfer. */
                            chStat = CSL_REG32_RD(baseAddr + MCSPI_CHSTAT(chNum));
                        }while ((chStat & CSL_MCSPI_CH0STAT_EOT_MASK) == 0U);
    
                        /* read the last data if any from Rx FIFO. */
                        if ((MCSPI_TR_MODE_TX_ONLY != chObj->chCfg->trMode) &&
                            (transaction->count != chObj->curRxWords))
                        {
                            /* This is a corner case. EOW is set at the end of transmission.
                                * the reception is not complete by the time we are processing EOW.
                                * Read the remaining bytes.
                                */
                            MCSPI_fifoRead(baseAddr, chObj, (transaction->count - chObj->curRxWords));
                        }
                        /* Clear all interrupts. */
                        MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
                        retVal = MCSPI_TRANSFER_COMPLETED;
                    }
                    else
                    {
                        MCSPI_initiateLastChunkTransfer(hMcspi, chObj, transaction);
                    }
                }
                else
                {
                    if (transaction->count == chObj->curRxWords)
                    {
                        do{
                            /* Wait for end of transfer. */
                            chStat = CSL_REG32_RD(baseAddr + MCSPI_CHSTAT(chNum));
                        }while ((chStat & CSL_MCSPI_CH0STAT_EOT_MASK) == 0u);
                        /* Clear all interrupts. */
                        MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
                        retVal = MCSPI_TRANSFER_COMPLETED;
                    }
                    else
                    {
                        MCSPI_initiateLastChunkTransfer(hMcspi, chObj, transaction);
                    }
                }
            }
    
            /* Check for Rx overflow or Tx underflow.
             * Cancel the current transfer and return error. */
            if ((irqStatus & ((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_OVERFLOW_MASK)) != 0U)
            {
                retVal = MCSPI_TRANSFER_CANCELLED;
                hMcspi->errorFlag |= MCSPI_ERROR_RX_OVERFLOW;
            }
    
            if (((irqStatus & ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK << (4U * chNum))) != 0U) &&
                (hMcspi->hMcspiInit->msMode == MCSPI_MS_MODE_PERIPHERAL))
            {
                retVal  = MCSPI_TRANSFER_CANCELLED;
                hMcspi->errorFlag |= MCSPI_ERROR_TX_UNDERFLOW;
            }
        }
    
        return retVal;
    }
    
    static int32_t MCSPI_transferControllerPoll(MCSPILLD_Handle hMcspi,
                                            MCSPI_ChObject *chObj,
                                            const MCSPI_Transaction *transaction)
    {
        int32_t                  status = MCSPI_STATUS_SUCCESS;
        uint32_t                 baseAddr, chNum;
        uint32_t                 numWordsToWrite, txEmptyMask, irqStatus = 0U;
        uint32_t                 timeout, startTicks, elapsedTicks;
        uint32_t                 timeoutElapsed  = FALSE;
        MCSPILLD_InitHandle      hMcspiInit = hMcspi->hMcspiInit;
    
        baseAddr = hMcspi->baseAddr;
        chNum    = chObj->chCfg->chNum;
        timeout  = transaction->timeout;
    
        /* Manual CS assert */
        if(MCSPI_CH_MODE_SINGLE == hMcspi->hMcspiInit->chMode)
        {
            if (chObj->csEnable ==  TRUE)
            {
                chObj->chConfRegVal |= CSL_MCSPI_CH0CONF_FORCE_MASK;
                CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chObj->chCfg->chNum), chObj->chConfRegVal);
                chObj->csEnable = FALSE;
            }
        }
    
        /* Enable channel */
        chObj->chCtrlRegVal |= CSL_MCSPI_CH0CTRL_EN_MASK;
        CSL_REG32_WR(baseAddr + MCSPI_CHCTRL(chNum), chObj->chCtrlRegVal);
    
        startTicks = hMcspiInit->clockP_get();
    
        /* wait for the Tx Empty bit to be set. */
        while (((MCSPI_readChStatusReg(baseAddr, chNum) & CSL_MCSPI_CH0STAT_TXS_MASK) == 0U)
                && (timeoutElapsed != TRUE))
        {
            elapsedTicks = hMcspiInit->clockP_get() - startTicks;
            if (elapsedTicks >= timeout)
            {
                /* timeout occured */
                timeoutElapsed = TRUE;
            }
            /* wait for the Tx Empty Event. */
        }
        /* Initially write the full Tx FIFO */
        if (transaction->count > chObj->effTxFifoDepth)
        {
            numWordsToWrite = chObj->effTxFifoDepth;
        }
        else
        {
            numWordsToWrite = transaction->count;
        }
        /* Write the data in TX FIFO.Even in RX only mode, dummy data has to
            be written to receive data from Peripheral */
        MCSPI_fifoWrite(baseAddr, chObj, numWordsToWrite);
    
        if(MCSPI_TR_MODE_TX_ONLY != chObj->chCfg->trMode)
        {
            while ((((transaction->count - chObj->curTxWords) != 0U) ||
                    ((transaction->count - chObj->curRxWords) != 0U)) &&
                   (timeoutElapsed != TRUE))
            {
                irqStatus = CSL_REG32_RD(baseAddr + CSL_MCSPI_IRQSTATUS);
                /* Now keep polling the CH_STAT register, if RXs bit is set, at least 1 word is available.
                Read the data from Rx register, also write the same number of bytes in Tx register.
                In case of Controller mode only when 1 word is sent out, 1 word will be received. */
                if ((MCSPI_readChStatusReg(baseAddr, chNum) & CSL_MCSPI_CH0STAT_RXS_MASK) != 0U)
                {
                    MCSPI_fifoRead(baseAddr, chObj, 1);
                    if (transaction->count > chObj->curTxWords)
                    {
                        MCSPI_fifoWrite(baseAddr, chObj, 1);
                    }
                }
                elapsedTicks = hMcspiInit->clockP_get() - startTicks;
                if (elapsedTicks >= timeout)
                {
                    /* timeout occured */
                    timeoutElapsed = TRUE;
                }
            }
        }
        else
        {
            txEmptyMask = Spi_mcspiGetTxMask(chNum);
            while (((transaction->count - chObj->curTxWords) != 0U) && (timeoutElapsed != (uint32_t)TRUE))
            {
                irqStatus = CSL_REG32_RD(baseAddr + CSL_MCSPI_IRQSTATUS);
    
                if ((irqStatus & chObj->intrMask) != 0U)
                {
                    /* Clear the interrupts being serviced. */
                    CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQSTATUS, (irqStatus & chObj->intrMask));
                    if ((irqStatus & txEmptyMask) == txEmptyMask)
                    {
                        numWordsToWrite = transaction->count - chObj->curTxWords;
                        if (numWordsToWrite > chObj->effTxFifoDepth)
                        {
                            numWordsToWrite = chObj->effTxFifoDepth;
                        }
    
                        /* Write the data in TX FIFO.Even in RX only mode, dummy data has to
                        be written to receive data from Peripheral */
                        MCSPI_fifoWrite(baseAddr, chObj, numWordsToWrite);
                    }
                }
                elapsedTicks = hMcspiInit->clockP_get() - startTicks;
                if (elapsedTicks >= timeout)
                {
                    /* timeout occured */
                    timeoutElapsed = TRUE;
                }
            }
            /* Wait for the last byte to be sent out. */
            while ((0U == (MCSPI_readChStatusReg(baseAddr, chNum) &
                            CSL_MCSPI_CH0STAT_TXFFE_MASK)) && (timeoutElapsed != TRUE))
            {
                /* Wait fot Tx FIFO to be empty for the last set of data. */
                elapsedTicks = hMcspiInit->clockP_get() - startTicks;
                if (elapsedTicks >= timeout)
                {
                    /* timeout occured */
                    timeoutElapsed = TRUE;
                }
            }
            while ((0U == (MCSPI_readChStatusReg(baseAddr, chNum) &
                            CSL_MCSPI_CH0STAT_EOT_MASK)) && (timeoutElapsed != TRUE))
            {
                /* Tx FIFO Empty is triggered when last word from FIFO is written to
                internal shift register. SO wait for the end of transfer of last word.
                The EOT gets set after every word when the transfer from shift
                register is complete and is reset when the transmission starts.
                So FIFO empty check is required to make sure the data in FIFO is
                sent out then wait for EOT for the last word. */
                elapsedTicks = hMcspiInit->clockP_get() - startTicks;
                if (elapsedTicks >= timeout)
                {
                    /* timeout occured */
                    timeoutElapsed = TRUE;
                }
            }
        }
    
        /* Check for Rx overflow or Tx underflow.
         * Cancel the current transfer and return error.
         */
        if ((irqStatus & ((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_OVERFLOW_MASK)) != 0U)
        {
            status = MCSPI_TRANSFER_CANCELLED;
            hMcspi->errorFlag |= MCSPI_ERROR_RX_OVERFLOW;
        }
    
        if(timeoutElapsed == TRUE)
        {
            status = MCSPI_TIMEOUT;
        }
    
        /* Stop MCSPI Channel */
        MCSPI_stop(hMcspi, chObj, chNum);
    
        return (status);
    }
    
    static void MCSPI_transferControllerIntr(MCSPILLD_Handle hMcspi,
                                             MCSPI_ChObject *chObj)
    {
        uint32_t  baseAddr, chNum;
    
        baseAddr = hMcspi->baseAddr;
        chNum    = chObj->chCfg->chNum;
    
        CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQENABLE, chObj->intrMask);
    
        /* Manual CS assert */
        if(MCSPI_CH_MODE_SINGLE == hMcspi->hMcspiInit->chMode)
        {
            if (chObj->csEnable == TRUE)
            {
                chObj->chConfRegVal |= CSL_MCSPI_CH0CONF_FORCE_MASK;
                CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chObj->chCfg->chNum), chObj->chConfRegVal);
                chObj->csEnable = FALSE;
            }
        }
    
        /* Enable channel */
        chObj->chCtrlRegVal |= CSL_MCSPI_CH0CTRL_EN_MASK;
        CSL_REG32_WR(baseAddr + MCSPI_CHCTRL(chNum), chObj->chCtrlRegVal);
    
        /*
         * Note: Once the channel is enabled, we will get the TX almost empty
         *       interrupt. No data transfer is required here!!
         */
        return;
    }
    
    static uint32_t MCSPI_continuePeripheralTxRx(MCSPILLD_Handle hMcspi,
                                                 MCSPI_ChObject *chObj,
                                                 const MCSPI_Transaction *transaction)
    {
        uint32_t            baseAddr, chNum, chStat;
        uint32_t            retVal = MCSPI_TRANSFER_STARTED;
        volatile uint32_t   irqStatus;
    
        baseAddr = hMcspi->baseAddr;
        chNum    = chObj->chCfg->chNum;
        irqStatus = CSL_REG32_RD(baseAddr + CSL_MCSPI_IRQSTATUS);
        if ((irqStatus & chObj->intrMask) != 0U)
        {
            /* Clear the interrupts being serviced. */
            CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQSTATUS, (irqStatus & chObj->intrMask));
            /* First read the data from the Rx FIFO. */
            if ((irqStatus & ((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK << (4U * chNum))) != 0U)
            {
                /* Perform RX only when enabled */
                if(MCSPI_TR_MODE_TX_ONLY != chObj->chCfg->trMode)
                {
                    uint32_t numWordsToRead = transaction->count - chObj->curRxWords;
                    if (numWordsToRead > chObj->effRxFifoDepth)
                    {
                        numWordsToRead = chObj->effRxFifoDepth;
                    }
                    if(hMcspi->hMcspiInit->multiWordAccess == TRUE)
                    {
                        /* In case of Multi word Access, always read 32 bits of data from RX FIFO. */
                        MCSPI_fifoReadMultiWord(baseAddr, chObj, numWordsToRead);
                    }
                    else
                    {
                        /* Read data from RX FIFO. */
                        MCSPI_fifoRead(baseAddr, chObj, numWordsToRead);
                    }
    
                    /* Check if transfer is completed for current transaction. */
                    if (transaction->count == chObj->curRxWords)
                    {
                        retVal = MCSPI_TRANSFER_COMPLETED;
                    }
                }
            }
            if ((irqStatus & ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK << (4U * chNum))) != 0U)
            {
                /* Perform TX only when enabled */
                if(MCSPI_TR_MODE_RX_ONLY != chObj->chCfg->trMode)
                {
                    uint32_t numWordsToWrite = transaction->count - chObj->curTxWords;
                    if (numWordsToWrite > chObj->effTxFifoDepth)
                    {
                        numWordsToWrite = chObj->effTxFifoDepth;
                    }
                    if(hMcspi->hMcspiInit->multiWordAccess == TRUE)
                    {
                        MCSPI_fifoWriteMultiWord(baseAddr, chObj, numWordsToWrite);
                    }
                    else
                    {
                        /* Write the data in TX FIFO. */
                        MCSPI_fifoWrite(baseAddr, chObj, numWordsToWrite);
                    }
    
                    if(MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
                    {
                        /* Check if transfer is completed for current transaction. */
                        if (transaction->count == chObj->curTxWords)
                        {
                            do{
                                /* Wait for TX FIFO Empty. */
                                chStat = CSL_REG32_RD(baseAddr + MCSPI_CHSTAT(chNum));
                            }while ((chStat & CSL_MCSPI_CH0STAT_TXFFE_MASK) == 0U);
                            do{
                                /* Wait for end of transfer. */
                                chStat = CSL_REG32_RD(baseAddr + MCSPI_CHSTAT(chNum));
                            }while ((chStat & CSL_MCSPI_CH0STAT_EOT_MASK) == 0U);
                            retVal = MCSPI_TRANSFER_COMPLETED;
                        }
                    }
                }
            }
    
            /* Check for Rx overflow or Tx underflow.
             * Cancel the current transfer and return error. */
            if ((irqStatus & ((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_OVERFLOW_MASK)) != 0U)
            {
                retVal = MCSPI_TRANSFER_CANCELLED;
                hMcspi->errorFlag |= MCSPI_ERROR_RX_OVERFLOW;
            }
    
            if ((irqStatus & ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK << (4U * chNum))) != 0U)
            {
                retVal = MCSPI_TRANSFER_CANCELLED;
                hMcspi->errorFlag |= MCSPI_ERROR_TX_UNDERFLOW;
            }
        }
        return retVal;
    }
    
    static int32_t MCSPI_transferPeripheralPoll(MCSPILLD_Handle hMcspi,
                                            MCSPI_ChObject *chObj,
                                            const MCSPI_Transaction *transaction)
    {
        int32_t                 status = MCSPI_STATUS_SUCCESS;
        uint32_t                baseAddr, chNum;
        uint32_t                transferStatus = MCSPI_TRANSFER_STARTED;
        uint32_t                timeout, startTicks, elapsedTicks;
        uint32_t                timeoutElapsed  = FALSE;
        MCSPILLD_InitHandle     hMcspiInit = hMcspi->hMcspiInit;
    
        baseAddr = hMcspi->baseAddr;
        chNum    = chObj->chCfg->chNum;
        timeout  = transaction->timeout;
    
        /* Enable channel */
        chObj->chCtrlRegVal |= CSL_MCSPI_CH0CTRL_EN_MASK;
        CSL_REG32_WR(baseAddr + MCSPI_CHCTRL(chNum), chObj->chCtrlRegVal);
    
        startTicks = hMcspiInit->clockP_get();
        /* Busy loop till channel transfer is completed */
        do
        {
            transferStatus = MCSPI_continuePeripheralTxRx(hMcspi, chObj, transaction);
            elapsedTicks = hMcspiInit->clockP_get() - startTicks;
            if (elapsedTicks >= timeout)
            {
                /* timeout occured */
                timeoutElapsed = TRUE;
            }
    
            if(transferStatus == MCSPI_TRANSFER_CANCELLED)
            {
                status = MCSPI_TRANSFER_CANCELLED;
                break;
            }
    
        } while ((transferStatus != (uint32_t)MCSPI_TRANSFER_COMPLETED) && (timeoutElapsed != TRUE));
    
        /* Stop MCSPI Channel */
        MCSPI_stop(hMcspi, chObj, chNum);
    
        if(timeoutElapsed == TRUE)
        {
            status = MCSPI_TIMEOUT;
        }
    
        return (status);
    }
    
    static void MCSPI_transferPeripheralIntr(MCSPILLD_Handle hMcspi,
                                            MCSPI_ChObject *chObj)
    {
        uint32_t        baseAddr, chNum;
    
        baseAddr = hMcspi->baseAddr;
        chNum    = chObj->chCfg->chNum;
    
        CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQENABLE, chObj->intrMask);
    
        /* Enable channel */
        chObj->chCtrlRegVal |= CSL_MCSPI_CH0CTRL_EN_MASK;
        CSL_REG32_WR(baseAddr + MCSPI_CHCTRL(chNum), chObj->chCtrlRegVal);
    
        /*
         * Note: Once the channel is enabled, we will get the TX almost empty
         *       interrupt. No data transfer is required here!!
         */
    
        return;
    }
    
    static inline void MCSPI_fifoWrite(uint32_t baseAddr, MCSPI_ChObject *chObj, uint32_t transferLength)
    {
        uint32_t        chNum;
    
        chNum = chObj->chCfg->chNum;
        if(NULL != chObj->curTxBufPtr)
        {
            if(0U == chObj->bufWidthShift)
            {
                chObj->curTxBufPtr = MCSPI_fifoWrite8(
                                         baseAddr,
                                         chNum,
                                         chObj->curTxBufPtr,
                                         transferLength);
            }
            else if(1U == chObj->bufWidthShift)
            {
                chObj->curTxBufPtr = (uint8_t *) MCSPI_fifoWrite16(
                                         baseAddr,
                                         chNum,
                                         (uint16_t *) chObj->curTxBufPtr,
                                         transferLength);
            }
            else
            {
                chObj->curTxBufPtr = (uint8_t *) MCSPI_fifoWrite32(
                                         baseAddr,
                                         chNum,
                                         (uint32_t *) chObj->curTxBufPtr,
                                         transferLength);
            }
        }
        else
        {
            /* NULL TX pointer provided. Use default data */
            MCSPI_fifoWriteDefault(
                baseAddr, chNum, chObj->chCfg->defaultTxData, transferLength);
        }
        chObj->curTxWords += transferLength;
    
        return;
    }
    
    static inline void MCSPI_fifoWriteMultiWord(uint32_t baseAddr,
                                               MCSPI_ChObject *chObj,
                                               uint32_t transferLength)
    {
        uint32_t    chNum = chObj->chCfg->chNum;
    
        /* Check if cuRxBufPtr is NULL */
        if(NULL != chObj->curRxBufPtr)
        {
            /* Read all the bytes that are multiple of 4 */
            if((transferLength % 4U) == 0U)
            {
                chObj->curTxBufPtr = (uint8_t *) MCSPI_fifoWrite32(
                                         baseAddr,
                                         chNum,
                                         (uint32_t *) chObj->curTxBufPtr,
                                         (transferLength / 4U));
    
                chObj->curTxWords += transferLength;
            }
        }
    
        return;
    }
    
    static inline void MCSPI_fifoRead(uint32_t baseAddr, MCSPI_ChObject *chObj, uint32_t transferLength)
    {
        uint32_t        chNum;
    
        chNum = chObj->chCfg->chNum;
        /* Check if cuRxBufPtr is NULL */
        if(NULL != chObj->curRxBufPtr)
        {
            if(0U == chObj->bufWidthShift)
            {
                chObj->curRxBufPtr = MCSPI_fifoRead8(
                                         baseAddr,
                                         chNum,
                                         chObj->curRxBufPtr,
                                         transferLength,
                                         chObj->dataWidthBitMask);
            }
            else if(1U == chObj->bufWidthShift)
            {
                chObj->curRxBufPtr = (uint8_t *) MCSPI_fifoRead16(
                                         baseAddr,
                                         chNum,
                                         (uint16_t *) chObj->curRxBufPtr,
                                         transferLength,
                                         chObj->dataWidthBitMask);
            }
            else
            {
                chObj->curRxBufPtr = (uint8_t *) MCSPI_fifoRead32(
                                         baseAddr,
                                         chNum,
                                         (uint32_t *) chObj->curRxBufPtr,
                                         transferLength,
                                         chObj->dataWidthBitMask);
            }
        }
        else
        {
            /* NULL RX pointer provided. Read and discard data */
            MCSPI_fifoReadDiscard(baseAddr, chNum, transferLength);
        }
        chObj->curRxWords += transferLength;
    
        return;
    }
    
    static inline void MCSPI_fifoReadMultiWord(uint32_t baseAddr,
                                               MCSPI_ChObject *chObj,
                                               uint32_t transferLength)
    {
        uint32_t    chNum = chObj->chCfg->chNum;
        uint32_t    dataWidthBitMask = 0xFFFFFFFFU;
    
        /* Check if cuRxBufPtr is NULL */
        if(NULL != chObj->curRxBufPtr)
        {
            /* Read all the bytes that are multiple of 4 */
            if((transferLength / 4U) > 0U)
            {
                chObj->curRxBufPtr = (uint8_t *) MCSPI_fifoRead32(
                                                baseAddr,
                                                chNum,
                                                (uint32_t *) chObj->curRxBufPtr,
                                                (transferLength / 4U),
                                                dataWidthBitMask);
    
                chObj->curRxWords += transferLength;
            }
        }
    
        return;
    }
    
    static void MCSPI_configInstance(MCSPILLD_Handle hMcspi)
    {
        uint32_t                regVal;
        uint32_t                baseAddr;
        MCSPILLD_InitHandle     hMcspiInit = hMcspi->hMcspiInit;
    
        baseAddr = hMcspi->baseAddr;
    
        /* Reset MCSPI */
        MCSPI_reset(baseAddr);
    
        /* Set sysconfig */
        regVal = (((uint32_t)CSL_MCSPI_SYSCONFIG_CLOCKACTIVITY_BOTH <<
                             CSL_MCSPI_SYSCONFIG_CLOCKACTIVITY_SHIFT) |
                  ((uint32_t)CSL_MCSPI_SYSCONFIG_SIDLEMODE_NO <<
                           CSL_MCSPI_SYSCONFIG_SIDLEMODE_SHIFT) |
                  ((uint32_t)CSL_MCSPI_SYSCONFIG_ENAWAKEUP_NOWAKEUP <<
                           CSL_MCSPI_SYSCONFIG_ENAWAKEUP_SHIFT) |
                  ((uint32_t)CSL_MCSPI_SYSCONFIG_AUTOIDLE_OFF <<
                           CSL_MCSPI_SYSCONFIG_AUTOIDLE_SHIFT));
        CSL_REG32_WR(baseAddr + CSL_MCSPI_SYSCONFIG, regVal);
    
        /* Set module control */
        regVal = (hMcspiInit->msMode << CSL_MCSPI_MODULCTRL_MS_SHIFT);
        /* Set multi word acces enable/disable */
        regVal |= (hMcspiInit->multiWordAccess << CSL_MCSPI_MODULCTRL_MOA_SHIFT);
        /* Configure Single/Multi Channel in Controller mode only */
        if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
        {
            regVal |= (hMcspiInit->chMode << CSL_MCSPI_MODULCTRL_SINGLE_SHIFT);
        }
        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 */
            regVal |= (hMcspiInit->pinMode << CSL_MCSPI_MODULCTRL_PIN34_SHIFT);
            if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
            {
                /* Init delay applicable only for single Controller mode */
                regVal |= (hMcspiInit->initDelay << CSL_MCSPI_MODULCTRL_INITDLY_SHIFT);
            }
        }
        CSL_REG32_WR(baseAddr + CSL_MCSPI_MODULCTRL, regVal);
    
        return;
    }
    
    static void MCSPI_setChConfig(MCSPILLD_Handle hMcspi,
                                  MCSPI_ChObject *chObj)
    {
        uint32_t                 regVal;
        uint32_t                 baseAddr, chNum;
        const MCSPI_ChConfig    *chCfg;
    
        baseAddr = hMcspi->baseAddr;
        chNum    = chObj->chCfg->chNum;
        chCfg    = chObj->chCfg;
    
        regVal = CSL_REG32_RD(baseAddr + MCSPI_CHCONF(chNum));
    
        /* Clear PHA, POL, DPE0, DPE1 and set PHA, POL fields */
        regVal &= ~((uint32_t) CSL_MCSPI_CH0CONF_PHA_MASK  |
                    (uint32_t) CSL_MCSPI_CH3CONF_POL_MASK  |
                    (uint32_t) CSL_MCSPI_CH0CONF_DPE0_MASK |
                    (uint32_t) CSL_MCSPI_CH0CONF_DPE1_MASK);
        regVal |= (chCfg->frameFormat & ((uint32_t) CSL_MCSPI_CH0CONF_PHA_MASK |
                                        (uint32_t) CSL_MCSPI_CH3CONF_POL_MASK));
        CSL_FINS(regVal, MCSPI_CH0CONF_EPOL, chCfg->csPolarity);
        CSL_FINS(regVal, MCSPI_CH0CONF_TRM, chCfg->trMode);
        CSL_FINS(regVal, MCSPI_CH0CONF_IS, chCfg->inputSelect);
        CSL_FINS(regVal, MCSPI_CH0CONF_DPE0, chCfg->dpe0);
        CSL_FINS(regVal, MCSPI_CH0CONF_DPE1, chCfg->dpe1);
        CSL_FINS(regVal, MCSPI_CH0CONF_SPIENSLV, chCfg->slvCsSelect);
        CSL_FINS(regVal, MCSPI_CH0CONF_SBE, chCfg->startBitEnable);
        CSL_FINS(regVal, MCSPI_CH0CONF_SBPOL, chCfg->startBitPolarity);
        CSL_FINS(regVal, MCSPI_CH0CONF_TURBO, chCfg->turboEnable);
        CSL_FINS(regVal, MCSPI_CH0CONF_TCS0, chCfg->csIdleTime);
    
        CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chNum), regVal);
    
        /* Set clock dividers */
        MCSPI_setClkConfig(baseAddr, chNum, hMcspi->hMcspiInit->inputClkFreq, chCfg->bitRate);
    
        if (hMcspi->hMcspiInit->msMode == MCSPI_MS_MODE_PERIPHERAL)
        {
            if(MCSPI_TR_MODE_TX_RX == chObj->chCfg->trMode)
            {
                chObj->intrMask = (((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK      << (4U * chNum)) |
                                   ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK     << (4U * chNum)) |
                                   ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK << (4U * chNum)) |
                                   ((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_OVERFLOW_MASK));
            }
            else if(MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
            {
                chObj->intrMask = (((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK     << (4U * chNum)) |
                                   ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK << (4U * chNum)));
            }
            else
            {
                chObj->intrMask = (((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK     << (4U * chNum)) |
                                   ((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_OVERFLOW_MASK));
            }
        }
        else
        {
            if(MCSPI_TR_MODE_TX_RX == chObj->chCfg->trMode)
            {
                chObj->intrMask =  (((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK  << (4U * chNum)) |
                                    ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK << (4U * chNum)) |
                                    (uint32_t)CSL_MCSPI_IRQSTATUS_EOW_MASK);
            }
            else if(MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
            {
                chObj->intrMask =  (((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK << (4U * chNum)) |
                                    ((uint32_t)CSL_MCSPI_IRQSTATUS_EOW_MASK));
            }
            else
            {
                chObj->intrMask = (((uint32_t)CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK << (4U * chNum)) |
                                   ((uint32_t)CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK << (4U * chNum)) |
                                   ((uint32_t)CSL_MCSPI_IRQSTATUS_EOW_MASK));
            }
        }
    
        /* Store Ch Conf, Ch Ctrl, Syst register values in channel object. */
        chObj->chConfRegVal = CSL_REG32_RD(baseAddr + MCSPI_CHCONF(chNum));
        chObj->chCtrlRegVal = CSL_REG32_RD(baseAddr + MCSPI_CHCTRL(chNum));
        chObj->systRegVal = CSL_REG32_RD(baseAddr + CSL_MCSPI_SYST) & (~(CSL_MCSPI_SYST_SSB_MASK));
    
        return;
    }
    
    static int32_t MCSPI_checkChConfig(MCSPILLD_Handle hMcspi, const MCSPI_ChConfig *chCfg)
    {
        int32_t     status = MCSPI_STATUS_SUCCESS;
    
        if((hMcspi->hMcspiInit->msMode == MCSPI_MS_MODE_PERIPHERAL) && (chCfg->chNum != 0U))
        {
            DebugP_logError("[MCSPI] Only channel 0 supported in peripheral mode !!!\r\n");
            status = MCSPI_INVALID_PARAM;
        }
    
        return (status);
    }
    
    static uint32_t MCSPI_getDataWidthBitMask(uint32_t dataWidth)
    {
        uint32_t    i, fifoBitMask = 0x0U;
        uint32_t    tmpVar = 0U;
    
        for (i = 0U; i < dataWidth; i++)
        {
            tmpVar = ((uint32_t)1U << i);
            fifoBitMask |= tmpVar;
        }
    
        return (fifoBitMask);
    }
    
    void MCSPI_reset(uint32_t baseAddr)
    {
        uint32_t    regVal;
    
        /* Set the SOFTRESET field of MCSPI_SYSCONFIG register. */
        CSL_REG32_FINS(
            baseAddr + CSL_MCSPI_SYSCONFIG,
            MCSPI_SYSCONFIG_SOFTRESET,
            CSL_MCSPI_SYSCONFIG_SOFTRESET_ON);
    
        /* Stay in the loop until reset is done. */
        while((bool)TRUE)
        {
            regVal = CSL_REG32_RD(baseAddr + CSL_MCSPI_SYSSTATUS);
            if((regVal & CSL_MCSPI_SYSSTATUS_RESETDONE_MASK) ==
                CSL_MCSPI_SYSSTATUS_RESETDONE_MASK)
            {
                break;
            }
            /* Busy wait */
        }
    }
    
    static void MCSPI_setClkConfig(uint32_t baseAddr,
                                   uint32_t chNum,
                                   uint32_t inputClkFreq,
                                   uint32_t bitRate)
    {
        uint32_t fRatio;
        uint32_t clkD;
        uint32_t extClk;
    
        /* Calculate the value of fRatio. */
        fRatio = inputClkFreq / bitRate;
        if(((inputClkFreq % bitRate) != 0U) && (fRatio < MCSPI_MAX_CLK_DIVIDER_SUPPORTED))
        {
            /* use a higher divider value in case the ratio
             * is fractional so that we get a lower SPI clock
             * than requested. This ensures we don't go beyond
             * recommended clock speed for the SPI peripheral */
            fRatio++;
        }
    
        /* If fRatio is not a power of 2, set granularity of 1 clock cycle */
        if((uint32_t) 0U != (fRatio & (fRatio - 1U)))
        {
            /* Set the clock granularity to 1 clock cycle */
            CSL_REG32_FINS(
                baseAddr + MCSPI_CHCONF(chNum),
                MCSPI_CH0CONF_CLKG,
                CSL_MCSPI_CH0CONF_CLKG_ONECYCLE);
    
            /* Calculate the ratios clkD and extClk based on fClk */
            extClk = (fRatio - 1U) >> 4U;
            clkD   = (fRatio - 1U) & (uint32_t) MCSPI_CLKD_MASK;
    
            /* Set the extClk field */
            CSL_REG32_FINS(
                baseAddr + MCSPI_CHCTRL(chNum),
                MCSPI_CH0CTRL_EXTCLK,
                extClk);
        }
        else
        {
            /* Clock granularity of power of 2 */
            CSL_REG32_FINS(
                baseAddr + MCSPI_CHCONF(chNum),
                MCSPI_CH0CONF_CLKG,
                CSL_MCSPI_CH0CONF_CLKG_POWERTWO);
    
            clkD = 0U;
            while (1U != fRatio)
            {
                fRatio >>= 1U;
                clkD++;
            }
        }
    
        /* Configure the clkD field */
        CSL_REG32_FINS(baseAddr + MCSPI_CHCONF(chNum), MCSPI_CH0CONF_CLKD, clkD);
    
        return;
    }
    
    static void MCSPI_setFifoConfig(MCSPILLD_Handle hMcspi,
                                    MCSPI_ChObject *chObj,
                                    uint32_t baseAddr,
                                    uint32_t numWordsTxRx)
    {
        uint32_t txFifoTrigLvl, rxFifoTrigLvl;
        uint32_t regVal;
        uint32_t reminder = 0, effNumWordsTxRx;
    
        if (MCSPI_OPER_MODE_INTERRUPT == hMcspi->hMcspiInit->operMode)
        {
            /* Start transferring only multiple of FIFO trigger level */
            if(MCSPI_TR_MODE_RX_ONLY != chObj->chCfg->trMode)
            {
                reminder = (numWordsTxRx & (chObj->effTxFifoDepth - 1U));
            }
            else
            {
                reminder = (numWordsTxRx & (chObj->effRxFifoDepth - 1U));
            }
    
            effNumWordsTxRx = numWordsTxRx - reminder;
        }
        else
        {
            effNumWordsTxRx = numWordsTxRx;
        }
    
        rxFifoTrigLvl = chObj->chCfg->rxFifoTrigLvl;
        txFifoTrigLvl = chObj->chCfg->txFifoTrigLvl;
    
        /* Handle transfers with less than FIFO level.
         * Set FIFO trigger level and word count to be equal to the
         * reminder word. Otherwise the HW doesn't generating TX
         * empty interrupt if WCNT is less than FIFO trigger level */
        if(effNumWordsTxRx == 0U)
        {
            effNumWordsTxRx = reminder;
            if(txFifoTrigLvl != 1U)
            {
                /* Set TX level only when TX FIFO is enabled */
                txFifoTrigLvl = reminder << chObj->bufWidthShift;
            }
            if(rxFifoTrigLvl != 1U)
            {
                /* Set RX level only when RX FIFO is enabled */
                rxFifoTrigLvl = reminder << chObj->bufWidthShift;
            }
        }
    
        /* Set FIFO trigger level and word count should be set to 0.
           Setting all fields in register below, so read modify write not required. */
        regVal = 0;
        regVal |= (((rxFifoTrigLvl - 1U) << CSL_MCSPI_XFERLEVEL_AFL_SHIFT) &
                   CSL_MCSPI_XFERLEVEL_AFL_MASK);
        regVal |= (((txFifoTrigLvl - 1U) << CSL_MCSPI_XFERLEVEL_AEL_SHIFT) &
                   CSL_MCSPI_XFERLEVEL_AEL_MASK);
        regVal |= ((effNumWordsTxRx << CSL_MCSPI_XFERLEVEL_WCNT_SHIFT) &
                   CSL_MCSPI_XFERLEVEL_WCNT_MASK);
        CSL_REG32_WR(baseAddr + CSL_MCSPI_XFERLEVEL, regVal);
    
        /* Enable TX and RX FIFO */
        chObj->chConfRegVal &= ~(CSL_MCSPI_CH0CONF_FFEW_MASK | CSL_MCSPI_CH0CONF_FFER_MASK);
        if(MCSPI_TR_MODE_TX_RX == chObj->chCfg->trMode)
        {
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFEW_FFENABLED << CSL_MCSPI_CH0CONF_FFEW_SHIFT);
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFER_FFENABLED << CSL_MCSPI_CH0CONF_FFER_SHIFT);
        }
        else if(MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
        {
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFEW_FFENABLED << CSL_MCSPI_CH0CONF_FFEW_SHIFT);
        }
        else
        {
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFER_FFENABLED << CSL_MCSPI_CH0CONF_FFER_SHIFT);
        }
        CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chObj->chCfg->chNum), chObj->chConfRegVal);
    
        return;
    }
    
    static uint32_t MCSPI_getFifoTrigLvl(uint32_t numWords, uint32_t fifoDepth)
    {
        uint32_t fifoTrigLvl = 1U;
        if (numWords > fifoDepth)
        {
            uint32_t i;
            for (i=fifoDepth; i>0U; i--)
            {
                if ((numWords%i) == 0U )
                {
                    fifoTrigLvl = i;
                    break;
                }
            }
        }
        else
        {
            fifoTrigLvl = numWords;
        }
        return fifoTrigLvl;
    }
    
    static void MCSPI_setPeripheralFifoConfig(MCSPI_ChObject *chObj,
                                         uint32_t baseAddr,
                                         uint32_t numWordsTxRx)
    {
        uint32_t txFifoTrigLvl, rxFifoTrigLvl;
        uint32_t regVal;
    
        /* Find Fifo depth to configure to be multiple of number of words to transfer. */
        chObj->effTxFifoDepth = MCSPI_getFifoTrigLvl(numWordsTxRx, chObj->chCfg->txFifoTrigLvl >> chObj->bufWidthShift);
        chObj->effRxFifoDepth = MCSPI_getFifoTrigLvl(numWordsTxRx, chObj->chCfg->rxFifoTrigLvl >> chObj->bufWidthShift);
    
    
        txFifoTrigLvl = chObj->effTxFifoDepth << chObj->bufWidthShift;
        rxFifoTrigLvl = chObj->effRxFifoDepth << chObj->bufWidthShift;
    
        /* Set FIFO trigger level. word count set to 0 for slve mode.
           Setting all fields in register below, so read modify write not required. */
        regVal  = 0U;
        regVal |= (((rxFifoTrigLvl - 1U) << CSL_MCSPI_XFERLEVEL_AFL_SHIFT) &
                   CSL_MCSPI_XFERLEVEL_AFL_MASK);
        regVal |= (((txFifoTrigLvl - 1U) << CSL_MCSPI_XFERLEVEL_AEL_SHIFT) &
                   CSL_MCSPI_XFERLEVEL_AEL_MASK);
        regVal &= ~CSL_MCSPI_XFERLEVEL_WCNT_MASK;
        CSL_REG32_WR(baseAddr + CSL_MCSPI_XFERLEVEL, regVal);
    
        /* Enable TX and RX FIFO */
        chObj->chConfRegVal &= ~(CSL_MCSPI_CH0CONF_FFEW_MASK | CSL_MCSPI_CH0CONF_FFER_MASK);
        if(MCSPI_TR_MODE_TX_RX == chObj->chCfg->trMode)
        {
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFEW_FFENABLED << CSL_MCSPI_CH0CONF_FFEW_SHIFT);
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFER_FFENABLED << CSL_MCSPI_CH0CONF_FFER_SHIFT);
        }
        else if(MCSPI_TR_MODE_TX_ONLY == chObj->chCfg->trMode)
        {
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFEW_FFENABLED << CSL_MCSPI_CH0CONF_FFEW_SHIFT);
        }
        else
        {
            chObj->chConfRegVal |= ((uint32_t)CSL_MCSPI_CH0CONF_FFER_FFENABLED << CSL_MCSPI_CH0CONF_FFER_SHIFT);
        }
        CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chObj->chCfg->chNum), chObj->chConfRegVal);
    
        return;
    }
    
    static inline uint8_t *MCSPI_fifoWrite8(uint32_t baseAddr,
                                            uint32_t chNum,
                                            uint8_t  *bufPtr,
                                            uint32_t transferLength)
    {
        uint32_t    i, txData;
        uint8_t    *bufferPtr = bufPtr;
    
        /* Write the data in TX FIFO for 8-bit transfer */
        for(i = 0U; i < transferLength; i++)
        {
            txData = *bufferPtr;
            bufferPtr++;
            CSL_REG32_WR(baseAddr + MCSPI_CHTX(chNum), txData);
        }
    
        return (bufferPtr);
    }
    
    static inline uint16_t *MCSPI_fifoWrite16(uint32_t baseAddr,
                                              uint32_t chNum,
                                              uint16_t *bufPtr,
                                              uint32_t transferLength)
    {
        uint32_t     i, txData;
        uint16_t    *bufferPtr = bufPtr;
    
        /* Write the data in TX FIFO for 16-bit transfer */
        for(i = 0U; i < transferLength; i++)
        {
            txData = *bufferPtr;
            bufferPtr++;
            CSL_REG32_WR(baseAddr + MCSPI_CHTX(chNum), txData);
        }
    
        return (bufferPtr);
    }
    
    static inline uint32_t *MCSPI_fifoWrite32(uint32_t baseAddr,
                                              uint32_t chNum,
                                              uint32_t *bufPtr,
                                              uint32_t transferLength)
    {
        uint32_t        i, txData;
        uint32_t    *bufferPtr = bufPtr;
    
        /* Write the data in TX FIFO for 32-bit transfer */
        for(i = 0U; i < transferLength; i++)
        {
            txData = *bufferPtr;
            bufferPtr++;
            CSL_REG32_WR(baseAddr + MCSPI_CHTX(chNum), txData);
        }
    
        return (bufferPtr);
    }
    
    static inline uint8_t *MCSPI_fifoRead8(uint32_t  baseAddr,
                                           uint32_t  chNum,
                                           uint8_t  *bufPtr,
                                           uint32_t  transferLength,
                                           uint32_t  dataWidthBitMask)
    {
        uint32_t     i, rxData;
        uint8_t     *bufferPtr = bufPtr;
    
        /* Read the data from RX FIFO for 8-bit transfer */
        for(i = 0U; i < transferLength; i++)
        {
            rxData = MCSPI_readRxDataReg(baseAddr, chNum);
            rxData &= dataWidthBitMask;         /* Clear unused bits */
           *bufferPtr = (uint8_t) rxData;
            bufferPtr++;
        }
    
        return (bufferPtr);
    }
    
    static inline uint16_t *MCSPI_fifoRead16(uint32_t  baseAddr,
                                             uint32_t  chNum,
                                             uint16_t  *bufPtr,
                                             uint32_t  transferLength,
                                             uint32_t  dataWidthBitMask)
    {
        uint32_t     i, rxData;
        uint16_t     *bufferPtr = bufPtr;
    
        /* Read the data from RX FIFO for 16-bit transfer */
        for(i = 0U; i < transferLength; i++)
        {
            rxData = MCSPI_readRxDataReg(baseAddr, chNum);
            rxData &= dataWidthBitMask;         /* Clear unused bits */
           *bufferPtr = (uint16_t) rxData;
            bufferPtr++;
        }
    
        return (bufferPtr);
    }
    
    static inline uint32_t *MCSPI_fifoRead32(uint32_t  baseAddr,
                                             uint32_t  chNum,
                                             uint32_t  *bufPtr,
                                             uint32_t  transferLength,
                                             uint32_t  dataWidthBitMask)
    {
        uint32_t     i, rxData;
        uint32_t     *bufferPtr = bufPtr;
    
        /* Read the data from RX FIFO for 32-bit transfer */
        for(i = 0U; i < transferLength; i++)
        {
            rxData = MCSPI_readRxDataReg(baseAddr, chNum);
            rxData &= dataWidthBitMask;         /* Clear unused bits */
           *bufferPtr = (uint32_t) rxData;
            bufferPtr++;
        }
    
        return (bufferPtr);
    }
    
    static inline void MCSPI_fifoWriteDefault(uint32_t baseAddr,
                                              uint32_t chNum,
                                              uint32_t defaultTxData,
                                              uint32_t transferLength)
    {
        uint32_t        i;
    
        /* Write default data to TX FIFO */
        for(i = 0U; i < transferLength; i++)
        {
            CSL_REG32_WR(baseAddr + MCSPI_CHTX(chNum), defaultTxData);
        }
    
        return;
    }
    
    static inline void MCSPI_fifoReadDiscard(uint32_t baseAddr,
                                             uint32_t chNum,
                                             uint32_t transferLength)
    {
        uint32_t            i;
        volatile uint32_t   rxData;
    
        /* Read the data from RX FIFO and discard it */
        for(i = 0U; i < transferLength; i++)
        {
            rxData = MCSPI_readRxDataReg(baseAddr, chNum);
            (void) rxData;
        }
    
        return;
    }
    
    void MCSPI_clearAllIrqStatus(uint32_t baseAddr)
    {
        /* Clear all previous interrupt status */
        CSL_REG32_FINS(baseAddr + CSL_MCSPI_SYST, MCSPI_SYST_SSB, CSL_MCSPI_SYST_SSB_OFF);
        CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQSTATUS, MCSPI_IRQSTATUS_CLEAR_ALL);
    
        return;
    }
    
    static uint32_t Spi_mcspiGetTxMask(uint32_t csNum)
    {
        uint32_t txEmptyMask;
    
        if ((uint32_t)MCSPI_CHANNEL_0 == csNum)
        {
            txEmptyMask = (uint32_t) CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK;
        }
        else if ((uint32_t)MCSPI_CHANNEL_1 == csNum)
        {
            txEmptyMask = (uint32_t) CSL_MCSPI_IRQSTATUS_TX1_EMPTY_MASK;
        }
        else if ((uint32_t)MCSPI_CHANNEL_2 == csNum)
        {
            txEmptyMask = (uint32_t) CSL_MCSPI_IRQSTATUS_TX2_EMPTY_MASK;
        }
        else
        {
            txEmptyMask = (uint32_t) CSL_MCSPI_IRQSTATUS_TX3_EMPTY_MASK;
        }
    
        return (txEmptyMask);
    }
    
    static uint32_t Spi_mcspiGetRxMask(uint32_t csNum)
    {
        uint32_t rxFullMask;
    
        if ((uint32_t)MCSPI_CHANNEL_0 == csNum)
        {
            rxFullMask = (uint32_t) CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK;
        }
        else if ((uint32_t)MCSPI_CHANNEL_1 == csNum)
        {
            rxFullMask = (uint32_t) CSL_MCSPI_IRQSTATUS_RX1_FULL_MASK;
        }
        else if ((uint32_t)MCSPI_CHANNEL_2 == csNum)
        {
            rxFullMask = (uint32_t) CSL_MCSPI_IRQSTATUS_RX2_FULL_MASK;
        }
        else
        {
            rxFullMask = (uint32_t) CSL_MCSPI_IRQSTATUS_RX3_FULL_MASK;
        }
    
        return (rxFullMask);
    }
    
    void MCSPI_stop(MCSPILLD_Handle hMcspi, MCSPI_ChObject *chObj, uint32_t chNum)
    {
        uint32_t regVal, baseAddr;
        MCSPILLD_InitHandle hMcspiInit = hMcspi->hMcspiInit;
    
        baseAddr = hMcspi->baseAddr;
        if (MCSPI_OPER_MODE_INTERRUPT == hMcspiInit->operMode)
        {
            /* Disable channel interrupts. */
            regVal = CSL_REG32_RD(baseAddr + CSL_MCSPI_IRQENABLE);
            regVal &= ~(chObj->intrMask);
            CSL_REG32_WR(baseAddr + CSL_MCSPI_IRQENABLE, regVal);
        }
        MCSPI_intrStatusClear(chObj, baseAddr, chObj->intrMask);
    
        if(MCSPI_MS_MODE_CONTROLLER == hMcspiInit->msMode)
        {
            /* Manual CS de-assert */
            if(MCSPI_CH_MODE_SINGLE == hMcspiInit->chMode)
            {
                if (chObj->csDisable ==  TRUE)
                {
                    chObj->chConfRegVal &= (~CSL_MCSPI_CH0CONF_FORCE_MASK);
                    CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chObj->chCfg->chNum), chObj->chConfRegVal);
                    chObj->csEnable = TRUE;
                }
            }
        }
    
        /* Disable channel */
        CSL_REG32_FINS(
            baseAddr + MCSPI_CHCTRL(chNum),
            MCSPI_CH0CTRL_EN,
            CSL_MCSPI_CH0CTRL_EN_NACT);
    
        /* Disable TX and RX FIFO This is required so that next CS can
         * use the FIFO */
        chObj->chConfRegVal &= ~(CSL_MCSPI_CH0CONF_FFEW_MASK | CSL_MCSPI_CH0CONF_FFER_MASK);
        CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chNum), chObj->chConfRegVal);
    
    }
    
    void MCSPI_setChDataSize(uint32_t baseAddr, MCSPI_ChObject *chObj,
                                    uint32_t dataSize, uint32_t csDisable)
    {
        uint32_t chNum;
    
        chNum = chObj->chCfg->chNum;
        CSL_FINS(chObj->chConfRegVal, MCSPI_CH0CONF_WL, (dataSize - 1U));
        CSL_REG32_WR(baseAddr + MCSPI_CHCONF(chNum), chObj->chConfRegVal);
    
        chObj->csDisable = csDisable;
        /* Calculate buffer access width */
        chObj->bufWidthShift = MCSPI_getBufWidthShift(dataSize);
    
        /* Calculate data width mask depending on SPI word size */
        chObj->dataWidthBitMask = MCSPI_getDataWidthBitMask(dataSize);
    
        chObj->effTxFifoDepth = chObj->chCfg->txFifoTrigLvl >> chObj->bufWidthShift;
        chObj->effRxFifoDepth = chObj->chCfg->rxFifoTrigLvl >> chObj->bufWidthShift;
    
        return;
    }
    
    uint32_t MCSPI_lld_getBaseAddr(MCSPILLD_Handle hMcspi)
    {
        uint32_t            baseAddr;
    
        /* Check parameters */
        if (NULL == hMcspi)
        {
            baseAddr = 0U;
        }
        else
        {
            baseAddr = hMcspi->baseAddr;
        }
    
        return baseAddr;
    }
    
    int32_t MCSPI_lld_reConfigFifo(MCSPILLD_Handle hMcspi,
                               uint32_t chNum,
                               uint32_t numWordsRxTx)
    {
        uint32_t               baseAddr;
        MCSPI_ChObject        *chObj;
        int32_t                status = MCSPI_STATUS_SUCCESS;
        MCSPILLD_InitHandle    hMcspiInit;
    
        /* Check parameters */
        if((NULL == hMcspi) ||
           (NULL == hMcspi->hMcspiInit) ||
           (chNum >= MCSPI_MAX_NUM_CHANNELS))
        {
            status = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            baseAddr = hMcspi->baseAddr;
            hMcspiInit = hMcspi->hMcspiInit;
            chObj = &hMcspiInit->chObj[chNum];
    
            /* Re-Configure word count */
            if(MCSPI_OPER_MODE_DMA != hMcspiInit->operMode)
            {
                MCSPI_setFifoConfig(hMcspi, chObj, baseAddr, numWordsRxTx);
            }
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isOperModeValid(uint32_t operMode)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if((operMode == MCSPI_OPER_MODE_POLLED) ||
           (operMode == MCSPI_OPER_MODE_INTERRUPT) ||
           (operMode == MCSPI_OPER_MODE_DMA))
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isChModeValid(uint32_t chMode)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if((chMode == MCSPI_CH_MODE_SINGLE) || (chMode == MCSPI_CH_MODE_MULTI))
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isPinModeValid(uint32_t pinMode)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if((pinMode == MCSPI_PINMODE_3PIN) ||
           (pinMode == MCSPI_PINMODE_4PIN))
    
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isInitDelayValid(uint32_t initDelay)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if((initDelay == MCSPI_INITDLY_0) ||
           (initDelay == MCSPI_INITDLY_4) ||
           (initDelay == MCSPI_INITDLY_8) ||
           (initDelay == MCSPI_INITDLY_16) ||
           (initDelay == MCSPI_INITDLY_32))
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isMsModeValid(uint32_t msMode)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if((msMode == MCSPI_MS_MODE_CONTROLLER) ||
           (msMode == MCSPI_MS_MODE_PERIPHERAL))
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isDataSizeValid(uint32_t dataSize)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if((dataSize >= 4U) && (dataSize <= 32U))
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isHandleValid(MCSPI_DmaHandle handle)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if(handle != NULL_PTR)
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    static inline int32_t MCSPI_lld_isParameterValid(uint32_t handleParameters)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if(handleParameters != 0U)
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isChannelValid(uint32_t channel)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if(channel < MCSPI_MAX_NUM_CHANNELS)
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }
    
    static inline int32_t MCSPI_lld_isChCfgValid(const MCSPI_ChConfig *chCfg)
    {
        int32_t status = MCSPI_INVALID_PARAM;
    
        if((void *)chCfg != NULL_PTR)
        {
            status = MCSPI_STATUS_SUCCESS;
        }
    
        return status;
    }

    mcspi_v0.c

    /*
     *  Copyright (C) 2021-24 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /**
     *  \file mcspi_v0.c
     *
     *  \brief File containing MCSPI Driver APIs implementation for version V0.
     *
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    /* This is needed for memset/memcpy */
    #include <string.h>
    #include <drivers/mcspi.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include <kernel/dpl/HwiP.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/AddrTranslateP.h>
    #include <drivers/mcspi/v0/lld/mcspi_lld.h>
    #include <drivers/mcspi/v0/lld/dma/mcspi_dma.h>
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    typedef struct
    {
        void                   *lock;
        /**< Driver lock - to protect across open/close */
        SemaphoreP_Object       lockObj;
        /**< Driver lock object */
    } MCSPI_DrvObj;
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    /* Driver internal functions */
    static int32_t MCSPI_checkOpenParams(const MCSPI_OpenParams *openPrms);
    /* Transfer complete callback function */
    void MCSPI_transferCallback (void *args, uint32_t transferStatus);
    /* Error callback function */
    void MCSPI_errorCallback (void  *args, uint32_t transferStatus);
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /** \brief Driver object */
    static MCSPI_DrvObj     gMcspiDrvObj =
    {
        .lock           = NULL,
    };
    
    extern uint32_t              gMcspiNumCh[];
    extern MCSPI_DmaHandle       gMcspiDmaHandle[];
    extern MCSPI_DmaChConfig    *gMcspiDmaChConfig[];
    extern MCSPI_ChConfig       *gConfigMcspiChCfg[];
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    void MCSPI_init(void)
    {
        uint32_t       cnt;
        MCSPI_Object  *obj;
        int32_t        status = SystemP_SUCCESS;
    
        /* Init each driver instance object */
        for (cnt = 0U; cnt < gMcspiConfigNum; cnt++)
        {
            /* initialize object varibles */
            obj = gMcspiConfig[cnt].object;
            DebugP_assert(NULL_PTR != obj);
            (void)memset(obj, 0, sizeof(MCSPI_Object));
        }
    
        /* Create driver lock */
        status = SemaphoreP_constructMutex(&gMcspiDrvObj.lockObj);
        if(status == SystemP_SUCCESS)
        {
            gMcspiDrvObj.lock = &gMcspiDrvObj.lockObj;
        }
    
        return;
    }
    
    void MCSPI_deinit(void)
    {
        /* Delete driver lock */
        if(NULL != gMcspiDrvObj.lock)
        {
            SemaphoreP_destruct(&gMcspiDrvObj.lockObj);
            gMcspiDrvObj.lock = NULL;
        }
    
        return;
    }
    
    MCSPI_Handle MCSPI_open(uint32_t index, const MCSPI_OpenParams *openPrms)
    {
        int32_t              status = SystemP_SUCCESS;
        uint8_t              configNum, chNum;
        MCSPI_Handle         handle = NULL;
        MCSPI_Config        *config = NULL;
        MCSPI_Object        *obj    = NULL;
        HwiP_Params          hwiPrms;
        MCSPILLD_Handle      mcspiLldHandle;
        MCSPILLD_InitHandle  mcspiLldInithandle;
        MCSPI_ChConfig      *lldChCfg, *chConfig;
        MCSPI_DmaChConfig    dmaChConfig;
        const MCSPI_Attrs   *attrs;
    
        /* Check index */
        if(index >= gMcspiConfigNum)
        {
            status = SystemP_FAILURE;
        }
        else
        {
            config = &gMcspiConfig[index];
        }
    
        DebugP_assert(NULL_PTR != gMcspiDrvObj.lock);
        status += SemaphoreP_pend(&gMcspiDrvObj.lockObj, SystemP_WAIT_FOREVER);
    
        if(SystemP_SUCCESS == status)
        {
            obj = config->object;
            DebugP_assert(NULL_PTR != obj);
            DebugP_assert(NULL_PTR != config->attrs);
            attrs = config->attrs;
    
            /* Init state */
            obj->handle = (MCSPI_Handle) config;
            (void)memset(&obj->chObj, 0, sizeof(obj->chObj));
            obj->baseAddr = (uint32_t) AddrTranslateP_getLocalAddr(attrs->baseAddr);
    
            if(NULL != openPrms)
            {
                (void)memcpy(&obj->openPrms, openPrms, sizeof(MCSPI_OpenParams));
            }
            else
            {
                /* Init with default if NULL is passed */
                MCSPI_OpenParams_init(&obj->openPrms);
            }
    
            /*  Mapping HLD parameter with LLD. */
            obj->mcspiLldHandle           = &obj->mcspiLldObject;
            mcspiLldHandle                = obj->mcspiLldHandle;
            mcspiLldHandle->hMcspiInit    = &obj->mcspiLldInitObj;
            mcspiLldInithandle            = mcspiLldHandle->hMcspiInit;
    
            /* Check open parameters */
            status += MCSPI_checkOpenParams(&obj->openPrms);
    
            if((status == SystemP_SUCCESS) && (openPrms != NULL))
            {
                /* populating LLD parameters. */
                mcspiLldHandle->baseAddr                 = obj->baseAddr;
                mcspiLldHandle->state                    = MCSPI_STATE_RESET;
                mcspiLldHandle->args                     = (MCSPI_Handle)obj->handle;
                mcspiLldHandle->errorFlag                = 0;
                mcspiLldInithandle->inputClkFreq         = attrs->inputClkFreq;
                mcspiLldInithandle->intrNum              = attrs->intrNum;
                mcspiLldInithandle->operMode             = attrs->operMode;
                mcspiLldInithandle->chMode               = attrs->chMode;
                mcspiLldInithandle->pinMode              = attrs->pinMode;
                mcspiLldInithandle->initDelay            = attrs->initDelay;
                mcspiLldInithandle->multiWordAccess      = attrs->multiWordAccess;
                mcspiLldInithandle->msMode               = openPrms->msMode;
                mcspiLldInithandle->mcspiDmaHandle       = (MCSPI_DmaHandle) gMcspiDmaHandle[0];
                mcspiLldInithandle->clockP_get           = ClockP_getTicks;
                mcspiLldInithandle->transferCallbackFxn  = MCSPI_transferCallback;
                mcspiLldInithandle->errorCallbackFxn     = MCSPI_errorCallback;
    
                chConfig    = gConfigMcspiChCfg[index];
                dmaChConfig = gMcspiDmaChConfig[index];
    
                for(configNum = 0; configNum < gMcspiNumCh[index]; configNum++)
                {
                    chNum = chConfig[configNum].chNum;
                    mcspiLldInithandle->chObj[chNum].chCfg = &chConfig[configNum];
                    lldChCfg = mcspiLldInithandle->chObj[chNum].chCfg;
    
                    lldChCfg->chNum         = chNum;
                    lldChCfg->frameFormat   = chConfig[configNum].frameFormat;
                    lldChCfg->bitRate       = chConfig[configNum].bitRate;
                    lldChCfg->csPolarity    = chConfig[configNum].csPolarity;
                    lldChCfg->trMode        = chConfig[configNum].trMode;
                    lldChCfg->inputSelect   = chConfig[configNum].inputSelect;
                    lldChCfg->dpe0          = chConfig[configNum].dpe0;
                    lldChCfg->dpe1          = chConfig[configNum].dpe1;
                    lldChCfg->slvCsSelect   = chConfig[configNum].slvCsSelect;
                    lldChCfg->startBitEnable   = chConfig[configNum].startBitEnable;
                    lldChCfg->startBitPolarity = chConfig[configNum].startBitPolarity;
                    lldChCfg->turboEnable   = chConfig[configNum].turboEnable;
                    lldChCfg->csIdleTime    = chConfig[configNum].csIdleTime;
                    lldChCfg->defaultTxData = chConfig[configNum].defaultTxData;
                    lldChCfg->txFifoTrigLvl = chConfig[configNum].txFifoTrigLvl;
                    lldChCfg->rxFifoTrigLvl = chConfig[configNum].rxFifoTrigLvl;
    
                    mcspiLldInithandle->chObj[chNum].dmaChCfg = dmaChConfig;
                    mcspiLldInithandle->chObj[chNum].dmaChConfigNum = configNum;
                    mcspiLldInithandle->chEnabled[chNum] = TRUE;
                }
            }
    
            if(MCSPI_OPER_MODE_DMA == attrs->operMode)
            {
                status = MCSPI_lld_initDma(mcspiLldHandle);
            }
            else
            {
                status = MCSPI_lld_init(mcspiLldHandle);
            }
            if(status == MCSPI_STATUS_SUCCESS)
            {
                status = SystemP_SUCCESS;
            }
            else
            {
                status = SystemP_FAILURE;
            }
        }
        if(SystemP_SUCCESS == status)
        {
            /* Create transfer sync semaphore */
            status = SemaphoreP_constructBinary(&obj->transferSemObj, 0U);
            obj->transferSem = &obj->transferSemObj;
            mcspiLldHandle->transferMutex = obj->transferSem;
    
            /* Register interrupt */
            if(MCSPI_OPER_MODE_INTERRUPT == attrs->operMode)
            {
                HwiP_Params_init(&hwiPrms);
                hwiPrms.intNum      = attrs->intrNum;
                hwiPrms.priority    = attrs->intrPriority;
                if(MCSPI_MS_MODE_CONTROLLER == obj->openPrms.msMode)
                {
                    hwiPrms.callback    = &MCSPI_lld_controllerIsr;
                }
                else
                {
                    hwiPrms.callback    = &MCSPI_lld_peripheralIsr;
                }
    
                hwiPrms.priority    = attrs->intrPriority;
                hwiPrms.args        = (void *) mcspiLldHandle;
                status += HwiP_construct(&obj->hwiObj, &hwiPrms);
                obj->hwiHandle = &obj->hwiObj;
                obj->hwiHandle = &obj->hwiObj;
            }
        }
    
        if(SystemP_SUCCESS == status)
        {
            obj->isOpen = TRUE;
            handle = (MCSPI_Handle) config;
        }
    
        SemaphoreP_post(&gMcspiDrvObj.lockObj);
    
        /* Free-up resources in case of error */
        if ((SystemP_SUCCESS != status) && ((NULL != config)))
        {
            MCSPI_close((MCSPI_Handle) config);
        }
    
        return (handle);
    }
    
    MCSPI_Handle MCSPI_getHandle(uint32_t index)
    {
        MCSPI_Handle         handle = NULL;
    
        /* Check index */
        if(index < gMcspiConfigNum)
        {
            MCSPI_Object *object;
    
            object = gMcspiConfig[index].object;
    
            if(object && (TRUE == object->isOpen))
            {
                /* valid handle */
                handle = object->handle;
            }
        }
    
        return handle;
    }
    
    void MCSPI_close(MCSPI_Handle handle)
    {
        MCSPI_Config        *config;
        MCSPI_Object        *obj;
        MCSPILLD_Handle      mcspiLldHandle;
        int32_t              status = SystemP_FAILURE;
    
        if(NULL != handle)
        {
            config = (MCSPI_Config *)handle;
            obj    = config->object;
            DebugP_assert(NULL_PTR != obj);
            DebugP_assert(NULL_PTR != config->attrs);
            DebugP_assert(NULL_PTR != gMcspiDrvObj.lock);
    
            mcspiLldHandle = obj->mcspiLldHandle;
            status = SemaphoreP_pend(&gMcspiDrvObj.lockObj, SystemP_WAIT_FOREVER);
    
            if(MCSPI_OPER_MODE_DMA == config->attrs->operMode)
            {
                status += MCSPI_lld_deInitDma(mcspiLldHandle);
                DebugP_assert(SystemP_SUCCESS == status);
            }
            else
            {
                status += MCSPI_lld_deInit(mcspiLldHandle);
                DebugP_assert(SystemP_SUCCESS == status);
            }
    
            if(NULL != obj->transferSem)
            {
                SemaphoreP_destruct(&obj->transferSemObj);
                obj->transferSem = NULL;
            }
            if(NULL != obj->hwiHandle)
            {
                HwiP_destruct(&obj->hwiObj);
                obj->hwiHandle = NULL;
            }
    
            obj->isOpen = FALSE;
            SemaphoreP_post(&gMcspiDrvObj.lockObj);
        }
    
        return;
    }
    
    int32_t MCSPI_chConfig(MCSPI_Handle handle, const MCSPI_ChConfig *chCfg)
    {
        /* MCSPI channels are already initialized in MCSPI_lld_init().
        *  Here this function is declared in order to avoid HLD flow
        */
        return SystemP_SUCCESS;
    }
    
    int32_t MCSPI_dmaChConfig(MCSPI_Handle handle,
                           const MCSPI_ChConfig *chCfg,
                           const MCSPI_DmaChConfig *dmaChCfg)
    {
        /* MCSPI dma channels are already initialized in MCSPI_lld_init().
        *  Here this function is declared in order to avoid HLD flow
        */
        return SystemP_SUCCESS;
    }
    
    int32_t MCSPI_transfer(MCSPI_Handle handle, MCSPI_Transaction *transaction)
    {
        int32_t             status = MCSPI_STATUS_SUCCESS, semStatus;
        int32_t             lldStatus = MCSPI_STATUS_SUCCESS;
        uint32_t            chNum = 0;
        MCSPI_Config       *config;
        MCSPI_Object       *obj;
        const MCSPI_Attrs  *attrs;
        uintptr_t key;
    
        MCSPILLD_Handle         mcspiLldHandle;
        MCSPILLD_InitHandle     mcspiLldInithandle;
        MCSPI_ExtendedParams    extendedParams;
    
        /* Check parameters */
        if((NULL == handle) || (NULL == transaction))
        {
            lldStatus = MCSPI_INVALID_PARAM;
        }
    
        if(MCSPI_STATUS_SUCCESS == lldStatus)
        {
            config = (MCSPI_Config *) handle;
            obj = config->object;
            DebugP_assert(NULL_PTR != obj);
            DebugP_assert(NULL_PTR != config->attrs);
            attrs = config->attrs;
    
            mcspiLldHandle = obj->mcspiLldHandle;
            mcspiLldInithandle = obj->mcspiLldHandle->hMcspiInit;
            /* populate transaction parameters. */
            extendedParams.channel   = transaction->channel;
            extendedParams.dataSize  = transaction->dataSize;
            extendedParams.csDisable = transaction->csDisable;
            extendedParams.args      = transaction->args;
    
            /*  update timeout parameter from syscfg  */
            transaction->timeout = obj->openPrms.transferTimeout;
            key = HwiP_disable();
    
            /* Check if any transaction is in progress */
            if(NULL == obj->transaction)
            {
                /* Start transfer */
                obj->transaction = transaction;
                obj->transaction->status = MCSPI_TRANSFER_STARTED;
                (void)memcpy(&mcspiLldHandle->transaction, obj->transaction,
                             sizeof(mcspiLldHandle->transaction));
                HwiP_restore(key);
    
                if ((MCSPI_OPER_MODE_INTERRUPT == attrs->operMode) ||
                    (MCSPI_OPER_MODE_DMA == attrs->operMode))
                {
                    if (MCSPI_OPER_MODE_INTERRUPT == attrs->operMode)
                    {
                        lldStatus = MCSPI_lld_readWriteIntr(mcspiLldHandle, transaction->txBuf,
                                                        transaction->rxBuf, transaction->count,
                                                        transaction->timeout, &extendedParams);
                    }
                    else
                    {
                        lldStatus = MCSPI_lld_readWriteDma(mcspiLldHandle, transaction->txBuf,
                                                        transaction->rxBuf, transaction->count,
                                                        transaction->timeout, &extendedParams);
                    }
                    if (lldStatus == MCSPI_STATUS_SUCCESS)
                    {
                        if (obj->openPrms.transferMode == MCSPI_TRANSFER_MODE_BLOCKING)
                        {
                            /* Block on transferSem till the transfer completion. */
                            DebugP_assert(NULL_PTR != obj->transferSem);
                            semStatus = SemaphoreP_pend(&obj->transferSemObj, obj->openPrms.transferTimeout);
                            if (semStatus == SystemP_SUCCESS)
                            {
                                status = SystemP_SUCCESS;
                            }
                            else
                            {
                                MCSPI_stop(mcspiLldHandle, &mcspiLldInithandle->chObj[chNum], chNum);
                                status = SystemP_FAILURE;
                                /* update HLD current transaction status from LLD */
                                (void)memcpy(obj->transaction,
                                             &mcspiLldHandle->transaction,
                                             sizeof(mcspiLldHandle->transaction));
    
                                transaction->status = MCSPI_TRANSFER_TIMEOUT;
                                obj->transaction = NULL;
                            }
                        }
                    }
                    else
                    {
                        status = SystemP_FAILURE;
                    }
                }
                else
                {
                    lldStatus = MCSPI_lld_readWrite(mcspiLldHandle, transaction->txBuf,
                                                transaction->rxBuf, transaction->count,
                                                transaction->timeout, &extendedParams);
    
                    if (lldStatus == MCSPI_STATUS_SUCCESS)
                    {
                        status = SystemP_SUCCESS;
                        /* update HLD current transaction status from LLD */
                        (void)memcpy(obj->transaction,
                                     &mcspiLldHandle->transaction,
                                     sizeof(mcspiLldHandle->transaction));
    
                        transaction->status = MCSPI_TRANSFER_COMPLETED;
                    }
                    else if(lldStatus == MCSPI_TRANSFER_TIMEOUT)
                    {
                        status = SystemP_FAILURE;
                        transaction->status = MCSPI_TRANSFER_TIMEOUT;
                    }
                    else
                    {
                        status  = SystemP_FAILURE;
                        transaction->status = MCSPI_TRANSFER_FAILED;
                    }
    
                    obj->transaction = NULL;
                }
            }
            else
            {
                HwiP_restore(key);
                /* other transaction is in progress */
                status = SystemP_FAILURE;
                transaction->status = MCSPI_TRANSFER_CANCELLED;
            }
        }
    
        return (status);
    }
    
    int32_t MCSPI_transferCancel(MCSPI_Handle handle)
    {
        int32_t             status = MCSPI_STATUS_SUCCESS;
        int32_t             lldStatus = MCSPI_STATUS_SUCCESS;
        MCSPI_Config        *config;
        MCSPI_Object        *obj;
        const MCSPI_Attrs   *attrs;
        MCSPILLD_Handle      mcspiLldHandle;
    
        /* Check parameters */
        if (NULL == handle)
        {
            status = MCSPI_STATUS_FAILURE;
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            config = (MCSPI_Config *) handle;
            obj    = config->object;
            DebugP_assert(NULL_PTR != obj);
            DebugP_assert(NULL_PTR != config->attrs);
            attrs = config->attrs;
            if (obj->transaction == NULL)
            {
                status = MCSPI_STATUS_FAILURE;
            }
        }
    
        if(MCSPI_STATUS_SUCCESS == status)
        {
            mcspiLldHandle = obj->mcspiLldHandle;
            if (MCSPI_OPER_MODE_DMA != attrs->operMode)
            {
                lldStatus = MCSPI_lld_readWriteCancel(mcspiLldHandle);
            }
            else
            {
                lldStatus = MCSPI_lld_readWriteDmaCancel(mcspiLldHandle);
            }
    
            obj->transaction->status = MCSPI_TRANSFER_CANCELLED;
            obj->transaction = NULL;
        }
        if ((lldStatus != MCSPI_STATUS_SUCCESS) &&
            (lldStatus == MCSPI_INVALID_PARAM)  &&
            (lldStatus != MCSPI_TRANSFER_CANCELLED))
        {
            status = SystemP_FAILURE;
        }
        else
        {
            status = SystemP_SUCCESS;
        }
    
        return (status);
    }
    
    static int32_t MCSPI_checkOpenParams(const MCSPI_OpenParams *openPrms)
    {
        int32_t     status = SystemP_SUCCESS;
    
        if((MCSPI_TRANSFER_MODE_CALLBACK == openPrms->transferMode) &&
           (NULL == openPrms->transferCallbackFxn))
        {
            DebugP_logError("[MCSPI] Callback should be provided when using callback mode !!!\r\n");
            status = SystemP_FAILURE;
        }
    
        return (status);
    }
    
    void MCSPI_transferCallback (void *args, uint32_t transferStatus)
    {
        MCSPI_Config   *config;
        MCSPI_Object   *obj;
    
        MCSPILLD_Handle hMcspi = (MCSPILLD_Handle)args;
        if(NULL != hMcspi)
        {
            MCSPI_Handle handle = (MCSPI_Handle)hMcspi->args;
    
            if(NULL != handle)
            {
                config = (MCSPI_Config *) handle;
                obj    = config->object;
    
                (void)memcpy(obj->transaction,
                             &hMcspi->transaction,
                             sizeof(hMcspi->transaction));
    
                if(transferStatus == (uint32_t) MCSPI_TRANSFER_CANCELLED)
                {
                    obj->transaction->status = MCSPI_TRANSFER_CANCELLED;
                }
                else
                {
                    obj->transaction->status = MCSPI_TRANSFER_COMPLETED;
                }
    
                if((obj->openPrms.transferMode) == MCSPI_TRANSFER_MODE_CALLBACK)
                {
                    obj->openPrms.transferCallbackFxn(hMcspi, obj->transaction);
                }
                else
                {
                    SemaphoreP_post((SemaphoreP_Object *)hMcspi->transferMutex);
                }
                obj->transaction = NULL;
            }
        }
    }
    
    void MCSPI_errorCallback (void *args, uint32_t transferStatus)
    {
        MCSPI_Config   *config;
        MCSPI_Object   *obj;
    
        MCSPILLD_Handle hMcspi = (MCSPILLD_Handle)args;
        if(NULL != hMcspi)
        {
            MCSPI_Handle handle = (MCSPI_Handle)hMcspi->args;
    
            if(NULL != handle)
            {
                config = (MCSPI_Config *) handle;
                obj    = config->object;
                if((obj->openPrms.transferMode) == MCSPI_TRANSFER_MODE_CALLBACK)
                {
                    obj->openPrms.transferCallbackFxn(hMcspi, &hMcspi->transaction);
                }
                else
                {
                    SemaphoreP_post((SemaphoreP_Object *)hMcspi->transferMutex);
                }
    
                (void)memcpy(obj->transaction,
                             &hMcspi->transaction,
                             sizeof(hMcspi->transaction));
    
                obj->transaction->status = MCSPI_TRANSFER_FAILED;
                obj->transaction = NULL;
            }
        }
    }
    
    /* ========================================================================== */
    /*                       Advanced Function Definitions                        */
    /* ========================================================================== */
    
    uint32_t MCSPI_getBaseAddr(MCSPI_Handle handle)
    {
        MCSPI_Config       *config;
        MCSPI_Object       *obj;
        uint32_t            baseAddr;
    
        /* Check parameters */
        if (NULL == handle)
        {
            baseAddr = 0U;
        }
        else
        {
            config   = (MCSPI_Config *) handle;
            obj      = config->object;
            baseAddr = obj->baseAddr;
        }
    
        return baseAddr;
    }
    
    int32_t MCSPI_reConfigFifo(MCSPI_Handle handle, uint32_t chNum, uint32_t numWordsRxTx)
    {
        MCSPI_Config        *config;
        MCSPI_Object        *obj;
        int32_t              status = SystemP_SUCCESS;
        MCSPILLD_Handle      hMcspi;
    
        /* Check parameters */
        if((NULL == handle) || (chNum >= MCSPI_MAX_NUM_CHANNELS))
        {
            status = SystemP_FAILURE;
        }
    
        if(SystemP_SUCCESS == status)
        {
            config = (MCSPI_Config *) handle;
            obj = config->object;
            hMcspi = obj->mcspiLldHandle;
    
            status = MCSPI_lld_reConfigFifo(hMcspi, chNum, numWordsRxTx);
        }
    
        return status;
    }

    Regards,

    Vaibhav

  • Hello Vaibhav,

    Thank you for the help!

    Best regards,

    Andrean