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_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)

View File

@ -13,9 +13,9 @@
#include "freertos/FreeRTOS.h"
#include "esp_event.h"
#include "esp_log.h"
#include "TheThingsNetwork.h"
#include "hal/hal_esp32.h"
#include "lmic/lmic.h"
#include "TheThingsNetwork.h"
#include "TTNProvisioning.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));
ASSERT(lmicEventQueue != nullptr);
ttn_hal.startBackgroundTask();
ttn_hal.startLMICTask();
}
void TheThingsNetwork::reset()
@ -301,7 +301,7 @@ void eventCallback(void* userData, ev_t event)
TTNLmicEvent result(ttnEvent);
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
@ -311,7 +311,7 @@ void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *messag
result.port = port;
result.message = message;
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)
@ -319,5 +319,5 @@ void messageTransmittedCallback(void *userData, int success)
{
waitingReason = eWaitingNone;
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 NOTIFY_BIT_DIO 1
#define NOTIFY_BIT_TIMER 2
#define NOTIFY_BIT_WAKEUP 4
static const char* const TAG = "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
@ -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;
pinDIO0 = (gpio_num_t)dio0;
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)
{
dioInterruptTime = hal_ticks();
dioNum = (u1_t)(long)arg;
BaseType_t higherPrioTaskWoken = pdFALSE;
HALQueueItem item { (HAL_Event)(long)arg, hal_ticks() };
xQueueSendFromISR(ttn_hal.dioQueue, &item, &higherPrioTaskWoken);
xTaskNotifyFromISR(lmicTask, NOTIFY_BIT_DIO, eSetBits, &higherPrioTaskWoken);
if (higherPrioTaskWoken)
portYIELD_FROM_ISR();
}
@ -92,21 +97,14 @@ void HAL_ESP32::ioInit()
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
gpio_pad_select_gpio(pinDIO0);
gpio_set_direction(pinDIO0, GPIO_MODE_INPUT);
gpio_set_intr_type(pinDIO0, GPIO_INTR_POSEDGE);
gpio_isr_handler_add(pinDIO0, dioIrqHandler, (void *)0);
gpio_pad_select_gpio(pinDIO1);
gpio_set_direction(pinDIO1, GPIO_MODE_INPUT);
gpio_set_intr_type(pinDIO1, GPIO_INTR_POSEDGE);
gpio_isr_handler_add(pinDIO1, dioIrqHandler, (void *)1);
ESP_LOGI(TAG, "IO initialized");
}
@ -257,7 +255,7 @@ void HAL_ESP32::timerInit()
{
esp_timer_create_args_t timerConfig = {
.callback = &timerCallback,
.arg = NULL,
.arg = nullptr,
.dispatch_method = ESP_TIMER_TASK,
.name = "lmic_job"
};
@ -289,8 +287,7 @@ void HAL_ESP32::disarmTimer()
void HAL_ESP32::timerCallback(void *arg)
{
HALQueueItem item { TIMER };
xQueueSend(ttn_hal.dioQueue, &item, 0);
xTaskNotify(lmicTask, NOTIFY_BIT_TIMER, eSetBits);
}
// 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;
while (true)
{
HALQueueItem item;
if (xQueueReceive(dioQueue, &item, ticksToWait) == pdFALSE)
uint32_t bits = ulTaskNotifyTake(pdTRUE, ticksToWait);
if (bits == 0)
return false;
if (item.ev == WAKEUP)
if ((bits & NOTIFY_BIT_WAKEUP) != 0)
{
if (waitKind != WAIT_FOR_TIMER)
{
@ -314,7 +311,7 @@ bool HAL_ESP32::wait(WaitKind waitKind)
return true;
}
}
else if (item.ev == TIMER)
else if ((bits & NOTIFY_BIT_TIMER) != 0)
{
disarmTimer();
setNextAlarm(0);
@ -326,7 +323,7 @@ bool HAL_ESP32::wait(WaitKind waitKind)
if (waitKind != WAIT_FOR_TIMER)
disarmTimer();
enterCriticalSection();
radio_irq_handler_v2(item.ev, item.osTime);
radio_irq_handler_v2(dioNum, dioInterruptTime);
leaveCriticalSection();
if (waitKind != WAIT_FOR_TIMER)
return true;
@ -363,8 +360,7 @@ void HAL_ESP32::waitUntil(uint32_t osTime)
// e.g. send a submitted messages.
void HAL_ESP32::wakeUp()
{
HALQueueItem item { WAKEUP };
xQueueSend(dioQueue, &item, 0);
xTaskNotify(lmicTask, NOTIFY_BIT_WAKEUP, eSetBits);
}
// 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();
}
@ -460,15 +456,19 @@ void HAL_ESP32::init()
timerInit();
}
void HAL_ESP32::startBackgroundTask() {
xTaskCreate(backgroundTask, "ttn_lora_task", 1024 * 4, NULL, CONFIG_TTN_BG_TASK_PRIO, NULL);
void HAL_ESP32::startLMICTask() {
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
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)
{
@ -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)
{
if (custom_hal_failure_handler != NULL)
if (custom_hal_failure_handler != nullptr)
(*custom_hal_failure_handler)(file, line);
ESP_LOGE(TAG, "LMIC failed and stopped: %s:%d", file, line);

View File

@ -16,19 +16,11 @@
#include <stdint.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <freertos/task.h>
#include <driver/spi_master.h>
#include <esp_timer.h>
enum HAL_Event {
DIO0 = 0,
DIO1,
DIO2,
TIMER,
WAKEUP
};
enum WaitKind {
CHECK_IO,
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 init();
void startBackgroundTask();
void startLMICTask();
void wakeUp();
void initCriticalSection();
@ -67,7 +59,7 @@ public:
int8_t rssiCal;
private:
static void backgroundTask(void* pvParameter);
static void lmicBackgroundTask(void* pvParameter);
static void dioIrqHandler(void* arg);
static void timerCallback(void *arg);
static int64_t osTimeToEspTime(int64_t espNow, uint32_t osTime);
@ -81,7 +73,10 @@ private:
void disarmTimer();
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_transaction_t spiTransaction;
SemaphoreHandle_t mutex;