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

Merged in mindnever/librepilot/LP-523_implement_uavobject_DataOverrideDefaults_method (pull request #430)

LP-523 Implement method for overriding uavobject defaults.

Approved-by: Philippe Renon <philippe_renon@yahoo.fr>
Approved-by: Vladimir Zidar <mr_w@mindnever.org>
Approved-by: Lalanne Laurent <f5soh@free.fr>
Approved-by: Brian Webb <webbbn@gmail.com>
Approved-by: Alessio Morale <alessiomorale@gmail.com>
This commit is contained in:
Vladimir Zidar 2017-06-13 19:53:58 +00:00 committed by Lalanne Laurent
commit 0448d627af
7 changed files with 104 additions and 44 deletions

View File

@ -71,6 +71,8 @@ typedef struct {
*/
typedef $(NAME)DataPacked __attribute__((aligned(4))) $(NAME)Data;
void $(NAME)DataOverrideDefaults($(NAME)Data * data);
/* Typesafe Object access functions */
static inline int32_t $(NAME)Get($(NAME)Data * dataOut) {
return UAVObjGetData($(NAME)Handle(), dataOut);
@ -94,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());

View File

@ -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);

View File

@ -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 */

View File

@ -63,14 +63,24 @@ 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;
}
static inline void DataOverrideDefaults(__attribute__((unused)) $(NAME)Data * data) {}
void $(NAME)DataOverrideDefaults($(NAME)Data * data) __attribute__((weak, alias("DataOverrideDefaults")));
/**
* Initialize object fields and metadata with the default values.
* If a default value is not specified the object fields
@ -84,6 +94,7 @@ void $(NAME)SetDefaults(UAVObjHandle obj, uint16_t instId)
UAVObjGetInstanceData(obj, instId, &data);
memset(&data, 0, sizeof($(NAME)Data));
$(INITFIELDS)
$(NAME)DataOverrideDefaults(&data);
UAVObjSetInstanceData(obj, instId, &data);
// Initialize object metadata to their default values

View File

@ -225,7 +225,7 @@ static struct UAVOData *UAVObjAllocSingle(uint32_t num_bytes)
uint32_t object_size = sizeof(struct UAVOSingle) + num_bytes;
/* Allocate the object from the heap */
struct UAVOSingle *uavo_single = (struct UAVOSingle *)pios_fastheapmalloc(object_size);
struct UAVOSingle *uavo_single = (struct UAVOSingle *)pios_malloc(object_size);
if (!uavo_single) {
return NULL;
@ -250,7 +250,7 @@ static struct UAVOData *UAVObjAllocMulti(uint32_t num_bytes)
uint32_t object_size = sizeof(struct UAVOMulti) + num_bytes;
/* Allocate the object from the heap */
struct UAVOMulti *uavo_multi = (struct UAVOMulti *)pios_fastheapmalloc(object_size);
struct UAVOMulti *uavo_multi = (struct UAVOMulti *)pios_malloc(object_size);
if (!uavo_multi) {
return NULL;
@ -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,8 +1633,8 @@ static InstanceHandle createInstance(struct UAVOData *obj, uint16_t instId)
}
/* Create the actual instance */
uint32_t size = sizeof(struct UAVOMultiInst) + obj->instance_size;
instEntry = (struct UAVOMultiInst *)pios_fastheapmalloc(size);
uint32_t size = sizeof(struct UAVOMultiInst) + obj->type->instance_size;
instEntry = (struct UAVOMultiInst *)pios_malloc(size);
if (!instEntry) {
return NULL;
}

View File

@ -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;
}

View File

@ -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();
}
}