Skip to content

Commit 6524872

Browse files
author
Jarkko Paso
authored
Implemented FHSS expedited forwarding mode (#2606)
* FHSS: expedited forwarding state implemented * FHSS WS: Unit tests for expedited forwarding * MAC: enable FHSS expedited forwarding when data req with EF priority * FHSS: macro EXPEDITED_FORWARDING_POLL_PERIOD to contain conversion to 50us slots * Use macro with default poll period
1 parent 91e0b4c commit 6524872

File tree

9 files changed

+149
-41
lines changed

9 files changed

+149
-41
lines changed

nanostack/fhss_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef struct fhss_callback fhss_callback_t;
4949
typedef enum {
5050
FHSS_UNSYNCHRONIZED,
5151
FHSS_SYNCHRONIZED,
52+
FHSS_EXPEDITED_FORWARDING
5253
} fhss_states;
5354

5455
/**

source/MAC/IEEE802_15_4/mac_mcps_sap.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
269269
switch (priority) {
270270
case MAC_DATA_EXPEDITE_FORWARD:
271271
buffer->priority = MAC_PD_DATA_EF_PRIORITY;
272+
// Enable FHSS expedited forwarding
273+
if (rf_mac_setup->fhss_api) {
274+
rf_mac_setup->fhss_api->synch_state_set(rf_mac_setup->fhss_api, FHSS_EXPEDITED_FORWARDING, 0);
275+
}
272276
break;
273277
case MAC_DATA_HIGH_PRIORITY:
274278
buffer->priority = MAC_PD_DATA_HIGH_PRIOTITY;

source/Service_Libs/fhss/fhss_ws.c

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -352,44 +352,51 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
352352
fhss_ws_start_timer(fhss_structure, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - ((int64_t) delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler);
353353
fhss_structure->ws->is_on_bc_channel = true;
354354
next_channel = fhss_structure->ws->bc_channel = fhss_ws_calc_bc_channel(fhss_structure);
355-
356-
/* Start timer with random timeout to trigger broadcast TX queue poll event.
357-
* Min random is 1/50 of the channel dwell interval.
358-
* Max random is 3/4 of the channel dwell interval.
359-
* Event timer resolution is 50us.
360-
*/
361-
uint32_t bc_dwell_us = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
362-
uint16_t bc_min_random = (bc_dwell_us / 50) / 50;
363-
uint16_t bc_max_random = (bc_dwell_us - (bc_dwell_us / 4)) / 50;
364-
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(bc_min_random, bc_max_random));
355+
if (fhss_structure->ws->expedited_forwarding_enabled_us) {
356+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
357+
} else {
358+
/* Start timer with random timeout to trigger broadcast TX queue poll event.
359+
* Min random is 1/50 of the channel dwell interval.
360+
* Max random is 3/4 of the channel dwell interval.
361+
* Event timer resolution is 50us.
362+
*/
363+
uint32_t bc_dwell_us = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
364+
uint16_t bc_min_random = (bc_dwell_us / 50) / 50;
365+
uint16_t bc_max_random = (bc_dwell_us - (bc_dwell_us / 4)) / 50;
366+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(bc_min_random, bc_max_random));
367+
}
365368
} else {
366369
fhss_structure->ws->unicast_start_time_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
367370
uint32_t timeout = MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
368371
fhss_ws_start_timer(fhss_structure, timeout - (delay_us * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler);
369372
fhss_structure->ws->is_on_bc_channel = false;
370373
// Should return to own (unicast) listening channel after broadcast channel
371374
next_channel = fhss_structure->rx_channel;
372-
/* Start timer with random timeout to trigger unicast TX queue poll event.
373-
* For hops 0,1,4,5,8,9,...
374-
* Min random is 1/100 of the TX slot length.
375-
* Max random is 1/5 of the TX slot length.
376-
*
377-
* For hops 2,3,6,7,10,11,...
378-
* Min random is 1/100 of the TX slot length plus 0.5*TX slot length.
379-
* Max random is 1/10 of the TX slot length plus 0.5*TX slot length.
380-
* Event timer resolution is 50us.
381-
*/
382-
// returns 1 if polling of TX queue is done on latter half of the TX slot
383-
uint8_t own_tx_trig_slot = calc_own_tx_trig_slot(fhss_structure->own_hop);
384-
uint32_t txrx_slot_length_us = MS_TO_US(fhss_structure->ws->txrx_slot_length_ms);
385-
uint16_t uc_min_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 100) / 50);
386-
uint16_t uc_max_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 5) / 50);
387-
bool tx_allowed = fhss_ws_check_tx_allowed(fhss_structure);
388-
if (!tx_allowed) {
389-
uc_min_random += (txrx_slot_length_us) / 50;
390-
uc_max_random += (txrx_slot_length_us) / 50;
375+
if (fhss_structure->ws->expedited_forwarding_enabled_us) {
376+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
377+
} else {
378+
/* Start timer with random timeout to trigger unicast TX queue poll event.
379+
* For hops 0,1,4,5,8,9,...
380+
* Min random is 1/100 of the TX slot length.
381+
* Max random is 1/5 of the TX slot length.
382+
*
383+
* For hops 2,3,6,7,10,11,...
384+
* Min random is 1/100 of the TX slot length plus 0.5*TX slot length.
385+
* Max random is 1/10 of the TX slot length plus 0.5*TX slot length.
386+
* Event timer resolution is 50us.
387+
*/
388+
// returns 1 if polling of TX queue is done on latter half of the TX slot
389+
uint8_t own_tx_trig_slot = calc_own_tx_trig_slot(fhss_structure->own_hop);
390+
uint32_t txrx_slot_length_us = MS_TO_US(fhss_structure->ws->txrx_slot_length_ms);
391+
uint16_t uc_min_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 100) / 50);
392+
uint16_t uc_max_random = (((txrx_slot_length_us / 2) * own_tx_trig_slot) / 50) + ((txrx_slot_length_us / 5) / 50);
393+
bool tx_allowed = fhss_ws_check_tx_allowed(fhss_structure);
394+
if (!tx_allowed) {
395+
uc_min_random += (txrx_slot_length_us) / 50;
396+
uc_max_random += (txrx_slot_length_us) / 50;
397+
}
398+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(uc_min_random, uc_max_random));
391399
}
392-
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(uc_min_random, uc_max_random));
393400

