contiki-ng / contiki-ng

Contiki-NG: The OS for Next Generation IoT Devices
https://www.contiki-ng.org/
BSD 3-Clause "New" or "Revised" License
1.29k stars 697 forks source link

RTIMER_BUSYWAIT_UNTIL_ABS() waits longer than maxtime when CCA enabled in Cooja #1535

Closed wonderfulnx closed 3 years ago

wonderfulnx commented 3 years ago

Using the example of 6tisch/simple-node, if set CCA with #define TSCH_CONF_CCA_ENABLED 1, the node will miss the deadline of transmitting. I added the following code in tsch-slot-operation.c to show the time offset of every statge.

#if TSCH_CCA_ENABLED
        cca_status = 1;
+        TSCH_LOG_ADD(tsch_log_message,
                     snprintf(log->message, sizeof(log->message),
                         "Before CCA, cur: %d, cca_off + cca: %u",
                         (int)(RTIMER_NOW()-current_slot_start), (unsigned)(tsch_timing[tsch_ts_cca_offset] + tsch_timing[tsch_ts_cca]));
        );
        /* delay before CCA */
        TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, tsch_timing[tsch_ts_cca_offset], "cca");
        TSCH_DEBUG_TX_EVENT();
        tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
        /* CCA */
+        TSCH_LOG_ADD(tsch_log_message,
                    snprintf(log->message, sizeof(log->message),
                        "Delay end, current time offset: %d", (int)(RTIMER_NOW()-current_slot_start));
        );
        RTIMER_BUSYWAIT_UNTIL_ABS(!(cca_status &= NETSTACK_RADIO.channel_clear()),
                           current_slot_start, tsch_timing[tsch_ts_cca_offset] + tsch_timing[tsch_ts_cca]);
+        TSCH_LOG_ADD(tsch_log_message,
                    snprintf(log->message, sizeof(log->message),
                        "CCA end, current time offset: %d", (int)(RTIMER_NOW()-current_slot_start));
        );
        TSCH_DEBUG_TX_EVENT();
        /* there is not enough time to turn radio off */
        /*  NETSTACK_RADIO.off(); */
        if(cca_status == 0) {
          mac_tx_status = MAC_TX_COLLISION;
        } else
#endif /* TSCH_CCA_ENABLED */

Screenshot from 2021-03-22 17-51-16

It seems that RTIMER_BUSYWAIT_UNTIL_ABS() function waits for 1000 ticks instead of 128 for the CCA process. It's wired since this function works well everywhere else.

atiselsts commented 3 years ago

This is because TSCH_SCHEDULE_AND_YIELD() switches the context in Cooja to another mote and puts the current mote in a sort of sleep. Cooja motes are scheduled with the granularity of a millisecond. Therefore, the minimum sleep time is one millisecond, which corresponds to 1000 Cooja mote rtimer clock ticks.

It's possible to change this minimum sleep time in the source code of the Cooja (under cooja/contikimote), but the simulation will become slower.

wonderfulnx commented 3 years ago

Thank you! I finally managed to change the sleep time in cooja/contikimote/interfaces/ContikiClock.java and it works exactly as you say now.

alexrayne commented 3 years ago

Thank you! I finally managed to change the sleep time in cooja/contikimote/interfaces/ContikiClock.java and it works exactly as you say now.

you could inspect #PR1257 - this problem has solves there too