More comments

This commit is contained in:
Manuel Bl 2019-10-12 00:02:31 +02:00
parent a8fd68ca5e
commit 43080636bc
4 changed files with 103 additions and 53 deletions

View File

@ -21,9 +21,15 @@
#include "TTNLogging.h"
#define NUM_RINGBUF_MSG 50
static const char* const TAG = "lmic";
static TTNLogging ttnLog;
/**
* @brief Message structure used in ring buffer
*
* The structure is sent from the LMIC task to the logging task.
*/
struct TTNLogMessage {
const char* message;
uint32_t datum;
@ -43,6 +49,7 @@ struct TTNLogMessage {
u1_t saveIrqFlags;
};
// Constants for formatting LORA values
static const char* const SF_NAMES[] = { "FSK", "SF7", "SF8", "SF9", "SF10", "SF11", "SF12", "SFrfu" };
static const char* const BW_NAMES[] = { "BW125", "BW250", "BW500", "BWrfu" };
static const char* const CR_NAMES[] = { "CR 4/5", "CR 4/6", "CR 4/7", "CR 4/8" };
@ -54,15 +61,17 @@ static void printEvtJoinFailed(TTNLogMessage* log);
static void bin2hex(const uint8_t* bin, unsigned len, char* buf, char sep = 0);
// Create singleton instance
TTNLogging* TTNLogging::initInstance()
{
ttnLog.init();
return &ttnLog;
}
// Initialize logging
void TTNLogging::init()
{
ringBuffer = xRingbufferCreate(50 * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT);
ringBuffer = xRingbufferCreate(NUM_RINGBUF_MSG * sizeof(TTNLogMessage), RINGBUF_TYPE_NOSPLIT);
if (ringBuffer == nullptr) {
ESP_LOGE(TAG, "Failed to create ring buffer");
ASSERT(0);
@ -72,6 +81,7 @@ void TTNLogging::init()
hal_set_failure_handler(logFatal);
}
// Record a logging event for later output
void TTNLogging::logEvent(int event, const char* message, uint32_t datum)
{
if (ringBuffer == nullptr)
@ -100,20 +110,22 @@ void TTNLogging::logEvent(int event, const char* message, uint32_t datum)
xRingbufferSend(ringBuffer, &log, sizeof(log), 0);
}
// record a fatal event (failed assert) for later output
void TTNLogging::logFatal(const char* file, uint16_t line)
{
ttnLog.logEvent(-3, file, line);
}
// Record an informational message for later output
// The message must not be freed.
extern "C" void LMICOS_logEvent(const char *pMessage)
{
ttnLog.logEvent(-1, pMessage, 0);
}
// Record an information message with an integer value for later output
// The message must not be freed.
extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum)
{
ttnLog.logEvent(-2, pMessage, datum);
@ -123,6 +135,7 @@ extern "C" void LMICOS_logEventUint32(const char *pMessage, uint32_t datum)
// ---------------------------------------------------------------------------
// Log output
// Tasks that receiveds the recorded messages, formats and outputs them.
void TTNLogging::loggingTask(void* param)
{
RingbufHandle_t ringBuffer = (RingbufHandle_t)param;
@ -140,6 +153,7 @@ void TTNLogging::loggingTask(void* param)
}
// Format and output a log message
void printMessage(TTNLogMessage* log)
{
switch((int)log->event)
@ -173,6 +187,7 @@ void printMessage(TTNLogMessage* log)
}
// Format and output the detail of a successful network join
void printEvtJoined(TTNLogMessage* log)
{
ESP_LOGI(TAG, "%s: ch=%d", log->message, (unsigned)log->txChnl);
@ -196,6 +211,7 @@ void printEvtJoined(TTNLogMessage* log)
}
// Format and output the detail of a failed network join
void printEvtJoinFailed(TTNLogMessage* log)
{
rps_t rps = log->rps;
@ -215,6 +231,14 @@ void printEvtJoinFailed(TTNLogMessage* log)
static const char* HEX_DIGITS = "0123456789ABCDEF";
/**
* @brief Convert binary data to hexadecimal representation.
*
* @param bin start of binary data
* @param len length of binary data (in bytes)
* @param buf buffer for hexadecimal result
* @param sep separator used between bytes (or 0 for none)
*/
void bin2hex(const uint8_t* bin, unsigned len, char* buf, char sep)
{
int tgt = 0;

View File

@ -20,6 +20,22 @@
#include <freertos/ringbuf.h>
/**
* @brief Logging class.
*
* Logs internal information from LMIC in an asynchrnous fashion in order
* not to distrub the sensitive LORA timing.
*
* A ring buffer and a separate logging task is ued. The LMIC core records
* relevant values from the current LORA settings and writes them to a ring
* buffer. The logging tasks receives the message and the values, formats
* them and outputs them via the regular ESP-IDF logging mechanism.
*
* In order to activate the detailed logging, set the macro
* `LMIC_ENABLE_event_logging` to 1.
*
* This class is not to be used directly.
*/
class TTNLogging {
public:
static TTNLogging* initInstance();

View File

@ -286,7 +286,7 @@ void TTNProvisioning::processLine()
ttn_hal.enterCriticalSection();
LMIC_reset();
ttn_hal.leaveCriticalSection();
onEvent(EV_RESET);
LMIC.client.eventCb(LMIC.client.eventUserData, EV_RESET);
}
uart_write_bytes(UART_NUM, is_ok ? "OK\r\n" : "ERROR\r\n", is_ok ? 4 : 7);

View File

@ -20,36 +20,45 @@
#include "TTNLogging.h"
enum TTNClientAction
/**
* @brief Reason the user code is waiting
*/
enum TTNWaitingReason
{
eActionUnrelated,
eActionJoining,
eActionTransmission
eWaitingNone,
eWaitingForJoin,
eWaitingForTransmission
};
/**
* @brief Event type
*/
enum TTNEvent {
EvtNone,
EvtJoinCompleted,
EvtJoinFailed,
EvtMessageReceived,
EvtTransmissionCompleted,
EvtTransmissionFailed
eEvtNone,
eEvtJoinCompleted,
eEvtJoinFailed,
eEvtMessageReceived,
eEvtTransmissionCompleted,
eEvtTransmissionFailed
};
struct TTNResult {
TTNResult(TTNEvent ev = EvtNone): event(ev) { }
/**
* @brief Event message sent from LMIC task to waiting client task
*/
struct TTNLmicEvent {
TTNLmicEvent(TTNEvent ev = eEvtNone): event(ev) { }
TTNEvent event;
uint8_t port;
const uint8_t *message;
const uint8_t* message;
size_t messageSize;
};
static const char *TAG = "ttn";
static TheThingsNetwork* ttnInstance;
static QueueHandle_t resultQueue;
static TTNClientAction clientAction = eActionUnrelated;
static QueueHandle_t lmicEventQueue = nullptr;
static TTNWaitingReason waitingReason = eWaitingNone;
static TTNProvisioning provisioning;
#if LMIC_ENABLE_event_logging
static TTNLogging* logging;
@ -66,7 +75,6 @@ TheThingsNetwork::TheThingsNetwork()
#if defined(TTN_IS_DISABLED)
ESP_LOGE(TAG, "TTN is disabled. Configure a frequency plan using 'make menuconfig'");
ASSERT(0);
esp_restart();
#endif
ASSERT(ttnInstance == nullptr);
@ -93,8 +101,8 @@ void TheThingsNetwork::configurePins(spi_host_device_t spi_host, uint8_t nss, ui
os_init_ex(nullptr);
reset();
resultQueue = xQueueCreate(4, sizeof(TTNResult));
ASSERT(resultQueue != nullptr);
lmicEventQueue = xQueueCreate(4, sizeof(TTNLmicEvent));
ASSERT(lmicEventQueue != nullptr);
ttn_hal.startBackgroundTask();
}
@ -102,6 +110,11 @@ void TheThingsNetwork::reset()
{
ttn_hal.enterCriticalSection();
LMIC_reset();
waitingReason = eWaitingNone;
if (lmicEventQueue != nullptr)
{
xQueueReset(lmicEventQueue);
}
ttn_hal.leaveCriticalSection();
}
@ -181,26 +194,26 @@ bool TheThingsNetwork::joinCore()
}
ttn_hal.enterCriticalSection();
clientAction = eActionJoining;
waitingReason = eWaitingForJoin;
LMIC_startJoining();
ttn_hal.wakeUp();
ttn_hal.leaveCriticalSection();
TTNResult result;
xQueueReceive(resultQueue, &result, portMAX_DELAY);
return result.event == EvtJoinCompleted;
TTNLmicEvent event;
xQueueReceive(lmicEventQueue, &event, portMAX_DELAY);
return event.event == eEvtJoinCompleted;
}
TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t length, port_t port, bool confirm)
{
ttn_hal.enterCriticalSection();
if (LMIC.opmode & OP_TXRXPEND)
if (waitingReason != eWaitingNone || (LMIC.opmode & OP_TXRXPEND) != 0)
{
ttn_hal.leaveCriticalSection();
return kTTNErrorTransmissionFailed;
}
clientAction = eActionTransmission;
waitingReason = eWaitingForTransmission;
LMIC.client.txMessageCb = messageTransmittedCallback;
LMIC.client.txMessageUserData = nullptr;
LMIC_setTxData2(port, (xref2u1_t)payload, length, confirm);
@ -209,20 +222,20 @@ TTNResponseCode TheThingsNetwork::transmitMessage(const uint8_t *payload, size_t
while (true)
{
TTNResult result;
xQueueReceive(resultQueue, &result, portMAX_DELAY);
TTNLmicEvent result;
xQueueReceive(lmicEventQueue, &result, portMAX_DELAY);
switch (result.event)
{
case EvtMessageReceived:
case eEvtMessageReceived:
if (messageCallback != nullptr)
messageCallback(result.message, result.messageSize, result.port);
break;
case EvtTransmissionCompleted:
case eEvtTransmissionCompleted:
return kTTNSuccessfulTransmission;
case EvtTransmissionFailed:
case eEvtTransmissionFailed:
return kTTNErrorTransmissionFailed;
default:
@ -260,7 +273,7 @@ const char *eventNames[] = { LMIC_EVENT_NAME_TABLE__INIT };
#endif
// Called by LMIC when an LMIC event (join, join failed, reset etc.) occurs
void eventCallback(void* userData, ev_t event)
{
#if LMIC_ENABLE_event_logging
@ -269,45 +282,42 @@ void eventCallback(void* userData, ev_t event)
ESP_LOGI(TAG, "event %s", eventNames[event]);
#endif
if (event == EV_TXCOMPLETE) {
if (LMIC.txrxFlags & TXRX_ACK)
ESP_LOGI(TAG, "ACK received\n");
}
TTNEvent ttnEvent = eEvtNone;
TTNEvent ttnEvent = EvtNone;
if (clientAction == eActionJoining)
if (waitingReason == eWaitingForJoin)
{
if (event == EV_JOINED)
{
ttnEvent = EvtJoinCompleted;
ttnEvent = eEvtJoinCompleted;
}
else if (event == EV_REJOIN_FAILED || event == EV_RESET)
{
ttnEvent = EvtJoinFailed;
ttnEvent = eEvtJoinFailed;
}
}
if (ttnEvent == EvtNone)
if (ttnEvent == eEvtNone)
return;
TTNResult result(ttnEvent);
clientAction = eActionUnrelated;
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
TTNLmicEvent result(ttnEvent);
waitingReason = eWaitingNone;
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS);
}
// Called by LMIC when a message has been received
void messageReceivedCallback(void *userData, uint8_t port, const uint8_t *message, size_t nMessage)
{
TTNResult result(EvtMessageReceived);
TTNLmicEvent result(eEvtMessageReceived);
result.port = port;
result.message = message;
result.messageSize = nMessage;
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS);
}
// Called by LMIC when a message has been transmitted (or the transmission failed)
void messageTransmittedCallback(void *userData, int success)
{
clientAction = eActionUnrelated;
TTNResult result(success ? EvtTransmissionCompleted : EvtTransmissionFailed);
xQueueSend(resultQueue, &result, 100 / portTICK_PERIOD_MS);
waitingReason = eWaitingNone;
TTNLmicEvent result(success ? eEvtTransmissionCompleted : eEvtTransmissionFailed);
xQueueSend(lmicEventQueue, &result, 100 / portTICK_PERIOD_MS);
}