2 ******************************************************************************
3 * @addtogroup UAVObjects OpenPilot UAVObjects
5 * @addtogroup UAV Object Manager
6 * @brief The core UAV Objects functions, most of which are wrappered by
7 * autogenerated defines
11 * @file uavobjectmanager.h
12 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
13 * @brief Object manager library. This library holds a collection of all objects.
14 * It can be used by all modules/libraries to find an object reference.
15 * @see The GNU Public License (GPL) Version 3
17 *****************************************************************************/
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 3 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful, but
25 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
26 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "openpilot.h"
35 #include "pios_struct_helper.h"
37 extern uintptr_t pios_uavo_settings_fs_id
;
39 #if (defined(__MACH__) && defined(__APPLE__))
40 #include <mach-o/getsect.h>
48 #define SET_BITS(var, shift, value, mask) var = (var & ~(mask << shift)) | (value << shift);
50 // Mach-o: dummy segment to calculate ASLR offset in sim_osx
51 #if (defined(__MACH__) && defined(__APPLE__))
52 static long _aslr_offset
__attribute__((section("__DATA,_aslr")));
55 /* Table of UAVO handles */
56 #if (defined(__MACH__) && defined(__APPLE__))
58 static struct UAVOData
* *__start__uavo_handles
;
59 static struct UAVOData
* *__stop__uavo_handles
;
61 /* ELF format: automagically defined at compile time */
62 extern struct UAVOData
*__start__uavo_handles
[] __attribute__((weak
));
63 extern struct UAVOData
*__stop__uavo_handles
[] __attribute__((weak
));
66 #define UAVO_LIST_ITERATE(_item) \
67 for (struct UAVOData * *_uavo_slot = __start__uavo_handles; \
68 _uavo_slot && _uavo_slot < __stop__uavo_handles; \
70 struct UAVOData *_item = *_uavo_slot; \
71 if (_item == NULL) { continue; }
74 * List of event queues and the eventmask associated with the queue.
77 /** opaque type for instances **/
78 typedef void *InstanceHandle
;
80 struct ObjectEventEntry
{
81 struct ObjectEventEntry
*next
;
83 UAVObjEventCallback cb
;
88 MetaInstance == [UAVOBase [UAVObjMetadata]]
89 SingleInstance == [UAVOBase [UAVOData [InstanceData]]]
90 MultiInstance == [UAVOBase [UAVOData [NumInstances [InstanceData0 [next]]]]
92 \-->[InstanceData1 [next]]
94 \-->[InstanceDataN [next]]
99 * - All Types of UAVObjects are of this base type
100 * - The flags determine what type(s) this object
103 /* Let these objects be added to an event queue */
104 struct ObjectEventEntry
*next_event
;
106 /* Describe the type of object that follows this header */
113 } __attribute__((packed
));
115 /* Augmented type for Meta UAVO */
117 struct UAVOBase base
;
118 UAVObjMetadata instance0
;
119 } __attribute__((packed
));
121 /* Shared data structure for all data-carrying UAVObjects (UAVOSingle and UAVOMulti) */
123 struct UAVOBase base
;
126 * Embed the Meta object as another complete UAVO
127 * inside the payload for this UAVO.
129 struct UAVOMeta metaObj
;
130 uint16_t instance_size
;
131 } __attribute__((packed
, aligned(4)));
133 /* Augmented type for Single Instance Data UAVO */
135 struct UAVOData uavo
;
139 * Additional space will be malloc'd here to hold the
140 * the data for this instance.
142 } __attribute__((packed
));
144 /* Part of a linked list of instances chained off of a multi instance UAVO. */
145 struct UAVOMultiInst
{
146 struct UAVOMultiInst
*next
;
149 * Additional space will be malloc'd here to hold the
150 * the data for this instance.
152 } __attribute__((packed
));
154 /* Augmented type for Multi Instance Data UAVO */
156 struct UAVOData uavo
;
157 uint16_t num_instances
;
158 struct UAVOMultiInst instance0
__attribute__((aligned(4)));
160 * Additional space will be malloc'd here to hold the
161 * the data for instance 0.
163 } __attribute__((packed
));
165 /** all information about a metaobject are hardcoded constants **/
166 #define MetaNumBytes sizeof(UAVObjMetadata)
167 #define MetaBaseObjectPtr(obj) ((struct UAVOData *)((obj) - offsetof(struct UAVOData, metaObj)))
168 #define MetaObjectPtr(obj) ((struct UAVODataMeta *)&((obj)->metaObj))
169 #define MetaDataPtr(obj) ((UAVObjMetadata *)&((obj)->instance0))
170 #define LinkedMetaDataPtr(obj) ((UAVObjMetadata *)&((obj)->metaObj.instance0))
172 /** all information about instances are dependant on object type **/
173 #define ObjSingleInstanceDataOffset(obj) ((void *)(&(((struct UAVOSingle *)obj)->instance0)))
174 #define InstanceDataOffset(inst) ((void *)&(((struct UAVOMultiInst *)inst)->instance))
175 #define InstanceData(instance) ((void *)instance)
178 static int32_t sendEvent(struct UAVOBase
*obj
, uint16_t instId
, UAVObjEventType event
);
179 static InstanceHandle
createInstance(struct UAVOData
*obj
, uint16_t instId
);
180 static InstanceHandle
getInstance(struct UAVOData
*obj
, uint16_t instId
);
181 static int32_t connectObj(UAVObjHandle obj_handle
, xQueueHandle queue
, UAVObjEventCallback cb
, uint8_t eventMask
);
182 static int32_t disconnectObj(UAVObjHandle obj_handle
, xQueueHandle queue
, UAVObjEventCallback cb
);
183 static void instanceAutoUpdated(UAVObjHandle obj_handle
, uint16_t instId
);
186 static xSemaphoreHandle mutex
;
187 static const UAVObjMetadata defMetadata
= {
188 .flags
= (ACCESS_READWRITE
<< UAVOBJ_ACCESS_SHIFT
|
189 ACCESS_READWRITE
<< UAVOBJ_GCS_ACCESS_SHIFT
|
190 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT
|
191 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT
|
192 UPDATEMODE_ONCHANGE
<< UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT
|
193 UPDATEMODE_ONCHANGE
<< UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT
),
194 .telemetryUpdatePeriod
= 0,
195 .gcsTelemetryUpdatePeriod
= 0,
196 .loggingUpdatePeriod
= 0,
199 static UAVObjStats stats
;
202 * Initialize the object manager
206 int32_t UAVObjInitialize()
208 // Initialize variables
209 memset(&stats
, 0, sizeof(UAVObjStats
));
211 /* Initialize _uavo_handles start/stop pointers */
212 #if (defined(__MACH__) && defined(__APPLE__))
213 uint64_t aslr_offset
= (uint64_t)&_aslr_offset
- getsectbyname("__DATA", "_aslr")->addr
;
214 __start__uavo_handles
= (struct UAVOData
* *)(getsectbyname("__DATA", "_uavo_handles")->addr
+ aslr_offset
);
215 __stop__uavo_handles
= (struct UAVOData
* *)((uint64_t)__start__uavo_handles
+ getsectbyname("__DATA", "_uavo_handles")->size
);
218 // Initialize the uavo handle table
219 memset(__start__uavo_handles
, 0,
220 (uintptr_t)__stop__uavo_handles
- (uintptr_t)__start__uavo_handles
);
223 mutex
= xSemaphoreCreateRecursiveMutex();
237 * Get the statistics counters
238 * @param[out] statsOut The statistics counters will be copied there
240 void UAVObjGetStats(UAVObjStats
*statsOut
)
242 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
243 memcpy(statsOut
, &stats
, sizeof(UAVObjStats
));
244 xSemaphoreGiveRecursive(mutex
);
248 * Clear the statistics counters
250 void UAVObjClearStats()
252 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
253 memset(&stats
, 0, sizeof(UAVObjStats
));
254 xSemaphoreGiveRecursive(mutex
);
257 /************************
258 * Object Initialization
259 ***********************/
261 static void UAVObjInitMetaData(struct UAVOMeta
*obj_meta
)
263 /* Fill in the common part of the UAVO */
264 struct UAVOBase
*uavo_base
= &(obj_meta
->base
);
266 memset(uavo_base
, 0, sizeof(*uavo_base
));
267 uavo_base
->flags
.isMeta
= true;
268 uavo_base
->flags
.isSingle
= true;
269 uavo_base
->next_event
= NULL
;
271 /* Clear the instance data carried in the UAVO */
272 memset(&(obj_meta
->instance0
), 0, sizeof(obj_meta
->instance0
));
275 static struct UAVOData
*UAVObjAllocSingle(uint32_t num_bytes
)
277 /* Compute the complete size of the object, including the data for a single embedded instance */
278 uint32_t object_size
= sizeof(struct UAVOSingle
) + num_bytes
;
280 /* Allocate the object from the heap */
281 struct UAVOSingle
*uavo_single
= (struct UAVOSingle
*)pios_malloc(object_size
);
287 /* Fill in the common part of the UAVO */
288 struct UAVOBase
*uavo_base
= &(uavo_single
->uavo
.base
);
289 memset(uavo_base
, 0, sizeof(*uavo_base
));
290 uavo_base
->flags
.isSingle
= true;
291 uavo_base
->next_event
= NULL
;
293 /* Clear the instance data carried in the UAVO */
294 memset(&(uavo_single
->instance0
), 0, num_bytes
);
296 /* Give back the generic UAVO part */
297 return &(uavo_single
->uavo
);
300 static struct UAVOData
*UAVObjAllocMulti(uint32_t num_bytes
)
302 /* Compute the complete size of the object, including the data for a single embedded instance */
303 uint32_t object_size
= sizeof(struct UAVOMulti
) + num_bytes
;
305 /* Allocate the object from the heap */
306 struct UAVOMulti
*uavo_multi
= (struct UAVOMulti
*)pios_malloc(object_size
);
312 /* Fill in the common part of the UAVO */
313 struct UAVOBase
*uavo_base
= &(uavo_multi
->uavo
.base
);
314 memset(uavo_base
, 0, sizeof(*uavo_base
));
315 uavo_base
->flags
.isSingle
= false;
316 uavo_base
->next_event
= NULL
;
318 /* Set up the type-specific part of the UAVO */
319 uavo_multi
->num_instances
= 1;
321 /* Clear the multi instance data carried in the UAVO */
322 memset(&(uavo_multi
->instance0
), 0, sizeof(struct UAVOMultiInst
) + num_bytes
);
324 /* Give back the generic UAVO part */
325 return &(uavo_multi
->uavo
);
328 /**************************
329 * UAVObject Database APIs
330 *************************/
333 * Register and new object in the object manager.
334 * \param[in] id Unique object ID
335 * \param[in] isSingleInstance Is this a single instance or multi-instance object
336 * \param[in] isSettings Is this a settings object
337 * \param[in] numBytes Number of bytes of object data (for one instance)
338 * \param[in] initCb Default field and metadata initialization function
339 * \return Object handle, or NULL if failure.
342 UAVObjHandle
UAVObjRegister(uint32_t id
,
343 bool isSingleInstance
, bool isSettings
, bool isPriority
,
345 UAVObjInitializeCallback initCb
)
347 struct UAVOData
*uavo_data
= NULL
;
349 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
351 /* Don't allow duplicate registrations */
352 if (UAVObjGetByID(id
)) {
356 /* Map the various flags to one of the UAVO types we understand */
357 if (isSingleInstance
) {
358 uavo_data
= UAVObjAllocSingle(num_bytes
);
360 uavo_data
= UAVObjAllocMulti(num_bytes
);
367 /* Fill in the details about this UAVO */
369 uavo_data
->instance_size
= num_bytes
;
371 uavo_data
->base
.flags
.isSettings
= true;
372 // settings defaults to being sent with priority
373 uavo_data
->base
.flags
.isPriority
= true;
375 uavo_data
->base
.flags
.isPriority
= isPriority
;
377 /* Initialize the embedded meta UAVO */
378 UAVObjInitMetaData(&uavo_data
->metaObj
);
380 /* Initialize object fields and metadata to default values */
382 initCb((UAVObjHandle
)uavo_data
, 0);
385 /* Always try to load the meta object from flash */
386 UAVObjLoad((UAVObjHandle
) & (uavo_data
->metaObj
), 0);
388 /* Attempt to load settings object from flash */
389 if (uavo_data
->base
.flags
.isSettings
) {
390 UAVObjLoad((UAVObjHandle
)uavo_data
, 0);
393 // fire events for outer object and its embedded meta object
394 instanceAutoUpdated((UAVObjHandle
)uavo_data
, 0);
395 instanceAutoUpdated((UAVObjHandle
) & (uavo_data
->metaObj
), 0);
398 xSemaphoreGiveRecursive(mutex
);
399 return (UAVObjHandle
)uavo_data
;
403 * Retrieve an object from the list given its id
404 * \param[in] The object ID
405 * \return The object or NULL if not found.
407 UAVObjHandle
UAVObjGetByID(uint32_t id
)
409 UAVObjHandle
*found_obj
= (UAVObjHandle
*)NULL
;
412 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
415 UAVO_LIST_ITERATE(tmp_obj
)
416 if (tmp_obj
->id
== id
) {
417 found_obj
= (UAVObjHandle
*)tmp_obj
;
420 if (MetaObjectId(tmp_obj
->id
) == id
) {
421 found_obj
= (UAVObjHandle
*)&(tmp_obj
->metaObj
);
427 xSemaphoreGiveRecursive(mutex
);
432 * Get the object's ID
433 * \param[in] obj The object handle
434 * \return The object ID
436 uint32_t UAVObjGetID(UAVObjHandle obj_handle
)
438 PIOS_Assert(obj_handle
);
440 /* Recover the common object header */
441 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
443 if (UAVObjIsMetaobject(obj_handle
)) {
444 /* We have a meta object, find our containing UAVO */
445 struct UAVOData
*uavo_data
= container_of((struct UAVOMeta
*)uavo_base
, struct UAVOData
, metaObj
);
447 return MetaObjectId(uavo_data
->id
);
449 /* We have a data object, augment our pointer */
450 struct UAVOData
*uavo_data
= (struct UAVOData
*)uavo_base
;
452 return uavo_data
->id
;
457 * Get the number of bytes of the object's data (for one instance)
458 * \param[in] obj The object handle
459 * \return The number of bytes
461 uint32_t UAVObjGetNumBytes(UAVObjHandle obj
)
465 uint32_t instance_size
;
467 /* Recover the common object header */
468 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj
;
470 if (uavo_base
->flags
.isMeta
) {
471 instance_size
= MetaNumBytes
;
473 /* We have a data object, augment our pointer */
474 struct UAVOData
*uavo
= (struct UAVOData
*)uavo_base
;
476 instance_size
= uavo
->instance_size
;
479 return instance_size
;
483 * Get the object this object is linked to. For regular objects, the linked object
484 * is the metaobject. For metaobjects the linked object is the parent object.
485 * This function is normally only needed by the telemetry module.
486 * \param[in] obj The object handle
487 * \return The object linked object handle
489 UAVObjHandle
UAVObjGetLinkedObj(UAVObjHandle obj_handle
)
491 PIOS_Assert(obj_handle
);
493 /* Recover the common object header */
494 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
496 if (UAVObjIsMetaobject(obj_handle
)) {
497 /* We have a meta object, find our containing UAVO. */
498 struct UAVOData
*uavo_data
= container_of((struct UAVOMeta
*)uavo_base
, struct UAVOData
, metaObj
);
500 return (UAVObjHandle
)uavo_data
;
502 /* We have a data object, augment our pointer */
503 struct UAVOData
*uavo_data
= (struct UAVOData
*)uavo_base
;
505 return (UAVObjHandle
) & (uavo_data
->metaObj
);
510 * Get the number of instances contained in the object.
511 * \param[in] obj The object handle
512 * \return The number of instances
514 uint16_t UAVObjGetNumInstances(UAVObjHandle obj_handle
)
516 PIOS_Assert(obj_handle
);
518 if (UAVObjIsSingleInstance(obj_handle
)) {
519 /* Only one instance is allowed */
522 /* Multi-instance object. Inspect the object */
523 /* Augment our pointer to reflect the proper type */
524 struct UAVOMulti
*uavo_multi
= (struct UAVOMulti
*)obj_handle
;
525 return uavo_multi
->num_instances
;
530 * Create a new instance in the object.
531 * \param[in] obj The object handle
532 * \return The instance ID or 0 if an error
534 uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle
,
535 UAVObjInitializeCallback initCb
)
537 PIOS_Assert(obj_handle
);
539 if (UAVObjIsMetaobject(obj_handle
)) {
544 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
546 InstanceHandle instEntry
;
549 // Create new instance
550 instId
= UAVObjGetNumInstances(obj_handle
);
551 instEntry
= createInstance((struct UAVOData
*)obj_handle
, instId
);
552 if (instEntry
== NULL
) {
556 // Initialize instance data
558 initCb(obj_handle
, instId
);
562 xSemaphoreGiveRecursive(mutex
);
568 * Does this object contains a single instance or multiple instances?
569 * \param[in] obj The object handle
570 * \return True (1) if this is a single instance object
572 bool UAVObjIsSingleInstance(UAVObjHandle obj_handle
)
574 PIOS_Assert(obj_handle
);
576 /* Recover the common object header */
577 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
579 return uavo_base
->flags
.isSingle
;
583 * Is this a metaobject?
584 * \param[in] obj The object handle
585 * \return True (1) if this is metaobject
587 bool UAVObjIsMetaobject(UAVObjHandle obj_handle
)
589 PIOS_Assert(obj_handle
);
591 /* Recover the common object header */
592 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
594 return uavo_base
->flags
.isMeta
;
598 * Is this a settings object?
599 * \param[in] obj The object handle
600 * \return True (1) if this is a settings object
602 bool UAVObjIsSettings(UAVObjHandle obj_handle
)
604 PIOS_Assert(obj_handle
);
606 /* Recover the common object header */
607 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
609 return uavo_base
->flags
.isSettings
;
613 * Is this a prioritized object?
614 * \param[in] obj The object handle
615 * \return True (1) if this is a prioritized object
617 bool UAVObjIsPriority(UAVObjHandle obj_handle
)
619 PIOS_Assert(obj_handle
);
621 /* Recover the common object header */
622 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
624 return uavo_base
->flags
.isPriority
;
629 * Unpack an object from a byte array
630 * \param[in] obj The object handle
631 * \param[in] instId The instance ID
632 * \param[in] dataIn The byte array
633 * \return 0 if success or -1 if failure
635 int32_t UAVObjUnpack(UAVObjHandle obj_handle
, uint16_t instId
, const uint8_t *dataIn
)
637 PIOS_Assert(obj_handle
);
640 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
644 if (UAVObjIsMetaobject(obj_handle
)) {
648 memcpy(MetaDataPtr((struct UAVOMeta
*)obj_handle
), dataIn
, MetaNumBytes
);
650 struct UAVOData
*obj
;
651 InstanceHandle instEntry
;
653 // Cast handle to object
654 obj
= (struct UAVOData
*)obj_handle
;
657 instEntry
= getInstance(obj
, instId
);
659 // If the instance does not exist create it and any other instances before it
660 if (instEntry
== NULL
) {
661 instEntry
= createInstance(obj
, instId
);
662 if (instEntry
== NULL
) {
667 memcpy(InstanceData(instEntry
), dataIn
, obj
->instance_size
);
671 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UNPACKED
);
675 xSemaphoreGiveRecursive(mutex
);
680 * Pack an object to a byte array
681 * \param[in] obj The object handle
682 * \param[in] instId The instance ID
683 * \param[out] dataOut The byte array
684 * \return 0 if success or -1 if failure
686 int32_t UAVObjPack(UAVObjHandle obj_handle
, uint16_t instId
, uint8_t *dataOut
)
688 PIOS_Assert(obj_handle
);
691 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
695 if (UAVObjIsMetaobject(obj_handle
)) {
699 memcpy(dataOut
, MetaDataPtr((struct UAVOMeta
*)obj_handle
), MetaNumBytes
);
701 struct UAVOData
*obj
;
702 InstanceHandle instEntry
;
704 // Cast handle to object
705 obj
= (struct UAVOData
*)obj_handle
;
708 instEntry
= getInstance(obj
, instId
);
709 if (instEntry
== NULL
) {
713 memcpy(dataOut
, InstanceData(instEntry
), obj
->instance_size
);
719 xSemaphoreGiveRecursive(mutex
);
724 * Update a CRC with an object data
725 * \param[in] obj The object handle
726 * \param[in] instId The instance ID
727 * \param[in] crc The crc to update
728 * \return the updated crc
730 uint8_t UAVObjUpdateCRC(UAVObjHandle obj_handle
, uint16_t instId
, uint8_t crc
)
732 PIOS_Assert(obj_handle
);
735 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
737 if (UAVObjIsMetaobject(obj_handle
)) {
743 struct UAVOData
*obj
;
744 InstanceHandle instEntry
;
746 // Cast handle to object
747 obj
= (struct UAVOData
*)obj_handle
;
750 instEntry
= getInstance(obj
, instId
);
751 if (instEntry
== NULL
) {
755 crc
= PIOS_CRC_updateCRC(crc
, (uint8_t *)InstanceData(instEntry
), (int32_t)obj
->instance_size
);
759 xSemaphoreGiveRecursive(mutex
);
764 * Actually write the object's data to the logfile
765 * \param[in] obj The object handle
766 * \param[in] instId The object instance ID
768 void UAVObjInstanceWriteToLog(UAVObjHandle obj_handle
, uint16_t instId
)
770 PIOS_Assert(obj_handle
);
773 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
775 if (UAVObjIsMetaobject(obj_handle
)) {
779 PIOS_DEBUGLOG_UAVObject(UAVObjGetID(obj_handle
), instId
, MetaNumBytes
, (uint8_t *)MetaDataPtr((struct UAVOMeta
*)obj_handle
));
781 struct UAVOData
*obj
;
782 InstanceHandle instEntry
;
784 // Cast handle to object
785 obj
= (struct UAVOData
*)obj_handle
;
788 instEntry
= getInstance(obj
, instId
);
789 if (instEntry
== NULL
) {
793 PIOS_DEBUGLOG_UAVObject(UAVObjGetID(obj_handle
), instId
, obj
->instance_size
, (uint8_t *)InstanceData(instEntry
));
797 xSemaphoreGiveRecursive(mutex
);
801 * Save the data of the specified object to the file system (SD card).
802 * If the object contains multiple instances, all of them will be saved.
803 * A new file with the name of the object will be created.
804 * The object data can be restored using the UAVObjLoad function.
805 * @param[in] obj The object handle.
806 * @param[in] instId The instance ID
807 * @return 0 if success or -1 if failure
809 int32_t UAVObjSave(UAVObjHandle obj_handle
, uint16_t instId
)
811 PIOS_Assert(obj_handle
);
813 if (UAVObjIsMetaobject(obj_handle
)) {
818 if (PIOS_FLASHFS_ObjSave(pios_uavo_settings_fs_id
, UAVObjGetID(obj_handle
), instId
, (uint8_t *)MetaDataPtr((struct UAVOMeta
*)obj_handle
), UAVObjGetNumBytes(obj_handle
)) != 0) {
822 InstanceHandle instEntry
= getInstance((struct UAVOData
*)obj_handle
, instId
);
824 if (instEntry
== NULL
) {
828 if (InstanceData(instEntry
) == NULL
) {
832 if (PIOS_FLASHFS_ObjSave(pios_uavo_settings_fs_id
, UAVObjGetID(obj_handle
), instId
, InstanceData(instEntry
), UAVObjGetNumBytes(obj_handle
)) != 0) {
841 * Load an object from the file system (SD card).
842 * A file with the name of the object will be opened.
843 * The object data can be saved using the UAVObjSave function.
844 * @param[in] obj The object handle.
845 * @param[in] instId The object instance
846 * @return 0 if success or -1 if failure
848 int32_t UAVObjLoad(UAVObjHandle obj_handle
, uint16_t instId
)
850 PIOS_Assert(obj_handle
);
852 if (UAVObjIsMetaobject(obj_handle
)) {
857 // Fire event on success
858 if (PIOS_FLASHFS_ObjLoad(pios_uavo_settings_fs_id
, UAVObjGetID(obj_handle
), instId
, (uint8_t *)MetaDataPtr((struct UAVOMeta
*)obj_handle
), UAVObjGetNumBytes(obj_handle
)) == 0) {
859 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UNPACKED
);
864 InstanceHandle instEntry
= getInstance((struct UAVOData
*)obj_handle
, instId
);
866 if (instEntry
== NULL
) {
870 // Fire event on success
871 if (PIOS_FLASHFS_ObjLoad(pios_uavo_settings_fs_id
, UAVObjGetID(obj_handle
), instId
, InstanceData(instEntry
), UAVObjGetNumBytes(obj_handle
)) == 0) {
872 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UNPACKED
);
883 * Delete an object from the file system (SD card).
884 * @param[in] obj The object handle.
885 * @param[in] instId The object instance
886 * @return 0 if success or -1 if failure
888 int32_t UAVObjDelete(UAVObjHandle obj_handle
, uint16_t instId
)
890 PIOS_Assert(obj_handle
);
891 PIOS_FLASHFS_ObjDelete(pios_uavo_settings_fs_id
, UAVObjGetID(obj_handle
), instId
);
896 * Save all settings objects to the SD card.
897 * @return 0 if success or -1 if failure
899 int32_t UAVObjSaveSettings()
902 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
906 // Save all settings objects
907 UAVO_LIST_ITERATE(obj
)
908 // Check if this is a settings object
909 if (UAVObjIsSettings(obj
)) {
911 if (UAVObjSave((UAVObjHandle
)obj
, 0) ==
921 xSemaphoreGiveRecursive(mutex
);
926 * Load all settings objects from the SD card.
927 * @return 0 if success or -1 if failure
929 int32_t UAVObjLoadSettings()
932 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
936 // Load all settings objects
937 UAVO_LIST_ITERATE(obj
)
938 // Check if this is a settings object
939 if (UAVObjIsSettings(obj
)) {
941 if (UAVObjLoad((UAVObjHandle
)obj
, 0) ==
951 xSemaphoreGiveRecursive(mutex
);
956 * Delete all settings objects from the SD card.
957 * @return 0 if success or -1 if failure
959 int32_t UAVObjDeleteSettings()
962 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
966 // Save all settings objects
967 UAVO_LIST_ITERATE(obj
)
968 // Check if this is a settings object
969 if (UAVObjIsSettings(obj
)) {
971 if (UAVObjDelete((UAVObjHandle
)obj
, 0)
981 xSemaphoreGiveRecursive(mutex
);
986 * Save all metaobjects to the SD card.
987 * @return 0 if success or -1 if failure
989 int32_t UAVObjSaveMetaobjects()
992 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
996 // Save all settings objects
997 UAVO_LIST_ITERATE(obj
)
999 if (UAVObjSave((UAVObjHandle
)MetaObjectPtr(obj
), 0) ==
1008 xSemaphoreGiveRecursive(mutex
);
1013 * Load all metaobjects from the SD card.
1014 * @return 0 if success or -1 if failure
1016 int32_t UAVObjLoadMetaobjects()
1019 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1023 // Load all settings objects
1024 UAVO_LIST_ITERATE(obj
)
1026 if (UAVObjLoad((UAVObjHandle
)MetaObjectPtr(obj
), 0) ==
1035 xSemaphoreGiveRecursive(mutex
);
1040 * Delete all metaobjects from the SD card.
1041 * @return 0 if success or -1 if failure
1043 int32_t UAVObjDeleteMetaobjects()
1046 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1050 // Load all settings objects
1051 UAVO_LIST_ITERATE(obj
)
1053 if (UAVObjDelete((UAVObjHandle
)MetaObjectPtr(obj
), 0)
1062 xSemaphoreGiveRecursive(mutex
);
1067 * Set the object data
1068 * \param[in] obj The object handle
1069 * \param[in] dataIn The object's data structure
1070 * \return 0 if success or -1 if failure
1072 int32_t UAVObjSetData(UAVObjHandle obj_handle
, const void *dataIn
)
1074 return UAVObjSetInstanceData(obj_handle
, 0, dataIn
);
1078 * Set the object data
1079 * \param[in] obj The object handle
1080 * \param[in] dataIn The object's data structure
1081 * \return 0 if success or -1 if failure
1083 int32_t UAVObjSetDataField(UAVObjHandle obj_handle
, const void *dataIn
, uint32_t offset
, uint32_t size
)
1085 return UAVObjSetInstanceDataField(obj_handle
, 0, dataIn
, offset
, size
);
1089 * Get the object data
1090 * \param[in] obj The object handle
1091 * \param[out] dataOut The object's data structure
1092 * \return 0 if success or -1 if failure
1094 int32_t UAVObjGetData(UAVObjHandle obj_handle
, void *dataOut
)
1096 return UAVObjGetInstanceData(obj_handle
, 0, dataOut
);
1100 * Get the object data
1101 * \param[in] obj The object handle
1102 * \param[out] dataOut The object's data structure
1103 * \return 0 if success or -1 if failure
1105 int32_t UAVObjGetDataField(UAVObjHandle obj_handle
, void *dataOut
, uint32_t offset
, uint32_t size
)
1107 return UAVObjGetInstanceDataField(obj_handle
, 0, dataOut
, offset
, size
);
1111 * Set the data of a specific object instance
1112 * \param[in] obj The object handle
1113 * \param[in] instId The object instance ID
1114 * \param[in] dataIn The object's data structure
1115 * \return 0 if success or -1 if failure
1117 int32_t UAVObjSetInstanceData(UAVObjHandle obj_handle
, uint16_t instId
,
1120 PIOS_Assert(obj_handle
);
1123 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1127 if (UAVObjIsMetaobject(obj_handle
)) {
1131 memcpy(MetaDataPtr((struct UAVOMeta
*)obj_handle
), dataIn
, MetaNumBytes
);
1133 struct UAVOData
*obj
;
1134 InstanceHandle instEntry
;
1136 // Cast to object info
1137 obj
= (struct UAVOData
*)obj_handle
;
1139 // Check access level
1140 if (UAVObjReadOnly(obj_handle
)) {
1143 // Get instance information
1144 instEntry
= getInstance(obj
, instId
);
1145 if (instEntry
== NULL
) {
1149 memcpy(InstanceData(instEntry
), dataIn
, obj
->instance_size
);
1153 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED
);
1157 xSemaphoreGiveRecursive(mutex
);
1162 * Set the data of a specific object instance
1163 * \param[in] obj The object handle
1164 * \param[in] instId The object instance ID
1165 * \param[in] dataIn The object's data structure
1166 * \return 0 if success or -1 if failure
1168 int32_t UAVObjSetInstanceDataField(UAVObjHandle obj_handle
, uint16_t instId
, const void *dataIn
, uint32_t offset
, uint32_t size
)
1170 PIOS_Assert(obj_handle
);
1173 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1177 if (UAVObjIsMetaobject(obj_handle
)) {
1178 // Get instance information
1183 // Check for overrun
1184 if ((size
+ offset
) > MetaNumBytes
) {
1189 memcpy(MetaDataPtr((struct UAVOMeta
*)obj_handle
) + offset
, dataIn
, size
);
1191 struct UAVOData
*obj
;
1192 InstanceHandle instEntry
;
1194 // Cast to object info
1195 obj
= (struct UAVOData
*)obj_handle
;
1197 // Check access level
1198 if (UAVObjReadOnly(obj_handle
)) {
1202 // Get instance information
1203 instEntry
= getInstance(obj
, instId
);
1204 if (instEntry
== NULL
) {
1208 // Check for overrun
1209 if ((size
+ offset
) > obj
->instance_size
) {
1214 memcpy(InstanceData(instEntry
) + offset
, dataIn
, size
);
1219 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED
);
1223 xSemaphoreGiveRecursive(mutex
);
1228 * Get the data of a specific object instance
1229 * \param[in] obj The object handle
1230 * \param[in] instId The object instance ID
1231 * \param[out] dataOut The object's data structure
1232 * \return 0 if success or -1 if failure
1234 int32_t UAVObjGetInstanceData(UAVObjHandle obj_handle
, uint16_t instId
,
1237 PIOS_Assert(obj_handle
);
1240 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1244 if (UAVObjIsMetaobject(obj_handle
)) {
1245 // Get instance information
1250 memcpy(dataOut
, MetaDataPtr((struct UAVOMeta
*)obj_handle
), MetaNumBytes
);
1252 struct UAVOData
*obj
;
1253 InstanceHandle instEntry
;
1255 // Cast to object info
1256 obj
= (struct UAVOData
*)obj_handle
;
1258 // Get instance information
1259 instEntry
= getInstance(obj
, instId
);
1260 if (instEntry
== NULL
) {
1264 memcpy(dataOut
, InstanceData(instEntry
), obj
->instance_size
);
1270 xSemaphoreGiveRecursive(mutex
);
1275 * Get the data of a specific object instance
1276 * \param[in] obj The object handle
1277 * \param[in] instId The object instance ID
1278 * \param[out] dataOut The object's data structure
1279 * \return 0 if success or -1 if failure
1281 int32_t UAVObjGetInstanceDataField(UAVObjHandle obj_handle
, uint16_t instId
, void *dataOut
, uint32_t offset
, uint32_t size
)
1283 PIOS_Assert(obj_handle
);
1286 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1290 if (UAVObjIsMetaobject(obj_handle
)) {
1291 // Get instance information
1296 // Check for overrun
1297 if ((size
+ offset
) > MetaNumBytes
) {
1302 memcpy(dataOut
, MetaDataPtr((struct UAVOMeta
*)obj_handle
) + offset
, size
);
1304 struct UAVOData
*obj
;
1305 InstanceHandle instEntry
;
1307 // Cast to object info
1308 obj
= (struct UAVOData
*)obj_handle
;
1310 // Get instance information
1311 instEntry
= getInstance(obj
, instId
);
1312 if (instEntry
== NULL
) {
1316 // Check for overrun
1317 if ((size
+ offset
) > obj
->instance_size
) {
1322 memcpy(dataOut
, InstanceData(instEntry
) + offset
, size
);
1328 xSemaphoreGiveRecursive(mutex
);
1333 * Set the object metadata
1334 * \param[in] obj The object handle
1335 * \param[in] dataIn The object's metadata structure
1336 * \return 0 if success or -1 if failure
1338 int32_t UAVObjSetMetadata(UAVObjHandle obj_handle
, const UAVObjMetadata
*dataIn
)
1340 PIOS_Assert(obj_handle
);
1342 // Set metadata (metadata of metaobjects can not be modified)
1343 if (UAVObjIsMetaobject(obj_handle
)) {
1347 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1349 UAVObjSetData((UAVObjHandle
)MetaObjectPtr((struct UAVOData
*)obj_handle
), dataIn
);
1351 xSemaphoreGiveRecursive(mutex
);
1356 * Get the object metadata
1357 * \param[in] obj The object handle
1358 * \param[out] dataOut The object's metadata structure
1359 * \return 0 if success or -1 if failure
1361 int32_t UAVObjGetMetadata(UAVObjHandle obj_handle
, UAVObjMetadata
*dataOut
)
1363 PIOS_Assert(obj_handle
);
1366 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1369 if (UAVObjIsMetaobject(obj_handle
)) {
1370 memcpy(dataOut
, &defMetadata
, sizeof(UAVObjMetadata
));
1372 UAVObjGetData((UAVObjHandle
)MetaObjectPtr((struct UAVOData
*)obj_handle
),
1377 xSemaphoreGiveRecursive(mutex
);
1381 /*******************************
1382 * Object Metadata Manipulation
1383 ******************************/
1386 * Get the UAVObject metadata access member
1387 * \param[in] metadata The metadata object
1388 * \return the access type
1390 UAVObjAccessType
UAVObjGetAccess(const UAVObjMetadata
*metadata
)
1392 PIOS_Assert(metadata
);
1393 return (metadata
->flags
>> UAVOBJ_ACCESS_SHIFT
) & 1;
1397 * Set the UAVObject metadata access member
1398 * \param[in] metadata The metadata object
1399 * \param[in] mode The access mode
1401 void UAVObjSetAccess(UAVObjMetadata
*metadata
, UAVObjAccessType mode
)
1403 PIOS_Assert(metadata
);
1404 SET_BITS(metadata
->flags
, UAVOBJ_ACCESS_SHIFT
, mode
, 1);
1408 * Get the UAVObject metadata GCS access member
1409 * \param[in] metadata The metadata object
1410 * \return the GCS access type
1412 UAVObjAccessType
UAVObjGetGcsAccess(const UAVObjMetadata
*metadata
)
1414 PIOS_Assert(metadata
);
1415 return (metadata
->flags
>> UAVOBJ_GCS_ACCESS_SHIFT
) & 1;
1419 * Set the UAVObject metadata GCS access member
1420 * \param[in] metadata The metadata object
1421 * \param[in] mode The access mode
1423 void UAVObjSetGcsAccess(UAVObjMetadata
*metadata
, UAVObjAccessType mode
)
1425 PIOS_Assert(metadata
);
1426 SET_BITS(metadata
->flags
, UAVOBJ_GCS_ACCESS_SHIFT
, mode
, 1);
1430 * Get the UAVObject metadata telemetry acked member
1431 * \param[in] metadata The metadata object
1432 * \return the telemetry acked boolean
1434 uint8_t UAVObjGetTelemetryAcked(const UAVObjMetadata
*metadata
)
1436 PIOS_Assert(metadata
);
1437 return (metadata
->flags
>> UAVOBJ_TELEMETRY_ACKED_SHIFT
) & 1;
1441 * Set the UAVObject metadata telemetry acked member
1442 * \param[in] metadata The metadata object
1443 * \param[in] val The telemetry acked boolean
1445 void UAVObjSetTelemetryAcked(UAVObjMetadata
*metadata
, uint8_t val
)
1447 PIOS_Assert(metadata
);
1448 SET_BITS(metadata
->flags
, UAVOBJ_TELEMETRY_ACKED_SHIFT
, val
, 1);
1452 * Get the UAVObject metadata GCS telemetry acked member
1453 * \param[in] metadata The metadata object
1454 * \return the telemetry acked boolean
1456 uint8_t UAVObjGetGcsTelemetryAcked(const UAVObjMetadata
*metadata
)
1458 PIOS_Assert(metadata
);
1459 return (metadata
->flags
>> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT
) & 1;
1463 * Set the UAVObject metadata GCS telemetry acked member
1464 * \param[in] metadata The metadata object
1465 * \param[in] val The GCS telemetry acked boolean
1467 void UAVObjSetGcsTelemetryAcked(UAVObjMetadata
*metadata
, uint8_t val
)
1469 PIOS_Assert(metadata
);
1470 SET_BITS(metadata
->flags
, UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT
, val
, 1);
1474 * Get the UAVObject metadata telemetry update mode
1475 * \param[in] metadata The metadata object
1476 * \return the telemetry update mode
1478 UAVObjUpdateMode
UAVObjGetTelemetryUpdateMode(const UAVObjMetadata
*metadata
)
1480 PIOS_Assert(metadata
);
1481 return (metadata
->flags
>> UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT
) & UAVOBJ_UPDATE_MODE_MASK
;
1485 * Set the UAVObject metadata telemetry update mode member
1486 * \param[in] metadata The metadata object
1487 * \param[in] val The telemetry update mode
1489 void UAVObjSetTelemetryUpdateMode(UAVObjMetadata
*metadata
, UAVObjUpdateMode val
)
1491 PIOS_Assert(metadata
);
1492 SET_BITS(metadata
->flags
, UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT
, val
, UAVOBJ_UPDATE_MODE_MASK
);
1496 * Get the UAVObject metadata GCS telemetry update mode
1497 * \param[in] metadata The metadata object
1498 * \return the GCS telemetry update mode
1500 UAVObjUpdateMode
UAVObjGetGcsTelemetryUpdateMode(const UAVObjMetadata
*metadata
)
1502 PIOS_Assert(metadata
);
1503 return (metadata
->flags
>> UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT
) & UAVOBJ_UPDATE_MODE_MASK
;
1507 * Set the UAVObject metadata GCS telemetry update mode member
1508 * \param[in] metadata The metadata object
1509 * \param[in] val The GCS telemetry update mode
1511 void UAVObjSetGcsTelemetryUpdateMode(UAVObjMetadata
*metadata
, UAVObjUpdateMode val
)
1513 PIOS_Assert(metadata
);
1514 SET_BITS(metadata
->flags
, UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT
, val
, UAVOBJ_UPDATE_MODE_MASK
);
1518 * Get the UAVObject metadata logging update mode
1519 * \param[in] metadata The metadata object
1520 * \return the GCS telemetry update mode
1522 UAVObjUpdateMode
UAVObjGetLoggingUpdateMode(const UAVObjMetadata
*metadata
)
1524 PIOS_Assert(metadata
);
1525 return (metadata
->flags
>> UAVOBJ_LOGGING_UPDATE_MODE_SHIFT
) & UAVOBJ_UPDATE_MODE_MASK
;
1529 * Set the UAVObject metadata logging update mode member
1530 * \param[in] metadata The metadata object
1531 * \param[in] val The GCS telemetry update mode
1533 void UAVObjSetLoggingUpdateMode(UAVObjMetadata
*metadata
, UAVObjUpdateMode val
)
1535 PIOS_Assert(metadata
);
1536 SET_BITS(metadata
->flags
, UAVOBJ_LOGGING_UPDATE_MODE_SHIFT
, val
, UAVOBJ_UPDATE_MODE_MASK
);
1541 * Check if an object is read only
1542 * \param[in] obj The object handle
1544 * \arg 0 if not read only
1545 * \arg 1 if read only
1546 * \arg -1 if unable to get meta data
1548 int8_t UAVObjReadOnly(UAVObjHandle obj_handle
)
1550 PIOS_Assert(obj_handle
);
1551 if (!UAVObjIsMetaobject(obj_handle
)) {
1552 return UAVObjGetAccess(LinkedMetaDataPtr((struct UAVOData
*)obj_handle
)) == ACCESS_READONLY
;
1558 * Connect an event queue to the object, if the queue is already connected then the event mask is only updated.
1559 * All events matching the event mask will be pushed to the event queue.
1560 * \param[in] obj The object handle
1561 * \param[in] queue The event queue
1562 * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
1563 * \return 0 if success or -1 if failure
1565 int32_t UAVObjConnectQueue(UAVObjHandle obj_handle
, xQueueHandle queue
,
1568 PIOS_Assert(obj_handle
);
1571 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1572 res
= connectObj(obj_handle
, queue
, 0, eventMask
);
1573 xSemaphoreGiveRecursive(mutex
);
1578 * Disconnect an event queue from the object.
1579 * \param[in] obj The object handle
1580 * \param[in] queue The event queue
1581 * \return 0 if success or -1 if failure
1583 int32_t UAVObjDisconnectQueue(UAVObjHandle obj_handle
, xQueueHandle queue
)
1585 PIOS_Assert(obj_handle
);
1588 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1589 res
= disconnectObj(obj_handle
, queue
, 0);
1590 xSemaphoreGiveRecursive(mutex
);
1595 * Connect an event callback to the object, if the callback is already connected then the event mask is only updated.
1596 * The supplied callback will be invoked on all events matching the event mask.
1597 * \param[in] obj The object handle
1598 * \param[in] cb The event callback
1599 * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
1600 * \return 0 if success or -1 if failure
1602 int32_t UAVObjConnectCallback(UAVObjHandle obj_handle
, UAVObjEventCallback cb
,
1605 PIOS_Assert(obj_handle
);
1607 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1608 res
= connectObj(obj_handle
, 0, cb
, eventMask
);
1609 xSemaphoreGiveRecursive(mutex
);
1614 * Disconnect an event callback from the object.
1615 * \param[in] obj The object handle
1616 * \param[in] cb The event callback
1617 * \return 0 if success or -1 if failure
1619 int32_t UAVObjDisconnectCallback(UAVObjHandle obj_handle
, UAVObjEventCallback cb
)
1621 PIOS_Assert(obj_handle
);
1623 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1624 res
= disconnectObj(obj_handle
, 0, cb
);
1625 xSemaphoreGiveRecursive(mutex
);
1630 * Request an update of the object's data from the GCS. The call will not wait for the response, a EV_UPDATED event
1631 * will be generated as soon as the object is updated.
1632 * \param[in] obj The object handle
1634 void UAVObjRequestUpdate(UAVObjHandle obj_handle
)
1636 UAVObjRequestInstanceUpdate(obj_handle
, UAVOBJ_ALL_INSTANCES
);
1640 * Request an update of the object's data from the GCS.
1641 * The call will not wait for the response, a EV_UPDATED event will be generated as soon as the object is updated.
1642 * \param[in] obj The object handle
1643 * \param[in] instId Object instance ID to update
1645 void UAVObjRequestInstanceUpdate(UAVObjHandle obj_handle
, uint16_t instId
)
1647 PIOS_Assert(obj_handle
);
1648 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1649 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATE_REQ
);
1650 xSemaphoreGiveRecursive(mutex
);
1654 * Trigger a EV_UPDATED_MANUAL event for an object.
1655 * \param[in] obj The object handle
1657 void UAVObjUpdated(UAVObjHandle obj_handle
)
1659 UAVObjInstanceUpdated(obj_handle
, UAVOBJ_ALL_INSTANCES
);
1663 * Trigger a EV_UPDATED_MANUAL event for an object instance.
1664 * \param[in] obj The object handle
1665 * \param[in] instId The object instance ID
1667 void UAVObjInstanceUpdated(UAVObjHandle obj_handle
, uint16_t instId
)
1669 PIOS_Assert(obj_handle
);
1670 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1671 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED_MANUAL
);
1672 xSemaphoreGiveRecursive(mutex
);
1676 * Trigger a EV_UPDATED event for an object instance.
1677 * \param[in] obj The object handle
1678 * \param[in] instId The object instance ID
1680 static void instanceAutoUpdated(UAVObjHandle obj_handle
, uint16_t instId
)
1682 PIOS_Assert(obj_handle
);
1683 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1684 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED
);
1685 xSemaphoreGiveRecursive(mutex
);
1689 * Log the object's data (triggers a EV_LOGGING_MANUAL event on this object).
1690 * \param[in] obj The object handle
1692 void UAVObjLogging(UAVObjHandle obj_handle
)
1694 UAVObjInstanceLogging(obj_handle
, UAVOBJ_ALL_INSTANCES
);
1698 * Log the object's data (triggers a EV_LOGGING_MANUAL event on this object).
1699 * \param[in] obj The object handle
1700 * \param[in] instId The object instance ID
1702 void UAVObjInstanceLogging(UAVObjHandle obj_handle
, uint16_t instId
)
1704 PIOS_Assert(obj_handle
);
1705 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1706 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_LOGGING_MANUAL
);
1707 xSemaphoreGiveRecursive(mutex
);
1711 * Iterate through all objects in the list.
1712 * \param iterator This function will be called once for each object,
1713 * the object will be passed as a parameter
1715 void UAVObjIterate(void (*iterator
)(UAVObjHandle obj
))
1717 PIOS_Assert(iterator
);
1720 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1722 // Iterate through the list and invoke iterator for each object
1723 UAVO_LIST_ITERATE (obj
)
1724 (*iterator
)((UAVObjHandle
)obj
);
1725 (*iterator
)((UAVObjHandle
) &obj
->metaObj
);
1729 xSemaphoreGiveRecursive(mutex
);
1733 * Send a triggered event to all event queues registered on the object.
1735 static int32_t sendEvent(struct UAVOBase
*obj
, uint16_t instId
, UAVObjEventType triggered_event
)
1737 /* Set up the message that will be sent to all registered listeners */
1739 .obj
= (UAVObjHandle
)obj
,
1740 .event
= triggered_event
,
1742 .lowPriority
= false,
1745 // Go through each object and push the event message in the queue (if event is activated for the queue)
1746 struct ObjectEventEntry
*event
;
1748 LL_FOREACH(obj
->next_event
, event
) {
1749 if (event
->eventMask
== 0 || (event
->eventMask
& triggered_event
) != 0) {
1750 // Send to queue if a valid queue is registered
1753 if (xQueueSend(event
->queue
, &msg
, 0) != pdTRUE
) {
1754 ++stats
.eventQueueErrors
;
1755 stats
.lastQueueErrorID
= UAVObjGetID(obj
);
1759 // Invoke callback (from event task) if a valid one is registered
1761 // invoke callback from the event task, will not block
1762 if (EventCallbackDispatch(&msg
, event
->cb
) != pdTRUE
) {
1763 ++stats
.eventCallbackErrors
;
1764 stats
.lastCallbackErrorID
= UAVObjGetID(obj
);
1774 * Create a new object instance, return the instance info or NULL if failure.
1776 static InstanceHandle
createInstance(struct UAVOData
*obj
, uint16_t instId
)
1778 struct UAVOMultiInst
*instEntry
;
1780 /* Don't allow more than one instance for single instance objects */
1781 if (UAVObjIsSingleInstance(&(obj
->base
))) {
1786 /* Don't create more than the allowed number of instances */
1787 if (instId
>= UAVOBJ_MAX_INSTANCES
) {
1791 /* Don't allow duplicate instances */
1792 if (instId
< UAVObjGetNumInstances(&(obj
->base
))) {
1796 // Create any missing instances (all instance IDs must be sequential)
1797 for (uint16_t n
= UAVObjGetNumInstances(&(obj
->base
)); n
< instId
; ++n
) {
1798 if (createInstance(obj
, n
) == NULL
) {
1803 /* Create the actual instance */
1804 uint32_t size
= sizeof(struct UAVOMultiInst
) + obj
->instance_size
;
1805 instEntry
= (struct UAVOMultiInst
*)pios_malloc(size
);
1809 memset(instEntry
, 0, size
);
1810 LL_APPEND(((struct UAVOMulti
*)obj
)->instance0
.next
, instEntry
);
1812 ((struct UAVOMulti
*)obj
)->num_instances
++;
1815 instanceAutoUpdated((UAVObjHandle
)obj
, instId
);
1818 return InstanceDataOffset(instEntry
);
1822 * Get the instance information or NULL if the instance does not exist
1824 static InstanceHandle
getInstance(struct UAVOData
*obj
, uint16_t instId
)
1826 if (UAVObjIsMetaobject(&obj
->base
)) {
1827 /* Metadata Instance */
1833 /* Augment our pointer to reflect the proper type */
1834 struct UAVOMeta
*uavo_meta
= (struct UAVOMeta
*)obj
;
1835 return &(uavo_meta
->instance0
);
1836 } else if (UAVObjIsSingleInstance(&(obj
->base
))) {
1837 /* Single Instance */
1843 /* Augment our pointer to reflect the proper type */
1844 struct UAVOSingle
*uavo_single
= (struct UAVOSingle
*)obj
;
1845 return &(uavo_single
->instance0
);
1847 /* Multi Instance */
1848 /* Augment our pointer to reflect the proper type */
1849 struct UAVOMulti
*uavo_multi
= (struct UAVOMulti
*)obj
;
1850 if (instId
>= uavo_multi
->num_instances
) {
1854 // Look for specified instance ID
1855 uint16_t instance
= 0;
1856 struct UAVOMultiInst
*instEntry
;
1857 LL_FOREACH(&(uavo_multi
->instance0
), instEntry
) {
1858 if (instance
++ == instId
) {
1860 return &(instEntry
->instance
);
1863 /* Instance was not found */
1869 * Connect an event queue to the object, if the queue is already connected then the event mask is only updated.
1870 * \param[in] obj The object handle
1871 * \param[in] queue The event queue
1872 * \param[in] cb The event callback
1873 * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
1874 * \return 0 if success or -1 if failure
1876 static int32_t connectObj(UAVObjHandle obj_handle
, xQueueHandle queue
,
1877 UAVObjEventCallback cb
, uint8_t eventMask
)
1879 struct ObjectEventEntry
*event
;
1880 struct UAVOBase
*obj
;
1882 // Check that the queue is not already connected, if it is simply update event mask
1883 obj
= (struct UAVOBase
*)obj_handle
;
1884 LL_FOREACH(obj
->next_event
, event
) {
1885 if (event
->queue
== queue
&& event
->cb
== cb
) {
1886 // Already connected, update event mask and return
1887 event
->eventMask
= eventMask
;
1892 // Add queue to list
1893 event
= (struct ObjectEventEntry
*)pios_malloc(sizeof(struct ObjectEventEntry
));
1894 if (event
== NULL
) {
1897 event
->queue
= queue
;
1899 event
->eventMask
= eventMask
;
1900 LL_APPEND(obj
->next_event
, event
);
1907 * Disconnect an event queue from the object
1908 * \param[in] obj The object handle
1909 * \param[in] queue The event queue
1910 * \param[in] cb The event callback
1911 * \return 0 if success or -1 if failure
1913 static int32_t disconnectObj(UAVObjHandle obj_handle
, xQueueHandle queue
,
1914 UAVObjEventCallback cb
)
1916 struct ObjectEventEntry
*event
;
1917 struct UAVOBase
*obj
;
1919 // Find queue and remove it
1920 obj
= (struct UAVOBase
*)obj_handle
;
1921 LL_FOREACH(obj
->next_event
, event
) {
1922 if ((event
->queue
== queue
1923 && event
->cb
== cb
)) {
1924 LL_DELETE(obj
->next_event
, event
);
1930 // If this point is reached the queue was not found