1096 lines
39 KiB
C
1096 lines
39 KiB
C
/**
|
|
*******************************************************************************
|
|
* @file hc32f4a0_spi.c
|
|
* @brief This file provides firmware functions to manage the Serial Peripheral
|
|
* Interface(SPI).
|
|
@verbatim
|
|
Change Logs:
|
|
Date Author Notes
|
|
2020-06-12 Wangmin First version
|
|
2020-08-31 Wangmin Modify for MISRAC2012
|
|
2020-10-13 Wangmin Define variable for count as __IO type
|
|
@endverbatim
|
|
*******************************************************************************
|
|
* Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
|
|
*
|
|
* This software component is licensed by HDSC under BSD 3-Clause license
|
|
* (the "License"); You may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at:
|
|
* opensource.org/licenses/BSD-3-Clause
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* Include files
|
|
******************************************************************************/
|
|
#include "hc32f4a0_spi.h"
|
|
#include "hc32f4a0_utility.h"
|
|
|
|
/**
|
|
* @addtogroup HC32F4A0_DDL_Driver
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @defgroup DDL_SPI SPI
|
|
* @brief Serial Peripheral Interface Driver Library
|
|
* @{
|
|
*/
|
|
|
|
#if (DDL_SPI_ENABLE == DDL_ON)
|
|
|
|
/*******************************************************************************
|
|
* Local type definitions ('typedef')
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Local pre-processor symbols/macros ('#define')
|
|
******************************************************************************/
|
|
/**
|
|
* @defgroup SPI_Local_Macros SPI Local Macros
|
|
* @{
|
|
*/
|
|
|
|
#define SPI_CFG1_DEFAULT (0x00000010UL)
|
|
#define SPI_CFG2_DEFAULT (0x00000F1DUL)
|
|
#define SPI_SR_DEFAULT (0x00000020UL)
|
|
|
|
#define SPI_IRQ_MASK ( SPI_INT_ERROR | \
|
|
SPI_INT_TX_BUFFER_EMPTY | \
|
|
SPI_INT_RX_BUFFER_FULL | \
|
|
SPI_INT_IDLE )
|
|
#define SPI_GET_STD_MASK ( SPI_FLAG_OVERLOAD | \
|
|
SPI_FLAG_IDLE | \
|
|
SPI_FLAG_MODE_FAULT | \
|
|
SPI_FLAG_PARITY_ERROR | \
|
|
SPI_FLAG_UNDERLOAD | \
|
|
SPI_FLAG_TX_BUFFER_EMPTY | \
|
|
SPI_FLAG_RX_BUFFER_FULL )
|
|
#define SPI_CLR_STD_MASK ( SPI_FLAG_OVERLOAD | \
|
|
SPI_FLAG_MODE_FAULT | \
|
|
SPI_FLAG_PARITY_ERROR | \
|
|
SPI_FLAG_UNDERLOAD )
|
|
|
|
#define SPI_SS0_VALID_CFG (0UL)
|
|
#define SPI_SS1_VALID_CFG (SPI_CFG2_SSA_0)
|
|
#define SPI_SS2_VALID_CFG (SPI_CFG2_SSA_1)
|
|
#define SPI_SS3_VALID_CFG (SPI_CFG2_SSA_0 | SPI_CFG2_SSA_1)
|
|
|
|
/**
|
|
* @defgroup SPI_Check_Parameters_Validity SPI check parameters validity
|
|
* @{
|
|
*/
|
|
|
|
/*! Parameter valid check for SPI peripheral */
|
|
#define IS_VALID_SPI_UNIT(x) \
|
|
( (M4_SPI1 == (x)) || \
|
|
(M4_SPI2 == (x)) || \
|
|
(M4_SPI3 == (x)) || \
|
|
(M4_SPI4 == (x)) || \
|
|
(M4_SPI5 == (x)) || \
|
|
(M4_SPI6 == (x)))
|
|
|
|
/*! Parameter valid check for SPI wire mode */
|
|
#define IS_SPI_WIRE_MODE(x) \
|
|
( ((x) == SPI_WIRE_4) || \
|
|
((x) == SPI_WIRE_3))
|
|
|
|
/*! Parameter valid check for SPI transfer mode */
|
|
#define IS_SPI_TRANS_MODE(x) \
|
|
( ((x) == SPI_FULL_DUPLEX) || \
|
|
((x) == SPI_SEND_ONLY))
|
|
|
|
/*! Parameter valid check for SPI master slave mode */
|
|
#define IS_SPI_MASTER_SLAVE(x) \
|
|
( ((x) == SPI_SLAVE) || \
|
|
((x) == SPI_MASTER))
|
|
|
|
/*! Parameter valid check for SPI loopback mode */
|
|
#define IS_SPI_SPLPBK(x) \
|
|
( ((x) == SPI_SPLPBK_INVALID) || \
|
|
((x) == SPI_SPLPBK_MOSI_INVERT) || \
|
|
((x) == SPI_SPLPBK_MOSI))
|
|
|
|
/*! Parameter valid check for SPI communication suspend function status */
|
|
#define IS_SPI_SUSP_MODE_STD(x) \
|
|
( ((x) == SPI_COM_SUSP_FUNC_OFF) || \
|
|
((x) == SPI_COM_SUSP_FUNC_ON))
|
|
|
|
/*! Parameter valid check for SPI fault dectet function status */
|
|
#define IS_SPI_MODFE_CMD(x) \
|
|
( ((x) == SPI_MODFE_DISABLE) || \
|
|
((x) == SPI_MODFE_ENABLE))
|
|
|
|
/*! Parameter valid check for SPI parity check mode */
|
|
#define IS_SPI_PARITY_CHECK(x) \
|
|
( ((x) == SPI_PARITY_INVALID) || \
|
|
((x) == SPI_PARITY_EVEN) || \
|
|
((x) == SPI_PARITY_ODD))
|
|
|
|
/*! Parameter valid check for SPI interval time delay */
|
|
#define IS_SPI_INTERVAL_DELAY(x) \
|
|
( ((x) == SPI_INTERVAL_TIME_1SCK_2PCLK1) || \
|
|
((x) == SPI_INTERVAL_TIME_2SCK_2PCLK1) || \
|
|
((x) == SPI_INTERVAL_TIME_3SCK_2PCLK1) || \
|
|
((x) == SPI_INTERVAL_TIME_4SCK_2PCLK1) || \
|
|
((x) == SPI_INTERVAL_TIME_5SCK_2PCLK1) || \
|
|
((x) == SPI_INTERVAL_TIME_6SCK_2PCLK1) || \
|
|
((x) == SPI_INTERVAL_TIME_7SCK_2PCLK1) || \
|
|
((x) == SPI_INTERVAL_TIME_8SCK_2PCLK1))
|
|
|
|
/*! Parameter valid check for SPI release time delay */
|
|
#define IS_SPI_RELEASE_DELAY(x) \
|
|
( ((x) == SPI_RELEASE_TIME_1SCK) || \
|
|
((x) == SPI_RELEASE_TIME_2SCK) || \
|
|
((x) == SPI_RELEASE_TIME_3SCK) || \
|
|
((x) == SPI_RELEASE_TIME_4SCK) || \
|
|
((x) == SPI_RELEASE_TIME_5SCK) || \
|
|
((x) == SPI_RELEASE_TIME_6SCK) || \
|
|
((x) == SPI_RELEASE_TIME_7SCK) || \
|
|
((x) == SPI_RELEASE_TIME_8SCK))
|
|
|
|
/*! Parameter valid check for SPI Setup time delay delay */
|
|
#define IS_SPI_SETUP_DELAY(x) \
|
|
( ((x) == SPI_SETUP_TIME_1SCK) || \
|
|
((x) == SPI_SETUP_TIME_2SCK) || \
|
|
((x) == SPI_SETUP_TIME_3SCK) || \
|
|
((x) == SPI_SETUP_TIME_4SCK) || \
|
|
((x) == SPI_SETUP_TIME_5SCK) || \
|
|
((x) == SPI_SETUP_TIME_6SCK) || \
|
|
((x) == SPI_SETUP_TIME_7SCK) || \
|
|
((x) == SPI_SETUP_TIME_8SCK))
|
|
|
|
/*! Parameter valid check for SPI SS active level */
|
|
#define IS_SPI_SS_ACTIVE_LEVEL(x) \
|
|
( ((x) == SPI_SS_ACTIVE_LOW) || \
|
|
((x) == SPI_SS_ACTIVE_HIGH))
|
|
|
|
/*! Parameter valid check for SPI read data register target buffer */
|
|
#define IS_SPI_RD_TARGET_BUFF(x) \
|
|
( ((x) == SPI_RD_TARGET_RD_BUF) || \
|
|
((x) == SPI_RD_TARGET_WR_BUF))
|
|
|
|
/*! Parameter valid check for SPI mode */
|
|
#define IS_SPI_SPI_MODE(x) \
|
|
( ((x) == SPI_MODE_0) || \
|
|
((x) == SPI_MODE_1) || \
|
|
((x) == SPI_MODE_2) || \
|
|
((x) == SPI_MODE_3))
|
|
|
|
/*! Parameter valid check for SPI SS signal */
|
|
#define IS_SPI_SS_PIN(x) \
|
|
( ((x) == SPI_PIN_SS0) || \
|
|
((x) == SPI_PIN_SS1) || \
|
|
((x) == SPI_PIN_SS2) || \
|
|
((x) == SPI_PIN_SS3))
|
|
|
|
/*! Parameter valid check for SPI baudrate prescaler */
|
|
#define IS_SPI_BIT_RATE_DIV(x) \
|
|
( ((x) == SPI_BR_PCLK1_DIV2) || \
|
|
((x) == SPI_BR_PCLK1_DIV4) || \
|
|
((x) == SPI_BR_PCLK1_DIV8) || \
|
|
((x) == SPI_BR_PCLK1_DIV16) || \
|
|
((x) == SPI_BR_PCLK1_DIV32) || \
|
|
((x) == SPI_BR_PCLK1_DIV64) || \
|
|
((x) == SPI_BR_PCLK1_DIV128) || \
|
|
((x) == SPI_BR_PCLK1_DIV256))
|
|
|
|
/*! Parameter valid check for SPI data bits */
|
|
#define IS_SPI_DATA_SIZE(x) \
|
|
( ((x) == SPI_DATA_SIZE_4BIT) || \
|
|
((x) == SPI_DATA_SIZE_5BIT) || \
|
|
((x) == SPI_DATA_SIZE_6BIT) || \
|
|
((x) == SPI_DATA_SIZE_7BIT) || \
|
|
((x) == SPI_DATA_SIZE_8BIT) || \
|
|
((x) == SPI_DATA_SIZE_9BIT) || \
|
|
((x) == SPI_DATA_SIZE_10BIT) || \
|
|
((x) == SPI_DATA_SIZE_11BIT) || \
|
|
((x) == SPI_DATA_SIZE_12BIT) || \
|
|
((x) == SPI_DATA_SIZE_13BIT) || \
|
|
((x) == SPI_DATA_SIZE_14BIT) || \
|
|
((x) == SPI_DATA_SIZE_15BIT) || \
|
|
((x) == SPI_DATA_SIZE_16BIT) || \
|
|
((x) == SPI_DATA_SIZE_20BIT) || \
|
|
((x) == SPI_DATA_SIZE_24BIT) || \
|
|
((x) == SPI_DATA_SIZE_32BIT))
|
|
|
|
/*! Parameter valid check for SPI data frame level */
|
|
#define IS_SPI_DATA_FRAME(x) \
|
|
( ((x) == SPI_FRAME_1) || \
|
|
((x) == SPI_FRAME_2) || \
|
|
((x) == SPI_FRAME_3) || \
|
|
((x) == SPI_FRAME_4))
|
|
|
|
/*! Parameter valid check for SPI LSB MSB mode */
|
|
#define IS_SPI_FIRST_BIT(x) \
|
|
( ((x) == SPI_FIRST_MSB) || \
|
|
((x) == SPI_FIRST_LSB))
|
|
|
|
/*! Parameter valid check for interrupt flag */
|
|
#define IS_SPI_IRQ_FLAG(x) \
|
|
( ((x) != 0UL) && \
|
|
(((x) | SPI_IRQ_MASK) == SPI_IRQ_MASK))
|
|
|
|
/*! Parameter valid check for SPI status flag */
|
|
#define IS_SPI_STD_FLAG(x) \
|
|
( ((x) != 0UL) && \
|
|
(((x) | SPI_GET_STD_MASK) == SPI_GET_STD_MASK))
|
|
|
|
/*! Parameter valid check for SPI status flag for clear */
|
|
#define IS_SPI_CLR_STD_FLAG(x) \
|
|
( ((x) != 0UL) && \
|
|
(((x) | SPI_CLR_STD_MASK) == SPI_CLR_STD_MASK))
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* Global variable definitions (declared in header file with 'extern')
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Local function prototypes ('static')
|
|
******************************************************************************/
|
|
/**
|
|
* @defgroup SPI_Local_Functions SPI Local Functions
|
|
* @{
|
|
*/
|
|
|
|
static en_result_t SPI_TxRx(M4_SPI_TypeDef *SPIx, const void *pvTxBuf, void *pvRxBuf, uint32_t u32Length);
|
|
static en_result_t SPI_Tx(M4_SPI_TypeDef *SPIx, const void *pvTxBuf, uint32_t u32Length);
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* Local variable definitions ('static')
|
|
******************************************************************************/
|
|
|
|
|
|
/*******************************************************************************
|
|
* Function implementation - global ('extern') and local ('static')
|
|
******************************************************************************/
|
|
/**
|
|
* @defgroup SPI_Global_Functions SPI Global Functions
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Initializes the SPI peripheral according to the specified parameters
|
|
* in the structure stc_spi_init.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] pstcInit Pointer to a stc_spi_init_t structure that contains
|
|
* the configuration information for the SPI.
|
|
* @retval An en_result_t enumeration value:
|
|
* @arg Ok: No errors occurred
|
|
* @arg ErrorInvalidParameter: pstcInit == NULL or configuration parameter error.
|
|
*/
|
|
en_result_t SPI_Init(M4_SPI_TypeDef *SPIx, const stc_spi_init_t *pstcInit)
|
|
{
|
|
en_result_t enRet = ErrorInvalidParameter;
|
|
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
|
|
if (NULL != pstcInit)
|
|
{
|
|
DDL_ASSERT(IS_SPI_WIRE_MODE(pstcInit->u32WireMode));
|
|
DDL_ASSERT(IS_SPI_TRANS_MODE(pstcInit->u32TransMode));
|
|
DDL_ASSERT(IS_SPI_MASTER_SLAVE(pstcInit->u32MasterSlave));
|
|
DDL_ASSERT(IS_SPI_SUSP_MODE_STD(pstcInit->u32SuspMode));
|
|
DDL_ASSERT(IS_SPI_MODFE_CMD(pstcInit->u32Modfe));
|
|
DDL_ASSERT(IS_SPI_PARITY_CHECK(pstcInit->u32Parity));
|
|
DDL_ASSERT(IS_SPI_SPI_MODE(pstcInit->u32SpiMode));
|
|
DDL_ASSERT(IS_SPI_BIT_RATE_DIV(pstcInit->u32BaudRatePrescaler));
|
|
DDL_ASSERT(IS_SPI_DATA_SIZE(pstcInit->u32DataBits));
|
|
DDL_ASSERT(IS_SPI_FIRST_BIT(pstcInit->u32FirstBit));
|
|
DDL_ASSERT(IS_SPI_DATA_FRAME(pstcInit->u32FrameLevel));
|
|
|
|
/* Configuration parameter check */
|
|
if((SPI_MASTER == pstcInit->u32MasterSlave)&&(SPI_MODFE_ENABLE == pstcInit->u32Modfe))
|
|
{
|
|
/* pstcInit->u32Modfe can not be SPI_MODFE_ENABLE in master mode */
|
|
}
|
|
else if((SPI_WIRE_3 == pstcInit->u32WireMode)
|
|
&& (SPI_SLAVE == pstcInit->u32MasterSlave)
|
|
&&((SPI_MODE_0 == pstcInit->u32SpiMode)||(SPI_MODE_2 == pstcInit->u32SpiMode)))
|
|
{
|
|
/* SPI_WIRE_3 can not support SPI_MODE_0 and SPI_MODE_2 */
|
|
}
|
|
else
|
|
{
|
|
WRITE_REG32(SPIx->CR1, pstcInit->u32WireMode
|
|
| pstcInit->u32TransMode
|
|
| pstcInit->u32MasterSlave
|
|
| pstcInit->u32SuspMode
|
|
| pstcInit->u32Modfe
|
|
| pstcInit->u32Parity );
|
|
|
|
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_FTHLV, pstcInit->u32FrameLevel);
|
|
|
|
WRITE_REG32(SPIx->CFG2, pstcInit->u32SpiMode
|
|
| pstcInit->u32BaudRatePrescaler
|
|
| pstcInit->u32DataBits
|
|
| pstcInit->u32FirstBit);
|
|
|
|
enRet = Ok;
|
|
}
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @brief De-initializes the SPI peripheral.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @retval None
|
|
*/
|
|
void SPI_DeInit(M4_SPI_TypeDef *SPIx)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
|
|
SPI_FunctionCmd(SPIx, Disable);
|
|
|
|
WRITE_REG32(SPIx->CR1, 0x00000000UL);
|
|
WRITE_REG32(SPIx->CFG1, SPI_CFG1_DEFAULT);
|
|
WRITE_REG32(SPIx->CFG2, SPI_CFG2_DEFAULT);
|
|
WRITE_REG32(SPIx->SR, SPI_SR_DEFAULT);
|
|
}
|
|
|
|
/**
|
|
* @brief Set a default value for the SPI initialization structure.
|
|
* @param [in] pstcInit Pointer to a stc_spi_init_t structure that
|
|
* contains configuration information.
|
|
* @retval An en_result_t enumeration value.
|
|
* @arg Ok: No errors occurred.
|
|
* @arg ErrorInvalidParameter: pstcInit == NULL.
|
|
*/
|
|
en_result_t SPI_StructInit(stc_spi_init_t *pstcInit)
|
|
{
|
|
en_result_t enRet = ErrorInvalidParameter;
|
|
|
|
if (NULL != pstcInit)
|
|
{
|
|
pstcInit->u32WireMode = SPI_WIRE_4;
|
|
pstcInit->u32TransMode = SPI_FULL_DUPLEX;
|
|
pstcInit->u32MasterSlave = SPI_MASTER;
|
|
pstcInit->u32SuspMode = SPI_COM_SUSP_FUNC_OFF;
|
|
pstcInit->u32Modfe = SPI_MODFE_DISABLE;
|
|
pstcInit->u32Parity = SPI_PARITY_INVALID;
|
|
pstcInit->u32SpiMode = SPI_MODE_0;
|
|
pstcInit->u32BaudRatePrescaler = SPI_BR_PCLK1_DIV8;
|
|
pstcInit->u32DataBits = SPI_DATA_SIZE_8BIT;
|
|
pstcInit->u32FirstBit = SPI_FIRST_MSB;
|
|
pstcInit->u32FrameLevel = SPI_FRAME_1;
|
|
|
|
enRet = Ok;
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @brief Enable or disable SPI interrupt.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32IntType SPI interrupt type. Can be one or any
|
|
* combination of the parameter @ref SPI_Interrupt_Type_Define
|
|
* @arg SPI_INT_ERROR
|
|
* @arg SPI_INT_TX_BUFFER_EMPTY
|
|
* @arg SPI_INT_RX_BUFFER_FULL
|
|
* @arg SPI_INT_IDLE
|
|
* @param [in] enNewState An en_functional_state_t enumeration value.
|
|
* @arg Enable: Enable the specified interrupt of SPI.
|
|
* @arg Disable: Disable the specified interrupt of SPI.
|
|
* @retval None
|
|
*/
|
|
void SPI_IntCmd(M4_SPI_TypeDef *SPIx, uint32_t u32IntType, en_functional_state_t enNewState)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
|
|
DDL_ASSERT(IS_SPI_IRQ_FLAG(u32IntType));
|
|
|
|
if (enNewState == Enable)
|
|
{
|
|
SET_REG32_BIT(SPIx->CR1, u32IntType);
|
|
}
|
|
else
|
|
{
|
|
CLEAR_REG32_BIT(SPIx->CR1, u32IntType);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief SPI function enable or disable.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] enNewState An en_functional_state_t enumeration value.
|
|
* @arg Enable: Enable SPI function.
|
|
* @arg Disable: Disable SPI function.
|
|
* @retval None
|
|
*/
|
|
void SPI_FunctionCmd(M4_SPI_TypeDef *SPIx, en_functional_state_t enNewState)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
|
|
|
|
if(Enable == enNewState)
|
|
{
|
|
SET_REG32_BIT(SPIx->CR1, SPI_CR1_SPE);
|
|
}
|
|
else
|
|
{
|
|
CLEAR_REG32_BIT(SPIx->CR1, SPI_CR1_SPE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Write SPI data register.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32Data The data will be written to the data register.
|
|
* @retval None.
|
|
*/
|
|
void SPI_WriteDataReg(M4_SPI_TypeDef *SPIx, uint32_t u32Data)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
WRITE_REG32(SPIx->DR, u32Data);
|
|
}
|
|
|
|
/**
|
|
* @brief Read SPI data register.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @retval A 32-bit data of SPI data register.
|
|
*/
|
|
uint32_t SPI_ReadDataReg(const M4_SPI_TypeDef *SPIx)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
|
|
return READ_REG32(SPIx->DR);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief SPI get status flag.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32Flag SPI state flag. Can be one or any
|
|
* combination of the parameter of @ref SPI_State_Flag_Define
|
|
* @arg SPI_FLAG_OVERLOAD
|
|
* @arg SPI_FLAG_IDLE
|
|
* @arg SPI_FLAG_MODE_FAULT
|
|
* @arg SPI_FLAG_PARITY_ERROR
|
|
* @arg SPI_FLAG_UNDERLOAD
|
|
* @arg SPI_FLAG_TX_BUFFER_EMPTY
|
|
* @arg SPI_FLAG_RX_BUFFER_FULL
|
|
* @retval An en_flag_status_t enumeration.
|
|
* @arg Set: The specified flag has set.
|
|
* @arg Reset: The specified flag has not set.
|
|
*/
|
|
en_flag_status_t SPI_GetStatus(const M4_SPI_TypeDef *SPIx, uint32_t u32Flag)
|
|
{
|
|
en_flag_status_t enFlag = Reset;
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_SPI_STD_FLAG(u32Flag));
|
|
|
|
if(0U != READ_REG32_BIT(SPIx->SR, u32Flag))
|
|
{
|
|
enFlag = Set;
|
|
}
|
|
|
|
return enFlag;
|
|
}
|
|
|
|
/**
|
|
* @brief SPI clear state flag.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32Flag SPI state flag.
|
|
* Can be one or any combination of the parameter below
|
|
* @arg SPI_FLAG_OVERLOAD
|
|
* @arg SPI_FLAG_MODE_FAULT
|
|
* @arg SPI_FLAG_PARITY_ERROR
|
|
* @arg SPI_FLAG_UNDERLOAD
|
|
* @retval None
|
|
*/
|
|
void SPI_ClearFlag(M4_SPI_TypeDef *SPIx, uint32_t u32Flag)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_SPI_CLR_STD_FLAG(u32Flag));
|
|
|
|
CLEAR_REG32_BIT(SPIx->SR, u32Flag);
|
|
}
|
|
|
|
/**
|
|
* @brief SPI loopback function configuration.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32Mode Loopback mode.
|
|
* Can be one parameter @ref SPI_Loopback_Selection_Define
|
|
* @arg SPI_SPLPBK_INVALID
|
|
* @arg SPI_SPLPBK_MOSI_INVERT
|
|
* @arg SPI_SPLPBK_MOSI
|
|
* @retval None
|
|
*/
|
|
void SPI_LoopbackModeCfg(M4_SPI_TypeDef *SPIx, uint32_t u32Mode)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_SPI_SPLPBK(u32Mode));
|
|
|
|
MODIFY_REG32(SPIx->CR1, SPI_CR1_SPLPBK | SPI_CR1_SPLPBK2, u32Mode);
|
|
}
|
|
|
|
/**
|
|
* @brief SPI parity check error self diagnosis function enable or disable.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] enNewState An en_functional_state_t enumeration value.
|
|
* @arg Enable: Enable function.
|
|
* @arg Disable: Disable function.
|
|
* @retval None
|
|
*/
|
|
void SPI_PateCmd(M4_SPI_TypeDef *SPIx, en_functional_state_t enNewState)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
|
|
|
|
if(Enable == enNewState)
|
|
{
|
|
SET_REG32_BIT(SPIx->CR1, SPI_CR1_PATE);
|
|
}
|
|
else
|
|
{
|
|
CLEAR_REG32_BIT(SPIx->CR1, SPI_CR1_PATE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief SPI signals delay time configuration
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] pstcDelayCfg Pointer to a stc_spi_delay_t structure that contains
|
|
* the configuration information for the SPI delay time.
|
|
* @retval An en_result_t enumeration value:
|
|
* @arg Ok: No errors occurred
|
|
* @arg ErrorInvalidParameter: pstcDelayCfg == NULL
|
|
*/
|
|
en_result_t SPI_DelayTimeCfg(M4_SPI_TypeDef *SPIx, const stc_spi_delay_t *pstcDelayCfg)
|
|
{
|
|
en_result_t enRet = ErrorInvalidParameter;
|
|
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
|
|
if (NULL != pstcDelayCfg)
|
|
{
|
|
DDL_ASSERT(IS_SPI_INTERVAL_DELAY(pstcDelayCfg->u32IntervalDelay));
|
|
DDL_ASSERT(IS_SPI_RELEASE_DELAY(pstcDelayCfg->u32ReleaseDelay));
|
|
DDL_ASSERT(IS_SPI_SETUP_DELAY(pstcDelayCfg->u32SetupDelay));
|
|
|
|
/* Interval delay */
|
|
if(SPI_INTERVAL_TIME_1SCK_2PCLK1 == pstcDelayCfg->u32IntervalDelay)
|
|
{
|
|
CLEAR_REG32_BIT(SPIx->CFG2, SPI_CFG2_MIDIE);
|
|
CLEAR_REG32_BIT(SPIx->CFG1, SPI_CFG1_MIDI);
|
|
}
|
|
else
|
|
{
|
|
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_MIDI, pstcDelayCfg->u32IntervalDelay);
|
|
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_MIDIE);
|
|
}
|
|
|
|
/* SCK release delay */
|
|
if(SPI_RELEASE_TIME_1SCK == pstcDelayCfg->u32ReleaseDelay)
|
|
{
|
|
CLEAR_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSDLE);
|
|
CLEAR_REG32_BIT(SPIx->CFG1, SPI_CFG1_MSSDL);
|
|
}
|
|
else
|
|
{
|
|
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSDLE);
|
|
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_MSSDL, pstcDelayCfg->u32ReleaseDelay);
|
|
}
|
|
|
|
/* Setup delay */
|
|
if(SPI_SETUP_TIME_1SCK == pstcDelayCfg->u32SetupDelay)
|
|
{
|
|
CLEAR_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSIE);
|
|
CLEAR_REG32_BIT(SPIx->CFG1, SPI_CFG1_MSSI);
|
|
}
|
|
else
|
|
{
|
|
SET_REG32_BIT(SPIx->CFG2, SPI_CFG2_MSSIE);
|
|
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_MSSI, pstcDelayCfg->u32SetupDelay);
|
|
}
|
|
|
|
enRet = Ok;
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @brief Set a default value for the SPI delay time configuration structure.
|
|
* @param [in] pstcDelayCfg Pointer to a stc_spi_delay_t structure that
|
|
* contains configuration information.
|
|
* @retval An en_result_t enumeration value.
|
|
* @arg Ok: No errors occurred.
|
|
* @arg ErrorInvalidParameter: pstcDelayCfg == NULL.
|
|
*/
|
|
en_result_t SPI_DelayStructInit(stc_spi_delay_t *pstcDelayCfg)
|
|
{
|
|
en_result_t enRet = ErrorInvalidParameter;
|
|
|
|
if (NULL != pstcDelayCfg)
|
|
{
|
|
pstcDelayCfg->u32IntervalDelay = SPI_INTERVAL_TIME_1SCK_2PCLK1;
|
|
pstcDelayCfg->u32ReleaseDelay = SPI_RELEASE_TIME_1SCK;
|
|
pstcDelayCfg->u32SetupDelay = SPI_SETUP_TIME_1SCK;
|
|
enRet = Ok;
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @brief SPI SS signal valid level configuration
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32SSPin Specify the SS pin @ref SPI_SS_Pin_Define
|
|
* @param [in] enNewState An en_functional_state_t enumeration value.
|
|
* @arg Enable: SS pin high level valid.
|
|
* @arg Disable: SS pin low level valid.
|
|
* @retval None
|
|
*/
|
|
void SPI_SSValidLevelCfg(M4_SPI_TypeDef *SPIx, uint32_t u32SSPin, en_functional_state_t enNewState)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_SPI_SS_PIN(u32SSPin));
|
|
DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
|
|
|
|
if(Enable == enNewState)
|
|
{
|
|
SET_REG32_BIT(SPIx->CFG1, u32SSPin);
|
|
}
|
|
else
|
|
{
|
|
CLEAR_REG32_BIT(SPIx->CFG1, u32SSPin);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief SPI valid SS signal configuration
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32SSPin Specify the SS pin @ref SPI_SS_Pin_Define
|
|
* @retval None
|
|
*/
|
|
void SPI_SSPinSel(M4_SPI_TypeDef *SPIx, uint32_t u32SSPin)
|
|
{
|
|
uint32_t u32RegCfg;
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_SPI_SS_PIN(u32SSPin));
|
|
|
|
switch (u32SSPin)
|
|
{
|
|
case SPI_PIN_SS0:
|
|
u32RegCfg = SPI_SS0_VALID_CFG;
|
|
break;
|
|
case SPI_PIN_SS1:
|
|
u32RegCfg = SPI_SS1_VALID_CFG;
|
|
break;
|
|
case SPI_PIN_SS2:
|
|
u32RegCfg = SPI_SS2_VALID_CFG;
|
|
break;
|
|
case SPI_PIN_SS3:
|
|
u32RegCfg = SPI_SS3_VALID_CFG;
|
|
break;
|
|
|
|
default:
|
|
u32RegCfg = SPI_SS0_VALID_CFG;
|
|
break;
|
|
}
|
|
MODIFY_REG32(SPIx->CFG2, SPI_CFG2_SSA, u32RegCfg);
|
|
}
|
|
|
|
/**
|
|
* @brief SPI read buffer configuration
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] u32ReadBuf Target buffer for read operation @ref SPI_Read_Target_Buffer_Define
|
|
* @retval None
|
|
*/
|
|
void SPI_ReadBufCfg(M4_SPI_TypeDef *SPIx, uint32_t u32ReadBuf)
|
|
{
|
|
DDL_ASSERT(IS_VALID_SPI_UNIT(SPIx));
|
|
DDL_ASSERT(IS_SPI_RD_TARGET_BUFF(u32ReadBuf));
|
|
|
|
MODIFY_REG32(SPIx->CFG1, SPI_CFG1_SPRDTD, u32ReadBuf);
|
|
}
|
|
|
|
/**
|
|
* @brief SPI transmit data.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
|
|
* @param [in] u32TxLength The length of the data to be sent.
|
|
* @retval An en_result_t enumeration value:
|
|
* @arg Ok: No errors occurred
|
|
* @arg ErrorTimeout: SPI transmit timeout.
|
|
* @arg ErrorInvalidParameter: pvTxBuf == NULL or u32TxLength == 0U
|
|
* @note -No SS pin active and inactive operation in 3-wire mode. Add operations of SS pin depending on your application.
|
|
* -This function supports full duplex mode and send only mode.
|
|
*/
|
|
en_result_t SPI_Transmit(M4_SPI_TypeDef *SPIx, const void *pvTxBuf, uint32_t u32TxLength)
|
|
{
|
|
uint32_t u32Flags;
|
|
en_result_t enRet = ErrorInvalidParameter;
|
|
|
|
if ((pvTxBuf != NULL) && (u32TxLength != 0U))
|
|
{
|
|
u32Flags = READ_REG32_BIT(SPIx->CR1, SPI_CR1_TXMDS);
|
|
if (u32Flags == SPI_SEND_ONLY)
|
|
{
|
|
/* Transmit data in send only mode. */
|
|
enRet = SPI_Tx(SPIx, pvTxBuf, u32TxLength);
|
|
}
|
|
else
|
|
{
|
|
/* Transmit data in full duplex mode. */
|
|
enRet = SPI_TxRx(SPIx, pvTxBuf, NULL, u32TxLength);
|
|
}
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @brief SPI receive data.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] pvRxBuf The pointer to the buffer which the received data to be stored.
|
|
* @param [in] u32RxLength The length of the data to be received.
|
|
* @retval An en_result_t enumeration value:
|
|
* @arg Ok: No errors occurred
|
|
* @arg ErrorTimeout: SPI receive timeout.
|
|
* @arg ErrorInvalidParameter: pvRxBuf == NULL or u32RxLength == 0U
|
|
* @note -No SS pin active and inactive operation in 3-wire mode. Add operations of SS pin depending on your application.
|
|
* -This function only works in full duplex master mode.
|
|
*/
|
|
en_result_t SPI_Receive(M4_SPI_TypeDef *SPIx, void *pvRxBuf, uint32_t u32RxLength)
|
|
{
|
|
en_result_t enRet = ErrorInvalidParameter;
|
|
|
|
if ((pvRxBuf != NULL) && (u32RxLength != 0U))
|
|
{
|
|
/* Receives data in full duplex master mode. */
|
|
enRet = SPI_TxRx(SPIx, NULL, pvRxBuf, u32RxLength);
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @brief SPI transmit and receive data.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
|
|
* If this pointer is NULL and the pvRxBuf is NOT NULL, the MOSI output high
|
|
* and the the received data will be stored in the buffer pointed by pvRxBuf.
|
|
* @param [out] pvRxBuf The pointer to the buffer which the received data will be stored.
|
|
* This for full duplex transfer.
|
|
* @param [in] u32Length The length of the data(in byte or half word) to be sent and received.
|
|
* @retval An en_result_t enumeration value:
|
|
* @arg Ok: No errors occurred
|
|
* @arg ErrorTimeout: SPI transmit and receive timeout.
|
|
* @arg ErrorInvalidParameter: pvRxBuf == NULL or pvRxBuf == NULL or u32Length == 0U
|
|
* @note SPI receives data while sending data. Only works in full duplex master mode.
|
|
*/
|
|
en_result_t SPI_TransmitReceive(M4_SPI_TypeDef *SPIx, const void *pvTxBuf, void *pvRxBuf, uint32_t u32Length)
|
|
{
|
|
en_result_t enRet = ErrorInvalidParameter;
|
|
|
|
if ((pvTxBuf != NULL) && (pvRxBuf != NULL) && (u32Length != 0U))
|
|
{
|
|
/* Transmit and receive data in full duplex master mode. */
|
|
enRet = SPI_TxRx(SPIx, pvTxBuf, pvRxBuf, u32Length);
|
|
}
|
|
return enRet;
|
|
}
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @addtogroup SPI_Local_Functions SPI Local Functions
|
|
* @{
|
|
*/
|
|
/**
|
|
* @brief SPI transmit and receive data in full duplex mode.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
|
|
* @param [out] pvRxBuf The pointer to the buffer which the received data will be stored.
|
|
* @param [in] u32Length The length of the data in byte or half word.
|
|
* @retval An en_result_t enumeration value:
|
|
* @arg Ok: No errors occurred
|
|
* @arg ErrorTimeout: SPI transmit and receive timeout.
|
|
*/
|
|
static en_result_t SPI_TxRx(M4_SPI_TypeDef *SPIx, const void *pvTxBuf, void *pvRxBuf, uint32_t u32Length)
|
|
{
|
|
uint32_t u32BitSize;
|
|
__IO uint32_t u32Timecount;
|
|
__IO uint32_t u32Count = 0U;
|
|
en_result_t enRet = Ok;
|
|
uint32_t u32Tmp;
|
|
__UNUSED __IO uint32_t u32Read;
|
|
|
|
/* Get data bit size, SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_32BIT */
|
|
u32BitSize = READ_REG32_BIT(SPIx->CFG2, SPI_CFG2_DSIZE);
|
|
|
|
while (u32Count < u32Length)
|
|
{
|
|
if (pvTxBuf != NULL)
|
|
{
|
|
if (u32BitSize <= SPI_DATA_SIZE_8BIT)
|
|
{
|
|
/* SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_8BIT */
|
|
WRITE_REG32(SPIx->DR, ((const uint8_t *)pvTxBuf)[u32Count]);
|
|
}
|
|
else if(u32BitSize <= SPI_DATA_SIZE_16BIT)
|
|
{
|
|
/* SPI_DATA_SIZE_9BIT ~ SPI_DATA_SIZE_16BIT */
|
|
WRITE_REG32(SPIx->DR, ((const uint16_t *)pvTxBuf)[u32Count]);
|
|
}
|
|
else
|
|
{
|
|
/* SPI_DATA_SIZE_20BIT ~ SPI_DATA_SIZE_32BIT */
|
|
WRITE_REG32(SPIx->DR, ((const uint32_t *)pvTxBuf)[u32Count]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WRITE_REG32(SPIx->DR, 0xFFFFFFFFUL);
|
|
}
|
|
|
|
/* Delay about 10ms */
|
|
u32Timecount = HCLK_VALUE/100UL;
|
|
do
|
|
{
|
|
if(0UL != READ_REG32_BIT(SPIx->SR, SPI_FLAG_RX_BUFFER_FULL))
|
|
{
|
|
break;
|
|
}
|
|
u32Timecount--;
|
|
} while (u32Timecount != 0U);
|
|
|
|
if (u32Timecount == 0U)
|
|
{
|
|
enRet = ErrorTimeout;
|
|
break;
|
|
}
|
|
|
|
u32Tmp = READ_REG32(SPIx->DR);
|
|
if (pvRxBuf != NULL)
|
|
{
|
|
if (u32BitSize <= SPI_DATA_SIZE_8BIT)
|
|
{
|
|
/* SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_8BIT */
|
|
((uint8_t *)pvRxBuf)[u32Count] = (uint8_t)u32Tmp;
|
|
}
|
|
else if(u32BitSize <= SPI_DATA_SIZE_16BIT)
|
|
{
|
|
/* SPI_DATA_SIZE_9BIT ~ SPI_DATA_SIZE_16BIT */
|
|
((uint16_t *)pvRxBuf)[u32Count] = (uint16_t)u32Tmp;
|
|
}
|
|
else
|
|
{
|
|
/* SPI_DATA_SIZE_20BIT ~ SPI_DATA_SIZE_32BIT */
|
|
((uint32_t *)pvRxBuf)[u32Count] = (uint32_t)u32Tmp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Dummy read */
|
|
u32Read = READ_REG32(SPIx->DR);
|
|
}
|
|
|
|
u32Count++;
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @brief SPI send data only.
|
|
* @param [in] SPIx SPI unit
|
|
* @arg M4_SPI1
|
|
* @arg M4_SPI2
|
|
* @arg M4_SPI3
|
|
* @arg M4_SPI4
|
|
* @arg M4_SPI5
|
|
* @arg M4_SPI6
|
|
* @param [in] pvTxBuf The pointer to the buffer which contains the data to be sent.
|
|
* @param [in] u32Length The length of the data in byte or half word or word.
|
|
* @retval An en_result_t enumeration value:
|
|
* @arg Ok: No errors occurred.
|
|
* @arg ErrorTimeout: SPI transmit timeout.
|
|
*/
|
|
static en_result_t SPI_Tx(M4_SPI_TypeDef *SPIx, const void *pvTxBuf, uint32_t u32Length)
|
|
{
|
|
__IO uint32_t u32Count = 0U;
|
|
__IO uint32_t u32Timecount;
|
|
uint32_t u32BitSize;
|
|
en_result_t enRet = Ok;
|
|
|
|
/* Get data bit size, SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_32BIT */
|
|
u32BitSize = READ_REG32_BIT(SPIx->CFG2, SPI_CFG2_DSIZE);
|
|
|
|
while (u32Count < u32Length)
|
|
{
|
|
if (u32BitSize <= SPI_DATA_SIZE_8BIT)
|
|
{
|
|
/* SPI_DATA_SIZE_4BIT ~ SPI_DATA_SIZE_8BIT */
|
|
WRITE_REG32(SPIx->DR, ((const uint8_t *)pvTxBuf)[u32Count]);
|
|
}
|
|
else if(u32BitSize <= SPI_DATA_SIZE_16BIT)
|
|
{
|
|
/* SPI_DATA_SIZE_9BIT ~ SPI_DATA_SIZE_16BIT */
|
|
WRITE_REG32(SPIx->DR, ((const uint16_t *)pvTxBuf)[u32Count]);
|
|
}
|
|
else
|
|
{
|
|
/* SPI_DATA_SIZE_20BIT ~ SPI_DATA_SIZE_32BIT */
|
|
WRITE_REG32(SPIx->DR, ((const uint32_t *)pvTxBuf)[u32Count]);
|
|
}
|
|
|
|
/* Delay about 10ms */
|
|
u32Timecount = HCLK_VALUE/100UL;
|
|
do
|
|
{
|
|
if(0UL != READ_REG32_BIT(SPIx->SR, SPI_FLAG_TX_BUFFER_EMPTY))
|
|
{
|
|
break;
|
|
}
|
|
u32Timecount--;
|
|
} while (u32Timecount != 0U);
|
|
|
|
if (u32Timecount == 0U)
|
|
{
|
|
enRet = ErrorTimeout;
|
|
}
|
|
|
|
u32Count++;
|
|
}
|
|
return enRet;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#endif /* DDL_SPI_ENABLE */
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/******************************************************************************
|
|
* EOF (not truncated)
|
|
*****************************************************************************/
|