Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
rt-thread
提交
8e314279
R
rt-thread
项目概览
BaiXuePrincess
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
未验证
提交
8e314279
编写于
4月 20, 2018
作者:
lymzzyh
提交者:
GitHub
4月 20, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1374 from uestczyh222/master
[Bsp][Tina]Add spi driver
上级
da704e69
39558535
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
1326 addition
and
1 deletion
+1326
-1
bsp/allwinner_tina/drivers/Kconfig
bsp/allwinner_tina/drivers/Kconfig
+16
-1
bsp/allwinner_tina/drivers/spi/SConscript
bsp/allwinner_tina/drivers/spi/SConscript
+9
-0
bsp/allwinner_tina/drivers/spi/drv_spi.c
bsp/allwinner_tina/drivers/spi/drv_spi.c
+793
-0
bsp/allwinner_tina/drivers/spi/drv_spi.h
bsp/allwinner_tina/drivers/spi/drv_spi.h
+428
-0
bsp/allwinner_tina/drivers/spi/drv_spi_flash.c
bsp/allwinner_tina/drivers/spi/drv_spi_flash.c
+80
-0
未找到文件。
bsp/allwinner_tina/drivers/Kconfig
浏览文件 @
8e314279
...
...
@@ -19,4 +19,19 @@ config TINA_USING_SDIO0
bool "Using SDIO0"
select RT_USING_SDIO
default y
\ No newline at end of file
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
bsp/allwinner_tina/drivers/spi/SConscript
0 → 100644
浏览文件 @
8e314279
from
building
import
*
cwd
=
GetCurrentDir
()
src
=
Glob
(
'*.c'
)
CPPPATH
=
[
cwd
,
str
(
Dir
(
'#'
))]
group
=
DefineGroup
(
'spi'
,
src
,
depend
=
[
''
],
CPPPATH
=
CPPPATH
)
Return
(
'group'
)
bsp/allwinner_tina/drivers/spi/drv_spi.c
0 → 100644
浏览文件 @
8e314279
/*
* 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
bsp/allwinner_tina/drivers/spi/drv_spi.h
0 → 100644
浏览文件 @
8e314279
/*
* 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 //
bsp/allwinner_tina/drivers/spi/drv_spi_flash.c
0 → 100644
浏览文件 @
8e314279
/*
* 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
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录