1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-17 02:52:12 +01:00

telemetry: stop registering periodic events for non-periodic UAVOs

Telemetry module was iterating over all UAVOs including
meta UAVOs and creating a periodic event item for each
object.  These items cost us about 32 bytes for each list
item.

This is wasteful for two main reasons.  First, meta UAVOs can't
meaningfully have periodic updates so excluding them entirely
makes sense.  That halves the number of objects in this list since
there is one meta object for every data object.  This is worth
about 500 bytes of RAM on CC.

Second, about half of the remaining UAVOs are not periodic by
default so they're wasting memory unless someone happens to want
to make them periodic at runtime.  This is worth another 450 bytes
of RAM on CC.

So, objects that are configured as periodic during board init will
support all of the periodic config at runtime.  Objects that are
*not* periodic during board init can only be made periodic on the
next boot.

Each object that you make periodic during init will cost you an
extra 32 bytes of RAM.

With erased settings, free RAM comparison for CC is:
  Before: 2736 bytes free
  After:  4048 bytes free

Total RAM savings with this update is 1312 bytes!
This commit is contained in:
Stacey Sheldon 2012-11-10 18:04:16 -05:00
parent 10865221b9
commit e2b019edd9

View File

@ -74,7 +74,6 @@ static void telemetryRxTask(void *parameters);
static int32_t transmitData(uint8_t * data, int32_t length);
static void registerObject(UAVObjHandle obj);
static void updateObject(UAVObjHandle obj, int32_t eventType);
static int32_t addObject(UAVObjHandle obj);
static int32_t setUpdatePeriod(UAVObjHandle obj, int32_t updatePeriodMs);
static void processObjEvent(UAVObjEvent * ev);
static void updateTelemetryStats();
@ -154,11 +153,31 @@ MODULE_INITCALL(TelemetryInitialize, TelemetryStart)
*/
static void registerObject(UAVObjHandle obj)
{
// Setup object for periodic updates
addObject(obj);
if (UAVObjIsMetaobject(obj)) {
/* Only connect change notifications for meta objects. No periodic updates */
UAVObjConnectQueue(obj, priorityQueue, EV_MASK_ALL_UPDATES);
return;
} else {
UAVObjMetadata metadata;
UAVObjUpdateMode updateMode;
UAVObjGetMetadata(obj, &metadata);
updateMode = UAVObjGetTelemetryUpdateMode(&metadata);
// Setup object for telemetry updates
updateObject(obj, EV_NONE);
/* Only create a periodic event for objects that are periodic */
if ((updateMode == UPDATEMODE_PERIODIC) ||
(updateMode == UPDATEMODE_THROTTLED)) {
// Setup object for periodic updates
UAVObjEvent ev = {
.obj = obj,
.instId = UAVOBJ_ALL_INSTANCES,
.event = EV_UPDATED_PERIODIC,
};
EventPeriodicQueueCreate(&ev, queue, 0);
}
// Setup object for telemetry updates
updateObject(obj, EV_NONE);
}
}
/**
@ -171,30 +190,35 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
UAVObjUpdateMode updateMode;
int32_t eventMask;
if (UAVObjIsMetaobject(obj)) {
/* This function updates the periodic updates for the object.
* Meta Objects cannot have periodic updates.
*/
PIOS_Assert(false);
return;
}
// Get metadata
UAVObjGetMetadata(obj, &metadata);
updateMode = UAVObjGetTelemetryUpdateMode(&metadata);
// Setup object depending on update mode
if (updateMode == UPDATEMODE_PERIODIC) {
switch (updateMode) {
case UPDATEMODE_PERIODIC:
// Set update period
setUpdatePeriod(obj, metadata.telemetryUpdatePeriod);
// Connect queue
eventMask = EV_UPDATED_PERIODIC | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
if (UAVObjIsMetaobject(obj)) {
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
}
UAVObjConnectQueue(obj, priorityQueue, eventMask);
} else if (updateMode == UPDATEMODE_ONCHANGE) {
break;
case UPDATEMODE_ONCHANGE:
// Set update period
setUpdatePeriod(obj, 0);
// Connect queue
eventMask = EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
if (UAVObjIsMetaobject(obj)) {
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
}
UAVObjConnectQueue(obj, priorityQueue, eventMask);
} else if (updateMode == UPDATEMODE_THROTTLED) {
break;
case UPDATEMODE_THROTTLED:
if ((eventType == EV_UPDATED_PERIODIC) || (eventType == EV_NONE)) {
// If we received a periodic update, we can change back to update on change
eventMask = EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
@ -205,19 +229,15 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
// Otherwise, we just received an object update, so switch to periodic for the timeout period to prevent more updates
eventMask = EV_UPDATED_PERIODIC | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
}
if (UAVObjIsMetaobject(obj)) {
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
}
UAVObjConnectQueue(obj, priorityQueue, eventMask);
} else if (updateMode == UPDATEMODE_MANUAL) {
break;
case UPDATEMODE_MANUAL:
// Set update period
setUpdatePeriod(obj, 0);
// Connect queue
eventMask = EV_UPDATED_MANUAL | EV_UPDATE_REQ;
if (UAVObjIsMetaobject(obj)) {
eventMask |= EV_UNPACKED; // we also need to act on remote updates (unpack events)
}
UAVObjConnectQueue(obj, priorityQueue, eventMask);
break;
}
}
@ -271,11 +291,11 @@ static void processObjEvent(UAVObjEvent * ev)
// If this is a metaobject then make necessary telemetry updates
if (UAVObjIsMetaobject(ev->obj)) {
updateObject(UAVObjGetLinkedObj(ev->obj), EV_NONE); // linked object will be the actual object the metadata are for
}
if((updateMode == UPDATEMODE_THROTTLED) && !UAVObjIsMetaobject(ev->obj)) {
// If this is UPDATEMODE_THROTTLED, the event mask changes on every event.
updateObject(ev->obj, ev->event);
} else {
if (updateMode == UPDATEMODE_THROTTLED) {
// If this is UPDATEMODE_THROTTLED, the event mask changes on every event.
updateObject(ev->obj, ev->event);
}
}
}
}
@ -380,23 +400,6 @@ static int32_t transmitData(uint8_t * data, int32_t length)
}
}
/**
* Setup object for periodic updates.
* \param[in] obj The object to update
* \return 0 Success
* \return -1 Failure
*/
static int32_t addObject(UAVObjHandle obj)
{
UAVObjEvent ev;
// Add object for periodic updates
ev.obj = obj;
ev.instId = UAVOBJ_ALL_INSTANCES;
ev.event = EV_UPDATED_PERIODIC;
return EventPeriodicQueueCreate(&ev, queue, 0);
}
/**
* Set update period of object (it must be already setup for periodic updates)
* \param[in] obj The object to update