Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
promise
OpenXG-RAN
Commits
818b27c1
Commit
818b27c1
authored
Oct 31, 2018
by
Wang Tsu-Han
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
renaming for gNB
parent
5d4cde09
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
123 additions
and
98 deletions
+123
-98
openair1/PHY/NR_TRANSPORT/nr_dci.h
openair1/PHY/NR_TRANSPORT/nr_dci.h
+1
-1
openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
+1
-1
openair1/PHY/defs_gNB.h
openair1/PHY/defs_gNB.h
+20
-11
openair1/SCHED_NR/fapi_nr_l1.c
openair1/SCHED_NR/fapi_nr_l1.c
+4
-4
openair1/SCHED_NR/fapi_nr_l1.h
openair1/SCHED_NR/fapi_nr_l1.h
+1
-1
openair1/SCHED_NR/phy_procedures_nr_gNB.c
openair1/SCHED_NR/phy_procedures_nr_gNB.c
+1
-1
openair1/SCHED_NR/sched_nr.h
openair1/SCHED_NR/sched_nr.h
+1
-1
targets/RT/USER/nr-gnb.c
targets/RT/USER/nr-gnb.c
+93
-77
targets/RT/USER/nr-ru.c
targets/RT/USER/nr-ru.c
+1
-1
No files found.
openair1/PHY/NR_TRANSPORT/nr_dci.h
View file @
818b27c1
...
@@ -49,7 +49,7 @@ void nr_pdcch_scrambling(uint32_t *in,
...
@@ -49,7 +49,7 @@ void nr_pdcch_scrambling(uint32_t *in,
void
nr_fill_dci_and_dlsch
(
PHY_VARS_gNB
*
gNB
,
void
nr_fill_dci_and_dlsch
(
PHY_VARS_gNB
*
gNB
,
int
frame
,
int
frame
,
int
subframe
,
int
subframe
,
gNB_rxtx_proc_t
*
proc
,
gNB_
L1_
rxtx_proc_t
*
proc
,
NR_gNB_DCI_ALLOC_t
*
dci_alloc
,
NR_gNB_DCI_ALLOC_t
*
dci_alloc
,
nfapi_nr_dl_config_request_pdu_t
*
pdu
);
nfapi_nr_dl_config_request_pdu_t
*
pdu
);
...
...
openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
View file @
818b27c1
...
@@ -108,7 +108,7 @@ void nr_fill_cce_list(NR_gNB_DCI_ALLOC_t* dci_alloc, uint16_t n_shift, uint8_t m
...
@@ -108,7 +108,7 @@ void nr_fill_cce_list(NR_gNB_DCI_ALLOC_t* dci_alloc, uint16_t n_shift, uint8_t m
void
nr_fill_dci_and_dlsch
(
PHY_VARS_gNB
*
gNB
,
void
nr_fill_dci_and_dlsch
(
PHY_VARS_gNB
*
gNB
,
int
frame
,
int
frame
,
int
subframe
,
int
subframe
,
gNB_rxtx_proc_t
*
proc
,
gNB_
L1_
rxtx_proc_t
*
proc
,
NR_gNB_DCI_ALLOC_t
*
dci_alloc
,
NR_gNB_DCI_ALLOC_t
*
dci_alloc
,
nfapi_nr_dl_config_request_pdu_t
*
pdu
)
nfapi_nr_dl_config_request_pdu_t
*
pdu
)
{
{
...
...
openair1/PHY/defs_gNB.h
View file @
818b27c1
...
@@ -99,22 +99,29 @@ typedef struct {
...
@@ -99,22 +99,29 @@ typedef struct {
int
frame_rx
;
int
frame_rx
;
/// \brief Instance count for RXn-TXnp4 processing thread.
/// \brief Instance count for RXn-TXnp4 processing thread.
/// \internal This variable is protected by \ref mutex_rxtx.
/// \internal This variable is protected by \ref mutex_rxtx.
int
instance_cnt
_rxtx
;
int
instance_cnt
;
/// pthread structure for RXn-TXnp4 processing thread
/// pthread structure for RXn-TXnp4 processing thread
pthread_t
pthread
_rxtx
;
pthread_t
pthread
;
/// pthread attributes for RXn-TXnp4 processing thread
/// pthread attributes for RXn-TXnp4 processing thread
pthread_attr_t
attr
_rxtx
;
pthread_attr_t
attr
;
/// condition variable for tx processing thread
/// condition variable for tx processing thread
pthread_cond_t
cond
_rxtx
;
pthread_cond_t
cond
;
/// mutex for RXn-TXnp4 processing thread
/// mutex for RXn-TXnp4 processing thread
pthread_mutex_t
mutex
_rxtx
;
pthread_mutex_t
mutex
;
/// scheduling parameters for RXn-TXnp4 thread
/// scheduling parameters for RXn-TXnp4 thread
struct
sched_param
sched_param_rxtx
;
struct
sched_param
sched_param_rxtx
;
}
gNB_rxtx_proc_t
;
/// \internal This variable is protected by \ref mutex_RUs.
int
instance_cnt_RUs
;
/// condition variable for tx processing thread
pthread_cond_t
cond_RUs
;
/// mutex for RXn-TXnp4 processing thread
pthread_mutex_t
mutex_RUs
;
}
gNB_L1_rxtx_proc_t
;
/// Context data structure for eNB subframe processing
/// Context data structure for eNB subframe processing
typedef
struct
gNB_proc_t_s
{
typedef
struct
gNB_
L1_
proc_t_s
{
/// Component Carrier index
/// Component Carrier index
uint8_t
CC_id
;
uint8_t
CC_id
;
/// thread index
/// thread index
...
@@ -181,17 +188,19 @@ typedef struct gNB_proc_t_s {
...
@@ -181,17 +188,19 @@ typedef struct gNB_proc_t_s {
pthread_mutex_t
mutex_asynch_rxtx
;
pthread_mutex_t
mutex_asynch_rxtx
;
/// mutex for RU access to eNB processing (PDSCH/PUSCH)
/// mutex for RU access to eNB processing (PDSCH/PUSCH)
pthread_mutex_t
mutex_RU
;
pthread_mutex_t
mutex_RU
;
/// mutex for RU_tx access to eNB_tx processing (PDSCH/PUSCH)
pthread_mutex_t
mutex_RU_tx
;
/// mutex for RU access to eNB processing (PRACH)
/// mutex for RU access to eNB processing (PRACH)
pthread_mutex_t
mutex_RU_PRACH
;
pthread_mutex_t
mutex_RU_PRACH
;
/// mutex for RU access to eNB processing (PRACH BR)
/// mutex for RU access to eNB processing (PRACH BR)
pthread_mutex_t
mutex_RU_PRACH_br
;
pthread_mutex_t
mutex_RU_PRACH_br
;
/// mask for RUs serving eNB (PDSCH/PUSCH)
/// mask for RUs serving eNB (PDSCH/PUSCH)
int
RU_mask
;
int
RU_mask
,
RU_mask_tx
;
/// mask for RUs serving eNB (PRACH)
/// mask for RUs serving eNB (PRACH)
int
RU_mask_prach
;
int
RU_mask_prach
;
/// set of scheduling variables RXn-TXnp4 threads
/// set of scheduling variables RXn-TXnp4 threads
gNB_
rxtx_proc_t
proc_rxtx
[
2
]
;
gNB_
L1_rxtx_proc_t
L1_proc
,
L1_proc_tx
;
}
gNB_proc_t
;
}
gNB_
L1_
proc_t
;
...
@@ -251,7 +260,7 @@ typedef struct PHY_VARS_gNB_s {
...
@@ -251,7 +260,7 @@ typedef struct PHY_VARS_gNB_s {
module_id_t
Mod_id
;
module_id_t
Mod_id
;
uint8_t
CC_id
;
uint8_t
CC_id
;
uint8_t
configured
;
uint8_t
configured
;
gNB_proc_t
proc
;
gNB_
L1_
proc_t
proc
;
int
single_thread_flag
;
int
single_thread_flag
;
int
abstraction_flag
;
int
abstraction_flag
;
int
num_RU
;
int
num_RU
;
...
...
openair1/SCHED_NR/fapi_nr_l1.c
View file @
818b27c1
...
@@ -37,7 +37,7 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req);
...
@@ -37,7 +37,7 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req);
extern
uint8_t
nfapi_mode
;
extern
uint8_t
nfapi_mode
;
void
handle_nr_nfapi_bch_pdu
(
PHY_VARS_gNB
*
gNB
,
void
handle_nr_nfapi_bch_pdu
(
PHY_VARS_gNB
*
gNB
,
gNB_rxtx_proc_t
*
proc
,
gNB_
L1_
rxtx_proc_t
*
proc
,
nfapi_nr_dl_config_request_pdu_t
*
dl_config_pdu
,
nfapi_nr_dl_config_request_pdu_t
*
dl_config_pdu
,
uint8_t
*
sdu
)
uint8_t
*
sdu
)
{
{
...
@@ -56,7 +56,7 @@ void handle_nr_nfapi_bch_pdu(PHY_VARS_gNB *gNB,
...
@@ -56,7 +56,7 @@ void handle_nr_nfapi_bch_pdu(PHY_VARS_gNB *gNB,
void
handle_nfapi_nr_dci_dl_pdu
(
PHY_VARS_gNB
*
gNB
,
void
handle_nfapi_nr_dci_dl_pdu
(
PHY_VARS_gNB
*
gNB
,
int
frame
,
int
subframe
,
int
frame
,
int
subframe
,
gNB_rxtx_proc_t
*
proc
,
gNB_
L1_
rxtx_proc_t
*
proc
,
nfapi_nr_dl_config_request_pdu_t
*
dl_config_pdu
)
nfapi_nr_dl_config_request_pdu_t
*
dl_config_pdu
)
{
{
int
idx
=
subframe
&
1
;
int
idx
=
subframe
&
1
;
...
@@ -73,7 +73,7 @@ void handle_nfapi_nr_dci_dl_pdu(PHY_VARS_gNB *gNB,
...
@@ -73,7 +73,7 @@ void handle_nfapi_nr_dci_dl_pdu(PHY_VARS_gNB *gNB,
void
nr_schedule_response
(
NR_Sched_Rsp_t
*
Sched_INFO
){
void
nr_schedule_response
(
NR_Sched_Rsp_t
*
Sched_INFO
){
PHY_VARS_gNB
*
gNB
;
PHY_VARS_gNB
*
gNB
;
gNB_rxtx_proc_t
*
proc
;
gNB_
L1_
rxtx_proc_t
*
proc
;
// copy data from L2 interface into L1 structures
// copy data from L2 interface into L1 structures
module_id_t
Mod_id
=
Sched_INFO
->
module_id
;
module_id_t
Mod_id
=
Sched_INFO
->
module_id
;
uint8_t
CC_id
=
Sched_INFO
->
CC_id
;
uint8_t
CC_id
=
Sched_INFO
->
CC_id
;
...
@@ -87,7 +87,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
...
@@ -87,7 +87,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
AssertFatal
(
RC
.
gNB
[
Mod_id
][
CC_id
]
!=
NULL
,
"RC.gNB[%d][%d] is null
\n
"
,
Mod_id
,
CC_id
);
AssertFatal
(
RC
.
gNB
[
Mod_id
][
CC_id
]
!=
NULL
,
"RC.gNB[%d][%d] is null
\n
"
,
Mod_id
,
CC_id
);
gNB
=
RC
.
gNB
[
Mod_id
][
CC_id
];
gNB
=
RC
.
gNB
[
Mod_id
][
CC_id
];
proc
=
&
gNB
->
proc
.
proc_rxtx
[
0
]
;
proc
=
&
gNB
->
proc
.
L1_proc
;
uint8_t
number_dl_pdu
=
DL_req
->
dl_config_request_body
.
number_pdu
;
uint8_t
number_dl_pdu
=
DL_req
->
dl_config_request_body
.
number_pdu
;
...
...
openair1/SCHED_NR/fapi_nr_l1.h
View file @
818b27c1
...
@@ -41,5 +41,5 @@
...
@@ -41,5 +41,5 @@
void
nr_schedule_response
(
NR_Sched_Rsp_t
*
Sched_INFO
);
void
nr_schedule_response
(
NR_Sched_Rsp_t
*
Sched_INFO
);
void
handle_nfapi_nr_dci_dl_pdu
(
PHY_VARS_gNB
*
gNB
,
void
handle_nfapi_nr_dci_dl_pdu
(
PHY_VARS_gNB
*
gNB
,
int
frame
,
int
subframe
,
int
frame
,
int
subframe
,
gNB_rxtx_proc_t
*
proc
,
gNB_
L1_
rxtx_proc_t
*
proc
,
nfapi_nr_dl_config_request_pdu_t
*
dl_config_pdu
);
nfapi_nr_dl_config_request_pdu_t
*
dl_config_pdu
);
openair1/SCHED_NR/phy_procedures_nr_gNB.c
View file @
818b27c1
...
@@ -152,7 +152,7 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) {
...
@@ -152,7 +152,7 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) {
}
}
void
phy_procedures_gNB_TX
(
PHY_VARS_gNB
*
gNB
,
void
phy_procedures_gNB_TX
(
PHY_VARS_gNB
*
gNB
,
gNB_rxtx_proc_t
*
proc
,
gNB_
L1_
rxtx_proc_t
*
proc
,
int
do_meas
)
int
do_meas
)
{
{
int
aa
;
int
aa
;
...
...
openair1/SCHED_NR/sched_nr.h
View file @
818b27c1
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
lte_subframe_t
nr_subframe_select
(
nfapi_nr_config_request_t
*
cfg
,
unsigned
char
subframe
);
lte_subframe_t
nr_subframe_select
(
nfapi_nr_config_request_t
*
cfg
,
unsigned
char
subframe
);
void
nr_set_ssb_first_subcarrier
(
nfapi_nr_config_request_t
*
cfg
,
NR_DL_FRAME_PARMS
*
fp
);
void
nr_set_ssb_first_subcarrier
(
nfapi_nr_config_request_t
*
cfg
,
NR_DL_FRAME_PARMS
*
fp
);
void
phy_procedures_gNB_TX
(
PHY_VARS_gNB
*
gNB
,
gNB_rxtx_proc_t
*
proc
,
int
do_meas
);
void
phy_procedures_gNB_TX
(
PHY_VARS_gNB
*
gNB
,
gNB_
L1_
rxtx_proc_t
*
proc
,
int
do_meas
);
void
nr_common_signal_procedures
(
PHY_VARS_gNB
*
gNB
,
int
frame
,
int
subframe
);
void
nr_common_signal_procedures
(
PHY_VARS_gNB
*
gNB
,
int
frame
,
int
subframe
);
void
nr_init_feptx_thread
(
RU_t
*
ru
,
pthread_attr_t
*
attr_feptx
);
void
nr_init_feptx_thread
(
RU_t
*
ru
,
pthread_attr_t
*
attr_feptx
);
void
nr_feptx_ofdm
(
RU_t
*
ru
);
void
nr_feptx_ofdm
(
RU_t
*
ru
);
...
...
targets/RT/USER/nr-gnb.c
View file @
818b27c1
...
@@ -154,7 +154,7 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
...
@@ -154,7 +154,7 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
static
inline
int
rxtx
(
PHY_VARS_gNB
*
gNB
,
gNB_rxtx_proc_t
*
proc
,
char
*
thread_name
)
{
static
inline
int
rxtx
(
PHY_VARS_gNB
*
gNB
,
gNB_
L1_
rxtx_proc_t
*
proc
,
char
*
thread_name
)
{
start_meas
(
&
softmodem_stats_rxtx_sf
);
start_meas
(
&
softmodem_stats_rxtx_sf
);
// *******************************************************************
// *******************************************************************
...
@@ -281,7 +281,7 @@ static inline int rxtx(PHY_VARS_gNB *gNB,gNB_rxtx_proc_t *proc, char *thread_nam
...
@@ -281,7 +281,7 @@ static inline int rxtx(PHY_VARS_gNB *gNB,gNB_rxtx_proc_t *proc, char *thread_nam
/*!
/*!
* \brief The RX UE-specific and TX thread of gNB.
* \brief The RX UE-specific and TX thread of gNB.
* \param param is a \ref gNB_proc_t structure which contains the info what to process.
* \param param is a \ref gNB_
L1_
proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
*/
...
@@ -289,7 +289,7 @@ static void* gNB_thread_rxtx( void* param ) {
...
@@ -289,7 +289,7 @@ static void* gNB_thread_rxtx( void* param ) {
static
int
gNB_thread_rxtx_status
;
static
int
gNB_thread_rxtx_status
;
gNB_
rxtx_proc_t
*
proc
=
(
gNB
_rxtx_proc_t
*
)
param
;
gNB_
L1_rxtx_proc_t
*
proc
=
(
gNB_L1
_rxtx_proc_t
*
)
param
;
PHY_VARS_gNB
*
gNB
=
RC
.
gNB
[
0
][
proc
->
CC_id
];
PHY_VARS_gNB
*
gNB
=
RC
.
gNB
[
0
][
proc
->
CC_id
];
char
thread_name
[
100
];
char
thread_name
[
100
];
...
@@ -299,13 +299,13 @@ static void* gNB_thread_rxtx( void* param ) {
...
@@ -299,13 +299,13 @@ static void* gNB_thread_rxtx( void* param ) {
gNB_thread_rxtx_status
=
0
;
gNB_thread_rxtx_status
=
0
;
sprintf
(
thread_name
,
"RXn_TXnp4_%d"
,
&
gNB
->
proc
.
proc_rxtx
[
0
]
==
proc
?
0
:
1
);
sprintf
(
thread_name
,
"RXn_TXnp4_%d"
,
&
gNB
->
proc
.
L1_proc
==
proc
?
0
:
1
);
thread_top_init
(
thread_name
,
1
,
850000L
,
1000000L
,
2000000L
);
thread_top_init
(
thread_name
,
1
,
850000L
,
1000000L
,
2000000L
);
while
(
!
oai_exit
)
{
while
(
!
oai_exit
)
{
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0
+
(
proc
->
subframe_rx
&
1
),
0
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0
+
(
proc
->
subframe_rx
&
1
),
0
);
if
(
wait_on_condition
(
&
proc
->
mutex
_rxtx
,
&
proc
->
cond_rxtx
,
&
proc
->
instance_cnt_rxtx
,
thread_name
)
<
0
)
break
;
if
(
wait_on_condition
(
&
proc
->
mutex
,
&
proc
->
cond
,
&
proc
->
instance_cnt
,
thread_name
)
<
0
)
break
;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0
+
(
proc
->
subframe_rx
&
1
),
1
);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0
+
(
proc
->
subframe_rx
&
1
),
1
);
...
@@ -317,7 +317,7 @@ static void* gNB_thread_rxtx( void* param ) {
...
@@ -317,7 +317,7 @@ static void* gNB_thread_rxtx( void* param ) {
}
}
if
(
release_thread
(
&
proc
->
mutex
_rxtx
,
&
proc
->
instance_cnt_rxtx
,
thread_name
)
<
0
)
break
;
if
(
release_thread
(
&
proc
->
mutex
,
&
proc
->
instance_cnt
,
thread_name
)
<
0
)
break
;
}
// while !oai_exit
}
// while !oai_exit
...
@@ -355,8 +355,8 @@ static void wait_system_ready (char *message, volatile int *start_flag) {
...
@@ -355,8 +355,8 @@ static void wait_system_ready (char *message, volatile int *start_flag) {
void
gNB_top
(
PHY_VARS_gNB
*
gNB
,
int
frame_rx
,
int
subframe_rx
,
char
*
string
,
struct
RU_t_s
*
ru
)
void
gNB_top
(
PHY_VARS_gNB
*
gNB
,
int
frame_rx
,
int
subframe_rx
,
char
*
string
,
struct
RU_t_s
*
ru
)
{
{
gNB_proc_t
*
proc
=
&
gNB
->
proc
;
gNB_
L1_
proc_t
*
proc
=
&
gNB
->
proc
;
gNB_
rxtx_proc_t
*
proc_rxtx
=
&
proc
->
proc_rxtx
[
0
]
;
gNB_
L1_rxtx_proc_t
*
L1_proc
=
&
proc
->
L1_proc
;
NR_DL_FRAME_PARMS
*
fp
=
ru
->
nr_frame_parms
;
NR_DL_FRAME_PARMS
*
fp
=
ru
->
nr_frame_parms
;
RU_proc_t
*
ru_proc
=&
ru
->
proc
;
RU_proc_t
*
ru_proc
=&
ru
->
proc
;
...
@@ -366,25 +366,25 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int subframe_rx, char *string, str
...
@@ -366,25 +366,25 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int subframe_rx, char *string, str
if
(
!
oai_exit
)
{
if
(
!
oai_exit
)
{
T
(
T_ENB_MASTER_TICK
,
T_INT
(
0
),
T_INT
(
proc
->
frame_rx
),
T_INT
(
proc
->
subframe_rx
));
T
(
T_ENB_MASTER_TICK
,
T_INT
(
0
),
T_INT
(
proc
->
frame_rx
),
T_INT
(
proc
->
subframe_rx
));
proc_rxtx
->
timestamp_tx
=
ru_proc
->
timestamp_rx
+
(
sf_ahead
*
fp
->
samples_per_subframe
);
L1_proc
->
timestamp_tx
=
ru_proc
->
timestamp_rx
+
(
sf_ahead
*
fp
->
samples_per_subframe
);
proc_rxtx
->
frame_rx
=
ru_proc
->
frame_rx
;
L1_proc
->
frame_rx
=
ru_proc
->
frame_rx
;
proc_rxtx
->
subframe_rx
=
ru_proc
->
subframe_rx
;
L1_proc
->
subframe_rx
=
ru_proc
->
subframe_rx
;
proc_rxtx
->
frame_tx
=
(
proc_rxtx
->
subframe_rx
>
(
9
-
sf_ahead
))
?
(
proc_rxtx
->
frame_rx
+
1
)
&
1023
:
proc_rxtx
->
frame_rx
;
L1_proc
->
frame_tx
=
(
L1_proc
->
subframe_rx
>
(
9
-
sf_ahead
))
?
(
L1_proc
->
frame_rx
+
1
)
&
1023
:
L1_proc
->
frame_rx
;
proc_rxtx
->
subframe_tx
=
(
proc_rxtx
->
subframe_rx
+
sf_ahead
)
%
10
;
L1_proc
->
subframe_tx
=
(
L1_proc
->
subframe_rx
+
sf_ahead
)
%
10
;
if
(
rxtx
(
gNB
,
proc_rxtx
,
string
)
<
0
)
LOG_E
(
PHY
,
"gNB %d CC_id %d failed during execution
\n
"
,
gNB
->
Mod_id
,
gNB
->
CC_id
);
if
(
rxtx
(
gNB
,
L1_proc
,
string
)
<
0
)
LOG_E
(
PHY
,
"gNB %d CC_id %d failed during execution
\n
"
,
gNB
->
Mod_id
,
gNB
->
CC_id
);
ru_proc
->
timestamp_tx
=
proc_rxtx
->
timestamp_tx
;
ru_proc
->
timestamp_tx
=
L1_proc
->
timestamp_tx
;
ru_proc
->
subframe_tx
=
proc_rxtx
->
subframe_tx
;
ru_proc
->
subframe_tx
=
L1_proc
->
subframe_tx
;
ru_proc
->
frame_tx
=
proc_rxtx
->
frame_tx
;
ru_proc
->
frame_tx
=
L1_proc
->
frame_tx
;
}
}
}
}
int
wakeup_rxtx
(
PHY_VARS_gNB
*
gNB
,
RU_t
*
ru
)
{
int
wakeup_rxtx
(
PHY_VARS_gNB
*
gNB
,
RU_t
*
ru
)
{
gNB_proc_t
*
proc
=&
gNB
->
proc
;
gNB_
L1_
proc_t
*
proc
=&
gNB
->
proc
;
gNB_
rxtx_proc_t
*
proc_rxtx
=&
proc
->
proc_rxtx
[
proc
->
frame_rx
&
1
]
;
gNB_
L1_rxtx_proc_t
*
L1_proc
=&
proc
->
L1_proc
;
NR_DL_FRAME_PARMS
*
fp
=
&
gNB
->
frame_parms
;
NR_DL_FRAME_PARMS
*
fp
=
&
gNB
->
frame_parms
;
...
@@ -415,24 +415,24 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
...
@@ -415,24 +415,24 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
wait
.
tv_nsec
=
5000000L
;
wait
.
tv_nsec
=
5000000L
;
/* accept some delay in processing - up to 5ms */
/* accept some delay in processing - up to 5ms */
for
(
i
=
0
;
i
<
10
&&
proc_rxtx
->
instance_cnt_rxtx
==
0
;
i
++
)
{
for
(
i
=
0
;
i
<
10
&&
L1_proc
->
instance_cnt
==
0
;
i
++
)
{
LOG_W
(
PHY
,
"[gNB] Frame %d Subframe %d, gNB RXn-TXnp4 thread busy!! (cnt
_rxtx %i)
\n
"
,
proc_rxtx
->
frame_tx
,
proc_rxtx
->
subframe_tx
,
proc_rxtx
->
instance_cnt_rxtx
);
LOG_W
(
PHY
,
"[gNB] Frame %d Subframe %d, gNB RXn-TXnp4 thread busy!! (cnt
%i)
\n
"
,
L1_proc
->
frame_tx
,
L1_proc
->
subframe_tx
,
L1_proc
->
instance_cnt
);
usleep
(
500
);
usleep
(
500
);
}
}
if
(
proc_rxtx
->
instance_cnt_rxtx
==
0
)
{
if
(
L1_proc
->
instance_cnt
==
0
)
{
exit_fun
(
"TX thread busy"
);
exit_fun
(
"TX thread busy"
);
return
(
-
1
);
return
(
-
1
);
}
}
// wake up TX for subframe n+sf_ahead
// wake up TX for subframe n+sf_ahead
// lock the TX mutex and make sure the thread is ready
// lock the TX mutex and make sure the thread is ready
if
(
pthread_mutex_timedlock
(
&
proc_rxtx
->
mutex_rxt
x
,
&
wait
)
!=
0
)
{
if
(
pthread_mutex_timedlock
(
&
L1_proc
->
mute
x
,
&
wait
)
!=
0
)
{
LOG_E
(
PHY
,
"[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)
\n
"
,
proc_rxtx
->
subframe_rx
&
1
,
proc_rxtx
->
instance_cnt_rxtx
);
LOG_E
(
PHY
,
"[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)
\n
"
,
L1_proc
->
subframe_rx
&
1
,
L1_proc
->
instance_cnt
);
exit_fun
(
"error locking mutex
_rxtx
"
);
exit_fun
(
"error locking mutex"
);
return
(
-
1
);
return
(
-
1
);
}
}
++
proc_rxtx
->
instance_cnt_rxtx
;
++
L1_proc
->
instance_cnt
;
// We have just received and processed the common part of a subframe, say n.
// We have just received and processed the common part of a subframe, say n.
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
...
@@ -440,27 +440,27 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
...
@@ -440,27 +440,27 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
// we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
// we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
// and proc->subframe_tx = proc->subframe_rx+sf_ahead
// and proc->subframe_tx = proc->subframe_rx+sf_ahead
proc_rxtx
->
timestamp_tx
=
proc
->
timestamp_rx
+
(
sf_ahead
*
fp
->
samples_per_subframe
);
L1_proc
->
timestamp_tx
=
proc
->
timestamp_rx
+
(
sf_ahead
*
fp
->
samples_per_subframe
);
proc_rxtx
->
frame_rx
=
proc
->
frame_rx
;
L1_proc
->
frame_rx
=
proc
->
frame_rx
;
proc_rxtx
->
subframe_rx
=
proc
->
subframe_rx
;
L1_proc
->
subframe_rx
=
proc
->
subframe_rx
;
proc_rxtx
->
frame_tx
=
(
proc_rxtx
->
subframe_rx
>
(
9
-
sf_ahead
))
?
(
proc_rxtx
->
frame_rx
+
1
)
&
1023
:
proc_rxtx
->
frame_rx
;
L1_proc
->
frame_tx
=
(
L1_proc
->
subframe_rx
>
(
9
-
sf_ahead
))
?
(
L1_proc
->
frame_rx
+
1
)
&
1023
:
L1_proc
->
frame_rx
;
proc_rxtx
->
subframe_tx
=
(
proc_rxtx
->
subframe_rx
+
sf_ahead
)
%
10
;
L1_proc
->
subframe_tx
=
(
L1_proc
->
subframe_rx
+
sf_ahead
)
%
10
;
// the thread can now be woken up
// the thread can now be woken up
if
(
pthread_cond_signal
(
&
proc_rxtx
->
cond_rxtx
)
!=
0
)
{
if
(
pthread_cond_signal
(
&
L1_proc
->
cond
)
!=
0
)
{
LOG_E
(
PHY
,
"[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread
\n
"
);
LOG_E
(
PHY
,
"[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread
\n
"
);
exit_fun
(
"ERROR pthread_cond_signal"
);
exit_fun
(
"ERROR pthread_cond_signal"
);
return
(
-
1
);
return
(
-
1
);
}
}
pthread_mutex_unlock
(
&
proc_rxtx
->
mutex_rxt
x
);
pthread_mutex_unlock
(
&
L1_proc
->
mute
x
);
return
(
0
);
return
(
0
);
}
}
/*
/*
void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
gNB_proc_t *proc = &gNB->proc;
gNB_
L1_
proc_t *proc = &gNB->proc;
LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms;
LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms;
int i;
int i;
...
@@ -519,7 +519,7 @@ void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
...
@@ -519,7 +519,7 @@ void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
/*!
/*!
* \brief The prach receive thread of gNB.
* \brief The prach receive thread of gNB.
* \param param is a \ref gNB_proc_t structure which contains the info what to process.
* \param param is a \ref gNB_
L1_
proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
*/
/*
/*
...
@@ -528,7 +528,7 @@ static void* gNB_thread_prach( void* param ) {
...
@@ -528,7 +528,7 @@ static void* gNB_thread_prach( void* param ) {
PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param;
PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param;
gNB_proc_t *proc = &gNB->proc;
gNB_
L1_
proc_t *proc = &gNB->proc;
// set default return value
// set default return value
gNB_thread_prach_status = 0;
gNB_thread_prach_status = 0;
...
@@ -568,8 +568,8 @@ void init_gNB_proc(int inst) {
...
@@ -568,8 +568,8 @@ void init_gNB_proc(int inst) {
int
i
=
0
;
int
i
=
0
;
int
CC_id
;
int
CC_id
;
PHY_VARS_gNB
*
gNB
;
PHY_VARS_gNB
*
gNB
;
gNB_proc_t
*
proc
;
gNB_
L1_
proc_t
*
proc
;
gNB_
rxtx_proc_t
*
proc_rx
tx
;
gNB_
L1_rxtx_proc_t
*
L1_proc
,
*
L1_proc_
tx
;
pthread_attr_t
*
attr0
=
NULL
,
*
attr1
=
NULL
;
pthread_attr_t
*
attr0
=
NULL
,
*
attr1
=
NULL
;
//*attr_prach=NULL;
//*attr_prach=NULL;
...
@@ -582,27 +582,32 @@ void init_gNB_proc(int inst) {
...
@@ -582,27 +582,32 @@ void init_gNB_proc(int inst) {
#endif
#endif
proc
=
&
gNB
->
proc
;
proc
=
&
gNB
->
proc
;
proc_rxtx
=
proc
->
proc_rxtx
;
L1_proc
=
&
proc
->
L1_proc
;
proc_rxtx
[
0
].
instance_cnt_rxtx
=
-
1
;
L1_proc_tx
=
&
proc
->
L1_proc_tx
;
proc_rxtx
[
1
].
instance_cnt_rxtx
=
-
1
;
L1_proc
->
instance_cnt
=
-
1
;
L1_proc_tx
->
instance_cnt
=
-
1
;
L1_proc
->
instance_cnt_RUs
=
0
;
L1_proc_tx
->
instance_cnt_RUs
=
0
;
proc
->
instance_cnt_prach
=
-
1
;
proc
->
instance_cnt_prach
=
-
1
;
proc
->
instance_cnt_asynch_rxtx
=
-
1
;
proc
->
instance_cnt_asynch_rxtx
=
-
1
;
proc
->
CC_id
=
CC_id
;
proc
->
CC_id
=
CC_id
;
proc
->
first_rx
=
1
;
proc
->
first_rx
=
1
;
proc
->
first_tx
=
1
;
proc
->
first_tx
=
1
;
proc
->
RU_mask
=
0
;
proc
->
RU_mask
=
0
;
proc
->
RU_mask_prach
=
0
;
proc
->
RU_mask_tx
=
(
1
<<
gNB
->
num_RU
)
-
1
;
proc
->
RU_mask_prach
=
0
;
pthread_mutex_init
(
&
gNB
->
UL_INFO_mutex
,
NULL
);
pthread_mutex_init
(
&
gNB
->
UL_INFO_mutex
,
NULL
);
pthread_mutex_init
(
&
proc_rxtx
[
0
].
mutex_rxt
x
,
NULL
);
pthread_mutex_init
(
&
L1_proc
->
mute
x
,
NULL
);
pthread_mutex_init
(
&
proc_rxtx
[
1
].
mutex_rxt
x
,
NULL
);
pthread_mutex_init
(
&
L1_proc_tx
->
mute
x
,
NULL
);
pthread_cond_init
(
&
proc_rxtx
[
0
].
cond_rxtx
,
NULL
);
pthread_cond_init
(
&
L1_proc
->
cond
,
NULL
);
pthread_cond_init
(
&
proc_rxtx
[
1
].
cond_rxtx
,
NULL
);
pthread_cond_init
(
&
L1_proc_tx
->
cond
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_prach
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_prach
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_asynch_rxtx
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_asynch_rxtx
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_RU
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_RU
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_RU_tx
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_RU_PRACH
,
NULL
);
pthread_mutex_init
(
&
proc
->
mutex_RU_PRACH
,
NULL
);
pthread_cond_init
(
&
proc
->
cond_prach
,
NULL
);
pthread_cond_init
(
&
proc
->
cond_prach
,
NULL
);
...
@@ -612,23 +617,23 @@ void init_gNB_proc(int inst) {
...
@@ -612,23 +617,23 @@ void init_gNB_proc(int inst) {
pthread_attr_init
(
&
proc
->
attr_asynch_rxtx
);
pthread_attr_init
(
&
proc
->
attr_asynch_rxtx
);
// pthread_attr_init( &proc->attr_td);
// pthread_attr_init( &proc->attr_td);
// pthread_attr_init( &proc->attr_te);
// pthread_attr_init( &proc->attr_te);
pthread_attr_init
(
&
proc_rxtx
[
0
].
attr_rxtx
);
pthread_attr_init
(
&
L1_proc
->
attr
);
pthread_attr_init
(
&
proc_rxtx
[
1
].
attr_rxtx
);
pthread_attr_init
(
&
L1_proc_tx
->
attr
);
LOG_I
(
PHY
,
"gNB->single_thread_flag:%d
\n
"
,
gNB
->
single_thread_flag
);
LOG_I
(
PHY
,
"gNB->single_thread_flag:%d
\n
"
,
gNB
->
single_thread_flag
);
if
(
gNB
->
single_thread_flag
==
0
)
{
/*if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT
) {
pthread_create
(
&
proc_rxtx
[
0
].
pthread_rxtx
,
attr0
,
gNB_thread_rxtx
,
&
proc_rxtx
[
0
]
);
pthread_create( &
L1_proc->pthread, attr0, L1_thread, proc
);
pthread_create
(
&
proc_rxtx
[
1
].
pthread_rxtx
,
attr1
,
gNB_thread_rxtx
,
&
proc_rxtx
[
1
]
);
pthread_create( &
L1_proc_tx->pthread, attr1, L1_thread_tx, proc
);
}
}
*/
//pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
//pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
char
name
[
16
];
char
name
[
16
];
if
(
gNB
->
single_thread_flag
==
0
)
{
if
(
gNB
->
single_thread_flag
==
0
)
{
snprintf
(
name
,
sizeof
(
name
),
"
RXTX0
%d"
,
i
);
snprintf
(
name
,
sizeof
(
name
),
"
L1
%d"
,
i
);
pthread_setname_np
(
proc_rxtx
[
0
].
pthread_rxtx
,
name
);
pthread_setname_np
(
L1_proc
->
pthread
,
name
);
snprintf
(
name
,
sizeof
(
name
),
"
RXTX1
%d"
,
i
);
snprintf
(
name
,
sizeof
(
name
),
"
L1TX
%d"
,
i
);
pthread_setname_np
(
proc_rxtx
[
1
].
pthread_rxtx
,
name
);
pthread_setname_np
(
L1_proc_tx
->
pthread
,
name
);
}
}
AssertFatal
(
proc
->
instance_cnt_prach
==
-
1
,
"instance_cnt_prach = %d
\n
"
,
proc
->
instance_cnt_prach
);
AssertFatal
(
proc
->
instance_cnt_prach
==
-
1
,
"instance_cnt_prach = %d
\n
"
,
proc
->
instance_cnt_prach
);
...
@@ -651,23 +656,27 @@ void kill_gNB_proc(int inst) {
...
@@ -651,23 +656,27 @@ void kill_gNB_proc(int inst) {
int
*
status
;
int
*
status
;
PHY_VARS_gNB
*
gNB
;
PHY_VARS_gNB
*
gNB
;
gNB_proc_t
*
proc
;
gNB_
L1_
proc_t
*
proc
;
gNB_
rxtx_proc_t
*
proc_rx
tx
;
gNB_
L1_rxtx_proc_t
*
L1_proc
,
*
L1_proc_
tx
;
for
(
int
CC_id
=
0
;
CC_id
<
MAX_NUM_CCs
;
CC_id
++
)
{
for
(
int
CC_id
=
0
;
CC_id
<
MAX_NUM_CCs
;
CC_id
++
)
{
gNB
=
RC
.
gNB
[
inst
][
CC_id
];
gNB
=
RC
.
gNB
[
inst
][
CC_id
];
proc
=
&
gNB
->
proc
;
proc
=
&
gNB
->
proc
;
proc_rxtx
=
&
proc
->
proc_rxtx
[
0
];
L1_proc
=
&
proc
->
L1_proc
;
L1_proc_tx
=
&
proc
->
L1_proc_tx
;
LOG_I
(
PHY
,
"Killing TX CC_id %d inst %d
\n
"
,
CC_id
,
inst
);
LOG_I
(
PHY
,
"Killing TX CC_id %d inst %d
\n
"
,
CC_id
,
inst
);
if
(
gNB
->
single_thread_flag
==
0
)
{
if
(
get_thread_parallel_conf
()
==
PARALLEL_RU_L1_SPLIT
||
get_thread_parallel_conf
()
==
PARALLEL_RU_L1_TRX_SPLIT
)
{
pthread_mutex_lock
(
&
proc_rxtx
[
0
].
mutex_rxtx
);
pthread_mutex_lock
(
&
L1_proc
->
mutex
);
proc_rxtx
[
0
].
instance_cnt_rxtx
=
0
;
L1_proc
->
instance_cnt
=
0
;
pthread_mutex_unlock
(
&
proc_rxtx
[
0
].
mutex_rxtx
);
pthread_cond_signal
(
&
L1_proc
->
cond
);
pthread_mutex_lock
(
&
proc_rxtx
[
1
].
mutex_rxtx
);
pthread_mutex_unlock
(
&
L1_proc
->
mutex
);
proc_rxtx
[
1
].
instance_cnt_rxtx
=
0
;
pthread_mutex_unlock
(
&
proc_rxtx
[
1
].
mutex_rxtx
);
pthread_mutex_lock
(
&
L1_proc_tx
->
mutex
);
L1_proc_tx
->
instance_cnt
=
0
;
pthread_cond_signal
(
&
L1_proc_tx
->
cond
);
pthread_mutex_unlock
(
&
L1_proc_tx
->
mutex
);
}
}
proc
->
instance_cnt_prach
=
0
;
proc
->
instance_cnt_prach
=
0
;
pthread_cond_signal
(
&
proc
->
cond_prach
);
pthread_cond_signal
(
&
proc
->
cond_prach
);
...
@@ -685,15 +694,22 @@ void kill_gNB_proc(int inst) {
...
@@ -685,15 +694,22 @@ void kill_gNB_proc(int inst) {
LOG_I
(
PHY
,
"Destroying UL_INFO mutex
\n
"
);
LOG_I
(
PHY
,
"Destroying UL_INFO mutex
\n
"
);
pthread_mutex_destroy
(
&
gNB
->
UL_INFO_mutex
);
pthread_mutex_destroy
(
&
gNB
->
UL_INFO_mutex
);
int
i
;
int
i
;
if
(
gNB
->
single_thread_flag
==
0
)
{
if
((
get_thread_parallel_conf
()
==
PARALLEL_RU_L1_SPLIT
||
get_thread_parallel_conf
()
==
PARALLEL_RU_L1_TRX_SPLIT
)
&&
nfapi_mode
!=
2
)
{
for
(
i
=
0
;
i
<
2
;
i
++
)
{
LOG_I
(
PHY
,
"Joining L1_proc mutex/cond
\n
"
);
LOG_I
(
PHY
,
"Joining rxtx[%d] mutex/cond
\n
"
,
i
);
pthread_join
(
L1_proc
->
pthread
,
(
void
**
)
&
status
);
pthread_join
(
proc_rxtx
[
i
].
pthread_rxtx
,
(
void
**
)
&
status
);
LOG_I
(
PHY
,
"Joining L1_proc_tx mutex/cond
\n
"
);
LOG_I
(
PHY
,
"Destroying rxtx[%d] mutex/cond
\n
"
,
i
);
pthread_join
(
L1_proc_tx
->
pthread
,
(
void
**
)
&
status
);
pthread_mutex_destroy
(
&
proc_rxtx
[
i
].
mutex_rxtx
);
}
pthread_cond_destroy
(
&
proc_rxtx
[
i
].
cond_rxtx
);
LOG_I
(
PHY
,
"Destroying L1_proc mutex/cond
\n
"
);
}
pthread_mutex_destroy
(
&
L1_proc
->
mutex
);
}
pthread_cond_destroy
(
&
L1_proc
->
cond
);
LOG_I
(
PHY
,
"Destroying L1_proc_tx mutex/cond
\n
"
);
pthread_mutex_destroy
(
&
L1_proc_tx
->
mutex
);
pthread_cond_destroy
(
&
L1_proc_tx
->
cond
);
pthread_mutex_destroy
(
&
proc
->
mutex_RU
);
pthread_mutex_destroy
(
&
proc
->
mutex_RU_tx
);
}
}
}
}
...
...
targets/RT/USER/nr-ru.c
View file @
818b27c1
...
@@ -874,7 +874,7 @@ void tx_rf(RU_t *ru) {
...
@@ -874,7 +874,7 @@ void tx_rf(RU_t *ru) {
/*!
/*!
* \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU.
* \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU.
* This handles the RX FH for an asynchronous RRU/UE
* This handles the RX FH for an asynchronous RRU/UE
* \param param is a \ref gNB_proc_t structure which contains the info what to process.
* \param param is a \ref gNB_
L1_
proc_t structure which contains the info what to process.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
*/
static
void
*
ru_thread_asynch_rxtx
(
void
*
param
)
{
static
void
*
ru_thread_asynch_rxtx
(
void
*
param
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment