8
8
#include <zephyr/drivers/gpio.h>
9
9
10
10
#include <openthread/error.h>
11
+ #include <openthread/platform/alarm-milli.h>
11
12
#include <openthread/platform/diag.h>
13
+ #include <openthread/platform/radio.h>
12
14
13
15
#include "platform-zephyr.h"
14
16
#include "zephyr/sys/util.h"
15
17
18
+ enum {
19
+ DIAG_TRANSMIT_MODE_IDLE ,
20
+ DIAG_TRANSMIT_MODE_PACKETS ,
21
+ DIAG_TRANSMIT_MODE_CARRIER ,
22
+ DIAG_TRANSMIT_MODE_MODCARRIER
23
+
24
+ } diag_trasmit_mode ;
25
+
16
26
/**
17
27
* Diagnostics mode variables.
18
28
*
19
29
*/
30
+
20
31
static bool sDiagMode ;
21
32
static void * sDiagCallbackContext ;
22
33
static otPlatDiagOutputCallback sDiagOutputCallback ;
34
+ static uint8_t sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
35
+ static uint8_t sChannel = 20 ;
36
+ static uint32_t sTxPeriod = 1 ;
37
+ static int32_t sTxCount ;
38
+ static int32_t sTxRequestedCount = 1 ;
23
39
24
40
static otError startModCarrier (otInstance * aInstance , uint8_t aArgsLength , char * aArgs []);
41
+ static otError processTransmit (otInstance * aInstance , uint8_t aArgsLength , char * aArgs []);
42
+
43
+ static otError parse_long (char * aArgs , long * aValue )
44
+ {
45
+ char * endptr ;
46
+ * aValue = strtol (aArgs , & endptr , 0 );
47
+ return (* endptr == '\0' ) ? OT_ERROR_NONE : OT_ERROR_PARSE ;
48
+ }
25
49
26
50
static void diag_output (const char * aFormat , ...)
27
51
{
@@ -48,15 +72,16 @@ void otPlatDiagSetOutputCallback(otInstance *aInstance,
48
72
49
73
otError otPlatDiagProcess (otInstance * aInstance , uint8_t aArgsLength , char * aArgs [])
50
74
{
51
- ARG_UNUSED (aInstance );
52
- ARG_UNUSED (aArgsLength );
53
-
54
75
#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS )
55
76
if (strcmp (aArgs [0 ], "modcarrier" ) == 0 ) {
56
77
return startModCarrier (aInstance , aArgsLength - 1 , aArgs + 1 );
57
78
}
58
79
#endif
59
80
81
+ if (strcmp (aArgs [0 ], "transmit" ) == 0 ) {
82
+ return processTransmit (aInstance , aArgsLength - 1 , aArgs + 1 );
83
+ }
84
+
60
85
/* Add more platform specific diagnostics features here. */
61
86
diag_output ("diag feature '%s' is not supported\r\n" , aArgs [0 ]);
62
87
@@ -80,6 +105,7 @@ bool otPlatDiagModeGet(void)
80
105
void otPlatDiagChannelSet (uint8_t aChannel )
81
106
{
82
107
ARG_UNUSED (aChannel );
108
+ sChannel = aChannel ;
83
109
}
84
110
85
111
void otPlatDiagTxPowerSet (int8_t aTxPower )
@@ -99,19 +125,21 @@ void otPlatDiagRadioReceived(otInstance *aInstance,
99
125
#if defined(CONFIG_IEEE802154_CARRIER_FUNCTIONS )
100
126
otError otPlatDiagRadioTransmitCarrier (otInstance * aInstance , bool aEnable )
101
127
{
102
- if (!otPlatDiagModeGet ()) {
128
+ if (!otPlatDiagModeGet () || (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE &&
129
+ sTransmitMode != DIAG_TRANSMIT_MODE_CARRIER )) {
103
130
return OT_ERROR_INVALID_STATE ;
104
131
}
105
132
133
+ if (aEnable ) {
134
+ sTransmitMode = DIAG_TRANSMIT_MODE_CARRIER ;
135
+ } else {
136
+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
137
+ }
138
+
106
139
return platformRadioTransmitCarrier (aInstance , aEnable );
107
140
}
108
141
#endif /* CONFIG_IEEE802154_CARRIER_FUNCTIONS */
109
142
110
- void otPlatDiagAlarmCallback (otInstance * aInstance )
111
- {
112
- ARG_UNUSED (aInstance );
113
- }
114
-
115
143
/*
116
144
* To enable gpio diag commands, in Devicetree create `openthread` node in `/options/` path
117
145
* with `compatible = "openthread,config"` property and `diag-gpios` property,
@@ -291,25 +319,154 @@ otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
291
319
292
320
static otError startModCarrier (otInstance * aInstance , uint8_t aArgsLength , char * aArgs [])
293
321
{
294
- ARG_UNUSED (aInstance );
295
- ARG_UNUSED (aArgsLength );
296
-
297
322
bool enable = true;
298
323
uint8_t data [OT_RADIO_FRAME_MAX_SIZE + 1 ];
299
324
300
325
if (aArgsLength <= 0 ) {
301
326
return OT_ERROR_INVALID_ARGS ;
302
327
}
303
328
329
+ if (!otPlatDiagModeGet () || (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE &&
330
+ sTransmitMode != DIAG_TRANSMIT_MODE_MODCARRIER )) {
331
+ return OT_ERROR_INVALID_STATE ;
332
+ }
333
+
304
334
if (strcmp (aArgs [0 ], "stop" ) == 0 ) {
305
335
enable = false;
336
+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
306
337
} else {
307
338
if (hex2bin (aArgs [0 ], strlen (aArgs [0 ]), data , ARRAY_SIZE (data )) == 0 ) {
308
339
return OT_ERROR_INVALID_ARGS ;
309
340
}
341
+ sTransmitMode = DIAG_TRANSMIT_MODE_MODCARRIER ;
310
342
}
311
343
312
344
return platformRadioTransmitModulatedCarrier (aInstance , enable , data );
313
345
}
314
346
315
347
#endif
348
+
349
+ void otPlatDiagAlarmCallback (otInstance * aInstance )
350
+ {
351
+ uint32_t now ;
352
+ otRadioFrame * txPacket ;
353
+ const uint16_t diag_packet_len = 30 ;
354
+
355
+ if (sTransmitMode == DIAG_TRANSMIT_MODE_PACKETS ) {
356
+ if ((sTxCount > 0 ) || (sTxCount == -1 )) {
357
+ txPacket = otPlatRadioGetTransmitBuffer (aInstance );
358
+
359
+ txPacket -> mInfo .mTxInfo .mTxDelayBaseTime = 0 ;
360
+ txPacket -> mInfo .mTxInfo .mTxDelay = 0 ;
361
+ txPacket -> mInfo .mTxInfo .mMaxCsmaBackoffs = 0 ;
362
+ txPacket -> mInfo .mTxInfo .mMaxFrameRetries = 0 ;
363
+ txPacket -> mInfo .mTxInfo .mRxChannelAfterTxDone = sChannel ;
364
+ txPacket -> mInfo .mTxInfo .mTxPower = OT_RADIO_POWER_INVALID ;
365
+ txPacket -> mInfo .mTxInfo .mIsHeaderUpdated = false;
366
+ txPacket -> mInfo .mTxInfo .mIsARetx = false;
367
+ txPacket -> mInfo .mTxInfo .mCsmaCaEnabled = false;
368
+ txPacket -> mInfo .mTxInfo .mCslPresent = false;
369
+ txPacket -> mInfo .mTxInfo .mIsSecurityProcessed = false;
370
+
371
+ txPacket -> mLength = diag_packet_len ;
372
+
373
+ for (uint8_t i = 0 ; i < diag_packet_len ; i ++ ) {
374
+ txPacket -> mPsdu [i ] = i ;
375
+ }
376
+
377
+ otPlatRadioTransmit (aInstance , txPacket );
378
+
379
+ if (sTxCount != -1 ) {
380
+ sTxCount -- ;
381
+ }
382
+
383
+ now = otPlatAlarmMilliGetNow ();
384
+ otPlatAlarmMilliStartAt (aInstance , now , sTxPeriod );
385
+ } else {
386
+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
387
+ otPlatAlarmMilliStop (aInstance );
388
+ otPlatLog (OT_LOG_LEVEL_DEBG , OT_LOG_REGION_PLATFORM , "Transmit done" );
389
+ }
390
+ }
391
+ }
392
+
393
+ static otError processTransmit (otInstance * aInstance , uint8_t aArgsLength , char * aArgs [])
394
+ {
395
+ otError error = OT_ERROR_NONE ;
396
+ long value ;
397
+ uint32_t now ;
398
+
399
+ if (!otPlatDiagModeGet ()) {
400
+ return OT_ERROR_INVALID_STATE ;
401
+ }
402
+
403
+ if (aArgsLength == 0 ) {
404
+ diag_output ("transmit will send %" PRId32 " diagnostic messages with %" PRIu32
405
+ " ms interval\r\n" ,
406
+ sTxRequestedCount , sTxPeriod );
407
+
408
+ } else if (strcmp (aArgs [0 ], "stop" ) == 0 ) {
409
+ if (sTransmitMode == DIAG_TRANSMIT_MODE_IDLE ) {
410
+ return OT_ERROR_INVALID_STATE ;
411
+ }
412
+
413
+ otPlatAlarmMilliStop (aInstance );
414
+ diag_output ("diagnostic message transmission is stopped\r\n" );
415
+ sTransmitMode = DIAG_TRANSMIT_MODE_IDLE ;
416
+ otPlatRadioReceive (aInstance , sChannel );
417
+
418
+ } else if (strcmp (aArgs [0 ], "start" ) == 0 ) {
419
+ if (sTransmitMode != DIAG_TRANSMIT_MODE_IDLE ) {
420
+ return OT_ERROR_INVALID_STATE ;
421
+ }
422
+
423
+ otPlatAlarmMilliStop (aInstance );
424
+ sTransmitMode = DIAG_TRANSMIT_MODE_PACKETS ;
425
+ sTxCount = sTxRequestedCount ;
426
+ now = otPlatAlarmMilliGetNow ();
427
+ otPlatAlarmMilliStartAt (aInstance , now , sTxPeriod );
428
+ diag_output ("sending %" PRId32 " diagnostic messages with %" PRIu32
429
+ " ms interval\r\n" ,
430
+ sTxRequestedCount , sTxPeriod );
431
+ } else if (strcmp (aArgs [0 ], "interval" ) == 0 ) {
432
+
433
+ if (aArgsLength != 2 ) {
434
+ return OT_ERROR_INVALID_ARGS ;
435
+ }
436
+
437
+ error = parse_long (aArgs [1 ], & value );
438
+ if (error != OT_ERROR_NONE ) {
439
+ return error ;
440
+ }
441
+
442
+ if (value <= 0 ) {
443
+ return OT_ERROR_INVALID_ARGS ;
444
+ }
445
+ sTxPeriod = (uint32_t )(value );
446
+ diag_output ("set diagnostic messages interval to %" PRIu32
447
+ " ms\r\n" , sTxPeriod );
448
+
449
+ } else if (strcmp (aArgs [0 ], "count" ) == 0 ) {
450
+
451
+ if (aArgsLength != 2 ) {
452
+ return OT_ERROR_INVALID_ARGS ;
453
+ }
454
+
455
+ error = parse_long (aArgs [1 ], & value );
456
+ if (error != OT_ERROR_NONE ) {
457
+ return error ;
458
+ }
459
+
460
+ if ((value <= 0 ) && (value != -1 )) {
461
+ return OT_ERROR_INVALID_ARGS ;
462
+ }
463
+
464
+ sTxRequestedCount = (uint32_t )(value );
465
+ diag_output ("set diagnostic messages count to %" PRId32 "\r\n" ,
466
+ sTxRequestedCount );
467
+ } else {
468
+ return OT_ERROR_INVALID_ARGS ;
469
+ }
470
+
471
+ return error ;
472
+ }
0 commit comments