Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
rt-thread
提交
257ce972
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看板
提交
257ce972
编写于
11月 22, 2018
作者:
Z
zylx
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[DeviceDrivers][spi]:add qspi support
上级
8ea5b770
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
375 addition
and
0 deletion
+375
-0
components/drivers/include/drivers/spi.h
components/drivers/include/drivers/spi.h
+108
-0
components/drivers/spi/qspi_core.c
components/drivers/spi/qspi_core.c
+265
-0
components/drivers/spi/spi_core.c
components/drivers/spi/spi_core.c
+2
-0
未找到文件。
components/drivers/include/drivers/spi.h
浏览文件 @
257ce972
...
...
@@ -45,6 +45,9 @@ extern "C"{
#define RT_SPI_MODE_MASK (RT_SPI_CPHA | RT_SPI_CPOL | RT_SPI_MSB)
#define RT_SPI_BUS_MODE_SPI (1<<0)
#define RT_SPI_BUS_MODE_QSPI (1<<1)
#define RT_SPI_CS_HIGH (1<<4)
/* Chipselect active high */
#define RT_SPI_NO_CS (1<<5)
/* No chipselect */
#define RT_SPI_3WIRE (1<<6)
/* SI/SO pin shared */
...
...
@@ -80,6 +83,7 @@ struct rt_spi_ops;
struct
rt_spi_bus
{
struct
rt_device
parent
;
rt_uint8_t
mode
;
const
struct
rt_spi_ops
*
ops
;
struct
rt_mutex
lock
;
...
...
@@ -106,6 +110,55 @@ struct rt_spi_device
struct
rt_spi_configuration
config
;
void
*
user_data
;
};
struct
rt_qspi_message
{
struct
rt_spi_message
parent
;
/* instruction stage */
struct
{
rt_uint8_t
content
;
rt_uint8_t
qspi_lines
;
}
instruction
;
/* address and alternate_bytes stage */
struct
{
rt_uint32_t
content
;
rt_uint8_t
size
;
rt_uint8_t
qspi_lines
;
}
address
,
alternate_bytes
;
/* dummy_cycles stage */
rt_uint32_t
dummy_cycles
;
/* number of lines in qspi data stage, the other configuration items are in parent */
rt_uint8_t
qspi_data_lines
;
};
struct
rt_qspi_configuration
{
struct
rt_spi_configuration
parent
;
/* The size of medium */
rt_uint32_t
medium_size
;
/* double data rate mode */
rt_uint8_t
ddr_mode
;
/* the number of lines connected to the hardware */
rt_uint8_t
qspi_hw_lines
;
};
struct
rt_qspi_device
{
struct
rt_spi_device
parent
;
struct
rt_qspi_configuration
config
;
void
(
*
enter_qspi_mode
)(
struct
rt_qspi_device
*
device
);
void
(
*
exit_qspi_mode
)(
struct
rt_qspi_device
*
device
);
};
#define SPI_DEVICE(dev) ((struct rt_spi_device *)(dev))
/* register a SPI bus */
...
...
@@ -255,6 +308,61 @@ rt_inline void rt_spi_message_append(struct rt_spi_message *list,
message
->
next
=
RT_NULL
;
}
/**
* This function can set configuration on QSPI device.
*
* @param device the QSPI device attached to QSPI bus.
* @param cfg the configuration pointer.
*
* @return the actual length of transmitted.
*/
rt_err_t
rt_qspi_configure
(
struct
rt_qspi_device
*
device
,
struct
rt_qspi_configuration
*
cfg
);
/**
* This function can register a SPI bus for QSPI mode.
*
* @param bus the SPI bus for QSPI mode.
* @param name The name of the spi bus.
* @param ops the SPI bus instance to be registered.
*
* @return the actual length of transmitted.
*/
rt_err_t
rt_qspi_bus_register
(
struct
rt_spi_bus
*
bus
,
const
char
*
name
,
const
struct
rt_spi_ops
*
ops
);
/**
* This function transmits data to QSPI device.
*
* @param device the QSPI device attached to QSPI bus.
* @param message the message pointer.
*
* @return the actual length of transmitted.
*/
rt_size_t
rt_qspi_transfer_message
(
struct
rt_qspi_device
*
device
,
struct
rt_qspi_message
*
message
);
/**
* This function can send data then receive data from QSPI device
*
* @param device the QSPI device attached to QSPI bus.
* @param send_buf the buffer to be transmitted to QSPI device.
* @param send_length the number of data to be transmitted.
* @param recv_buf the buffer to be recivied from QSPI device.
* @param recv_length the data to be recivied.
*
* @return the status of transmit.
*/
rt_err_t
rt_qspi_send_then_recv
(
struct
rt_qspi_device
*
device
,
const
void
*
send_buf
,
rt_size_t
send_length
,
void
*
recv_buf
,
rt_size_t
recv_length
);
/**
* This function can send data to QSPI device
*
* @param device the QSPI device attached to QSPI bus.
* @param send_buf the buffer to be transmitted to QSPI device.
* @param send_length the number of data to be transmitted.
*
* @return the status of transmit.
*/
rt_err_t
rt_qspi_send
(
struct
rt_qspi_device
*
device
,
const
void
*
send_buf
,
rt_size_t
length
);
#ifdef __cplusplus
}
#endif
...
...
components/drivers/spi/qspi_core.c
0 → 100644
浏览文件 @
257ce972
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-16 zylx first version.
*/
#include <drivers/spi.h>
rt_err_t
rt_qspi_configure
(
struct
rt_qspi_device
*
device
,
struct
rt_qspi_configuration
*
cfg
)
{
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
cfg
!=
RT_NULL
);
struct
rt_qspi_device
*
qspi_device
=
(
struct
rt_qspi_device
*
)
device
;
rt_err_t
result
=
RT_EOK
;
/* copy configuration items */
qspi_device
->
config
.
parent
.
mode
=
cfg
->
parent
.
mode
;
qspi_device
->
config
.
parent
.
max_hz
=
cfg
->
parent
.
max_hz
;
qspi_device
->
config
.
parent
.
data_width
=
cfg
->
parent
.
data_width
;
qspi_device
->
config
.
parent
.
reserved
=
cfg
->
parent
.
reserved
;
qspi_device
->
config
.
medium_size
=
cfg
->
medium_size
;
qspi_device
->
config
.
ddr_mode
=
cfg
->
ddr_mode
;
qspi_device
->
config
.
qspi_hw_lines
=
cfg
->
qspi_hw_lines
;
result
=
rt_spi_configure
(
&
device
->
parent
,
&
cfg
->
parent
);
return
result
;
}
rt_err_t
rt_qspi_bus_register
(
struct
rt_spi_bus
*
bus
,
const
char
*
name
,
const
struct
rt_spi_ops
*
ops
)
{
rt_err_t
result
=
RT_EOK
;
result
=
rt_spi_bus_register
(
bus
,
name
,
ops
);
if
(
result
==
RT_EOK
)
{
/* set SPI bus to qspi modes */
bus
->
mode
=
RT_SPI_BUS_MODE_QSPI
;
}
return
result
;
}
rt_size_t
rt_qspi_transfer_message
(
struct
rt_qspi_device
*
device
,
struct
rt_qspi_message
*
message
)
{
rt_err_t
result
;
RT_ASSERT
(
device
!=
RT_NULL
);
RT_ASSERT
(
message
!=
RT_NULL
);
result
=
rt_mutex_take
(
&
(
device
->
parent
.
bus
->
lock
),
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
rt_set_errno
(
-
RT_EBUSY
);
return
0
;
}
/* reset errno */
rt_set_errno
(
RT_EOK
);
/* configure SPI bus */
if
(
device
->
parent
.
bus
->
owner
!=
&
device
->
parent
)
{
/* not the same owner as current, re-configure SPI bus */
result
=
device
->
parent
.
bus
->
ops
->
configure
(
&
device
->
parent
,
&
device
->
parent
.
config
);
if
(
result
==
RT_EOK
)
{
/* set SPI bus owner */
device
->
parent
.
bus
->
owner
=
&
device
->
parent
;
}
else
{
/* configure SPI bus failed */
rt_set_errno
(
-
RT_EIO
);
goto
__exit
;
}
}
/* transmit each SPI message */
result
=
device
->
parent
.
bus
->
ops
->
xfer
(
&
device
->
parent
,
&
message
->
parent
);
if
(
result
==
0
)
{
rt_set_errno
(
-
RT_EIO
);
}
__exit:
/* release bus lock */
rt_mutex_release
(
&
(
device
->
parent
.
bus
->
lock
));
return
result
;
}
rt_err_t
rt_qspi_send_then_recv
(
struct
rt_qspi_device
*
device
,
const
void
*
send_buf
,
rt_size_t
send_length
,
void
*
recv_buf
,
rt_size_t
recv_length
)
{
RT_ASSERT
(
send_buf
);
RT_ASSERT
(
recv_buf
);
RT_ASSERT
(
send_length
!=
0
);
struct
rt_qspi_message
message
;
unsigned
char
*
ptr
=
(
unsigned
char
*
)
send_buf
;
rt_size_t
count
=
0
;
rt_err_t
result
=
0
;
message
.
instruction
.
content
=
ptr
[
0
];
message
.
instruction
.
qspi_lines
=
1
;
count
++
;
/* get address */
if
(
send_length
>
1
)
{
if
(
device
->
config
.
medium_size
>
0x1000000
&&
send_length
>=
5
)
{
/* medium size greater than 16Mb, address size is 4 Byte */
message
.
address
.
content
=
(
ptr
[
1
]
<<
24
)
|
(
ptr
[
2
]
<<
16
)
|
(
ptr
[
3
]
<<
8
)
|
(
ptr
[
4
]);
message
.
address
.
size
=
32
;
count
+=
4
;
}
else
if
(
send_length
>=
4
)
{
/* address size is 3 Byte */
message
.
address
.
content
=
(
ptr
[
1
]
<<
16
)
|
(
ptr
[
2
]
<<
8
)
|
(
ptr
[
3
]);
message
.
address
.
size
=
24
;
count
+=
3
;
}
else
{
return
-
RT_ERROR
;
}
message
.
address
.
qspi_lines
=
1
;
}
else
{
/* no address stage */
message
.
address
.
content
=
0
;
message
.
address
.
qspi_lines
=
0
;
message
.
address
.
size
=
0
;
}
message
.
alternate_bytes
.
content
=
0
;
message
.
alternate_bytes
.
size
=
0
;
message
.
alternate_bytes
.
qspi_lines
=
0
;
/* set dummy cycles */
if
(
count
!=
send_length
)
{
message
.
dummy_cycles
=
(
send_length
-
count
)
*
8
;
}
else
{
message
.
dummy_cycles
=
0
;
}
/* set recv buf and recv size */
message
.
parent
.
recv_buf
=
recv_buf
;
message
.
parent
.
send_buf
=
RT_NULL
;
message
.
parent
.
length
=
recv_length
;
message
.
parent
.
cs_take
=
1
;
message
.
parent
.
cs_release
=
1
;
message
.
qspi_data_lines
=
1
;
result
=
rt_qspi_transfer_message
(
device
,
&
message
);
if
(
result
==
0
)
{
result
=
-
RT_EIO
;
}
else
{
result
=
recv_length
;
}
return
result
;
}
rt_err_t
rt_qspi_send
(
struct
rt_qspi_device
*
device
,
const
void
*
send_buf
,
rt_size_t
length
)
{
RT_ASSERT
(
send_buf
);
RT_ASSERT
(
length
!=
0
);
struct
rt_qspi_message
message
;
char
*
ptr
=
(
char
*
)
send_buf
;
rt_size_t
count
=
0
;
rt_err_t
result
=
0
;
message
.
instruction
.
content
=
ptr
[
0
];
message
.
instruction
.
qspi_lines
=
1
;
count
++
;
/* get address */
if
(
length
>
1
)
{
if
(
device
->
config
.
medium_size
>
0x1000000
&&
length
>=
5
)
{
/* medium size greater than 16Mb, address size is 4 Byte */
message
.
address
.
content
=
(
ptr
[
1
]
<<
24
)
|
(
ptr
[
2
]
<<
16
)
|
(
ptr
[
3
]
<<
8
)
|
(
ptr
[
4
]);
message
.
address
.
size
=
32
;
message
.
address
.
qspi_lines
=
1
;
count
+=
4
;
}
else
if
(
length
>=
4
)
{
/* address size is 3 Byte */
message
.
address
.
content
=
(
ptr
[
1
]
<<
16
)
|
(
ptr
[
2
]
<<
8
)
|
(
ptr
[
3
]);
message
.
address
.
size
=
24
;
message
.
address
.
qspi_lines
=
1
;
count
+=
3
;
}
else
{
return
-
RT_ERROR
;
}
}
else
{
/* no address stage */
message
.
address
.
content
=
0
;
message
.
address
.
qspi_lines
=
0
;
message
.
address
.
size
=
0
;
}
message
.
alternate_bytes
.
content
=
0
;
message
.
alternate_bytes
.
size
=
0
;
message
.
alternate_bytes
.
qspi_lines
=
0
;
message
.
dummy_cycles
=
0
;
/* determine if there is data to send */
if
(
length
-
count
>
0
)
{
message
.
qspi_data_lines
=
1
;
}
else
{
message
.
qspi_data_lines
=
0
;
}
/* set send buf and send size */
message
.
parent
.
send_buf
=
ptr
+
count
;
message
.
parent
.
recv_buf
=
RT_NULL
;
message
.
parent
.
length
=
length
-
count
;
message
.
parent
.
cs_take
=
1
;
message
.
parent
.
cs_release
=
1
;
result
=
rt_qspi_transfer_message
(
device
,
&
message
);
if
(
result
==
0
)
{
result
=
-
RT_EIO
;
}
else
{
result
=
length
;
}
return
result
;
}
components/drivers/spi/spi_core.c
浏览文件 @
257ce972
...
...
@@ -34,6 +34,8 @@ rt_err_t rt_spi_bus_register(struct rt_spi_bus *bus,
bus
->
ops
=
ops
;
/* initialize owner */
bus
->
owner
=
RT_NULL
;
/* set bus mode */
bus
->
mode
=
RT_SPI_BUS_MODE_SPI
;
return
RT_EOK
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录