aboutsummaryrefslogtreecommitdiff
path: root/src/mcu/peripheral/rtl876x_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mcu/peripheral/rtl876x_spi.c')
-rw-r--r--src/mcu/peripheral/rtl876x_spi.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/src/mcu/peripheral/rtl876x_spi.c b/src/mcu/peripheral/rtl876x_spi.c
new file mode 100644
index 0000000..f831f06
--- /dev/null
+++ b/src/mcu/peripheral/rtl876x_spi.c
@@ -0,0 +1,352 @@
+/**
+*********************************************************************************************************
+* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved.
+**********************************************************************************************************
+* @file rtl876x_spi.c
+* @brief This file provides all the Spi firmware functions.
+* @details
+* @author elliot chen
+* @date 2015-05-06
+* @version v0.1
+*********************************************************************************************************
+*/
+
+/* Includes ------------------------------------------------------------------*/
+#include "rtl876x_spi.h"
+#include "rtl876x_rcc.h"
+
+/**
+ * @brief Deinitializes the SPIx peripheral registers to their default reset values.
+ * @param SPIx: where x can be 0 or 1 to select the SPI peripheral.
+ * @retval None
+ */
+void SPI_DeInit(SPI_TypeDef *SPIx)
+{
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+
+ /*Disable SPI clock */
+ if (SPIx == SPI0)
+ {
+ RCC_PeriphClockCmd(APBPeriph_SPI0, APBPeriph_SPI0_CLOCK, DISABLE);
+ }
+ else
+ {
+ RCC_PeriphClockCmd(APBPeriph_SPI1, APBPeriph_SPI1_CLOCK, DISABLE);
+ }
+}
+
+/**
+ * @brief Initializes the SPIx peripheral according to the specified
+ * parameters in the SPI_InitStruct.
+ * @param SPIx: where x can be 0 or 1 to select the SPI peripheral.
+ * @param SPI_InitStruct: pointer to a SPI_InitTypeDef structure that
+ * contains the configuration information for the specified SPI peripheral.
+ * @retval None
+ */
+void SPI_Init(SPI_TypeDef *SPIx, SPI_InitTypeDef *SPI_InitStruct)
+{
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+
+ /* Check the SPI parameters */
+ assert_param(IS_SPI_DIRECTION_MODE(SPI_InitStruct->SPI_Direction));
+ assert_param(IS_SPI_MODE(SPI_InitStruct->SPI_Mode));
+ assert_param(IS_SPI_DATASIZE(SPI_InitStruct->SPI_DataSize));
+ assert_param(IS_SPI_CPOL(SPI_InitStruct->SPI_CPOL));
+ assert_param(IS_SPI_CPHA(SPI_InitStruct->SPI_CPHA));
+ assert_param(IS_SPI_FRAME_FORMAT(SPI_InitStruct->SPI_FrameFormat));
+
+ /* Disable SPI device before change configuration */
+ SPIx->SSIENR &= ~0x01;
+
+ /*Set SPI Rx sample delay */
+ SPIx->RX_SAMPLE_DLY = 0x01;
+
+ /* Configure SPI0 mode if select SPI0 */
+ if (SPIx == SPI0)
+ {
+ if (SPI_InitStruct->SPI_Mode == SPI_Mode_Master)
+ {
+ /*Enable SPI0 master mode*/
+ *((volatile uint32_t *)0x40000308) = *((volatile uint32_t *)0x40000308) | BIT(0);
+ /* configure SPI parameters */
+ SPIx->CTRLR0 = (SPI_InitStruct->SPI_DataSize << 16)\
+ | (SPI_InitStruct->SPI_FrameFormat << 4) \
+ | (SPI_InitStruct->SPI_CPHA << 6)\
+ | (SPI_InitStruct->SPI_CPOL << 7) \
+ | (SPI_InitStruct->SPI_Direction << 8) \
+ | (SPI_InitStruct->SPI_ToggleEn << 24);
+ }
+ else
+ {
+ /*Enable SPI0 slave mode*/
+ *((volatile uint32_t *)0x40000308) = *((volatile uint32_t *)0x40000308) & (~(BIT(0)));
+ /* configure SPI parameters */
+ SPIx->CTRLR0 = (SPI_InitStruct->SPI_DataSize)
+ | (SPI_InitStruct->SPI_FrameFormat << 4)
+ | (SPI_InitStruct->SPI_CPHA << 6)
+ | (SPI_InitStruct->SPI_CPOL << 7)
+ | (SPI_InitStruct->SPI_Direction << 8)
+ | (SPI_InitStruct->SPI_SwapTxBitEn << 22)
+ | (SPI_InitStruct->SPI_SwapRxBitEn << 24)
+ | (SPI_InitStruct->SPI_SwapTxByteEn << 21)
+ | (SPI_InitStruct->SPI_SwapRxByteEn << 23)
+ | (SPI_InitStruct->SPI_ToggleEn << 31);
+ }
+
+ }
+ else if (SPIx == SPI1)
+ {
+ /* configure SPI parameters */
+ SPIx->CTRLR0 = (SPI_InitStruct->SPI_DataSize << 16)
+ | (SPI_InitStruct->SPI_FrameFormat << 4)
+ | (SPI_InitStruct->SPI_CPHA << 6)
+ | (SPI_InitStruct->SPI_CPOL << 7)
+ | (SPI_InitStruct->SPI_Direction << 8)
+ | (SPI_InitStruct->SPI_ToggleEn << 24);
+ }
+
+ /* configure SPI clock speed in master mode or enable slave output in slave mode */
+ if (SPI_InitStruct->SPI_Mode == SPI_Mode_Master)
+ {
+ SPIx->BAUDR = (SPI_InitStruct->SPI_BaudRatePrescaler) % 0xFFFF;
+ /* Enable slave Select function in master mode */
+ SPIx->SER |= BIT(0);
+ }
+ else
+ {
+ /* Enable slave output */
+ SPIx->CTRLR0 &= ~(BIT(10));
+ }
+
+ /*set SPI Tx and Rx threshold level ,below this level or equal this level would trigger Tx and Rx FIFO empty interrupt */
+ SPIx->TXFTLR = SPI_InitStruct->SPI_TxThresholdLevel;
+ SPIx->RXFTLR = SPI_InitStruct->SPI_RxThresholdLevel;
+
+ /* mask SPI interrupt in REG_DW_SSI_IMR */
+ SPIx->IMR = 0;
+
+ /* set read length in SPI EEPROM & rx only mode */
+ if ((SPI_InitStruct->SPI_Direction == 0x02) || (SPI_InitStruct->SPI_Direction == 0x03))
+ {
+ SPIx->CTRLR1 = SPI_InitStruct->SPI_NDF;
+ }
+#if 1
+
+ /* Config SPI dma mode */
+ SPIx->DMACR = ((SPI_InitStruct->SPI_RxDmaEn)\
+ | ((SPI_InitStruct->SPI_TxDmaEn) << 1));
+
+ /* Config SPI waterlevel */
+ SPIx->DMARDLR = SPI_InitStruct->SPI_RxWaterlevel;
+ SPIx->DMATDLR = SPI_InitStruct->SPI_TxWaterlevel;
+#endif
+}
+
+/**
+ * @brief Fills each SPI_InitStruct member with its default value.
+ * @param SPI_InitStruct : pointer to a SPI_InitTypeDef structure which will be initialized.
+ * @retval None
+ */
+void SPI_StructInit(SPI_InitTypeDef *SPI_InitStruct)
+{
+ SPI_InitStruct->SPI_Mode = SPI_Mode_Master;
+ SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b; /* 8-bit serial data transfer */
+ SPI_InitStruct->SPI_FrameFormat = 0; /* 0:FRF_MOTOROLA_SPI; 1,2,3:Reserved */
+ SPI_InitStruct->SPI_Direction =
+ 0; /* 0:TX and RX Mode; 1:TX Only Mode; 2:RX Only Mode;
+ 3:EEPROM Read Mode */
+ SPI_InitStruct->SPI_CPOL =
+ 1; /* 0:inactive state of clock is low; 1:inactive
+ state of clock is high */
+ SPI_InitStruct->SPI_CPHA =
+ 1; /* 1:Serial clock toggles in first of first data bit;
+ 0:Serial clock toggles in middle of first data bit*/
+ SPI_InitStruct->SPI_BaudRatePrescaler =
+ SPI_BaudRatePrescaler_128; /* Speed = SPI Clock source/ SPI_ClkDIV*/
+ SPI_InitStruct->SPI_TxThresholdLevel = 1; /* Transmit FIFO Threshold */
+ SPI_InitStruct->SPI_RxThresholdLevel = 0; /* Receive FIFO Threshold */
+ SPI_InitStruct->SPI_NDF = 1;
+ SPI_InitStruct->SPI_SwapRxBitEn = SPI_SWAP_DISABLE; /* reverse the rx bit or not */
+ SPI_InitStruct->SPI_SwapTxBitEn = SPI_SWAP_DISABLE;
+ SPI_InitStruct->SPI_SwapRxByteEn = SPI_SWAP_DISABLE;
+ SPI_InitStruct->SPI_SwapTxByteEn = SPI_SWAP_DISABLE;
+ SPI_InitStruct->SPI_ToggleEn = DISABLE;
+
+ SPI_InitStruct->SPI_RxDmaEn = DISABLE;
+ SPI_InitStruct->SPI_TxDmaEn = DISABLE;
+ SPI_InitStruct->SPI_RxWaterlevel =
+ 1; /* SPI Rx waterlevel, should be less than fifo threshold, the best value is
+ GDMA Msize */
+ SPI_InitStruct->SPI_TxWaterlevel =
+ 35; /* SPI Tx waterlevel, should be less than fifo threshold, the best value is
+ SPI FIFO Depth minus GDMA Msize */
+}
+
+/**
+ * @brief Enables or disables the specified SPI peripheral.
+ * @param SPIx: where x can be 0 or 1 to select the SPI peripheral.
+ * @param NewState: new state of the SPIx peripheral.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void SPI_Cmd(SPI_TypeDef *SPIx, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected SPI peripheral */
+ SPIx->SSIENR |= 0x01;
+ }
+ else
+ {
+ /* Disable the selected SPI peripheral */
+ SPIx->SSIENR &= ~0x01;
+ }
+}
+
+/**
+ * @brief Transmits a number of bytes through the SPIx peripheral.
+ * @param SPIx: where x can be 0 or 1
+ * @param Data : bytes to be transmitted.
+ * @retval None
+ */
+void SPI_SendBuffer(SPI_TypeDef *SPIx, uint8_t *pBuf, uint16_t len)
+{
+ uint16_t i = 0;
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+
+ for (i = 0; i < len; i++)
+ {
+ SPIx->DR[0] = (*pBuf++);
+ /*read TFNF bit status in SR register: SET is Tx FIFO is not full*/
+ while (!(SPIx->SR & BIT(1)));
+ }
+}
+
+/**
+ * @brief Transmits a number of words through the SPIx peripheral.
+ * @param SPIx: where x can be 0 or 1
+ * @param Data : words to be transmitted.
+ * @retval None
+ */
+void SPI_SendWord(SPI_TypeDef *SPIx, uint32_t *pBuf, uint16_t len)
+{
+ uint16_t i = 0;
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+
+ for (i = 0; i < len; i++)
+ {
+ SPIx->DR[0] = (*pBuf++);
+ /*read TFNF bit status in SR register: SET is Tx FIFO is not full*/
+ while (!(SPIx->SR & BIT(1)));
+ }
+}
+
+/**
+ * @brief Transmits a number of halfWords through the SPIx peripheral.
+ * @param SPIx: where x can be 0 or 1
+ * @param Data : Halfwords to be transmitted.
+ * @retval None
+ */
+void SPI_SendHalfWord(SPI_TypeDef *SPIx, uint16_t *pBuf, uint16_t len)
+{
+ uint16_t i = 0;
+
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+
+ for (i = 0; i < len; i++)
+ {
+ SPIx->DR[0] = (*pBuf++);
+ /*read TFNF bit status in SR register: SET is Tx FIFO is not full*/
+ while (!(SPIx->SR & BIT(1)));
+ }
+}
+
+/**
+ * @brief Enables or disables the specified SPI/I2S interrupts.
+ * @param SPIx: where x can be 0 or 1
+ * @param SPI_IT: specifies the SPI/I2S interrupt source to be enabled or disabled.
+ * This parameter can be one of the following values:
+ * @arg SPI_INT_TXE: Tx buffer empty interrupt mask
+ * @arg SPI_INT_TXO: Tx buffer overflow interrupt mask
+ * @arg SPI_INT_RXU: receive FIFO Underflow Interrupt mask
+ * @arg SPI_INT_RXO: receive FIFO Overflow Interrupt mask
+ * @arg SPI_INT_RXF: receive FIFO Full Interrupt mask which equal RXNE Interrupt!!!
+ * @arg SPI_INT_MST: multi-Master Contention Interrupt mask
+ * @param NewState: new state of the specified SPI interrupt.
+ * This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void SPI_INTConfig(SPI_TypeDef *SPIx, uint8_t SPI_IT, FunctionalState NewState)
+{
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+ assert_param(IS_FUNCTIONAL_STATE(NewState));
+ assert_param(IS_SPI_CONFIG_IT(SPI_IT));
+
+ if (NewState != DISABLE)
+ {
+ /* Enable the selected SPI interrupt */
+ SPIx->IMR |= SPI_IT;
+ }
+ else
+ {
+ /* Disable the selected SPI interrupt */
+ SPIx->IMR &= (uint16_t)~(SPI_IT);
+ }
+}
+
+/**
+ * @brief Clear the specified SPI interrupt.
+ * @param SPIx: where x can be 0 or 1
+ * @param SPI_IT: specifies the SPI interrupt to clear.
+ * This parameter can be one of the following values:
+ * @arg SPI_INT_MST: Multi-Master Contention Interrupt.
+ * @arg SPI_INT_RXO: Receive FIFO Overflow Interrupt.
+ * @arg SPI_INT_RXU: Receive FIFO Underflow Interrupt.
+ * @arg SPI_INT_TXO: Transmit FIFO Overflow Interrupt .
+ * @retval None.
+ */
+void SPI_ClearINTPendingBit(SPI_TypeDef *SPIx, uint16_t SPI_IT)
+{
+ /* Check the parameters */
+ assert_param(IS_SPI_ALL_PERIPH(SPIx));
+ assert_param(IS_SPI_CONFIG_IT(SPI_IT));
+
+ switch (SPI_IT)
+ {
+ case SPI_INT_RXO:
+ SPIx->RXOICR;
+ break;
+ case SPI_INT_RXU:
+ SPIx->RXUICR;
+ break;
+ case SPI_INT_TXO:
+ SPIx->TXOICR;
+ break;
+ case SPI_INT_MST:
+ SPIx->FAEICR;
+ break;
+ case SPI_INT_TUF:
+ SPIx->TXUICR;
+ break;
+ case SPI_INT_RIG:
+ SPIx->SSRICR;
+ break;
+ default:
+ break;
+ }
+
+}
+/******************* (C) COPYRIGHT 2015 Realtek Semiconductor Corporation *****END OF FILE****/
+