Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
混口饭吃,
rt-thread
提交
58b05abc
R
rt-thread
项目概览
混口饭吃,
/
rt-thread
与 Fork 源项目一致
Fork自
Mr_Pangza / 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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
58b05abc
编写于
8月 01, 2020
作者:
Thomas_Fly
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[bsp/nrf5x]: add the driver of pwm
上级
e22bbf97
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
564 addition
and
18 deletion
+564
-18
bsp/nrf5x/libraries/drivers/SConscript
bsp/nrf5x/libraries/drivers/SConscript
+4
-0
bsp/nrf5x/libraries/drivers/drv_pwm.c
bsp/nrf5x/libraries/drivers/drv_pwm.c
+432
-0
bsp/nrf5x/nrf52840/board/Kconfig
bsp/nrf5x/nrf52840/board/Kconfig
+128
-18
未找到文件。
bsp/nrf5x/libraries/drivers/SConscript
浏览文件 @
58b05abc
...
...
@@ -19,8 +19,12 @@ if GetDepend(['BSP_USING_QSPI_FLASH']):
if
GetDepend
([
'BSP_USING_SPI'
]):
src
+=
[
'drv_spi.c'
]
if
GetDepend
([
'BSP_USING_GPIO'
]):
src
+=
[
'drv_gpio.c'
]
if
GetDepend
([
'BSP_USING_PWM'
]):
src
+=
[
'drv_pwm.c'
]
path
=
[
cwd
]
...
...
bsp/nrf5x/libraries/drivers/drv_pwm.c
0 → 100644
浏览文件 @
58b05abc
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-07-26 supperthomas first version
*
*/
#include <board.h>
#include "rtdevice.h"
#include "rtservice.h"
#ifdef RT_USING_PWM
#include <nrfx_pwm.h>
struct
mcu_pwm
{
struct
rt_device_pwm
pwm_device
;
nrfx_pwm_t
*
pwm_handle
;
nrf_pwm_values_individual_t
m_demo1_seq_values
;
nrf_pwm_sequence_t
m_demo1_seq
;
rt_uint8_t
channel
;
char
*
name
;
rt_uint64_t
pwm_src_clk
;
uint8_t
channel_0_pin
;
uint8_t
channel_1_pin
;
uint8_t
channel_2_pin
;
uint8_t
channel_3_pin
;
};
enum
{
#ifdef BSP_USING_PWM0
PWM0_INDEX
,
#endif
#ifdef BSP_USING_PWM1
PWM1_INDEX
,
#endif
#ifdef BSP_USING_PWM2
PWM2_INDEX
,
#endif
#ifdef BSP_USING_PWM3
PWM3_INDEX
,
#endif
};
#ifdef BSP_USING_PWM0
static
nrfx_pwm_t
m_pwm0
=
NRFX_PWM_INSTANCE
(
0
);
#define PWM0_CONFIG \
{ \
.pwm_handle = &m_pwm0, \
.name = "pwm0", \
.pwm_src_clk = 1000000, \
}
#endif
#ifdef BSP_USING_PWM1
static
nrfx_pwm_t
m_pwm1
=
NRFX_PWM_INSTANCE
(
1
);
#define PWM1_CONFIG \
{ \
.pwm_handle = &m_pwm1, \
.name = "pwm1", \
.pwm_src_clk = 1000000, \
}
#endif
#ifdef BSP_USING_PWM2
static
nrfx_pwm_t
m_pwm2
=
NRFX_PWM_INSTANCE
(
2
);
#define PWM2_CONFIG \
{ \
.pwm_handle = &m_pwm2, \
.name = "pwm2", \
.pwm_src_clk = 1000000, \
}
#endif
#ifdef BSP_USING_PWM3
static
nrfx_pwm_t
m_pwm3
=
NRFX_PWM_INSTANCE
(
3
);
#define PWM3_CONFIG \
{ \
.pwm_handle = &m_pwm3, \
.name = "pwm3", \
.pwm_src_clk = 1000000, \
}
#endif
static
struct
mcu_pwm
mcu_pwm_obj
[]
=
{
#ifdef BSP_USING_PWM0
PWM0_CONFIG
,
#endif
#ifdef BSP_USING_PWM1
PWM1_CONFIG
,
#endif
#ifdef BSP_USING_PWM2
PWM2_CONFIG
,
#endif
#ifdef BSP_USING_PWM3
PWM3_CONFIG
,
#endif
};
static
rt_err_t
drv_pwm_control
(
struct
rt_device_pwm
*
device
,
int
cmd
,
void
*
arg
);
static
struct
rt_pwm_ops
drv_ops
=
{
drv_pwm_control
};
static
rt_err_t
drv_pwm_enable
(
struct
mcu_pwm
*
p_mcu
,
struct
rt_pwm_configuration
*
configuration
,
rt_bool_t
enable
)
{
if
(
!
enable
)
{
nrfx_pwm_stop
(
p_mcu
->
pwm_handle
,
true
);
}
else
{
(
void
)
nrfx_pwm_simple_playback
(
p_mcu
->
pwm_handle
,
&
p_mcu
->
m_demo1_seq
,
1
,
NRFX_PWM_FLAG_LOOP
);
}
return
RT_EOK
;
}
uint8_t
mcu_get_channel_number
(
uint8_t
channel
)
{
if
(
channel
&
0x01
)
{
return
0
;
}
else
if
(
channel
&
0x02
)
{
return
1
;
}
else
if
(
channel
&
0x04
)
{
return
2
;
}
else
if
(
channel
&
0x08
)
{
return
3
;
}
return
0
;
}
static
rt_err_t
drv_pwm_get
(
struct
mcu_pwm
*
pwm_handle
,
struct
rt_pwm_configuration
*
configuration
)
{
rt_uint8_t
channel_number
=
mcu_get_channel_number
(
configuration
->
channel
);
uint8_t
tick_pscond
;
tick_pscond
=
pwm_handle
->
pwm_src_clk
/
1000000UL
;
configuration
->
period
=
pwm_handle
->
pwm_handle
->
p_registers
->
COUNTERTOP
*
1000UL
/
tick_pscond
;
configuration
->
pulse
=
pwm_handle
->
pwm_handle
->
p_registers
->
SEQ
[
channel_number
].
PTR
/
tick_pscond
;
return
RT_EOK
;
}
static
void
nrfx_set_prioid
(
nrfx_pwm_t
*
pwm_handle
,
uint32_t
perioid
)
{
pwm_handle
->
p_registers
->
COUNTERTOP
=
perioid
;
}
static
rt_err_t
drv_pwm_set
(
struct
mcu_pwm
*
p_mcu
,
struct
rt_pwm_configuration
*
configuration
)
{
rt_uint32_t
period
,
pulse
;
uint8_t
tick_pscond
;
tick_pscond
=
p_mcu
->
pwm_src_clk
/
1000000UL
;
p_mcu
->
pwm_handle
->
p_registers
->
COUNTERTOP
=
(
unsigned
long
long
)
configuration
->
period
*
tick_pscond
;
if
(
configuration
->
channel
&
0x01
)
{
p_mcu
->
m_demo1_seq_values
.
channel_0
=
configuration
->
pulse
;
}
if
(
configuration
->
channel
&
0x02
)
{
p_mcu
->
m_demo1_seq_values
.
channel_1
=
configuration
->
pulse
;
}
if
(
configuration
->
channel
&
0x04
)
{
p_mcu
->
m_demo1_seq_values
.
channel_2
=
configuration
->
pulse
;
}
if
(
configuration
->
channel
&
0x08
)
{
p_mcu
->
m_demo1_seq_values
.
channel_3
=
configuration
->
pulse
;
}
return
RT_EOK
;
}
static
rt_err_t
drv_pwm_control
(
struct
rt_device_pwm
*
device
,
int
cmd
,
void
*
arg
)
{
struct
rt_pwm_configuration
*
configuration
=
(
struct
rt_pwm_configuration
*
)
arg
;
void
*
pwm_handle
=
(
void
*
)
device
->
parent
.
user_data
;
nrfx_pwm_t
*
p_handle
=
(
nrfx_pwm_t
*
)
pwm_handle
;
struct
mcu_pwm
*
p_mcu
=
rt_container_of
(
p_handle
,
struct
mcu_pwm
,
pwm_handle
);
switch
(
cmd
)
{
case
PWM_CMD_ENABLE
:
return
drv_pwm_enable
(
p_mcu
,
configuration
,
RT_TRUE
);
case
PWM_CMD_DISABLE
:
return
drv_pwm_enable
(
p_mcu
,
configuration
,
RT_FALSE
);
case
PWM_CMD_SET
:
return
drv_pwm_set
(
p_mcu
,
configuration
);
case
PWM_CMD_GET
:
return
drv_pwm_get
(
p_mcu
,
configuration
);
default:
return
RT_EINVAL
;
}
}
static
rt_err_t
mcu_hw_pwm_init
(
struct
mcu_pwm
*
device
)
{
#define NRFX_PWM_PIN_INVERTED 0x80
#define _PRIO_APP_LOWEST 7
nrfx_pwm_config_t
config0
=
{
.
irq_priority
=
_PRIO_APP_LOWEST
,
.
base_clock
=
NRF_PWM_CLK_1MHz
,
//default value
.
count_mode
=
NRF_PWM_MODE_UP
,
.
top_value
=
5000
,
//default vaule
.
load_mode
=
NRF_PWM_LOAD_INDIVIDUAL
,
.
step_mode
=
NRF_PWM_STEP_AUTO
};
rt_err_t
result
=
RT_EOK
;
if
(
device
->
pwm_src_clk
==
1000000
)
{
config0
.
base_clock
=
NRF_PWM_CLK_1MHz
;
}
else
if
(
device
->
pwm_src_clk
==
2000000
)
{
config0
.
base_clock
=
NRF_PWM_CLK_2MHz
;
}
else
if
(
device
->
pwm_src_clk
==
8000000
)
{
config0
.
base_clock
=
NRF_PWM_CLK_8MHz
;
}
else
{
config0
.
base_clock
=
NRF_PWM_CLK_1MHz
;
}
if
(
device
->
channel
&
0x01
)
{
config0
.
output_pins
[
0
]
=
device
->
channel_0_pin
|
NRFX_PWM_PIN_INVERTED
;
}
if
(
device
->
channel
&
0x02
)
{
config0
.
output_pins
[
1
]
=
device
->
channel_1_pin
|
NRFX_PWM_PIN_INVERTED
;
}
if
(
device
->
channel
&
0x04
)
{
config0
.
output_pins
[
2
]
=
device
->
channel_2_pin
|
NRFX_PWM_PIN_INVERTED
;
}
if
(
device
->
channel
&
0x08
)
{
config0
.
output_pins
[
3
]
=
device
->
channel_3_pin
|
NRFX_PWM_PIN_INVERTED
;
}
device
->
m_demo1_seq
.
values
.
p_individual
=
&
device
->
m_demo1_seq_values
;
device
->
m_demo1_seq
.
length
=
NRF_PWM_VALUES_LENGTH
(
device
->
m_demo1_seq_values
),
nrfx_pwm_init
(
device
->
pwm_handle
,
&
config0
,
NULL
,
NULL
);
return
result
;
}
static
void
pwm_get_channel
(
void
)
{
#ifdef BSP_USING_PWM0_CH0
mcu_pwm_obj
[
PWM0_INDEX
].
channel
|=
1
<<
0
;
mcu_pwm_obj
[
PWM0_INDEX
].
channel_0_pin
=
BSP_USING_PWM0_CH0
;
#endif
#ifdef BSP_USING_PWM0_CH1
mcu_pwm_obj
[
PWM0_INDEX
].
channel
|=
1
<<
1
;
mcu_pwm_obj
[
PWM0_INDEX
].
channel_1_pin
=
BSP_USING_PWM0_CH1
;
#endif
#ifdef BSP_USING_PWM0_CH2
mcu_pwm_obj
[
PWM0_INDEX
].
channel
|=
1
<<
2
;
mcu_pwm_obj
[
PWM0_INDEX
].
channel_2_pin
=
BSP_USING_PWM0_CH2
;
#endif
#ifdef BSP_USING_PWM0_CH3
mcu_pwm_obj
[
PWM0_INDEX
].
channel
|=
1
<<
3
;
mcu_pwm_obj
[
PWM0_INDEX
].
channel_3_pin
=
BSP_USING_PWM0_CH3
;
#endif
#ifdef BSP_USING_PWM1_CH0
mcu_pwm_obj
[
PWM1_INDEX
].
channel
|=
1
<<
0
;
mcu_pwm_obj
[
PWM1_INDEX
].
channel_0_pin
=
BSP_USING_PWM1_CH0
;
#endif
#ifdef BSP_USING_PWM1_CH1
mcu_pwm_obj
[
PWM1_INDEX
].
channel
|=
1
<<
1
;
mcu_pwm_obj
[
PWM1_INDEX
].
channel_1_pin
=
BSP_USING_PWM1_CH1
;
#endif
#ifdef BSP_USING_PWM1_CH2
mcu_pwm_obj
[
PWM1_INDEX
].
channel
|=
1
<<
2
;
mcu_pwm_obj
[
PWM1_INDEX
].
channel_2_pin
=
BSP_USING_PWM1_CH2
;
#endif
#ifdef BSP_USING_PWM1_CH3
mcu_pwm_obj
[
PWM1_INDEX
].
channel
|=
1
<<
3
;
mcu_pwm_obj
[
PWM1_INDEX
].
channel_3_pin
=
BSP_USING_PWM1_CH3
;
#endif
#ifdef BSP_USING_PWM2_CH0
mcu_pwm_obj
[
PWM2_INDEX
].
channel
|=
1
<<
0
;
mcu_pwm_obj
[
PWM2_INDEX
].
channel_0_pin
=
BSP_USING_PWM2_CH0
;
#endif
#ifdef BSP_USING_PWM2_CH1
mcu_pwm_obj
[
PWM2_INDEX
].
channel
|=
1
<<
1
;
mcu_pwm_obj
[
PWM2_INDEX
].
channel_1_pin
=
BSP_USING_PWM2_CH1
;
#endif
#ifdef BSP_USING_PWM2_CH2
mcu_pwm_obj
[
PWM2_INDEX
].
channel
|=
1
<<
2
;
mcu_pwm_obj
[
PWM2_INDEX
].
channel_2_pin
=
BSP_USING_PWM2_CH2
;
#endif
#ifdef BSP_USING_PWM2_CH3
mcu_pwm_obj
[
PWM2_INDEX
].
channel
|=
1
<<
3
;
mcu_pwm_obj
[
PWM2_INDEX
].
channel_3_pin
=
BSP_USING_PWM2_CH3
;
#endif
#ifdef BSP_USING_PWM3_CH0
mcu_pwm_obj
[
PWM3_INDEX
].
channel
|=
1
<<
0
;
mcu_pwm_obj
[
PWM3_INDEX
].
channel_0_pin
=
BSP_USING_PWM3_CH0
;
#endif
#ifdef BSP_USING_PWM3_CH1
mcu_pwm_obj
[
PWM3_INDEX
].
channel
|=
1
<<
1
;
mcu_pwm_obj
[
PWM3_INDEX
].
channel_1_pin
=
BSP_USING_PWM3_CH1
;
#endif
#ifdef BSP_USING_PWM3_CH2
mcu_pwm_obj
[
PWM3_INDEX
].
channel
|=
1
<<
2
;
mcu_pwm_obj
[
PWM3_INDEX
].
channel_2_pin
=
BSP_USING_PWM3_CH2
;
#endif
#ifdef BSP_USING_PWM3_CH3
mcu_pwm_obj
[
PWM3_INDEX
].
channel
|=
1
<<
3
;
mcu_pwm_obj
[
PWM3_INDEX
].
channel_3_pin
=
BSP_USING_PWM3_CH3
;
#endif
}
static
int
mcu_pwm_init
(
void
)
{
int
i
=
0
;
int
result
=
RT_EOK
;
pwm_get_channel
();
for
(
i
=
0
;
i
<
sizeof
(
mcu_pwm_obj
)
/
sizeof
(
mcu_pwm_obj
[
0
]);
i
++
)
{
/* pwm init */
if
(
mcu_hw_pwm_init
(
&
mcu_pwm_obj
[
i
])
!=
RT_EOK
)
{
rt_kprintf
(
"
\r\n
%s init failed"
,
mcu_pwm_obj
[
i
].
name
);
result
=
-
RT_ERROR
;
goto
__exit
;
}
else
{
rt_kprintf
(
"
\r\n
%s init success"
,
mcu_pwm_obj
[
i
].
name
);
/* register pwm device */
if
(
rt_device_pwm_register
(
&
mcu_pwm_obj
[
i
].
pwm_device
,
mcu_pwm_obj
[
i
].
name
,
&
drv_ops
,
&
mcu_pwm_obj
[
i
].
pwm_handle
)
==
RT_EOK
)
{
rt_kprintf
(
"
\r\n
%s register success"
,
mcu_pwm_obj
[
i
].
name
);
}
else
{
rt_kprintf
(
"
\r\n
%s register failed"
,
mcu_pwm_obj
[
i
].
name
);
result
=
-
RT_ERROR
;
}
}
}
__exit:
return
result
;
}
INIT_DEVICE_EXPORT
(
mcu_pwm_init
);
/* test example */
#define PWM_DEV_NAME "pwm0"
/* PWM name*/
#define PWM_DEV_CHANNEL 15
/* PWM channel */
struct
rt_device_pwm
*
pwm_dev
;
static
int
pwm_led_sample
(
int
argc
,
char
*
argv
[])
{
rt_uint32_t
period
,
pulse
,
dir
;
period
=
50000
;
/* 50ms*/
dir
=
1
;
pulse
=
0
;
pwm_dev
=
(
struct
rt_device_pwm
*
)
rt_device_find
(
PWM_DEV_NAME
);
if
(
pwm_dev
==
RT_NULL
)
{
rt_kprintf
(
"pwm sample run failed! can't find %s device!
\n
"
,
PWM_DEV_NAME
);
return
RT_ERROR
;
}
rt_pwm_set
(
pwm_dev
,
PWM_DEV_CHANNEL
,
period
,
pulse
);
rt_pwm_enable
(
pwm_dev
,
PWM_DEV_CHANNEL
);
while
(
1
)
{
rt_thread_mdelay
(
50
);
if
(
dir
)
{
pulse
+=
500
;
}
else
{
pulse
-=
500
;
}
if
(
pulse
>=
period
)
{
dir
=
0
;
}
if
(
0
==
pulse
)
{
dir
=
1
;
}
rt_pwm_set
(
pwm_dev
,
PWM_DEV_CHANNEL
,
period
,
pulse
);
}
}
MSH_CMD_EXPORT
(
pwm_led_sample
,
pwm
sample
);
#endif
\ No newline at end of file
bsp/nrf5x/nrf52840/board/Kconfig
浏览文件 @
58b05abc
...
...
@@ -7,6 +7,12 @@ config SOC_NRF52840
select RT_USING_USER_MAIN
default y
config SOC_NORDIC
bool
config SOC_NORDIC
default y
menu "Onboard Peripheral Drivers"
config BSP_USING_JLINK_TO_USART
bool "Enable JLINK TO USART (uart0|RX_PIN:8|TX_PIN:6)"
...
...
@@ -55,38 +61,142 @@ menu "On-chip Peripheral Drivers"
bool "Enable GPIO"
select RT_USING_PIN
default y
menuconfig BSP_USING_PWM
bool "Enable PWM"
select RT_USING_PWM
default n
if BSP_USING_PWM
config NRFX_PWM_ENABLED
int
default 1
config BSP_USING_PWM0
bool "Enable PWM0 bus"
default y
if BSP_USING_PWM0
config NRFX_PWM0_ENABLED
int
default 1
config BSP_USING_PWM0_CH0
int "PWM0 channel 0 pin number set"
range 0 47
default 13
config BSP_USING_PWM0_CH1
int "PWM0 channel 1 pin number set"
range 0 47
default 14
config BSP_USING_PWM0_CH2
int "PWM0 channel 2 pin number set"
range 0 47
default 15
config BSP_USING_PWM0_CH3
int "PWM0 channel 3 pin number set"
range 0 47
default 16
endif
config BSP_USING_PWM1
bool "Enable PWM1 bus"
default n
if BSP_USING_PWM1
config NRFX_PWM1_ENABLED
int
default 1
config BSP_USING_PWM1_CH0
int "PWM1 channel 0 pin number set"
range 0 47
default 13
config BSP_USING_PWM1_CH1
int "PWM1 channel 1 pin number set"
range 0 47
default 14
config BSP_USING_PWM1_CH2
int "PWM1 channel 2 pin number set"
range 0 47
default 15
config BSP_USING_PWM1_CH3
int "PWM1 channel 3 pin number set"
range 0 47
default 16
endif
config BSP_USING_PWM2
bool "Enable PWM2 bus"
default n
if BSP_USING_PWM2
config NRFX_PWM2_ENABLED
int
default 1
config BSP_USING_PWM2_CH0
int "PWM2 channel 0 pin number set"
range 0 47
default 13
config BSP_USING_PWM2_CH1
int "PWM2 channel 1 pin number set"
range 0 47
default 14
config BSP_USING_PWM2_CH2
int "PWM2 channel 2 pin number set"
range 0 47
default 15
config BSP_USING_PWM2_CH3
int "PWM2 channel 3 pin number set"
range 0 47
default 16
endif
config BSP_USING_PWM3
bool "Enable PWM3 bus"
default n
if BSP_USING_PWM3
config NRFX_PWM3_ENABLED
int
default 1
config BSP_USING_PWM3_CH0
int "PWM3 channel 0 pin number set"
range 0 47
default 13
config BSP_USING_PWM3_CH1
int "PWM3 channel 1 pin number set"
range 0 47
default 14
config BSP_USING_PWM3_CH2
int "PWM3 channel 2 pin number set"
range 0 47
default 15
config BSP_USING_PWM3_CH3
int "PWM3 channel 3 pin number set"
range 0 47
default 16
endif
endif
menuconfig BSP_USING_SOFTDEVICE
bool "Enable NRF SOFTDEVICE"
select PKG_USING_NRF5X_SDK
select NRFX_CLOCK_ENABLED
default n
if BSP_USING_SOFTDEVICE
config NRFX_CLOCK_ENABLED
int "NRFX_CLOCK_ENABLED"
int
default 1
config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY
int "NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY"
config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY
int
default 7
config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY
int "NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY"
default
7
config NRFX_RTC
_ENABLED
int "NRFX_RTC_ENABLED"
config NRFX_RTC_ENABLED
int
default
1
config NRFX_RTC1
_ENABLED
int
default 1
config NRF_CLOCK_ENABLED
int "NRF_CLOCK_ENABLED"
config NRF_CLOCK_ENABLED
int
default 1
config NRF_SDH_BLE_ENABLED
int "NRF_SDH_BLE_ENABLED"
config NRF_SDH_BLE_ENABLED
int
default 1
config NRF_SDH_ENABLED
int "NRF_SDH_ENABLED"
config NRF_SDH_ENABLED
int
default 1
config NRF_SDH_SOC_ENABLED
int "NRF_SDH_SOC_ENABLED"
config NRF_SDH_SOC_ENABLED
int
default 1
endif
menuconfig BSP_USING_UART
bool "Enable UART"
default y
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录