394401
#ifdef FHSS_CHANNEL_DEBUG
395402
tr_info("%"PRIu32" UC %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), fhss_structure->rx_channel);
@@ -438,9 +445,19 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots)
438445
return;
439446
}
440447

441-
// No one would poll TX queue if schedule timers were not started. Start poll timer with 10ms (200*50us) interval.
442-
if ((fhss_structure->ws->unicast_timer_running == false) && (fhss_structure->ws->broadcast_timer_running == false)) {
443-
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, 200);
448+
if (fhss_structure->ws->expedited_forwarding_enabled_us) {
449+
if ((fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) - fhss_structure->ws->expedited_forwarding_enabled_us) > S_TO_US(EXPEDITED_FORWARDING_PERIOD)) {
450+
fhss_structure->ws->expedited_forwarding_enabled_us = 0;
451+
}
452+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
453+
if (fhss_structure->ws->is_on_bc_channel == true) {
454+
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true);
455+
} else {
456+
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false);
457+
}
458+
} else if ((fhss_structure->ws->unicast_timer_running == false) && (fhss_structure->ws->broadcast_timer_running == false)) {
459+
// No one would poll TX queue if schedule timers were not started. Start poll timer with default interval.
460+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, DEFAULT_POLL_PERIOD);
444461
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false);
445462
} else {
446463
if (fhss_structure->ws->is_on_bc_channel == true) {
@@ -535,6 +552,16 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat
535552
if (!fhss_structure) {
536553
return -1;
537554
}
555+
if (fhss_state == FHSS_EXPEDITED_FORWARDING) {
556+
if (!fhss_structure->ws->expedited_forwarding_enabled_us) {
557+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, EXPEDITED_FORWARDING_POLL_PERIOD);
558+
}
559+
fhss_structure->ws->expedited_forwarding_enabled_us = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
560+
if (!fhss_structure->ws->expedited_forwarding_enabled_us) {
561+
fhss_structure->ws->expedited_forwarding_enabled_us++;
562+
}
563+
return 0;
564+
}
538565
if (fhss_state == FHSS_SYNCHRONIZED) {
539566
uint32_t fhss_broadcast_interval = fhss_structure->ws->fhss_configuration.fhss_broadcast_interval;
540567
uint8_t fhss_bc_dwell_interval = fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval;
@@ -1139,9 +1166,9 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
11391166
channel_count_uc = channel_count_bc;
11401167
}
11411168

1142-
// No one would poll TX queue if schedule timers were not started. Start poll timer with 10ms (200*50us) interval.
1169+
// No one would poll TX queue if schedule timers were not started. Start poll timer with default interval.
11431170
if ((fhss_structure->ws->unicast_timer_running == false) && (fhss_structure->ws->broadcast_timer_running == false)) {
1144-
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, 200);
1171+
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, DEFAULT_POLL_PERIOD);
11451172
}
11461173

