From 9f12a27f53420169f9bcb3ca1309ff8ca857cfd9 Mon Sep 17 00:00:00 2001 From: Vladimir Zidar Date: Wed, 31 May 2017 14:41:09 +0200 Subject: [PATCH] LP-523 Move object id and instance_size members from UAVOData structure into UAVObjType and keep only pointer to it. UAVObjType contains init_callback too to allow resetting data to default values. --- flight/uavobjects/inc/uavobject.h.template | 2 +- flight/uavobjects/inc/uavobjectmanager.h | 12 ++- flight/uavobjects/inc/uavobjectprivate.h | 5 +- flight/uavobjects/uavobject.c.template | 10 +- flight/uavobjects/uavobjectmanager.c | 100 ++++++++++++------ flight/uavobjects/uavobjectpersistence.c | 4 +- .../uavobjectbrowserwidget.cpp | 2 + 7 files changed, 94 insertions(+), 41 deletions(-) diff --git a/flight/uavobjects/inc/uavobject.h.template b/flight/uavobjects/inc/uavobject.h.template index c9c70ed18..147478671 100644 --- a/flight/uavobjects/inc/uavobject.h.template +++ b/flight/uavobjects/inc/uavobject.h.template @@ -96,7 +96,7 @@ static inline int32_t $(NAME)ConnectFastCallback(UAVObjEventCallback cb) { return UAVObjConnectCallback($(NAME)Handle(), cb, EV_MASK_ALL_UPDATES, true); } static inline uint16_t $(NAME)CreateInstance() { - return UAVObjCreateInstance($(NAME)Handle(), &$(NAME)SetDefaults); + return UAVObjCreateInstance($(NAME)Handle()); } static inline void $(NAME)RequestUpdate() { UAVObjRequestUpdate($(NAME)Handle()); diff --git a/flight/uavobjects/inc/uavobjectmanager.h b/flight/uavobjects/inc/uavobjectmanager.h index 7317e99df..e73ac86a6 100644 --- a/flight/uavobjects/inc/uavobjectmanager.h +++ b/flight/uavobjects/inc/uavobjectmanager.h @@ -182,16 +182,22 @@ typedef struct { uint32_t lastQueueErrorID; } UAVObjStats; +typedef struct { + uint32_t id; + UAVObjInitializeCallback init_callback; + uint16_t instance_size; +} __attribute__((packed, aligned(4))) UAVObjType; + int32_t UAVObjInitialize(); void UAVObjGetStats(UAVObjStats *statsOut); void UAVObjClearStats(); -UAVObjHandle UAVObjRegister(uint32_t id, bool isSingleInstance, bool isSettings, bool isPriority, uint32_t num_bytes, UAVObjInitializeCallback initCb); +UAVObjHandle UAVObjRegister(const UAVObjType *type, bool isSingleInstance, bool isSettings, bool isPriority); UAVObjHandle UAVObjGetByID(uint32_t id); uint32_t UAVObjGetID(UAVObjHandle obj); uint32_t UAVObjGetNumBytes(UAVObjHandle obj); uint16_t UAVObjGetNumInstances(UAVObjHandle obj); UAVObjHandle UAVObjGetLinkedObj(UAVObjHandle obj); -uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle, UAVObjInitializeCallback initCb); +uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle); bool UAVObjIsSingleInstance(UAVObjHandle obj); bool UAVObjIsMetaobject(UAVObjHandle obj); bool UAVObjIsSettings(UAVObjHandle obj); @@ -208,10 +214,12 @@ int32_t UAVObjDeleteSettings(); int32_t UAVObjSaveMetaobjects(); int32_t UAVObjLoadMetaobjects(); int32_t UAVObjDeleteMetaobjects(); +int32_t UAVObjSetDefaults(UAVObjHandle obj_handle); int32_t UAVObjSetData(UAVObjHandle obj_handle, const void *dataIn); int32_t UAVObjSetDataField(UAVObjHandle obj_handle, const void *dataIn, uint32_t offset, uint32_t size); int32_t UAVObjGetData(UAVObjHandle obj_handle, void *dataOut); int32_t UAVObjGetDataField(UAVObjHandle obj_handle, void *dataOut, uint32_t offset, uint32_t size); +int32_t UAVObjSetInstanceDefaults(UAVObjHandle obj_handle, uint16_t instId); int32_t UAVObjSetInstanceData(UAVObjHandle obj_handle, uint16_t instId, const void *dataIn); int32_t UAVObjSetInstanceDataField(UAVObjHandle obj_handle, uint16_t instId, const void *dataIn, uint32_t offset, uint32_t size); int32_t UAVObjGetInstanceData(UAVObjHandle obj_handle, uint16_t instId, void *dataOut); diff --git a/flight/uavobjects/inc/uavobjectprivate.h b/flight/uavobjects/inc/uavobjectprivate.h index 88229f44e..2177539fd 100644 --- a/flight/uavobjects/inc/uavobjectprivate.h +++ b/flight/uavobjects/inc/uavobjectprivate.h @@ -112,14 +112,13 @@ struct UAVOMeta { /* Shared data structure for all data-carrying UAVObjects (UAVOSingle and UAVOMulti) */ struct UAVOData { - struct UAVOBase base; - uint32_t id; + struct UAVOBase base; + const UAVObjType *type; /* this contains id, instance_size and data initializer */ /* * Embed the Meta object as another complete UAVO * inside the payload for this UAVO. */ struct UAVOMeta metaObj; - uint16_t instance_size; } __attribute__((packed, aligned(4))); /* Augmented type for Single Instance Data UAVO */ diff --git a/flight/uavobjects/uavobject.c.template b/flight/uavobjects/uavobject.c.template index e50906a6f..4ec89d540 100644 --- a/flight/uavobjects/uavobject.c.template +++ b/flight/uavobjects/uavobject.c.template @@ -63,9 +63,15 @@ int32_t $(NAME)Initialize(void) return -2; } + static const UAVObjType objType = { + .id = $(NAMEUC)_OBJID, + .instance_size = $(NAMEUC)_NUMBYTES, + .init_callback = &$(NAME)SetDefaults, + }; + // Register object with the object manager - handle = UAVObjRegister($(NAMEUC)_OBJID, - $(NAMEUC)_ISSINGLEINST, $(NAMEUC)_ISSETTINGS, $(NAMEUC)_ISPRIORITY, $(NAMEUC)_NUMBYTES, &$(NAME)SetDefaults); + handle = UAVObjRegister(&objType, + $(NAMEUC)_ISSINGLEINST, $(NAMEUC)_ISSETTINGS, $(NAMEUC)_ISPRIORITY); // Done return handle ? 0 : -1; diff --git a/flight/uavobjects/uavobjectmanager.c b/flight/uavobjects/uavobjectmanager.c index 8368f87a3..0d9de00ea 100644 --- a/flight/uavobjects/uavobjectmanager.c +++ b/flight/uavobjects/uavobjectmanager.c @@ -278,33 +278,30 @@ static struct UAVOData *UAVObjAllocMulti(uint32_t num_bytes) /** * Register and new object in the object manager. - * \param[in] id Unique object ID + * \param[in] pointer to UAVObjType structure that holds Unique object ID, instance size, initialization function * \param[in] isSingleInstance Is this a single instance or multi-instance object * \param[in] isSettings Is this a settings object - * \param[in] numBytes Number of bytes of object data (for one instance) - * \param[in] initCb Default field and metadata initialization function + * \param[in] isPriority * \return Object handle, or NULL if failure. * \return */ -UAVObjHandle UAVObjRegister(uint32_t id, - bool isSingleInstance, bool isSettings, bool isPriority, - uint32_t num_bytes, - UAVObjInitializeCallback initCb) +UAVObjHandle UAVObjRegister(const UAVObjType *type, + bool isSingleInstance, bool isSettings, bool isPriority) { struct UAVOData *uavo_data = NULL; xSemaphoreTakeRecursive(mutex, portMAX_DELAY); /* Don't allow duplicate registrations */ - if (UAVObjGetByID(id)) { + if (UAVObjGetByID(type->id)) { goto unlock_exit; } /* Map the various flags to one of the UAVO types we understand */ if (isSingleInstance) { - uavo_data = UAVObjAllocSingle(num_bytes); + uavo_data = UAVObjAllocSingle(type->instance_size); } else { - uavo_data = UAVObjAllocMulti(num_bytes); + uavo_data = UAVObjAllocMulti(type->instance_size); } if (!uavo_data) { @@ -312,8 +309,7 @@ UAVObjHandle UAVObjRegister(uint32_t id, } /* Fill in the details about this UAVO */ - uavo_data->id = id; - uavo_data->instance_size = num_bytes; + uavo_data->type = type; if (isSettings) { uavo_data->base.flags.isSettings = true; // settings defaults to being sent with priority @@ -325,8 +321,8 @@ UAVObjHandle UAVObjRegister(uint32_t id, UAVObjInitMetaData(&uavo_data->metaObj); /* Initialize object fields and metadata to default values */ - if (initCb) { - initCb((UAVObjHandle)uavo_data, 0); + if (type->init_callback) { + type->init_callback((UAVObjHandle)uavo_data, 0); } /* Always try to load the meta object from flash */ @@ -360,11 +356,11 @@ UAVObjHandle UAVObjGetByID(uint32_t id) // Look for object UAVO_LIST_ITERATE(tmp_obj) - if (tmp_obj->id == id) { + if (tmp_obj->type->id == id) { found_obj = (UAVObjHandle *)tmp_obj; goto unlock_exit; } - if (MetaObjectId(tmp_obj->id) == id) { + if (MetaObjectId(tmp_obj->type->id) == id) { found_obj = (UAVObjHandle *)&(tmp_obj->metaObj); goto unlock_exit; } @@ -391,12 +387,12 @@ uint32_t UAVObjGetID(UAVObjHandle obj_handle) /* We have a meta object, find our containing UAVO */ struct UAVOData *uavo_data = container_of((struct UAVOMeta *)uavo_base, struct UAVOData, metaObj); - return MetaObjectId(uavo_data->id); + return MetaObjectId(uavo_data->type->id); } else { /* We have a data object, augment our pointer */ struct UAVOData *uavo_data = (struct UAVOData *)uavo_base; - return uavo_data->id; + return uavo_data->type->id; } } @@ -420,7 +416,7 @@ uint32_t UAVObjGetNumBytes(UAVObjHandle obj) /* We have a data object, augment our pointer */ struct UAVOData *uavo = (struct UAVOData *)uavo_base; - instance_size = uavo->instance_size; + instance_size = uavo->type->instance_size; } return instance_size; @@ -478,8 +474,7 @@ uint16_t UAVObjGetNumInstances(UAVObjHandle obj_handle) * \param[in] obj The object handle * \return The instance ID or 0 if an error */ -uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle, - UAVObjInitializeCallback initCb) +uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle) { PIOS_Assert(obj_handle); @@ -501,8 +496,8 @@ uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle, } // Initialize instance data - if (initCb) { - initCb(obj_handle, instId); + if (((struct UAVOData *)obj_handle)->type->init_callback) { + ((struct UAVOData *)obj_handle)->type->init_callback(obj_handle, instId); } unlock_exit: @@ -550,7 +545,7 @@ int32_t UAVObjUnpack(UAVObjHandle obj_handle, uint16_t instId, const uint8_t *da } } // Set the data - memcpy(InstanceData(instEntry), dataIn, obj->instance_size); + memcpy(InstanceData(instEntry), dataIn, obj->type->instance_size); } // Fire event @@ -596,7 +591,7 @@ int32_t UAVObjPack(UAVObjHandle obj_handle, uint16_t instId, uint8_t *dataOut) goto unlock_exit; } // Pack data - memcpy(dataOut, InstanceData(instEntry), obj->instance_size); + memcpy(dataOut, InstanceData(instEntry), obj->type->instance_size); } rc = 0; @@ -638,7 +633,7 @@ uint8_t UAVObjUpdateCRC(UAVObjHandle obj_handle, uint16_t instId, uint8_t crc) goto unlock_exit; } // Update crc - crc = PIOS_CRC_updateCRC(crc, (uint8_t *)InstanceData(instEntry), (int32_t)obj->instance_size); + crc = PIOS_CRC_updateCRC(crc, (uint8_t *)InstanceData(instEntry), (int32_t)obj->type->instance_size); } unlock_exit: @@ -677,7 +672,7 @@ void UAVObjInstanceWriteToLog(UAVObjHandle obj_handle, uint16_t instId) goto unlock_exit; } // Pack data - PIOS_DEBUGLOG_UAVObject(UAVObjGetID(obj_handle), instId, obj->instance_size, (uint8_t *)InstanceData(instEntry)); + PIOS_DEBUGLOG_UAVObject(UAVObjGetID(obj_handle), instId, obj->type->instance_size, (uint8_t *)InstanceData(instEntry)); } unlock_exit: @@ -857,6 +852,11 @@ xSemaphoreGiveRecursive(mutex); return rc; } +int32_t UAVObjSetDefaults(UAVObjHandle obj_handle) +{ + return UAVObjSetInstanceDefaults(obj_handle, 0); +} + /** * Set the object data * \param[in] obj The object handle @@ -901,6 +901,42 @@ int32_t UAVObjGetDataField(UAVObjHandle obj_handle, void *dataOut, uint32_t offs return UAVObjGetInstanceDataField(obj_handle, 0, dataOut, offset, size); } +int32_t UAVObjSetInstanceDefaults(UAVObjHandle obj_handle, uint16_t instId) +{ + PIOS_Assert(obj_handle); + + // Lock + xSemaphoreTakeRecursive(mutex, portMAX_DELAY); + + int32_t rc = -1; + + if (IsMetaobject(obj_handle)) { + if (instId != 0) { + goto unlock_exit; + } +// How do we set meta data defaults? +// MetaDataPtr((struct UAVOMeta *)obj_handle), MetaNumBytes; + } else { + // Check access level + if (UAVObjReadOnly(obj_handle)) { + goto unlock_exit; + } + + // Set default data + if (((struct UAVOData *)obj_handle)->type->init_callback) { + ((struct UAVOData *)obj_handle)->type->init_callback(obj_handle, instId); + } + } + + // Fire event + sendEvent((struct UAVOBase *)obj_handle, instId, EV_UPDATED); + rc = 0; + +unlock_exit: + xSemaphoreGiveRecursive(mutex); + return rc; +} + /** * Set the data of a specific object instance * \param[in] obj The object handle @@ -940,7 +976,7 @@ int32_t UAVObjSetInstanceData(UAVObjHandle obj_handle, uint16_t instId, goto unlock_exit; } // Set data - memcpy(InstanceData(instEntry), dataIn, obj->instance_size); + memcpy(InstanceData(instEntry), dataIn, obj->type->instance_size); } // Fire event @@ -1000,7 +1036,7 @@ int32_t UAVObjSetInstanceDataField(UAVObjHandle obj_handle, uint16_t instId, con } // Check for overrun - if ((size + offset) > obj->instance_size) { + if ((size + offset) > obj->type->instance_size) { goto unlock_exit; } @@ -1055,7 +1091,7 @@ int32_t UAVObjGetInstanceData(UAVObjHandle obj_handle, uint16_t instId, goto unlock_exit; } // Set data - memcpy(dataOut, InstanceData(instEntry), obj->instance_size); + memcpy(dataOut, InstanceData(instEntry), obj->type->instance_size); } rc = 0; @@ -1108,7 +1144,7 @@ int32_t UAVObjGetInstanceDataField(UAVObjHandle obj_handle, uint16_t instId, voi } // Check for overrun - if ((size + offset) > obj->instance_size) { + if ((size + offset) > obj->type->instance_size) { goto unlock_exit; } @@ -1597,7 +1633,7 @@ static InstanceHandle createInstance(struct UAVOData *obj, uint16_t instId) } /* Create the actual instance */ - uint32_t size = sizeof(struct UAVOMultiInst) + obj->instance_size; + uint32_t size = sizeof(struct UAVOMultiInst) + obj->type->instance_size; instEntry = (struct UAVOMultiInst *)pios_malloc(size); if (!instEntry) { return NULL; diff --git a/flight/uavobjects/uavobjectpersistence.c b/flight/uavobjects/uavobjectpersistence.c index 4acbd41e5..0f0395ce7 100644 --- a/flight/uavobjects/uavobjectpersistence.c +++ b/flight/uavobjects/uavobjectpersistence.c @@ -121,6 +121,8 @@ int32_t UAVObjLoad(UAVObjHandle obj_handle, uint16_t instId) int32_t UAVObjDelete(UAVObjHandle obj_handle, uint16_t instId) { PIOS_Assert(obj_handle); - PIOS_FLASHFS_ObjDelete(pios_uavo_settings_fs_id, UAVObjGetID(obj_handle), instId); + if (PIOS_FLASHFS_ObjDelete(pios_uavo_settings_fs_id, UAVObjGetID(obj_handle), instId) == 0) { + UAVObjSetInstanceDefaults(obj_handle, instId); + } return 0; } diff --git a/ground/gcs/src/plugins/uavobjectbrowser/uavobjectbrowserwidget.cpp b/ground/gcs/src/plugins/uavobjectbrowser/uavobjectbrowserwidget.cpp index 93b1b76c5..b7ab69aef 100644 --- a/ground/gcs/src/plugins/uavobjectbrowser/uavobjectbrowserwidget.cpp +++ b/ground/gcs/src/plugins/uavobjectbrowser/uavobjectbrowserwidget.cpp @@ -212,6 +212,8 @@ void UAVObjectBrowserWidget::eraseObject() UAVObject *obj = objItem->object(); Q_ASSERT(obj); updateObjectPersistance(ObjectPersistence::OPERATION_DELETE, obj); + // Retrieve object so that correct default value is displayed + requestUpdate(); } }