Task notification instead of queue for LMIC task

This commit is contained in:
Manuel Bl 2019-10-13 20:26:15 +02:00
parent 43080636bc
commit baa6c93d5f
4 changed files with 45 additions and 50 deletions

View File

@ -90,7 +90,7 @@ void TTNProvisioning::startTask()
esp_err_t err = uart_driver_install(UART_NUM, 2048, 2048, 20, &uart_queue, 0); esp_err_t err = uart_driver_install(UART_NUM, 2048, 2048, 20, &uart_queue, 0);
ESP_ERROR_CHECK(err); ESP_ERROR_CHECK(err);
xTaskCreate(ttn_provisioning_task_caller, "provisioning", 2048, this, 1, nullptr); xTaskCreate(ttn_provisioning_task_caller, "ttn_provision", 2048, this, 1, nullptr);
} }
void ttn_provisioning_task_caller(void* pvParameter) void ttn_provisioning_task_caller(void* pvParameter)

View File

@ -13,9 +13,9 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_log.h" #include "esp_log.h"
#include "TheThingsNetwork.h"
#include "hal/hal_esp32.h" #include "hal/hal_esp32.h"
#include "lmic/lmic.h" #include "lmic/lmic.h"
#include "TheThingsNetwork.h"
#include "TTNProvisioning.h" #include "TTNProvisioning.h"
#include "TTNLogging.h" #include "TTNLogging.h"
@ -103,7 +103,7 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui
lmicEventQueue = xQueueCreate(4, sizeof(TTNLmicEvent)); lmicEventQueue = xQueueCreate(4, sizeof(TTNLmicEvent));
ASSERT(lmicEventQueue != nullptr); ASSERT(lmicEventQueue != nullptr);
ttn_hal.startBackgroundTask(); ttn_hal.startLMICTask();
} }
void TheThingsNetwork::reset() void TheThingsNetwork::reset()
@ -301,7 +301,7 @@ void eventCallback(void* userData, ev_t event)
TTNLmicEvent result(ttnEvent); TTNLmicEvent result(ttnEvent);
waitingReason = eWaitingNone; waitingReason = eWaitingNone;
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS); xQueueSend(lmicEventQueue, &result, pdMS_TO_TICKS(100));
} }
// Called by LMIC when a message has been received // Called by LMIC when a message has been received
@ -311,7 +311,7 @@ void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *messag
result.port = port; result.port = port;
result.message = message; result.message = message;
result.messageSize = nMessage; result.messageSize = nMessage;
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS); xQueueSend(lmicEventQueue, &result, pdMS_TO_TICKS(100));
} }
// Called by LMIC when a message has been transmitted (or the transmission failed) // Called by LMIC when a message has been transmitted (or the transmission failed)
@ -319,5 +319,5 @@ void messageTransmittedCallback(void *userData, int success)
{ {
waitingReason = eWaitingNone; waitingReason = eWaitingNone;
TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed); TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed);
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS); xQueueSend(lmicEventQueue, &result, pdMS_TO_TICKS(100));
} }

View File