11471174
fhss_structure->number_of_channels = fhss_configuration->channel_mask_size;

source/Service_Libs/fhss/fhss_ws.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,23 @@
1818
#define FHSS_WS_H_
1919

2020
// TX slot length is optimised to this packet length
21-
#define OPTIMAL_PACKET_LENGTH 500
21+
#define OPTIMAL_PACKET_LENGTH 500
2222
// Max TX/RX slot length in milliseconds. Is used when datarate is not given by PHY or calculated slot length exceeds maximum allowed.
23-
#define WS_TXRX_SLOT_LEN_MS_MAX 100
23+
#define WS_TXRX_SLOT_LEN_MS_MAX 100
2424
// Min TX/RX slot length in milliseconds. Is used when calculated slot length is under minimum allowed.
25-
#define WS_TXRX_SLOT_LEN_MS_MIN 13
25+
#define WS_TXRX_SLOT_LEN_MS_MIN 13
2626
// Default minimum broadcast synchronization interval in seconds
27-
#define DEFAULT_MIN_SYNCH_INTERVAL 60
27+
#define DEFAULT_MIN_SYNCH_INTERVAL 60
2828
// Drift compensation allowed if at least SYNCH_COMPENSATION_MIN_INTERVAL (seconds) since last synchronization
29-
#define SYNCH_COMPENSATION_MIN_INTERVAL 60
29+
#define SYNCH_COMPENSATION_MIN_INTERVAL 60
3030
// MAX compensation per received synchronization info in ns
31-
#define MAX_DRIFT_COMPENSATION_STEP 10
31+
#define MAX_DRIFT_COMPENSATION_STEP 10
32+
// Length of expedited forwarding period in seconds
33+
#define EXPEDITED_FORWARDING_PERIOD 5
34+
// TX poll interval for expedited forwarding in 50us slots
35+
#define EXPEDITED_FORWARDING_POLL_PERIOD (5000 / 50)
36+
// TX poll interval used when channel schedules are not yet started (50us slots)
37+
#define DEFAULT_POLL_PERIOD (10000 / 50)
3238
typedef struct fhss_ws fhss_ws_t;
3339

