This is an automated email from the ASF dual-hosted git repository. wes3 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push: new ee51a8c Implement low-power support in the LoRa stack (#1670) ee51a8c is described below commit ee51a8cf8d099a2641e971a17776af90c78e6287 Author: amrbekhit <amrbek...@gmail.com> AuthorDate: Tue May 14 07:03:36 2019 +0300 Implement low-power support in the LoRa stack (#1670) * Implement low-power support in the LoRa stack and modify the nRF timer code to use the HFXO manager. Use of timers in the LoRa stack has been split into critical and non-critial timers. Non-critical timers (such as retry delays) are now implemented using the os_cputime functions. The os_cputime needs to be configured to use a lower power time in the BSP (such as is done by the BLE stack via the BLE_LP_CLOCK syscfg). Critical timers are only used to time the opening of the RX windows. These continue to use the hal_timer functions, but require that the user implements two callback functions (lora_low_power_enter and lora_low_power_exit) to turn the LORA_MAC_TIMER off and on. This is necessary as turning a timer on is a hardware-specific operation that may require that the caller pass in a custom configuration struct. This patch also modifies the nRF timer code to use the HFXO manager found in hw/mcu/nordic/nrf52xxx/src/nrf5x_clock.c. This allows multiple different timers to be turned on and off independently and manager will automatically turn the nRF HFXO on and off as required. This is necessary in order for the LoRa and BLE stacks to be able to run side by side. * Correct HFXO manager header files. * Correct calls to to HFXO manager. * Correct HFXO manager header. * Make SX1272 DIO3 IRQ optional. The SX1272 DIO3 IRQ is used during Carrier Detect (CAD). This is neither necessary for LoRa operation, nor used in the current driver. Therefore, by making this pin optional, an extra GPIO/IRQ can be freed for other tasks. * -Fixed a bug when calculating the delays for the TX retry timer (https://github.com/apache/mynewt-core/pull/1670#discussion_r266275964). -Resolved minor formatting issues. * -Reverted the HFXO changes in the hal_system and hal_timer files. These will be added to a separate pull request. * -Modified the low power callbacks so that there is only one rather than two: lora_bsp_enable_mac_timer. This is because the hal_timer functions already allow application code to disable timers in a hardware-agnostic fashion using the hal_timer_deinit function. The LoRa code now turns the timer off itself, but requires the BSP to implement lora_bsp_enable_mac_timer in order to turn the timer on. * -Modified the b-l072z-lrwan1 and telee02 BSPs to implement the lora_bsp_enable_mac_timer function in order to allow CI to pass. --- hw/bsp/b-l072z-lrwan1/src/hal_bsp.c | 19 ++++++++ hw/bsp/telee02/src/hal_bsp.c | 9 ++++ hw/drivers/lora/include/lora/utilities.h | 8 --- hw/drivers/lora/src/utilities.c | 16 ++---- hw/drivers/lora/sx1272/src/sx1272.c | 84 ++++++++++++++++---------------- hw/drivers/lora/sx1276/src/sx1276.c | 74 +++++++++++++--------------- net/lora/node/include/node/lora.h | 1 - net/lora/node/include/node/lora_priv.h | 8 +++ net/lora/node/include/node/utilities.h | 8 --- net/lora/node/src/lora_cli.c | 12 +++++ net/lora/node/src/lora_node.c | 28 ++++++++++- net/lora/node/src/mac/LoRaMac.c | 56 +++++++++++++-------- net/lora/node/src/utilities.c | 6 --- net/lora/node/syscfg.yml | 5 ++ 14 files changed, 196 insertions(+), 138 deletions(-) diff --git a/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c b/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c index a352ae3..46a5281 100644 --- a/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c +++ b/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c @@ -175,3 +175,22 @@ hal_bsp_get_nvic_priority(int irq_num, uint32_t pri) /* Add any interrupt priorities configured by the bsp here */ return pri; } + +#if MYNEWT_VAL(LORA_NODE) +void lora_bsp_enable_mac_timer(void) +{ + /* Turn on the LoRa MAC timer. This function is automatically + * called by the LoRa stack when exiting low power mode.*/ + #if MYNEWT_VAL(LORA_MAC_TIMER_NUM) == 0 + #define TIMER_INIT TIM2 + #elif MYNEWT_VAL(LORA_MAC_TIMER_NUM) == 1 + #define TIMER_INIT TIM3 + #elif MYNEWT_VAL(LORA_MAC_TIMER_NUM) == 2 + #define TIMER_INIT TIM21 + #else + #error "Invalid LORA_MAC_TIMER_NUM" + #endif + + hal_timer_init(MYNEWT_VAL(LORA_MAC_TIMER_NUM), TIMER_INIT); +} +#endif diff --git a/hw/bsp/telee02/src/hal_bsp.c b/hw/bsp/telee02/src/hal_bsp.c index 464d2a4..abaf113 100644 --- a/hw/bsp/telee02/src/hal_bsp.c +++ b/hw/bsp/telee02/src/hal_bsp.c @@ -157,3 +157,12 @@ hal_bsp_init(void) rc = hal_gpio_init_out(SX1276_ANT_HF_CTRL, 1); assert(rc == 0); } + +#if MYNEWT_VAL(LORA_NODE) +void lora_bsp_enable_mac_timer(void) +{ + /* Turn on the LoRa MAC timer. This function is automatically + * called by the LoRa stack when exiting low power mode.*/ + hal_timer_init(MYNEWT_VAL(LORA_MAC_TIMER_NUM), NULL); +} +#endif diff --git a/hw/drivers/lora/include/lora/utilities.h b/hw/drivers/lora/include/lora/utilities.h index fa0b81f..181dcbe 100644 --- a/hw/drivers/lora/include/lora/utilities.h +++ b/hw/drivers/lora/include/lora/utilities.h @@ -40,12 +40,4 @@ uint32_t timer_get_current_time(void); */ uint32_t timer_get_elapsed_time(uint32_t saved_time); -/*! - * \brief Return the Time elapsed since a fix moment in Time - * - * \param [IN] event_in_future fix moment in the future - * \retval time returns difference between now and future event - */ -uint32_t timer_get_future_time(uint32_t event_in_future); - #endif // __LORA_UTILITIES_H__ diff --git a/hw/drivers/lora/src/utilities.c b/hw/drivers/lora/src/utilities.c index e800e6a..810f2e8 100644 --- a/hw/drivers/lora/src/utilities.c +++ b/hw/drivers/lora/src/utilities.c @@ -17,25 +17,19 @@ * under the License. */ -#include <stdlib.h> +#include <stdint.h> -#include "os/mynewt.h" -#include "lora/utilities.h" +#include "os/os.h" uint32_t timer_get_current_time(void) { - return hal_timer_read(MYNEWT_VAL(LORA_MAC_TIMER_NUM)); + /* Convert the OS time ticks to seconds, and then to us*/ + return os_cputime_ticks_to_usecs(os_cputime_get32()); } uint32_t timer_get_elapsed_time(uint32_t saved_time) { - return hal_timer_read(MYNEWT_VAL(LORA_MAC_TIMER_NUM)) - saved_time; -} - -uint32_t -timer_get_future_time(uint32_t event_in_future) -{ - return hal_timer_read(MYNEWT_VAL(LORA_MAC_TIMER_NUM)) + event_in_future; + return timer_get_current_time() - saved_time; } diff --git a/hw/drivers/lora/sx1272/src/sx1272.c b/hw/drivers/lora/sx1272/src/sx1272.c index 64b349a..df7c988 100644 --- a/hw/drivers/lora/sx1272/src/sx1272.c +++ b/hw/drivers/lora/sx1272/src/sx1272.c @@ -16,21 +16,15 @@ Maintainer: Miguel Luis and Gregory Cristian #include <string.h> #include <stdlib.h> #include "os/mynewt.h" +#include "os/os.h" #include "hal/hal_gpio.h" #include "hal/hal_spi.h" -#include "hal/hal_timer.h" #include "bsp/bsp.h" #include "radio/radio.h" #include "sx1272.h" #include "sx1272-board.h" #include "lora/utilities.h" -#if MYNEWT_VAL(LORA_MAC_TIMER_NUM) == -1 -#error "Must define a Lora MAC timer number" -#else -#define SX1272_TIMER_NUM MYNEWT_VAL(LORA_MAC_TIMER_NUM) -#endif - /* XXX: dummy for now to read sx1272 */ #if MYNEWT_VAL(BSP_USE_HAL_SPI) void bsp_spi_read_buf(uint8_t addr, uint8_t *buf, uint8_t size); @@ -214,7 +208,11 @@ DioIrqHandler *DioIrq[] = { SX1272OnDio0Irq, SX1272OnDio1Irq, SX1272OnDio2Irq, +#if (SX1272_DIO3 >= 0) SX1272OnDio3Irq, +#else + NULL, +#endif #if (SX1272_DIO4 >= 0) SX1272OnDio4Irq, #else @@ -265,9 +263,9 @@ SX1272Init(RadioEvents_t *events) RadioEvents = events; // Initialize driver timeout timers - hal_timer_set_cb(SX1272_TIMER_NUM, &TxTimeoutTimer, SX1272OnTimeoutIrq, NULL); - hal_timer_set_cb(SX1272_TIMER_NUM, &RxTimeoutTimer, SX1272OnTimeoutIrq, NULL); - hal_timer_set_cb(SX1272_TIMER_NUM, &RxTimeoutSyncWord, SX1272OnTimeoutIrq, NULL); + os_cputime_timer_init(&TxTimeoutTimer, SX1272OnTimeoutIrq, NULL); + os_cputime_timer_init(&RxTimeoutTimer, SX1272OnTimeoutIrq, NULL); + os_cputime_timer_init(&RxTimeoutSyncWord, SX1272OnTimeoutIrq, NULL); SX1272IoInit(); SX1272IoIrqInit(DioIrq); @@ -315,7 +313,7 @@ SX1272IsChannelFree(RadioModems_t modem, uint32_t freq, int16_t rssiThresh, SX1272SetOpMode(RF_OPMODE_RECEIVER); /* Delay for 1 msec */ - hal_timer_delay(SX1272_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); carrierSenseTime = timer_get_current_time( ); @@ -357,7 +355,7 @@ SX1272Random(void) SX1272SetOpMode(RF_OPMODE_RECEIVER); for (i = 0; i < 32; i++) { - hal_timer_delay(SX1272_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); // Unfiltered RSSI value reading. Only takes the LSB value rnd |= ((uint32_t)SX1272Read(REG_LR_RSSIWIDEBAND) & 0x01) << i; } @@ -729,7 +727,7 @@ SX1272Send(uint8_t *buffer, uint8_t size) // FIFO operations can not take place in Sleep mode if ((SX1272Read(REG_OPMODE) & ~RF_OPMODE_MASK) == RF_OPMODE_SLEEP) { SX1272SetStby(); - hal_timer_delay(SX1272_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); } // Write payload buffer @@ -747,8 +745,8 @@ SX1272Send(uint8_t *buffer, uint8_t size) void SX1272SetSleep(void) { - hal_timer_stop(&RxTimeoutTimer); - hal_timer_stop(&TxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&TxTimeoutTimer); SX1272SetOpMode(RF_OPMODE_SLEEP); SX1272.Settings.State = RF_IDLE; @@ -757,8 +755,8 @@ SX1272SetSleep(void) void SX1272SetStby(void) { - hal_timer_stop(&RxTimeoutTimer); - hal_timer_stop(&TxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&TxTimeoutTimer); SX1272SetOpMode(RF_OPMODE_STANDBY); SX1272.Settings.State = RF_IDLE; @@ -845,16 +843,16 @@ SX1272SetRx(uint32_t timeout) SX1272.Settings.State = RF_RX_RUNNING; if (timeout != 0) { - hal_timer_stop(&RxTimeoutTimer); - hal_timer_start(&RxTimeoutTimer, timeout * 1000); + os_cputime_timer_stop(&RxTimeoutTimer); + os_cputime_timer_relative(&RxTimeoutTimer, timeout * 1000); } if (SX1272.Settings.Modem == MODEM_FSK) { SX1272SetOpMode(RF_OPMODE_RECEIVER); if (rxcontinuous == false) { - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, SX1272.Settings.Fsk.RxSingleTimeout * 1000); } @@ -917,8 +915,8 @@ SX1272SetTx(uint32_t timeout) } SX1272.Settings.State = RF_TX_RUNNING; - hal_timer_stop(&TxTimeoutTimer); - hal_timer_start(&TxTimeoutTimer, timeout * 1000); + os_cputime_timer_stop(&TxTimeoutTimer); + os_cputime_timer_relative(&TxTimeoutTimer, timeout * 1000); SX1272SetOpMode(RF_OPMODE_TRANSMITTER); } @@ -964,10 +962,10 @@ SX1272SetTxContinuousWave(uint32_t freq, int8_t power, uint16_t time) SX1272Write(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 | RF_DIOMAPPING1_DIO1_11); SX1272Write(REG_DIOMAPPING2, RF_DIOMAPPING2_DIO4_10 | RF_DIOMAPPING2_DIO5_10); - hal_timer_stop(&TxTimeoutTimer); + os_cputime_timer_stop(&TxTimeoutTimer); SX1272.Settings.State = RF_TX_RUNNING; - hal_timer_start(&TxTimeoutTimer, timeout * 1000); + os_cputime_timer_relative(&TxTimeoutTimer, timeout * 1000); SX1272SetOpMode(RF_OPMODE_TRANSMITTER); } @@ -1005,9 +1003,9 @@ SX1272Reset(void) { hal_gpio_init_out(SX1272_NRESET, 1); - hal_timer_delay(SX1272_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); hal_gpio_init_in(SX1272_NRESET, HAL_GPIO_PULL_NONE); - hal_timer_delay(SX1272_TIMER_NUM, 6000); + os_cputime_delay_usecs(6000); } void @@ -1176,12 +1174,12 @@ SX1272OnTimeoutIrq(void *unused) { // Continuous mode restart Rx chain SX1272Write(REG_RXCONFIG, SX1272Read(REG_RXCONFIG) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, SX1272.Settings.Fsk.RxSingleTimeout * 1000); } else { SX1272.Settings.State = RF_IDLE; - hal_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_stop(&RxTimeoutSyncWord); } } @@ -1246,16 +1244,16 @@ SX1272OnDio0Irq(void *unused) RF_IRQFLAGS1_SYNCADDRESSMATCH); SX1272Write(REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN); - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); if (SX1272.Settings.Fsk.RxContinuous == false) { - hal_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_stop(&RxTimeoutSyncWord); SX1272.Settings.State = RF_IDLE; } else { // Continuous mode restart Rx chain SX1272Write(REG_RXCONFIG, SX1272Read(REG_RXCONFIG) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, SX1272.Settings.Fsk.RxSingleTimeout * 1000); } @@ -1284,16 +1282,16 @@ SX1272OnDio0Irq(void *unused) SX1272.Settings.FskPacketHandler.NbBytes += (SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes); } - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); if (SX1272.Settings.Fsk.RxContinuous == false) { SX1272.Settings.State = RF_IDLE; - hal_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_stop(&RxTimeoutSyncWord); } else { // Continuous mode restart Rx chain SX1272Write(REG_RXCONFIG, SX1272Read(REG_RXCONFIG) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, SX1272.Settings.Fsk.RxSingleTimeout * 1000); } @@ -1317,7 +1315,7 @@ SX1272OnDio0Irq(void *unused) if (SX1272.Settings.LoRa.RxContinuous == false) { SX1272.Settings.State = RF_IDLE; } - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); if ((RadioEvents != NULL) && (RadioEvents->RxError != NULL)) { RadioEvents->RxError(); @@ -1351,7 +1349,7 @@ SX1272OnDio0Irq(void *unused) if (SX1272.Settings.LoRa.RxContinuous == false) { SX1272.Settings.State = RF_IDLE; } - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); if ((RadioEvents != NULL) && (RadioEvents->RxDone != NULL)) { RadioEvents->RxDone(g_rxtx_buffer, @@ -1365,7 +1363,7 @@ SX1272OnDio0Irq(void *unused) } break; case RF_TX_RUNNING: - hal_timer_stop(&TxTimeoutTimer); + os_cputime_timer_stop(&TxTimeoutTimer); // TxDone interrupt switch (SX1272.Settings.Modem) { case MODEM_LORA: @@ -1414,7 +1412,7 @@ SX1272OnDio1Irq(void *unused) break; case MODEM_LORA: // Sync time out - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); // Clear Irq SX1272Write(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXTIMEOUT); @@ -1461,7 +1459,7 @@ SX1272OnDio2Irq(void *unused) case MODEM_FSK: if ((SX1272.Settings.FskPacketHandler.PreambleDetected == true) && (SX1272.Settings.FskPacketHandler.SyncWordDetected == false)) { - hal_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_stop(&RxTimeoutSyncWord); SX1272.Settings.FskPacketHandler.SyncWordDetected = true; diff --git a/hw/drivers/lora/sx1276/src/sx1276.c b/hw/drivers/lora/sx1276/src/sx1276.c index 107edb9..de59b03 100644 --- a/hw/drivers/lora/sx1276/src/sx1276.c +++ b/hw/drivers/lora/sx1276/src/sx1276.c @@ -16,21 +16,15 @@ Maintainer: Miguel Luis, Gregory Cristian and Wael Guibene #include <math.h> #include <string.h> #include "os/mynewt.h" +#include "os/os.h" #include "hal/hal_gpio.h" #include "hal/hal_spi.h" -#include "hal/hal_timer.h" #include "bsp/bsp.h" #include "radio/radio.h" #include "sx1276.h" #include "sx1276-board.h" #include "lora/utilities.h" -#if MYNEWT_VAL(LORA_MAC_TIMER_NUM) == -1 -#error "Must define a Lora MAC timer number" -#else -#define SX1276_TIMER_NUM MYNEWT_VAL(LORA_MAC_TIMER_NUM) -#endif - /* * Local types definition */ @@ -299,9 +293,9 @@ SX1276Init(RadioEvents_t *events) RadioEvents = events; // Initialize driver timeout timers. NOTE: assumes timer configured. - hal_timer_set_cb(SX1276_TIMER_NUM, &TxTimeoutTimer, SX1276OnTimeoutIrq, NULL); - hal_timer_set_cb(SX1276_TIMER_NUM, &RxTimeoutTimer, SX1276OnTimeoutIrq, NULL); - hal_timer_set_cb(SX1276_TIMER_NUM, &RxTimeoutSyncWord, SX1276OnTimeoutIrq, NULL); + os_cputime_timer_init(&TxTimeoutTimer, SX1276OnTimeoutIrq, NULL); + os_cputime_timer_init(&RxTimeoutTimer, SX1276OnTimeoutIrq, NULL); + os_cputime_timer_init(&RxTimeoutSyncWord, SX1276OnTimeoutIrq, NULL); SX1276IoInit(); SX1276IoIrqInit(DioIrq); @@ -353,7 +347,7 @@ SX1276IsChannelFree(RadioModems_t modem, uint32_t freq, int16_t rssiThresh, SX1276SetOpMode(RF_OPMODE_RECEIVER); /* Delay for 1 msec */ - hal_timer_delay(SX1276_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); carrierSenseTime = timer_get_current_time(); @@ -395,7 +389,7 @@ SX1276Random(void) SX1276SetOpMode(RF_OPMODE_RECEIVER); for (i = 0; i < 32; i++) { - hal_timer_delay(SX1276_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); // Unfiltered RSSI value reading. Only takes the LSB value rnd |= ((uint32_t)SX1276Read(REG_LR_RSSIWIDEBAND) & 0x01) << i; } @@ -899,7 +893,7 @@ SX1276Send(uint8_t *buffer, uint8_t size) // FIFO operations can not take place in Sleep mode if ((SX1276Read(REG_OPMODE) & ~RF_OPMODE_MASK) == RF_OPMODE_SLEEP) { SX1276SetStby(); - hal_timer_delay(SX1276_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); } // Write payload buffer SX1276WriteFifo(buffer, size); @@ -913,8 +907,8 @@ SX1276Send(uint8_t *buffer, uint8_t size) void SX1276SetSleep(void) { - hal_timer_stop(&RxTimeoutTimer); - hal_timer_stop(&TxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&TxTimeoutTimer); SX1276SetOpMode(RF_OPMODE_SLEEP); SX1276.Settings.State = RF_IDLE; @@ -923,8 +917,8 @@ SX1276SetSleep(void) void SX1276SetStby(void) { - hal_timer_stop(&RxTimeoutTimer); - hal_timer_stop(&TxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&TxTimeoutTimer); SX1276SetOpMode(RF_OPMODE_STANDBY); SX1276.Settings.State = RF_IDLE; @@ -1054,8 +1048,8 @@ SX1276SetRx(uint32_t timeout) SX1276.Settings.State = RF_RX_RUNNING; if (timeout != 0) { - hal_timer_stop(&RxTimeoutTimer); - hal_timer_start(&RxTimeoutTimer, timeout * 1000); + os_cputime_timer_stop(&RxTimeoutTimer); + os_cputime_timer_relative(&RxTimeoutTimer, timeout * 1000); } if (SX1276.Settings.Modem == MODEM_FSK) { @@ -1067,8 +1061,8 @@ SX1276SetRx(uint32_t timeout) ((SX1276Read(REG_SYNCCONFIG) & ~RF_SYNCCONFIG_SYNCSIZE_MASK) + 1.0) + 10.0) / (double)SX1276.Settings.Fsk.Datarate) * 1e3) + 4; - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, rx_timeout_sync_delay * 1000); + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, rx_timeout_sync_delay * 1000); } } else { if (rxcontinuous == true) { @@ -1130,8 +1124,8 @@ SX1276SetTx(uint32_t timeout) } SX1276.Settings.State = RF_TX_RUNNING; - hal_timer_stop(&TxTimeoutTimer); - hal_timer_start(&TxTimeoutTimer, timeout * 1000); + os_cputime_timer_stop(&TxTimeoutTimer); + os_cputime_timer_relative(&TxTimeoutTimer, timeout * 1000); SX1276SetOpMode(RF_OPMODE_TRANSMITTER); } @@ -1193,13 +1187,13 @@ SX1276Reset(void) hal_gpio_init_out(SX1276_NRESET, 0); // Wait 1 ms - hal_timer_delay(SX1276_TIMER_NUM, 1000); + os_cputime_delay_usecs(1000); // Configure RESET as input hal_gpio_init_in(SX1276_NRESET, HAL_GPIO_PULL_NONE); // Wait 6 ms - hal_timer_delay(SX1276_TIMER_NUM, 6000); + os_cputime_delay_usecs(6000); } void @@ -1362,11 +1356,11 @@ SX1276OnTimeoutIrq(void *unused) // Continuous mode restart Rx chain SX1276Write(REG_RXCONFIG, SX1276Read(REG_RXCONFIG) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); assert(rx_timeout_sync_delay != (uint32_t)-1); - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, rx_timeout_sync_delay*1000); + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, rx_timeout_sync_delay*1000); } else { SX1276.Settings.State = RF_IDLE; - hal_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_stop(&RxTimeoutSyncWord); } } SX1276RxTimeout(); @@ -1402,17 +1396,17 @@ SX1276OnDio0Irq(void *unused) RF_IRQFLAGS1_SYNCADDRESSMATCH); SX1276Write(REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN); - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); if (SX1276.Settings.Fsk.RxContinuous == false) { - hal_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_stop(&RxTimeoutSyncWord); SX1276.Settings.State = RF_IDLE; } else { // Continuous mode restart Rx chain SX1276Write(REG_RXCONFIG, SX1276Read(REG_RXCONFIG) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); assert(rx_timeout_sync_delay != (uint32_t)-1); - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, rx_timeout_sync_delay*1000); + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, rx_timeout_sync_delay*1000); } SX1276RxError(); @@ -1441,15 +1435,15 @@ SX1276OnDio0Irq(void *unused) if (SX1276.Settings.Fsk.RxContinuous == false) { SX1276.Settings.State = RF_IDLE; assert(rx_timeout_sync_delay != (uint32_t)-1); - hal_timer_stop(&RxTimeoutSyncWord); - hal_timer_start(&RxTimeoutSyncWord, rx_timeout_sync_delay*1000); + os_cputime_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_relative(&RxTimeoutSyncWord, rx_timeout_sync_delay*1000); } else { // Continuous mode restart Rx chain SX1276Write(REG_RXCONFIG, SX1276Read(REG_RXCONFIG) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); } - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); SX1276RxDone(RxTxBuffer, SX1276.Settings.FskPacketHandler.Size, SX1276.Settings.FskPacketHandler.RssiValue, 0); SX1276.Settings.FskPacketHandler.PreambleDetected = false; @@ -1469,7 +1463,7 @@ SX1276OnDio0Irq(void *unused) if (SX1276.Settings.LoRa.RxContinuous == false) { SX1276.Settings.State = RF_IDLE; } - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); SX1276RxError(); break; @@ -1512,7 +1506,7 @@ SX1276OnDio0Irq(void *unused) if (SX1276.Settings.LoRa.RxContinuous == false) { SX1276.Settings.State = RF_IDLE; } - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); SX1276RxDone(RxTxBuffer, SX1276.Settings.LoRaPacketHandler.Size, SX1276.Settings.LoRaPacketHandler.RssiValue, SX1276.Settings.LoRaPacketHandler.SnrValue); break; @@ -1521,7 +1515,7 @@ SX1276OnDio0Irq(void *unused) } break; case RF_TX_RUNNING: - hal_timer_stop(&TxTimeoutTimer); + os_cputime_timer_stop(&TxTimeoutTimer); // TxDone interrupt switch (SX1276.Settings.Modem) { case MODEM_LORA: @@ -1567,7 +1561,7 @@ SX1276OnDio1Irq(void *unused) break; case MODEM_LORA: // Sync time out - hal_timer_stop(&RxTimeoutTimer); + os_cputime_timer_stop(&RxTimeoutTimer); SX1276Write(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXTIMEOUT); SX1276.Settings.State = RF_IDLE; SX1276RxTimeout(); @@ -1609,7 +1603,7 @@ SX1276OnDio2Irq(void *unused) case MODEM_FSK: if ((SX1276.Settings.FskPacketHandler.PreambleDetected == true) && (SX1276.Settings.FskPacketHandler.SyncWordDetected == false)) { - hal_timer_stop(&RxTimeoutSyncWord); + os_cputime_timer_stop(&RxTimeoutSyncWord); SX1276.Settings.FskPacketHandler.SyncWordDetected = true; diff --git a/net/lora/node/include/node/lora.h b/net/lora/node/include/node/lora.h index f12f8c3..8c0a5b8 100644 --- a/net/lora/node/include/node/lora.h +++ b/net/lora/node/include/node/lora.h @@ -301,7 +301,6 @@ int lora_app_link_check(void); */ int lora_node_link_qual(int16_t *rssi, int16_t *snr); - /* * Maximum payload that can be sent in the next frame. */ diff --git a/net/lora/node/include/node/lora_priv.h b/net/lora/node/include/node/lora_priv.h index d817123..f755923 100644 --- a/net/lora/node/include/node/lora_priv.h +++ b/net/lora/node/include/node/lora_priv.h @@ -263,9 +263,17 @@ extern uint16_t g_lnd_log_index; #define LORA_NODE_LOG_RX_ADR_REQ (80) #define LORA_NODE_LOG_PROC_MAC_CMD (85) #define LORA_NODE_LOG_LINK_CHK (90) +#define LORA_NODE_LOG_LP_ENTER (95) +#define LORA_NODE_LOG_LP_EXIT (96) +#define LORA_NODE_LOG_RX_WIN2_TIMEOUT (97) +#define LORA_NODE_LOG_RX_WIN2_CANCEL (98) #else #define lora_node_log(a,b,c,d) #endif +void lora_enter_low_power(void); +void lora_exit_low_power(void); +void lora_config_peripherals(void); + #endif diff --git a/net/lora/node/include/node/utilities.h b/net/lora/node/include/node/utilities.h index 66bb2a8..cb26797 100644 --- a/net/lora/node/include/node/utilities.h +++ b/net/lora/node/include/node/utilities.h @@ -137,12 +137,4 @@ TimerTime_t TimerGetCurrentTime( void ); */ TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ); -/*! - * \brief Return the Time elapsed since a fix moment in Time - * - * \param [IN] eventInFuture fix moment in the future - * \retval time returns difference between now and future event - */ -TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture ); - #endif // __UTILITIES_H__ diff --git a/net/lora/node/src/lora_cli.c b/net/lora/node/src/lora_cli.c index 75d2a31..27d6fcb 100644 --- a/net/lora/node/src/lora_cli.c +++ b/net/lora/node/src/lora_cli.c @@ -676,6 +676,18 @@ lora_cli_log_cmd(int argc, char **argv) case LORA_NODE_LOG_LINK_CHK: console_printf("LINK_CHK status=%lu", g_lnd_log[i].lnd_p32); break; + case LORA_NODE_LOG_LP_ENTER: + console_printf("LOW POWER ENTER"); + break; + case LORA_NODE_LOG_LP_EXIT: + console_printf("LOW POWER EXIT"); + break; + case LORA_NODE_LOG_RX_WIN2_TIMEOUT: + console_printf("RX_WIN2 TIMEOUT"); + break; + case LORA_NODE_LOG_RX_WIN2_CANCEL: + console_printf("RX_WIN2 CANCEL"); + break; default: console_printf("id=%u p8=%u p16=%u p32=%lu", g_lnd_log[i].lnd_id, g_lnd_log[i].lnd_p8, diff --git a/net/lora/node/src/lora_node.c b/net/lora/node/src/lora_node.c index d8a964b..5796356 100644 --- a/net/lora/node/src/lora_node.c +++ b/net/lora/node/src/lora_node.c @@ -19,6 +19,7 @@ #include <string.h> #include "os/mynewt.h" +#include "node/lora.h" #include "node/lora_priv.h" #include "node/lora_band.h" @@ -88,6 +89,9 @@ struct lm_join_ev_arg_obj g_lm_join_ev_arg; struct lora_node_debug_log_entry g_lnd_log[LORA_NODE_DEBUG_LOG_ENTRIES]; uint16_t g_lnd_log_index; +/* Low power callback functions */ +extern void lora_bsp_enable_mac_timer(void); + void lora_node_log(uint8_t logid, uint8_t p8, uint16_t p16, uint32_t p32) { @@ -98,8 +102,7 @@ lora_node_log(uint8_t logid, uint8_t p8, uint16_t p16, uint32_t p32) g_lnd_log[g_lnd_log_index].lnd_p8 = p8; g_lnd_log[g_lnd_log_index].lnd_p16 = p16; g_lnd_log[g_lnd_log_index].lnd_p32 = p32; - g_lnd_log[g_lnd_log_index].lnd_cputime = - hal_timer_read(MYNEWT_VAL(LORA_MAC_TIMER_NUM)); + g_lnd_log[g_lnd_log_index].lnd_cputime = TimerGetCurrentTime(); ++g_lnd_log_index; if (g_lnd_log_index == LORA_NODE_DEBUG_LOG_ENTRIES) { @@ -679,3 +682,24 @@ lora_node_init(void) assert(lms == LORAMAC_STATUS_OK); #endif } + +static bool low_power_active = true; + +void lora_enter_low_power(void) +{ + if (!low_power_active) { + low_power_active = true; + hal_timer_deinit(MYNEWT_VAL(LORA_MAC_TIMER_NUM)); + lora_node_log(LORA_NODE_LOG_LP_ENTER, 0, 0, 0); + } +} + +void lora_exit_low_power(void) +{ + if (low_power_active) { + low_power_active = false; + lora_bsp_enable_mac_timer(); + lora_node_log(LORA_NODE_LOG_LP_EXIT, 0, 0, 0); + lora_config_peripherals(); + } +} diff --git a/net/lora/node/src/mac/LoRaMac.c b/net/lora/node/src/mac/LoRaMac.c index b254eb0..41e5abf 100644 --- a/net/lora/node/src/mac/LoRaMac.c +++ b/net/lora/node/src/mac/LoRaMac.c @@ -32,6 +32,7 @@ #include <string.h> #include <assert.h> #include "os/mynewt.h" +#include "os/os.h" #include "node/lora.h" #include "node/utilities.h" #include "node/mac/LoRaMacCrypto.h" @@ -39,6 +40,7 @@ #include "node/mac/LoRaMacTest.h" #include "hal/hal_timer.h" #include "node/lora_priv.h" +#include "lora/utilities.h" #if MYNEWT_VAL(LORA_MAC_TIMER_NUM) == -1 #error "Must define a Lora MAC timer number" @@ -253,7 +255,7 @@ lora_mac_rx_disable(void) static void lora_mac_rtx_timer_stop(void) { - hal_timer_stop(&g_lora_mac_data.rtx_timer); + os_cputime_timer_stop(&g_lora_mac_data.rtx_timer); os_eventq_remove(lora_node_mac_evq_get(), &g_lora_mac_rtx_timeout_event); } @@ -268,7 +270,9 @@ lora_mac_rx_win2_stop(void) { if (LoRaMacDeviceClass == CLASS_A) { hal_timer_stop(&RxWindowTimer2); + lora_enter_low_power(); os_eventq_remove(lora_node_mac_evq_get(), &g_lora_mac_rx_win2_event); + lora_node_log(LORA_NODE_LOG_RX_WIN2_CANCEL, 0, 0, 0); } } @@ -721,9 +725,9 @@ lora_mac_join_req_tx_fail(void) this but probably should be modified */ /* Add some transmit delay between join request transmissions */ LoRaMacState |= LORAMAC_TX_DELAYED; - hal_timer_stop(&TxDelayedTimer); - hal_timer_start(&TxDelayedTimer, - randr(0, MYNEWT_VAL(LORA_JOIN_REQ_RAND_DELAY) * 1000)); + os_cputime_timer_stop(&TxDelayedTimer); + os_cputime_timer_relative(&TxDelayedTimer, + randr(0, MYNEWT_VAL(LORA_JOIN_REQ_RAND_DELAY * 1000))); } } @@ -803,15 +807,16 @@ lora_mac_process_radio_tx(struct os_event *ev) PhyParam_t phyParam; SetBandTxDoneParams_t txDone; - /* XXX: We need to time this more accurately */ - uint32_t curTime = hal_timer_read(LORA_MAC_TIMER_NUM); - + lora_exit_low_power(); if (LoRaMacDeviceClass != CLASS_C) { Radio.Sleep( ); } else { lora_mac_rx_on_window2(); } + /* XXX: We need to time this more accurately */ + uint32_t curTime = hal_timer_read(LORA_MAC_TIMER_NUM); + /* Always start receive window 1 */ hal_timer_start_at(&RxWindowTimer1, curTime + (g_lora_mac_data.rx_win1_delay * 1000)); @@ -833,7 +838,8 @@ lora_mac_process_radio_tx(struct os_event *ev) if (LM_F_NODE_ACK_REQ()) { getPhy.Attribute = PHY_ACK_TIMEOUT; phyParam = RegionGetPhyParam(LoRaMacRegion, &getPhy); - hal_timer_start_at(&g_lora_mac_data.rtx_timer, curTime + + os_cputime_timer_stop(&g_lora_mac_data.rtx_timer); + os_cputime_timer_relative(&g_lora_mac_data.rtx_timer, ((g_lora_mac_data.rx_win2_delay + phyParam.Value) * 1000)); } else { /* @@ -853,7 +859,8 @@ lora_mac_process_radio_tx(struct os_event *ev) timeout += (uint32_t)((RxWindow2Config.tsymbol * 1000) * RxWindow2Config.WindowTimeout); } - hal_timer_start_at(&g_lora_mac_data.rtx_timer, curTime + timeout); + os_cputime_timer_stop(&g_lora_mac_data.rtx_timer); + os_cputime_timer_relative(&g_lora_mac_data.rtx_timer, timeout); } } @@ -863,11 +870,11 @@ lora_mac_process_radio_tx(struct os_event *ev) // Update last tx done time for the current channel txDone.Channel = g_lora_mac_data.cur_chan; txDone.Joined = LM_F_IS_JOINED(); - txDone.LastTxDoneTime = curTime; + txDone.LastTxDoneTime = timer_get_current_time(); RegionSetBandTxDone(LoRaMacRegion, &txDone); // Update Aggregated last tx done time - g_lora_mac_data.aggr_last_tx_done_time = curTime; + g_lora_mac_data.aggr_last_tx_done_time = txDone.LastTxDoneTime; if (!LM_F_NODE_ACK_REQ()) { g_lora_mac_data.nb_rep_cntr++; @@ -1501,6 +1508,9 @@ lora_mac_rx_on_window2(void) static void lora_mac_process_rx_win2_timeout(struct os_event *ev) { + /* Turn off the high resolution timer */ + lora_enter_low_power(); + lora_node_log(LORA_NODE_LOG_RX_WIN2_TIMEOUT, 0, 0, 0); /* * There are two cases here. Either the radio is still receiving in which * case the radio status is not idle, or the radio finished receiving @@ -1973,8 +1983,8 @@ ScheduleTx(void) // Send later - prepare timer LoRaMacState |= LORAMAC_TX_DELAYED; - hal_timer_stop(&TxDelayedTimer); - hal_timer_start(&TxDelayedTimer, duty_cycle_time_off); + os_cputime_timer_stop(&TxDelayedTimer); + os_cputime_timer_relative(&TxDelayedTimer, duty_cycle_time_off); lora_node_log(LORA_NODE_LOG_TX_DELAY, g_lora_mac_data.max_dc, 0, duty_cycle_time_off); @@ -2494,16 +2504,17 @@ LoRaMacInitialization(LoRaMacCallback_t *callbacks, LoRaMacRegion_t region) ResetMacParameters( ); - /* XXX: determine which of these should be os callouts */ - hal_timer_config(LORA_MAC_TIMER_NUM, LORA_MAC_TIMER_FREQ); - hal_timer_set_cb(LORA_MAC_TIMER_NUM, &TxDelayedTimer, OnTxDelayedTimerEvent, - NULL); + /* TxDelayedTimer and RTX timers are configured to use the CPU timer, which should be configured + as a low power timer. The accuracy of these timers is not critical. */ + os_cputime_timer_init(&TxDelayedTimer, OnTxDelayedTimerEvent, NULL); + os_cputime_timer_init(&g_lora_mac_data.rtx_timer, lora_mac_rtx_timer_cb, NULL); + + /* The RX Window timers are configured to use the high resolution LORA_MAC_TIMER, + as their accuracy is critical. */ hal_timer_set_cb(LORA_MAC_TIMER_NUM, &RxWindowTimer1, OnRxWindow1TimerEvent, NULL); hal_timer_set_cb(LORA_MAC_TIMER_NUM, &RxWindowTimer2, OnRxWindow2TimerEvent, NULL); - hal_timer_set_cb(LORA_MAC_TIMER_NUM, &g_lora_mac_data.rtx_timer, - lora_mac_rtx_timer_cb, NULL); /* Init MAC radio events */ g_lora_mac_radio_tx_timeout_event.ev_cb = lora_mac_process_radio_tx_timeout; @@ -3289,3 +3300,10 @@ lora_mac_extract_mac_cmds(uint8_t max_cmd_bytes, uint8_t *buf) return bytes_added; } + +/* Reconfigure peripherals after exiting low power mode */ +void +lora_config_peripherals(void) +{ + hal_timer_config(LORA_MAC_TIMER_NUM, LORA_MAC_TIMER_FREQ); +} diff --git a/net/lora/node/src/utilities.c b/net/lora/node/src/utilities.c index 793d260..335cb06 100644 --- a/net/lora/node/src/utilities.c +++ b/net/lora/node/src/utilities.c @@ -40,9 +40,3 @@ TimerGetElapsedTime(TimerTime_t savedTime) { return timer_get_elapsed_time(savedTime); } - -TimerTime_t -TimerGetFutureTime(TimerTime_t eventInFuture) -{ - return timer_get_future_time(eventInFuture); -} diff --git a/net/lora/node/syscfg.yml b/net/lora/node/syscfg.yml index 28305b9..0841b51 100644 --- a/net/lora/node/syscfg.yml +++ b/net/lora/node/syscfg.yml @@ -93,6 +93,11 @@ syscfg.defs: the network is public; private otherwise value: 0 + LORA_LP_CLOCK: + description: > + Used by BSP packages to configure LP clock for the LoRa system. + value: 1 + LORA_NODE_SYSINIT_STAGE: description: > Sysinit stage for the LoRa endpoint.