@ -22,19 +22,19 @@
#define LMIC_UNUSED_PIN 0xff #define LMIC_UNUSED_PIN 0xff
#define NOTIFY_BIT_DIO 1
#define NOTIFY_BIT_TIMER 2
#define NOTIFY_BIT_WAKEUP 4
static const char* const TAG = "ttn_hal"; static const char* const TAG = "ttn_hal";
HAL_ESP32 ttn_hal; HAL_ESP32 ttn_hal;
TaskHandle_t HAL_ESP32::lmicTask = nullptr;
uint32_t HAL_ESP32::dioInterruptTime = 0;
uint8_t HAL_ESP32::dioNum = 0;
struct HALQueueItem
{
uint32_t osTime;
HAL_Event ev;
HALQueueItem() : osTime(0), ev(DIO0) { }
HALQueueItem(HAL_Event e, int64_t t = 0) : osTime(t), ev(e) { }
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Constructor // Constructor
@ -55,14 +55,19 @@ void HAL_ESP32::configurePins(spi_host_device_t spi_host, uint8_t nss, uint8_t r
pinRst = (gpio_num_t)rst; pinRst = (gpio_num_t)rst;
pinDIO0 = (gpio_num_t)dio0; pinDIO0 = (gpio_num_t)dio0;
pinDIO1 = (gpio_num_t)dio1; pinDIO1 = (gpio_num_t)dio1;
// Until the background process has been started, use the current task
// for supporting calls like `hal_waitUntil()`.
lmicTask = xTaskGetCurrentTaskHandle();
} }
void IRAM_ATTR HAL_ESP32::dioIrqHandler(void *arg) void IRAM_ATTR HAL_ESP32::dioIrqHandler(void *arg)
{ {
dioInterruptTime = hal_ticks();
dioNum = (u1_t)(long)arg;
BaseType_t higherPrioTaskWoken = pdFALSE; BaseType_t higherPrioTaskWoken = pdFALSE;
HALQueueItem item { (HAL_Event)(long)arg, hal_ticks() }; xTaskNotifyFromISR(lmicTask, NOTIFY_BIT_DIO, eSetBits, &higherPrioTaskWoken);
xQueueSendFromISR(ttn_hal.dioQueue, &item, &higherPrioTaskWoken);
if (higherPrioTaskWoken) if (higherPrioTaskWoken)
portYIELD_FROM_ISR(); portYIELD_FROM_ISR();
} }
@ -92,21 +97,14 @@ void HAL_ESP32::ioInit()
gpio_set_direction(pinRst, GPIO_MODE_OUTPUT); gpio_set_direction(pinRst, GPIO_MODE_OUTPUT);
} }
// queue to communicate from interrupts / timer callbacks
// to LMIC core
dioQueue = xQueueCreate(12, sizeof(HALQueueItem));
ASSERT(dioQueue != NULL);
// DIO pins with interrupt handlers // DIO pins with interrupt handlers
gpio_pad_select_gpio(pinDIO0); gpio_pad_select_gpio(pinDIO0);
gpio_set_direction(pinDIO0, GPIO_MODE_INPUT); gpio_set_direction(pinDIO0, GPIO_MODE_INPUT);
gpio_set_intr_type(pinDIO0, GPIO_INTR_POSEDGE); gpio_set_intr_type(pinDIO0, GPIO_INTR_POSEDGE);
gpio_isr_handler_add(pinDIO0, dioIrqHandler, (void *)0);
gpio_pad_select_gpio(pinDIO1); gpio_pad_select_gpio(pinDIO1);
gpio_set_direction(pinDIO1, GPIO_MODE_INPUT); gpio_set_direction(pinDIO1, GPIO_MODE_INPUT);
gpio_set_intr_type(pinDIO1, GPIO_INTR_POSEDGE); gpio_set_intr_type(pinDIO1, GPIO_INTR_POSEDGE);
gpio_isr_handler_add(pinDIO1, dioIrqHandler, (void *)1);
ESP_LOGI(TAG, "IO initialized"); ESP_LOGI(TAG, "IO initialized");
} }
@ -257,7 +255,7 @@ void HAL_ESP32::timerInit()
{ {
esp_timer_create_args_t timerConfig = { esp_timer_create_args_t timerConfig = {
.callback = &timerCallback, .callback = &timerCallback,
.arg = NULL, .arg = nullptr,
.dispatch_method = ESP_TIMER_TASK, .dispatch_method = ESP_TIMER_TASK,
.name = "lmic_job" .name = "lmic_job"
}; };
@ -289,8 +287,7 @@ void HAL_ESP32::disarmTimer()
void HAL_ESP32::timerCallback(void *arg) void HAL_ESP32::timerCallback(void *arg)
{ {
HALQueueItem item { TIMER }; xTaskNotify(lmicTask, NOTIFY_BIT_TIMER, eSetBits);
xQueueSend(ttn_hal.dioQueue, &item, 0);
} }
// Wait for the next external event. Either: // Wait for the next external event. Either:
@ -302,11 +299,11 @@ bool HAL_ESP32::wait(WaitKind waitKind)
TickType_t ticksToWait = waitKind == CHECK_IO ? 0 : portMAX_DELAY; TickType_t ticksToWait = waitKind == CHECK_IO ? 0 : portMAX_DELAY;
while (true) while (true)
{ {
HALQueueItem item; uint32_t bits = ulTaskNotifyTake(pdTRUE, ticksToWait);
if (xQueueReceive(dioQueue, &item, ticksToWait) == pdFALSE) if (bits == 0)
return false; return false;
if (item.ev == WAKEUP) if ((bits & NOTIFY_BIT_WAKEUP) != 0)
{ {
if (waitKind != WAIT_FOR_TIMER) if (waitKind != WAIT_FOR_TIMER)
{ {
@ -314,7 +311,7 @@ bool HAL_ESP32::wait(WaitKind waitKind)
return true; return true;
} }
} }
else if (item.ev == TIMER) else if ((bits & NOTIFY_BIT_TIMER) != 0)
{ {
disarmTimer(); disarmTimer();
setNextAlarm(0); setNextAlarm(0);
@ -326,7 +323,7 @@ bool HAL_ESP32::wait(WaitKind waitKind)
if (waitKind != WAIT_FOR_TIMER) if (waitKind != WAIT_FOR_TIMER)
disarmTimer(); disarmTimer();
enterCriticalSection(); enterCriticalSection();
radio_irq_handler_v2(item.ev, item.osTime); radio_irq_handler_v2(dioNum, dioInterruptTime);
leaveCriticalSection(); leaveCriticalSection();
if (waitKind != WAIT_FOR_TIMER) if (waitKind != WAIT_FOR_TIMER)
return true; return true;
@ -363,8 +360,7 @@ void HAL_ESP32::waitUntil(uint32_t osTime)
// e.g. send a submitted messages. // e.g. send a submitted messages.
void HAL_ESP32::wakeUp() void HAL_ESP32::wakeUp()
{ {
HALQueueItem item { WAKEUP }; xTaskNotify(lmicTask, NOTIFY_BIT_WAKEUP, eSetBits);
xQueueSend(dioQueue, &item, 0);
} }
// Check if the specified time has been reached or almost reached. // Check if the specified time has been reached or almost reached.
@ -441,7 +437,7 @@ void HAL_ESP32::leaveCriticalSection()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void HAL_ESP32::backgroundTask(void* pvParameter) { void HAL_ESP32::lmicBackgroundTask(void* pvParameter) {
os_runloop(); os_runloop();
} }
@ -460,15 +456,19 @@ void HAL_ESP32::init()
timerInit(); timerInit();
} }
void HAL_ESP32::startBackgroundTask() { void HAL_ESP32::startLMICTask() {
xTaskCreate(backgroundTask, "ttn_lora_task", 1024 * 4, NULL, CONFIG_TTN_BG_TASK_PRIO, NULL); xTaskCreate(lmicBackgroundTask, "ttn_lmic", 1024 * 4, nullptr, CONFIG_TTN_BG_TASK_PRIO, &lmicTask);
// enable interrupts
gpio_isr_handler_add(pinDIO0, dioIrqHandler, (void *)0);
gpio_isr_handler_add(pinDIO1, dioIrqHandler, (void *)1);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Fatal failure // Fatal failure
static hal_failure_handler_t* custom_hal_failure_handler = NULL; static hal_failure_handler_t* custom_hal_failure_handler = nullptr;
void hal_set_failure_handler(const hal_failure_handler_t* const handler) void hal_set_failure_handler(const hal_failure_handler_t* const handler)
{ {
@ -477,7 +477,7 @@ void hal_set_failure_handler(const hal_failure_handler_t* const handler)
void hal_failed(const char *file, u2_t line) void hal_failed(const char *file, u2_t line)
{ {
if (custom_hal_failure_handler != NULL) if (custom_hal_failure_handler != nullptr)
(*custom_hal_failure_handler)(file, line); (*custom_hal_failure_handler)(file, line);
ESP_LOGE(TAG, "LMIC failed and stopped: %s:%d", file, line); ESP_LOGE(TAG, "LMIC failed and stopped: %s:%d", file, line);

View File

@ -16,19 +16,11 @@
#include <stdint.h> #include <stdint.h>
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/queue.h> #include <freertos/queue.h>
#include <freertos/task.h>
#include <driver/spi_master.h> #include <driver/spi_master.h>
#include <esp_timer.h> #include <esp_timer.h>
enum HAL_Event {
DIO0 = 0,
DIO1,
DIO2,
TIMER,
WAKEUP
};
enum WaitKind { enum WaitKind {
CHECK_IO, CHECK_IO,
WAIT_FOR_ANY_EVENT, WAIT_FOR_ANY_EVENT,
@ -44,7 +36,7 @@ public:
void configurePins(spi_host_device_t spi_host, uint8_t nss, uint8_t rxtx, uint8_t rst, uint8_t dio0, uint8_t dio1); void configurePins(spi_host_device_t spi_host, uint8_t nss, uint8_t rxtx, uint8_t rst, uint8_t dio0, uint8_t dio1);
void init(); void init();
void startBackgroundTask(); void startLMICTask();
void wakeUp(); void wakeUp();
void initCriticalSection(); void initCriticalSection();
@ -67,7 +59,7 @@ public:
int8_t rssiCal; int8_t rssiCal;
private: private:
static void backgroundTask(void* pvParameter); static void lmicBackgroundTask(void* pvParameter);
static void dioIrqHandler(void* arg); static void dioIrqHandler(void* arg);
static void timerCallback(void *arg); static void timerCallback(void *arg);
static int64_t osTimeToEspTime(int64_t espNow, uint32_t osTime); static int64_t osTimeToEspTime(int64_t espNow, uint32_t osTime);
@ -81,7 +73,10 @@ private:
void disarmTimer(); void disarmTimer();
bool wait(WaitKind waitKind); bool wait(WaitKind waitKind);
QueueHandle_t dioQueue; static TaskHandle_t lmicTask;
static uint32_t dioInterruptTime;
static uint8_t dioNum;
spi_device_handle_t spiHandle; spi_device_handle_t spiHandle;
spi_transaction_t spiTransaction; spi_transaction_t spiTransaction;
SemaphoreHandle_t mutex; SemaphoreHandle_t mutex;