3440
struct fhss_ws {
@@ -44,6 +50,7 @@ struct fhss_ws {
4450
uint8_t *tr51_output_table;
4551
uint32_t next_uc_timeout;
4652
uint32_t next_bc_timeout;
53+
uint32_t expedited_forwarding_enabled_us;
4754
bool unicast_timer_running;
4855
bool broadcast_timer_running;
4956
bool is_on_bc_channel;

test/nanostack/unittest/service_libs/fhss_ws/fhsswstest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,8 @@ TEST(fhssws, test_fhss_ws_remove_parent)
102102
{
103103
CHECK(test_fhss_ws_remove_parent());
104104
}
105+
106+
TEST(fhssws, test_fhss_event_timer_cb)
107+
{
108+
CHECK(test_fhss_event_timer_cb());
109+
}

test/nanostack/unittest/service_libs/fhss_ws/test_fhss_ws.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "fhss_callbacks_stub.h"
3030
#include "fhss_platform_stub.h"
3131
#include "channel_functions_stub.h"
32+
#include "ns_timer_stub.h"
3233

3334
#define VENDOR_CHANNEL 89
3435
#define DEFAULT_CHANNEL 99
@@ -980,3 +981,63 @@ bool test_fhss_ws_remove_parent()
980981
}
981982
return true;
982983
}
984+
985+
bool test_fhss_event_timer_cb()
986+
{
987+
fhss_api_t *fhss_api = test_generate_fhss_api();
988+
fhss_ws_configuration_t fhss_configuration;
989+
fhss_timer_t fhss_timer;
990+
fhss_common_stub.bool_value = true;
991+
channel_list_stub.uint8_value = 1;
992+
nsdynmemlib_stub.returnCounter = 3;
993+
ns_timer_stub.cb_counter = 1;
994+
// Enabling FHSS will register the TX poll timer
995+
if (fhss_ws_enable(fhss_api, &fhss_configuration, &fhss_timer) == NULL) {
996+
return false;
997+
}
998+
999+
fhss_common_stub.fhss_struct.ws->unicast_timer_running = true;
1000+
fhss_common_stub.fhss_struct.ws->broadcast_timer_running = true;
1001+
test_set_platform_api(&fhss_common_stub.fhss_struct.platform_functions);
1002+
fhss_platform_stub.remaining_slots_value = 200000;
1003+
fhss_common_stub.fhss_struct.ws->fhss_configuration.fhss_broadcast_interval = 1020;
1004+
fhss_common_stub.fhss_struct.ws->txrx_slot_length_ms = 54;
1005+
fhss_callbacks_stub.uint8_value = 5;
1006+
1007+
// Test that timer is started with correct value for expedited forwarding
1008+
fhss_common_stub.fhss_struct.ws->expedited_forwarding_enabled_us = 1000000;
1009+
fhss_callbacks_stub.uint32_value = 5000000;
1010+
ns_timer_stub.cb(1, 100);
1011+
if (ns_timer_stub.start_slots != EXPEDITED_FORWARDING_POLL_PERIOD) {
1012+
printf("Fail: Wrong EF poll timer start value: %u. Expected: %u\r\n", ns_timer_stub.start_slots, EXPEDITED_FORWARDING_POLL_PERIOD);
1013+
return false;
1014+
}
1015+
1016+
// Test that expedited forwarding is stopped after period is over
1017+
fhss_common_stub.fhss_struct.ws->expedited_forwarding_enabled_us = 1000000;
1018+
fhss_callbacks_stub.uint32_value = fhss_common_stub.fhss_struct.ws->expedited_forwarding_enabled_us + (EXPEDITED_FORWARDING_PERIOD * 1000000) + 1;
1019+
ns_timer_stub.cb(1, 100);
1020+
if ((ns_timer_stub.start_slots != EXPEDITED_FORWARDING_POLL_PERIOD) || fhss_common_stub.fhss_struct.ws->expedited_forwarding_enabled_us) {
1021+
printf("Fail: Wrong EF stop value: %u. Expected: %u. EF enabled: %s\r\n", ns_timer_stub.start_slots, EXPEDITED_FORWARDING_POLL_PERIOD, fhss_common_stub.fhss_struct.ws->expedited_forwarding_enabled_us ? "true" : "false");
1022+
return false;
1023+
}
1024+
// Test that normal polling is started after expedited forwarding
1025+
ns_timer_stub.cb(1, 100);
1026+
if (ns_timer_stub.start_slots != ((fhss_common_stub.fhss_struct.ws->txrx_slot_length_ms * 2 * 1000) / 50)) {
1027+
printf("Fail: Wrong UC poll timer start value: %u. Expected: %u\r\n", ns_timer_stub.start_slots, ((fhss_common_stub.fhss_struct.ws->txrx_slot_length_ms * 2 * 1000) / 50));
1028+
return false;
1029+
}
1030+
// Test that on broadcast channel the poll timer is not restarted
1031+
fhss_common_stub.fhss_struct.ws->is_on_bc_channel = true;
1032+
ns_timer_stub.start_slots = 0xffff;
1033+
ns_timer_stub.cb(1, 100);
1034+
if (ns_timer_stub.start_slots != 0xffff) {
1035+
printf("Fail: Wrong BC poll timer start value: %u. Expected: %u\r\n", ns_timer_stub.start_slots, 0xffff);
1036+
return false;
1037+
}
1038+
1039+
free(fhss_common_stub.fhss_struct.ws->tr51_channel_table);
1040+
free(fhss_common_stub.fhss_struct.ws->tr51_output_table);
1041+
free(fhss_common_stub.fhss_struct.ws);
1042+
return true;
1043+
}

test/nanostack/unittest/service_libs/fhss_ws/test_fhss_ws.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ bool test_fhss_ws_update_uc_channel_callback();
3939
bool test_fhss_unicast_handler();
4040
bool test_fhss_ws_set_parent();
4141
bool test_fhss_ws_remove_parent();
42+
bool test_fhss_event_timer_cb();
4243

4344
#ifdef __cplusplus
4445
}

test/nanostack/unittest/stub/ns_timer_stub.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ int8_t ns_timer_sleep(void)
5252

5353
int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots)
5454
{
55+
ns_timer_stub.start_slots = slots;
5556
return ns_timer_stub.int8_value;
5657
}
5758

test/nanostack/unittest/stub/ns_timer_stub.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ extern "C" {
2424
typedef struct {
2525
int8_t int8_value;
2626
uint8_t cb_counter;
27+
uint16_t start_slots;
2728
void (*cb)(int8_t, uint16_t);
2829
} ns_timer_stub_def;
2930

0 commit comments

Comments
 (0)