Merge pull request #1374 from uestczyh222/master
[Bsp][Tina]Add spi driver
This commit is contained in:
commit
8e31427970
|
@ -19,4 +19,19 @@ config TINA_USING_SDIO0
|
|||
bool "Using SDIO0"
|
||||
select RT_USING_SDIO
|
||||
default y
|
||||
|
||||
|
||||
config TINA_USING_SPI0
|
||||
bool "Using spi0"
|
||||
select RT_USING_SPI
|
||||
default y
|
||||
|
||||
config TINA_USING_SPI1
|
||||
bool "Using spi1"
|
||||
select RT_USING_SPI
|
||||
default y
|
||||
|
||||
config TINA_USING_SPI_FLASH
|
||||
bool "Using flash"
|
||||
select TINA_USING_SPI0
|
||||
select RT_USING_SFUD
|
||||
default y
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd, str(Dir('#'))]
|
||||
|
||||
group = DefineGroup('spi', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
|
@ -0,0 +1,793 @@
|
|||
/*
|
||||
* File : drv_spi.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2017, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-08-30 tanek first implementation.
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <rtdevice.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "drv_spi.h"
|
||||
#include "drv_gpio.h"
|
||||
#include "drv_clock.h"
|
||||
|
||||
#define SPI_BUS_MAX_CLK (30 * 1000 * 1000)
|
||||
|
||||
#define DBG_ENABLE
|
||||
#define DBG_SECTION_NAME "[SPI]"
|
||||
#define DBG_LEVEL DBG_WARNING
|
||||
#define DBG_COLOR
|
||||
#include <rtdbg.h>
|
||||
|
||||
#ifdef RT_USING_SPI
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#define ARR_LEN(__N) (sizeof(__N) / sizeof(__N[0]))
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINTF(...)
|
||||
#endif
|
||||
|
||||
|
||||
#define __SPI_STATIC_INLINE__ rt_inline
|
||||
|
||||
/*
|
||||
* @brief Hardware Layer Interface
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
rt_uint32_t SPI_GetVersion(SPI_T *spi)
|
||||
{
|
||||
return spi->VER;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_Reset(SPI_T *spi)
|
||||
{
|
||||
HAL_SET_BIT(spi->CTRL, SPI_CTRL_RST_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetMode(SPI_T *spi, SPI_CTRL_Mode mode)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->CTRL, SPI_CTRL_MODE_MASK, mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_Enable(SPI_T *spi)
|
||||
{
|
||||
HAL_SET_BIT(spi->CTRL, SPI_CTRL_EN_MASK);
|
||||
}
|
||||
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_Disable(SPI_T *spi)
|
||||
{
|
||||
HAL_CLR_BIT(spi->CTRL, SPI_CTRL_EN_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_StartTransmit(SPI_T *spi)
|
||||
{
|
||||
HAL_SET_BIT(spi->TCTRL, SPI_TCTRL_XCH_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetFirstTransmitBit(SPI_T *spi, SPI_TCTRL_Fbs bit)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_FBS_MASK, bit);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_EnableRapidsMode(SPI_T *spi, bool delay_sample)
|
||||
{
|
||||
HAL_SET_BIT(spi->TCTRL, SPI_TCTRL_RPSM_MASK);
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SDC_MASK, delay_sample << SPI_TCTRL_SDC_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_DisableRapidsMode(SPI_T *spi)
|
||||
{
|
||||
HAL_CLR_BIT(spi->TCTRL, SPI_TCTRL_RPSM_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetDuplex(SPI_T *spi, SPI_TCTRL_DHB_Duplex duplex)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_DHB_MASK, duplex);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetCsLevel(SPI_T *spi, bool level)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_LEVEL_MASK, level << SPI_TCTRL_SS_LEVEL_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_ManualChipSelect(SPI_T *spi, SPI_TCTRL_SS_Sel cs)
|
||||
{
|
||||
HAL_SET_BIT(spi->TCTRL, SPI_TCTRL_SS_OWNER_MASK);
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_SEL_MASK, cs);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_AutoChipSelect(SPI_T *spi, SPI_TCTRL_SS_Sel cs, bool cs_remain)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_SEL_MASK, cs);
|
||||
HAL_CLR_BIT(spi->TCTRL, SPI_TCTRL_SS_OWNER_MASK);
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_CTL_MASK, (!cs_remain) << SPI_TCTRL_SS_CTL_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetCsIdle(SPI_T *spi, bool idle)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SPOL_MASK, (!!idle) << SPI_TCTRL_SPOL_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetSclkMode(SPI_T *spi, SPI_SCLK_Mode mode)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_CPOL_MASK | SPI_TCTRL_CPHA_MASK, mode);
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPI_INT_CS_DESELECT = SPI_IER_SS_INT_EN_MASK,
|
||||
SPI_INT_TRANSFER_COMPLETE = SPI_IER_TC_INT_EN_MASK,
|
||||
SPI_INT_TXFIFO_UNDER_RUN = SPI_IER_TF_UDR_INT_EN_MASK,
|
||||
SPI_INT_TXFIFO_OVERFLOW = SPI_IER_TF_OVF_INT_EN_MASK,
|
||||
SPI_INT_RXFIFO_UNDER_RUN = SPI_IER_RF_UDR_INT_EN_MASK,
|
||||
SPI_INT_RXFIFO_OVERFLOW = SPI_IER_RF_OVF_INT_EN_MASK,
|
||||
SPI_INT_TXFIFO_FULL = SPI_IER_TF_FUL_INT_EN_MASK,
|
||||
SPI_INT_TXFIFO_EMPTY = SPI_IER_TX_EMP_INT_EN_MASK,
|
||||
SPI_INT_TXFIFO_READY = SPI_IER_TX_ERQ_INT_EN_MASK,
|
||||
SPI_INT_RXFIFO_FULL = SPI_IER_RF_FUL_INT_EN_MASK,
|
||||
SPI_INT_RXFIFO_EMPTY = SPI_IER_RX_EMP_INT_EN_MASK,
|
||||
SPI_INT_RXFIFO_READY = SPI_IER_RF_RDY_INT_EN_MASK
|
||||
} SPI_Int_Type;
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_EnableInt(SPI_T *spi, SPI_Int_Type type)
|
||||
{
|
||||
HAL_SET_BIT(spi->IER, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_DisableInt(SPI_T *spi, SPI_Int_Type type)
|
||||
{
|
||||
HAL_CLR_BIT(spi->IER, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
bool SPI_IntState(SPI_T *spi, SPI_Int_Type type)
|
||||
{
|
||||
return !!HAL_GET_BIT(spi->STA, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
bool SPI_ClearInt(SPI_T *spi, SPI_Int_Type type)
|
||||
{
|
||||
HAL_SET_BIT(spi->STA, type);
|
||||
return HAL_GET_BIT(spi->STA, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_DebugReadTx(SPI_T *spi, rt_uint32_t *data)
|
||||
{
|
||||
// tbc...
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_DebugWriteRx(SPI_T *spi, rt_uint32_t *data)
|
||||
{
|
||||
// tbc...
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_ResetTxFifo(SPI_T *spi)
|
||||
{
|
||||
HAL_SET_BIT(spi->FCTL, SPI_FCTL_TF_RST_MASK);
|
||||
while (HAL_GET_BIT(spi->FCTL, SPI_FCTL_TF_RST_MASK) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_ResetRxFifo(SPI_T *spi)
|
||||
{
|
||||
HAL_SET_BIT(spi->FCTL, SPI_FCTL_RF_RST_MASK);
|
||||
while (HAL_GET_BIT(spi->FCTL, SPI_FCTL_RF_RST_MASK) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_DMA(SPI_T *spi, bool txEn, bool rxEn)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->FCTL,
|
||||
SPI_FCTL_TF_DRQ_EN_MASK | SPI_FCTL_RF_DRQ_EN_MASK,
|
||||
((!!txEn) << SPI_FCTL_TF_DRQ_EN_SHIFT) | ((!!rxEn) << SPI_FCTL_RF_DRQ_EN_SHIFT));
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetTxFifoThreshold(SPI_T *spi, uint8_t threshold)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->FCTL, SPI_FCTL_TX_TRIG_LEVEL_MASK, threshold << SPI_FCTL_TX_TRIG_LEVEL_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetRxFifoThreshold(SPI_T *spi, uint8_t threshold)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->FCTL, SPI_FCTL_RX_TRIG_LEVEL_MASK, threshold << SPI_FCTL_RX_TRIG_LEVEL_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
uint8_t SPI_GetTxFifoCounter(SPI_T *spi)
|
||||
{
|
||||
return (uint8_t)((spi->FST & SPI_FST_TF_CNT_MASK) >> SPI_FST_TF_CNT_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
uint8_t SPI_GetRxFifoCounter(SPI_T *spi)
|
||||
{
|
||||
return (uint8_t)((spi->FST & SPI_FST_RF_CNT_MASK) >> SPI_FST_RF_CNT_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_EnableDualMode(SPI_T *spi)
|
||||
{
|
||||
HAL_SET_BIT(spi->BCC, SPI_BCC_DRM_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_DisableDualMode(SPI_T *spi)
|
||||
{
|
||||
HAL_CLR_BIT(spi->BCC, SPI_BCC_DRM_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetInterval(SPI_T *spi, uint16_t nSCLK)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->WAIT, SPI_WAIT_WCC_MASK, nSCLK << SPI_WAIT_WCC_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
static void SPI_SetClkDiv(SPI_T *spi, uint16_t div)
|
||||
{
|
||||
uint8_t n = 0;
|
||||
if (div < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (div > 2 * (0xFF + 1))
|
||||
{
|
||||
HAL_CLR_BIT(spi->CCTR, SPI_CCTR_DRS_MASK);
|
||||
do
|
||||
{
|
||||
div = (div == 1) ? 0 : ((div + 1) / 2);
|
||||
n++;
|
||||
}
|
||||
while (div);
|
||||
|
||||
HAL_MODIFY_REG(spi->CCTR, SPI_CCTR_CDR1_MASK, (n & 0x0F) << SPI_CCTR_CDR1_SHIFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_SET_BIT(spi->CCTR, SPI_CCTR_DRS_MASK);
|
||||
n = ((div + 1) / 2) - 1;
|
||||
HAL_MODIFY_REG(spi->CCTR, SPI_CCTR_CDR2_MASK, (n & 0xFF) << SPI_CCTR_CDR2_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_SetDataSize(SPI_T *spi, rt_uint32_t data_size, rt_uint32_t dummy_size)
|
||||
{
|
||||
HAL_MODIFY_REG(spi->BC, SPI_BC_MBC_MASK, data_size + dummy_size);
|
||||
HAL_MODIFY_REG(spi->TC, SPI_TC_MWTC_MASK, data_size);
|
||||
HAL_MODIFY_REG(spi->BCC, SPI_BCC_STC_MASK, data_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_Write(SPI_T *spi, uint8_t *data)
|
||||
{
|
||||
HAL_REG_8BIT(&spi->TXD) = *data;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
void SPI_Read(SPI_T *spi, uint8_t *data)
|
||||
{
|
||||
*data = HAL_REG_8BIT(&spi->RXD);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
uint8_t *SPI_TxAddress(SPI_T *spi)
|
||||
{
|
||||
return (uint8_t *)&spi->TXD;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
__SPI_STATIC_INLINE__
|
||||
uint8_t *SPI_RxAddress(SPI_T *spi)
|
||||
{
|
||||
return (uint8_t *)&spi->RXD;
|
||||
}
|
||||
|
||||
/* private rt-thread spi ops function */
|
||||
static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
|
||||
static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message);
|
||||
|
||||
static struct rt_spi_ops tina_spi_ops =
|
||||
{
|
||||
configure,
|
||||
xfer
|
||||
};
|
||||
|
||||
static rt_err_t configure(struct rt_spi_device *device,
|
||||
struct rt_spi_configuration *configuration)
|
||||
{
|
||||
struct rt_spi_bus *spi_bus = (struct rt_spi_bus *)device->bus;
|
||||
struct tina_spi_cs *tina_spi_cs = device->parent.user_data;
|
||||
struct tina_spi *_spi_info = (struct tina_spi *)spi_bus->parent.user_data;
|
||||
SPI_T *spi = _spi_info->spi;
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
RT_ASSERT(device != RT_NULL);
|
||||
RT_ASSERT(configuration != RT_NULL);
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
DEBUG_PRINTF("spi address: %08X\n", (rt_uint32_t)spi);
|
||||
|
||||
SPI_Disable(spi);
|
||||
SPI_Reset(spi);
|
||||
SPI_ResetRxFifo(spi);
|
||||
SPI_ResetTxFifo(spi);
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
/* data_width */
|
||||
if (configuration->data_width != 8)
|
||||
{
|
||||
DEBUG_PRINTF("error: data_width is %d\n", configuration->data_width);
|
||||
return RT_EIO;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
SPI_SetDuplex(spi, SPI_TCTRL_DHB_FULL_DUPLEX);
|
||||
SPI_SetMode(spi, SPI_CTRL_MODE_MASTER);
|
||||
|
||||
/* MSB or LSB */
|
||||
if (configuration->mode & RT_SPI_MSB)
|
||||
{
|
||||
SPI_SetFirstTransmitBit(spi, SPI_TCTRL_FBS_MSB);
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_SetFirstTransmitBit(spi, SPI_TCTRL_FBS_LSB);
|
||||
}
|
||||
|
||||
switch (configuration->mode)
|
||||
{
|
||||
case RT_SPI_MODE_0:
|
||||
SPI_SetSclkMode(spi, SPI_SCLK_Mode0);
|
||||
break;
|
||||
case RT_SPI_MODE_1:
|
||||
SPI_SetSclkMode(spi, SPI_SCLK_Mode1);
|
||||
break;
|
||||
case RT_SPI_MODE_2:
|
||||
SPI_SetSclkMode(spi, SPI_SCLK_Mode2);
|
||||
break;
|
||||
case RT_SPI_MODE_3:
|
||||
SPI_SetSclkMode(spi, SPI_SCLK_Mode3);
|
||||
break;
|
||||
}
|
||||
|
||||
/* baudrate */
|
||||
{
|
||||
unsigned int spi_clock = 0;
|
||||
rt_uint32_t max_hz;
|
||||
rt_uint32_t div;
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
max_hz = configuration->max_hz;
|
||||
|
||||
if (max_hz > SPI_BUS_MAX_CLK)
|
||||
{
|
||||
max_hz = SPI_BUS_MAX_CLK;
|
||||
}
|
||||
spi_clock = ahb_get_clk();
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
div = (spi_clock + max_hz - 1) / max_hz;
|
||||
|
||||
dbg_log(DBG_LOG, "configuration->max_hz: %d\n", configuration->max_hz);
|
||||
dbg_log(DBG_LOG, "max freq: %d\n", max_hz);
|
||||
dbg_log(DBG_LOG, "spi_clock: %d\n", spi_clock);
|
||||
dbg_log(DBG_LOG, "div: %d\n", div);
|
||||
|
||||
SPI_SetClkDiv(spi, div / 2);
|
||||
} /* baudrate */
|
||||
|
||||
SPI_ManualChipSelect(spi, tina_spi_cs->cs);
|
||||
SPI_SetDataSize(spi, 0, 0);
|
||||
SPI_Enable(spi);
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
return RT_EOK;
|
||||
};
|
||||
|
||||
static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message)
|
||||
{
|
||||
struct rt_spi_bus *r6_spi_bus = (struct rt_spi_bus *)device->bus;
|
||||
struct tina_spi *_spi_info = (struct tina_spi *)r6_spi_bus->parent.user_data;
|
||||
SPI_T *spi = _spi_info->spi;
|
||||
struct rt_spi_configuration *config = &device->config;
|
||||
struct tina_spi_cs *tina_spi_cs = device->parent.user_data;
|
||||
|
||||
RT_ASSERT(device != NULL);
|
||||
RT_ASSERT(message != NULL);
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
DEBUG_PRINTF("spi_info: %08X\n", (rt_uint32_t)_spi_info);
|
||||
DEBUG_PRINTF("spi address: %08X\n", (rt_uint32_t)spi);
|
||||
|
||||
/* take CS */
|
||||
if (message->cs_take)
|
||||
{
|
||||
SPI_ManualChipSelect(spi, tina_spi_cs->cs);
|
||||
SPI_SetCsLevel(spi, false);
|
||||
DEBUG_PRINTF("spi take cs\n");
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
{
|
||||
if ((config->data_width <= 8) && (message->length > 0))
|
||||
{
|
||||
const rt_uint8_t *send_ptr = message->send_buf;
|
||||
rt_uint8_t *recv_ptr = message->recv_buf;
|
||||
rt_uint32_t tx_size = message->length;
|
||||
rt_uint32_t rx_size = message->length;
|
||||
|
||||
DEBUG_PRINTF("spi poll transfer start: %d\n", tx_size);
|
||||
|
||||
SPI_ResetTxFifo(spi);
|
||||
SPI_ResetRxFifo(spi);
|
||||
SPI_SetDataSize(spi, tx_size, 0);
|
||||
|
||||
SPI_StartTransmit(spi);
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
while (tx_size > 0 || rx_size > 0)
|
||||
{
|
||||
uint8_t tx_data = 0xFF;
|
||||
uint8_t rx_data = 0xFF;
|
||||
|
||||
while ((SPI_GetTxFifoCounter(spi) < SPI_FIFO_SIZE) && (tx_size > 0))
|
||||
{
|
||||
if (send_ptr != RT_NULL)
|
||||
{
|
||||
tx_data = *send_ptr++;
|
||||
}
|
||||
SPI_Write(spi, &tx_data);
|
||||
tx_size--;
|
||||
}
|
||||
|
||||
while (SPI_GetRxFifoCounter(spi) > 0)
|
||||
{
|
||||
rx_size--;
|
||||
SPI_Read(spi, &rx_data);
|
||||
|
||||
if (recv_ptr != RT_NULL)
|
||||
{
|
||||
*recv_ptr++ = rx_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
if ((tx_size != 0) || (rx_size != 0))
|
||||
{
|
||||
DEBUG_PRINTF("spi_tx_rx error with tx count = %d, rx count = %d.\n", tx_size, rx_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
while (SPI_IntState(spi, SPI_INT_TRANSFER_COMPLETE) == 0);
|
||||
SPI_ClearInt(spi, SPI_INT_TRANSFER_COMPLETE);
|
||||
|
||||
DEBUG_PRINTF("spi poll transfer finsh\n");
|
||||
}
|
||||
else if (config->data_width > 8)
|
||||
{
|
||||
DEBUG_PRINTF("data width: %d\n", config->data_width);
|
||||
RT_ASSERT(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* release CS */
|
||||
if (message->cs_release)
|
||||
{
|
||||
SPI_SetCsLevel(spi, true);
|
||||
DEBUG_PRINTF("spi release cs\n");
|
||||
}
|
||||
|
||||
return message->length;
|
||||
};
|
||||
|
||||
#ifdef TINA_USING_SPI0
|
||||
static struct rt_spi_bus spi_bus0;
|
||||
#endif
|
||||
|
||||
#ifdef TINA_USING_SPI1
|
||||
static struct rt_spi_bus spi_bus1;
|
||||
#endif
|
||||
|
||||
static const struct tina_spi spis[] =
|
||||
{
|
||||
#ifdef TINA_USING_SPI0
|
||||
{(SPI_T *)SPI0_BASE_ADDR, SPI0_GATING, &spi_bus0},
|
||||
#endif
|
||||
|
||||
#ifdef TINA_USING_SPI1
|
||||
{(SPI_T *)SPI1_BASE_ADDR, SPI1_GATING, &spi_bus1},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** \brief init and register r6 spi bus.
|
||||
*
|
||||
* \param SPI: R6 SPI, e.g: SPI1,SPI2,SPI3.
|
||||
* \param spi_bus_name: spi bus name, e.g: "spi1"
|
||||
* \return
|
||||
*
|
||||
*/
|
||||
rt_err_t tina_spi_bus_register(SPI_T *spi, const char *spi_bus_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
RT_ASSERT(spi_bus_name != RT_NULL);
|
||||
|
||||
for (i = 0; i < ARR_LEN(spis); i++)
|
||||
{
|
||||
if (spi == spis[i].spi)
|
||||
{
|
||||
bus_software_reset_disalbe(spis[i].spi_gate);
|
||||
bus_gate_clk_enalbe(spis[i].spi_gate);
|
||||
|
||||
spis[i].spi_bus->parent.user_data = (void *)&spis[i];
|
||||
DEBUG_PRINTF("bus addr: %08X\n", (rt_uint32_t)spis[i].spi_bus);
|
||||
DEBUG_PRINTF("user_data: %08X\n", (rt_uint32_t)spis[i].spi_bus->parent.user_data);
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
rt_spi_bus_register(spis[i].spi_bus, spi_bus_name, &tina_spi_ops);
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
return RT_EOK;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
return RT_ERROR;
|
||||
}
|
||||
|
||||
int rt_hw_spi_init(void)
|
||||
{
|
||||
DEBUG_PRINTF("register spi bus\n");
|
||||
|
||||
#ifdef TINA_USING_SPI0
|
||||
/* register spi bus */
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
gpio_set_func(GPIO_PORT_C, GPIO_PIN_0, IO_FUN_1);
|
||||
gpio_set_func(GPIO_PORT_C, GPIO_PIN_2, IO_FUN_1);
|
||||
gpio_set_func(GPIO_PORT_C, GPIO_PIN_3, IO_FUN_1);
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
result = tina_spi_bus_register((SPI_T *)SPI0_BASE_ADDR, "spi0");
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
/* attach cs */
|
||||
{
|
||||
static struct rt_spi_device spi_device;
|
||||
static struct tina_spi_cs spi_cs;
|
||||
rt_err_t result;
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
spi_cs.cs = SPI_TCTRL_SS_SEL_SS0;
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
gpio_set_func(GPIO_PORT_C, GPIO_PIN_1, IO_FUN_1);
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
result = rt_spi_bus_attach_device(&spi_device, "spi00", "spi0", (void *)&spi_cs);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
#endif
|
||||
|
||||
#ifdef TINA_USING_SPI1
|
||||
/* register spi bus */
|
||||
{
|
||||
rt_err_t result;
|
||||
|
||||
gpio_set_func(GPIO_PORT_A, GPIO_PIN_1, IO_FUN_5);
|
||||
gpio_set_func(GPIO_PORT_A, GPIO_PIN_2, IO_FUN_5);
|
||||
gpio_set_func(GPIO_PORT_A, GPIO_PIN_3, IO_FUN_5);
|
||||
|
||||
result = tina_spi_bus_register((SPI_T *)SPI1_BASE_ADDR, "spi1");
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
DEBUG_PRINTF("register spi bus faild: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("attach cs\n");
|
||||
/* attach cs */
|
||||
{
|
||||
static struct rt_spi_device spi_device;
|
||||
static struct tina_spi_cs spi_cs;
|
||||
rt_err_t result;
|
||||
|
||||
spi_cs.cs = SPI_TCTRL_SS_SEL_SS0;
|
||||
gpio_set_func(GPIO_PORT_A, GPIO_PIN_0, IO_FUN_5);
|
||||
|
||||
result = rt_spi_bus_attach_device(&spi_device, "spi10", "spi1", (void *)&spi_cs);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
DEBUG_PRINTF("attach cs faild: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_BOARD_EXPORT(rt_hw_spi_init);
|
||||
#endif
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* File : drv_spi.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2017, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-02-08 RT-Thread the first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_SPI_H__
|
||||
#define __DRV_SPI_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/********************** private ************************************/
|
||||
|
||||
#define SPI0_BASE_ADDR (0x01C05000)
|
||||
#define SPI1_BASE_ADDR (0x01C06000)
|
||||
|
||||
/**
|
||||
* @brief Serial Peripheral Interface
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
volatile rt_uint32_t VER; /* SPI Version number Register, Address offset: 0x00 */
|
||||
volatile rt_uint32_t CTRL; /* SPI Global Control Register, Address offset: 0x04 */
|
||||
volatile rt_uint32_t TCTRL; /* SPI Transfer Control Register, Address offset: 0x08 */
|
||||
volatile rt_uint32_t RESERVED1[1]; /* Reserved, 0x0C */
|
||||
volatile rt_uint32_t IER; /* SPI Interrupt Control Register, Address offset: 0x10 */
|
||||
volatile rt_uint32_t STA; /* SPI Interrupt Status Register, Address offset: 0x14 */
|
||||
volatile rt_uint32_t FCTL; /* SPI FIFO Control Register, Address offset: 0x18 */
|
||||
volatile rt_uint32_t FST; /* SPI FIFO Status Register, Address offset: 0x1C */
|
||||
volatile rt_uint32_t WAIT; /* SPI Wait Clock Counter Register, Address offset: 0x20 */
|
||||
volatile rt_uint32_t CCTR; /* SPI Clock Rate Control Register, Address offset: 0x24 */
|
||||
volatile rt_uint32_t RESERVED2[2]; /* Reserved, 0x28-0x2C */
|
||||
volatile rt_uint32_t BC; /* SPI Master mode Burst Control Register, Address offset: 0x30 */
|
||||
volatile rt_uint32_t TC; /* SPI Master mode Transmit Counter Register, Address offset: 0x34 */
|
||||
volatile rt_uint32_t BCC; /* SPI Burst Control Register, Address offset: 0x38 */
|
||||
volatile rt_uint32_t RESERVED3[19]; /* Reserved, 0x3C-0x84 */
|
||||
volatile rt_uint32_t NDMA_MODE_CTRL; /* SPI Nomal DMA Mode Control Regist Address offset: 0x88 */
|
||||
volatile rt_uint32_t RESERVED4[93]; /* Reserved, 0x8C-0x1FC */
|
||||
volatile rt_uint32_t TXD; /* SPI TX Date Register, Address offset: 0x200 */
|
||||
volatile rt_uint32_t RESERVED5[63]; /* Reserved, 0x204-0x2FC */
|
||||
volatile rt_uint32_t RXD; /* SPI RX Date Register, Address offset: 0x300 */
|
||||
} SPI_T;
|
||||
|
||||
/*
|
||||
* @brief SPI Global Control Register
|
||||
*/
|
||||
#define SPI_CTRL_RST_SHIFT (31)
|
||||
#define SPI_CTRL_RST_MASK (0x1U << SPI_CTRL_RST_SHIFT)
|
||||
|
||||
#define SPI_CTRL_TP_EN_SHIFT (7)
|
||||
#define SPI_CTRL_TP_EN_MASK (0x1U << SPI_CTRL_TP_EN_SHIFT)
|
||||
|
||||
#define SPI_CTRL_MODE_SHIFT (1)
|
||||
#define SPI_CTRL_MODE_MASK (0x1U << SPI_CTRL_MODE_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_CTRL_MODE_SLAVE = 0 << SPI_CTRL_MODE_SHIFT,
|
||||
SPI_CTRL_MODE_MASTER = 1 << SPI_CTRL_MODE_SHIFT
|
||||
} SPI_CTRL_Mode;
|
||||
|
||||
#define SPI_CTRL_EN_SHIFT (0)
|
||||
#define SPI_CTRL_EN_MASK (0x1U << SPI_CTRL_EN_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_CTRL_EN_DISABLE = 0 << SPI_CTRL_EN_SHIFT,
|
||||
SPI_CTRL_EN_ENABLE = 1 << SPI_CTRL_EN_SHIFT
|
||||
} SPI_CTRL_En;
|
||||
|
||||
/*
|
||||
* @brief SPI Transfer Control Register
|
||||
*/
|
||||
#define SPI_TCTRL_XCH_SHIFT (31)
|
||||
#define SPI_TCTRL_XCH_MASK (0x1U << SPI_TCTRL_XCH_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_XCH_IDLE = 0 << SPI_TCTRL_XCH_SHIFT,
|
||||
SPI_TCTRL_XCH_START = 1 << SPI_TCTRL_XCH_SHIFT
|
||||
} SPI_TCTRL_Xch;
|
||||
|
||||
#define SPI_TCTRL_SDDM_SHIFT (14)
|
||||
#define SPI_TCTRL_SDDM_MASK (0x0U << SPI_TCTRL_SDDM_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_SDDM_SEND_NODELAY = 0 << SPI_TCTRL_SDDM_SHIFT,
|
||||
SPI_TCTRL_SDDM_SEND_DELAY = 1 << SPI_TCTRL_SDDM_SHIFT
|
||||
} SPI_TCTRL_Sddm;
|
||||
|
||||
#define SPI_TCTRL_SDM_SHIFT (13)
|
||||
#define SPI_TCTRL_SDM_MASK (0x1U << SPI_TCTRL_SDM_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_SDM_SAMPLE_NODELAY = 1 << SPI_TCTRL_SDM_SHIFT,
|
||||
SPI_TCTRL_SDM_SAMPLE_DELAY = 0 << SPI_TCTRL_SDM_SHIFT
|
||||
} SPI_TCTRL_Sdm;
|
||||
|
||||
#define SPI_TCTRL_FBS_SHIFT (12)
|
||||
#define SPI_TCTRL_FBS_MASK (0x1U << SPI_TCTRL_FBS_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_FBS_MSB = 0 << SPI_TCTRL_FBS_SHIFT,
|
||||
SPI_TCTRL_FBS_LSB = 1 << SPI_TCTRL_FBS_SHIFT
|
||||
} SPI_TCTRL_Fbs;
|
||||
|
||||
#define SPI_TCTRL_SDC_SHIFT (11)
|
||||
#define SPI_TCTRL_SDC_MASK (0x1U << SPI_TCTRL_SDC_SHIFT)
|
||||
|
||||
#define SPI_TCTRL_RPSM_SHIFT (10)
|
||||
#define SPI_TCTRL_RPSM_MASK (0x1U << SPI_TCTRL_RPSM_SHIFT)
|
||||
|
||||
#define SPI_TCTRL_DDB_SHIFT (9)
|
||||
#define SPI_TCTRL_DDB_MASK (0x1U << SPI_TCTRL_DDB_SHIFT)
|
||||
|
||||
#define SPI_TCTRL_DHB_SHIFT (8)
|
||||
#define SPI_TCTRL_DHB_MASK (0x1U << SPI_TCTRL_DHB_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_DHB_FULL_DUPLEX = 0 << SPI_TCTRL_DHB_SHIFT,
|
||||
SPI_TCTRL_DHB_HALF_DUPLEX = 1 << SPI_TCTRL_DHB_SHIFT
|
||||
} SPI_TCTRL_DHB_Duplex;
|
||||
|
||||
#define SPI_TCTRL_SS_LEVEL_SHIFT (7)
|
||||
#define SPI_TCTRL_SS_LEVEL_MASK (0x1U << SPI_TCTRL_SS_LEVEL_SHIFT)
|
||||
|
||||
#define SPI_TCTRL_SS_OWNER_SHIFT (6)
|
||||
#define SPI_TCTRL_SS_OWNER_MASK (0x1U << SPI_TCTRL_SS_OWNER_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_SS_OWNER_CONTROLLER = 0 << SPI_TCTRL_SS_OWNER_SHIFT,
|
||||
SPI_TCTRL_SS_OWNER_SOFTWARE = 1 << SPI_TCTRL_SS_OWNER_SHIFT
|
||||
} SPI_TCTRL_SS_OWNER;
|
||||
|
||||
#define SPI_TCTRL_SS_SEL_SHIFT (4)
|
||||
#define SPI_TCTRL_SS_SEL_MASK (0x3U << SPI_TCTRL_SS_SEL_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_SS_SEL_SS0 = 0 << SPI_TCTRL_SS_SEL_SHIFT,
|
||||
SPI_TCTRL_SS_SEL_SS1 = 1 << SPI_TCTRL_SS_SEL_SHIFT,
|
||||
SPI_TCTRL_SS_SEL_SS2 = 2 << SPI_TCTRL_SS_SEL_SHIFT,
|
||||
SPI_TCTRL_SS_SEL_SS3 = 3 << SPI_TCTRL_SS_SEL_SHIFT
|
||||
} SPI_TCTRL_SS_Sel;
|
||||
|
||||
#define SPI_TCTRL_SS_CTL_SHIFT (3)
|
||||
#define SPI_TCTRL_SS_CTL_MASK (0x1U << SPI_TCTRL_SS_CTL_SHIFT)
|
||||
|
||||
#define SPI_TCTRL_SPOL_SHIFT (2)
|
||||
#define SPI_TCTRL_SPOL_MASK (0x1U << SPI_TCTRL_SPOL_SHIFT)
|
||||
|
||||
#define SPI_TCTRL_CPOL_SHIFT (1)
|
||||
#define SPI_TCTRL_CPOL_MASK (0x1U << SPI_TCTRL_CPOL_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_CPOL_HIGH = 0 << SPI_TCTRL_CPOL_SHIFT,
|
||||
SPI_TCTRL_CPOL_LOW = 1 << SPI_TCTRL_CPOL_SHIFT
|
||||
} SPI_TCTRL_Cpol;
|
||||
|
||||
#define SPI_TCTRL_CPHA_SHIFT (0)
|
||||
#define SPI_TCTRL_CPHA_MASK (0x1U << SPI_TCTRL_CPHA_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_TCTRL_CPHA_PHASE0 = 0 << SPI_TCTRL_CPHA_SHIFT,
|
||||
SPI_TCTRL_CPHA_PHASE1 = 1 << SPI_TCTRL_CPHA_SHIFT
|
||||
} SPI_TCTRL_Cpha;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPI_SCLK_Mode0 = 0 << SPI_TCTRL_CPHA_SHIFT,
|
||||
SPI_SCLK_Mode1 = 1 << SPI_TCTRL_CPHA_SHIFT,
|
||||
SPI_SCLK_Mode2 = 2 << SPI_TCTRL_CPHA_SHIFT,
|
||||
SPI_SCLK_Mode3 = 3 << SPI_TCTRL_CPHA_SHIFT
|
||||
} SPI_SCLK_Mode;
|
||||
|
||||
/*
|
||||
* @brief SPI Interrupt Control Register
|
||||
*/
|
||||
#define SPI_IER_SS_INT_EN_SHIFT (13)
|
||||
#define SPI_IER_SS_INT_EN_MASK (0x1U << SPI_IER_SS_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_TC_INT_EN_SHIFT (12)
|
||||
#define SPI_IER_TC_INT_EN_MASK (0x1U << SPI_IER_TC_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_TF_UDR_INT_EN_SHIFT (11)
|
||||
#define SPI_IER_TF_UDR_INT_EN_MASK (0x1U << SPI_IER_TF_UDR_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_TF_OVF_INT_EN_SHIFT (10)
|
||||
#define SPI_IER_TF_OVF_INT_EN_MASK (0x1U << SPI_IER_TF_OVF_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_RF_UDR_INT_EN_SHIFT (9)
|
||||
#define SPI_IER_RF_UDR_INT_EN_MASK (0x1U << SPI_IER_RF_UDR_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_RF_OVF_INT_EN_SHIFT (8)
|
||||
#define SPI_IER_RF_OVF_INT_EN_MASK (0x1U << SPI_IER_RF_OVF_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_TF_FUL_INT_EN_SHIFT (6)
|
||||
#define SPI_IER_TF_FUL_INT_EN_MASK (0x1U << SPI_IER_TF_FUL_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_TX_EMP_INT_EN_SHIFT (5)
|
||||
#define SPI_IER_TX_EMP_INT_EN_MASK (0x1U << SPI_IER_TX_EMP_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_TX_ERQ_INT_EN_SHIFT (4)
|
||||
#define SPI_IER_TX_ERQ_INT_EN_MASK (0x1U << SPI_IER_TX_ERQ_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_RF_FUL_INT_EN_SHIFT (2)
|
||||
#define SPI_IER_RF_FUL_INT_EN_MASK (0x1U << SPI_IER_RF_FUL_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_RX_EMP_INT_EN_SHIFT (1)
|
||||
#define SPI_IER_RX_EMP_INT_EN_MASK (0x1U << SPI_IER_RX_EMP_INT_EN_SHIFT)
|
||||
|
||||
#define SPI_IER_RF_RDY_INT_EN_SHIFT (0)
|
||||
#define SPI_IER_RF_RDY_INT_EN_MASK (0x1U << SPI_IER_RF_RDY_INT_EN_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI Interrupt Status Register
|
||||
*/
|
||||
#define SPI_STA_SSI_SHIFT (13)
|
||||
#define SPI_STA_SSI_MASK (0x1U << SPI_STA_SSI_SHIFT)
|
||||
|
||||
#define SPI_STA_TC_SHIFT (12)
|
||||
#define SPI_STA_TC_MASK (0x1U << SPI_STA_TC_SHIFT)
|
||||
|
||||
#define SPI_STA_TF_UDF_SHIFT (11)
|
||||
#define SPI_STA_TF_UDF_MASK (0x1U << SPI_STA_TF_UDF_SHIFT)
|
||||
|
||||
#define SPI_STA_TF_OVF_SHIFT (10)
|
||||
#define SPI_STA_TF_OVF_MASK (0x1U << SPI_STA_TF_OVF_SHIFT)
|
||||
|
||||
#define SPI_STA_RX_UDF_SHIFT (9)
|
||||
#define SPI_STA_RX_UDF_MASK (0x1U << SPI_STA_RX_UDF_SHIFT)
|
||||
|
||||
#define SPI_STA_RX_OVF_SHIFT (8)
|
||||
#define SPI_STA_RX_OVF_MASK (0x1U << SPI_STA_RX_OVF_SHIFT)
|
||||
|
||||
#define SPI_STA_TX_FULL_SHIFT (6)
|
||||
#define SPI_STA_TX_FULL_MASK (0x1U << SPI_STA_TX_FULL_SHIFT)
|
||||
|
||||
#define SPI_STA_TX_EMP_SHIFT (5)
|
||||
#define SPI_STA_TX_EMP_MASK (0x1U << SPI_STA_TX_EMP_SHIFT)
|
||||
|
||||
#define SPI_STA_TX_READY_SHIFT (4)
|
||||
#define SPI_STA_TX_READY_MASK (0x1U << SPI_STA_TX_READY_SHIFT)
|
||||
|
||||
#define SPI_STA_RX_FULL_SHIFT (2)
|
||||
#define SPI_STA_RX_FULL_MASK (0x1U << SPI_STA_RX_FULL_SHIFT)
|
||||
|
||||
#define SPI_STA_RX_EMP_SHIFT (1)
|
||||
#define SPI_STA_RX_EMP_MASK (0x1U << SPI_STA_RX_EMP_SHIFT)
|
||||
|
||||
#define SPI_STA_RX_RDY_SHIFT (0)
|
||||
#define SPI_STA_RX_RDY_MASK (0x1U << SPI_STA_RX_RDY_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI FIFO Control Register
|
||||
*/
|
||||
#define SPI_FCTL_TF_RST_SHIFT (31)
|
||||
#define SPI_FCTL_TF_RST_MASK (0x1U << SPI_FCTL_TF_RST_SHIFT)
|
||||
|
||||
#define SPI_FCTL_TF_TEST_EN_SHIFT (30)
|
||||
#define SPI_FCTL_TF_TEST_EN_MASK (0x1U << SPI_FCTL_TF_TEST_EN_SHIFT)
|
||||
|
||||
#define SPI_FCTL_TF_DRQ_EN_SHIFT (24)
|
||||
#define SPI_FCTL_TF_DRQ_EN_MASK (0x1U << SPI_FCTL_TF_DRQ_EN_SHIFT)
|
||||
#define SPI_FCTL_TF_DRQ_EN_BIT HAL_BIT(24)
|
||||
|
||||
#define SPI_FCTL_TX_TRIG_LEVEL_SHIFT (16)
|
||||
#define SPI_FCTL_TX_TRIG_LEVEL_MASK (0xFFU << SPI_FCTL_TX_TRIG_LEVEL_SHIFT)
|
||||
|
||||
#define SPI_FCTL_RF_RST_SHIFT (15)
|
||||
#define SPI_FCTL_RF_RST_MASK (0x1U << SPI_FCTL_RF_RST_SHIFT)
|
||||
|
||||
#define SPI_FCTL_RF_TEST_SHIFT (14)
|
||||
#define SPI_FCTL_RF_TEST_MASK (0x1U << SPI_FCTL_RF_TEST_SHIFT)
|
||||
|
||||
#define SPI_FCTL_RF_DRQ_EN_SHIFT (8)
|
||||
#define SPI_FCTL_RF_DRQ_EN_MASK (0x1U << SPI_FCTL_RF_DRQ_EN_SHIFT)
|
||||
|
||||
#define SPI_FCTL_RX_TRIG_LEVEL_SHIFT (0)
|
||||
#define SPI_FCTL_RX_TRIG_LEVEL_MASK (0xFFU << SPI_FCTL_RX_TRIG_LEVEL_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI FIFO Status Registe
|
||||
*/
|
||||
#define SPI_FST_TB_WR_SHIFT (31)
|
||||
#define SPI_FST_TB_WR_MASK (0x1U << SPI_FST_TB_WR_SHIFT)
|
||||
|
||||
#define SPI_FST_TB_CNT_SHIFT (28)
|
||||
#define SPI_FST_TB_CNT_MASK (0x7U << SPI_FST_TB_CNT_SHIFT)
|
||||
|
||||
#define SPI_FST_TF_CNT_SHIFT (16)
|
||||
#define SPI_FST_TF_CNT_MASK (0xFFU << SPI_FST_TF_CNT_SHIFT)
|
||||
|
||||
#define SPI_FST_RB_WR_SHIFT (15)
|
||||
#define SPI_FST_RB_WR_MASK (0x1U << SPI_FST_RB_WR_SHIFT)
|
||||
|
||||
#define SPI_FST_RB_CNT_SHIFT (12)
|
||||
#define SPI_FST_RB_CNT_MASK (0x7U << SPI_FST_RB_CNT_SHIFT)
|
||||
|
||||
#define SPI_FST_RF_CNT_SHIFT (0)
|
||||
#define SPI_FST_RF_CNT_MASK (0xFFU << SPI_FST_RF_CNT_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI Wait Clock Counter Register
|
||||
*/
|
||||
#define SPI_WAIT_SWC_SHIFT (16)
|
||||
#define SPI_WAIT_SWC_MASK (0xFU << SPI_WAIT_SWC_SHIFT)
|
||||
|
||||
#define SPI_WAIT_WCC_SHIFT (0)
|
||||
#define SPI_WAIT_WCC_MASK (0xFFFFU << SPI_WAIT_WCC_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI Clock Rate Control Register
|
||||
*/
|
||||
#define SPI_CCTR_DRS_SHIFT (12)
|
||||
#define SPI_CCTR_DRS_MASK (0x1U << SPI_CCTR_DRS_SHIFT)
|
||||
typedef enum
|
||||
{
|
||||
SPI_CCTR_DRS_type_divRate1 = 0 << SPI_CCTR_DRS_SHIFT,
|
||||
SPI_CCTR_DRS_type_divRate2 = 1 << SPI_CCTR_DRS_SHIFT
|
||||
} SPI_CCTR_DRS_type;
|
||||
|
||||
#define SPI_CCTR_CDR1_SHIFT (8)
|
||||
#define SPI_CCTR_CDR1_MASK (0xFU << SPI_CCTR_CDR1_SHIFT)
|
||||
|
||||
#define SPI_CCTR_CDR2_SHIFT (0)
|
||||
#define SPI_CCTR_CDR2_MASK (0xFFU << SPI_CCTR_CDR2_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI Master mode Burst Control Register
|
||||
*/
|
||||
#define SPI_BC_MBC_SHIFT (0)
|
||||
#define SPI_BC_MBC_MASK (0xFFFFFFU << SPI_BC_MBC_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI Master mode Transmit Counter Register
|
||||
*/
|
||||
#define SPI_TC_MWTC_SHIFT (0)
|
||||
#define SPI_TC_MWTC_MASK (0xFFFFFFU << SPI_TC_MWTC_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI Burst Control Register
|
||||
*/
|
||||
#define SPI_BCC_DRM_SHIFT (28)
|
||||
#define SPI_BCC_DRM_MASK (0x1U << SPI_BCC_DRM_SHIFT)
|
||||
|
||||
#define SPI_BCC_DBC_SHIFT (24)
|
||||
#define SPI_BCC_DBC_MASK (0xFU << SPI_BCC_DBC_SHIFT)
|
||||
|
||||
#define SPI_BCC_STC_SHIFT (0)
|
||||
#define SPI_BCC_STC_MASK (0xFFFFFFU << SPI_BCC_STC_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI Nomal DMA Mode Control Regist
|
||||
*/
|
||||
#define SPI_NDMA_MODE_CTRL_SHIFT (0)
|
||||
#define SPI_NDMA_MODE_CTRL_MASK (0xFFU << SPI_NDMA_MODE_CTRL_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI TX Date Register
|
||||
*/
|
||||
#define SPI_TXD_SHIFT (0)
|
||||
#define SPI_TXD_MASK (0xFFFFFFFFU << SPI_TXD_SHIFT)
|
||||
|
||||
/*
|
||||
* @brief SPI RX Date Register
|
||||
*/
|
||||
#define SPI_RXD_SHIFT (0)
|
||||
#define SPI_RXD_MASK (0xFFFFFFFFU << SPI_RXD_SHIFT)
|
||||
|
||||
/* other */
|
||||
#define SPI_FIFO_SIZE (64)
|
||||
#define SPI_MAX_WAIT_MS (2000)
|
||||
#define SPI_SOURCE_CLK (24 * 1000 * 1000)
|
||||
|
||||
/* io ops */
|
||||
#define HAL_BIT(pos) (1U << (pos))
|
||||
|
||||
#define HAL_SET_BIT(reg, mask) ((reg) |= (mask))
|
||||
#define HAL_CLR_BIT(reg, mask) ((reg) &= ~(mask))
|
||||
#define HAL_GET_BIT(reg, mask) ((reg) & (mask))
|
||||
#define HAL_GET_BIT_VAL(reg, shift, vmask) (((reg) >> (shift)) & (vmask))
|
||||
|
||||
#define HAL_MODIFY_REG(reg, clr_mask, set_mask) \
|
||||
((reg) = (((reg) & (~(clr_mask))) | (set_mask)))
|
||||
|
||||
/* access LSBs of a 32-bit register (little endian only) */
|
||||
#define HAL_REG_32BIT(reg_addr) (*((volatile rt_uint32_t *)(reg_addr)))
|
||||
#define HAL_REG_16BIT(reg_addr) (*((volatile rt_uint16_t *)(reg_addr)))
|
||||
#define HAL_REG_8BIT(reg_addr) (*((volatile rt_uint8_t *)(reg_addr)))
|
||||
|
||||
#define HAL_WAIT_FOREVER OS_WAIT_FOREVER
|
||||
|
||||
#define HAL_ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
|
||||
|
||||
struct tina_spi
|
||||
{
|
||||
SPI_T *spi;
|
||||
unsigned int spi_gate;
|
||||
struct rt_spi_bus *spi_bus;
|
||||
};
|
||||
|
||||
struct tina_spi_cs
|
||||
{
|
||||
SPI_TCTRL_SS_Sel cs;
|
||||
};
|
||||
/* public function */
|
||||
rt_err_t r6_spi_bus_register(SPI_T *spi, const char *spi_bus_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* File : drv_spi_flash.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2017, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-02-08 RT-Thread the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_ENABLE
|
||||
#define DBG_SECTION_NAME "[FLASH]"
|
||||
#define DBG_LEVEL DBG_LOG
|
||||
#define DBG_COLOR
|
||||
#include <rtdbg.h>
|
||||
|
||||
#define SPI_FLASH_DEVICE_NAME "spi00"
|
||||
#define SPI_FLASH_CHIP "gd25qxx"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINTF(...)
|
||||
#endif
|
||||
|
||||
#ifdef TINA_USING_SPI_FLASH
|
||||
|
||||
#include "spi_flash.h"
|
||||
|
||||
#if defined(RT_USING_SFUD)
|
||||
#include "spi_flash_sfud.h"
|
||||
rt_spi_flash_device_t spi_device;
|
||||
int rt_hw_spi_flash_with_sfud_init(void)
|
||||
{
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
spi_device = rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME);
|
||||
if (spi_device == NULL)
|
||||
{
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
return RT_ERROR;
|
||||
};
|
||||
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_PREV_EXPORT(rt_hw_spi_flash_with_sfud_init);
|
||||
|
||||
#elif defined(RT_USING_W25QXX)
|
||||
#include "spi_flash_w25qxx.h"
|
||||
|
||||
int rt_hw_spi_flash_init(void)
|
||||
{
|
||||
DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__);
|
||||
return w25qxx_init(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME);
|
||||
}
|
||||
INIT_DEVICE_EXPORT(rt_hw_spi_flash_init);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue