dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uavobjectmanager.c
Go to the documentation of this file.
1 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26  * for more details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with this program; if not, see <http://www.gnu.org/licenses/>
30  *
31  * Additional note on redistribution: The copyright and license notices above
32  * must be maintained in each individual source file that is a derivative work
33  * of this source file; otherwise redistribution is prohibited.
34  */
35 
36 #include "openpilot.h"
37 #include <utlist.h>
38 
39 #include "pios_struct_helper.h"
40 #include "pios_heap.h" /* PIOS_malloc_no_dma */
41 #include "pios_mutex.h"
42 #include "pios_queue.h"
43 #include "pios_thread.h"
44 #include "misc_math.h"
45 
46 extern uintptr_t pios_uavo_settings_fs_id;
47 
48 // Constants
49 
50 // Private types
51 
52 // Macros
53 #define SET_BITS(var, shift, value, mask) var = (var & ~(mask << shift)) | (value << shift);
54 
60 typedef void* InstanceHandle;
61 
63  union {
64  struct pios_queue *queue;
65  void *cbCtx;
66  } cbInfo;
67 
69  uint8_t hasThrottle : 1;
70  uint8_t eventMask : 7;
72 };
73 
75  struct ObjectEventEntry entry; // MUST be first! So throttled entry can be interpreted as ObjectEventEntry
76 
77  uint32_t when;
78  uint16_t interval;
79  volatile uint8_t inhibited;
80 };
81 
82 /*
83  MetaInstance == [UAVOBase [UAVObjMetadata]]
84  SingleInstance == [UAVOBase [UAVOData [InstanceData]]]
85  MultiInstance == [UAVOBase [UAVOData [NumInstances [InstanceData0 [next]]]]
86  ____________________/
87  \-->[InstanceData1 [next]]
88  _________...________/
89  \-->[InstanceDataN [next]]
90  */
91 
92 /*
93  * UAVO Base Type
94  * - All Types of UAVObjects are of this base type
95  * - The flags determine what type(s) this object
96  */
97 struct UAVOBase {
98  /* Let these objects be added to an event queue */
100 
101  /* Describe the type of object that follows this header */
102  struct UAVOInfo {
103  bool isMeta : 1;
104  bool isSingle : 1;
105  bool isSettings : 1;
106  } flags;
107 
108 } __attribute__((packed));
109 
110 /* Augmented type for Meta UAVO */
111 struct UAVOMeta {
112  struct UAVOBase base;
113  UAVObjMetadata instance0;
114 } __attribute__((packed));
115 
116 /* Shared data structure for all data-carrying UAVObjects (UAVOSingle and UAVOMulti) */
117 struct UAVOData {
118  struct UAVOBase base;
119  uint32_t id;
120  /*
121  * Embed the Meta object as another complete UAVO
122  * inside the payload for this UAVO.
123  */
125  struct UAVOData * next;
126  uint16_t instance_size;
127 } __attribute__((packed));
128 
129 /* Augmented type for Single Instance Data UAVO */
130 struct UAVOSingle {
131  struct UAVOData uavo;
132 
133  uint8_t instance0[];
134  /*
135  * Additional space will be malloc'd here to hold the
136  * the data for this instance.
137  */
138 } __attribute__((packed));
139 
140 /* Part of a linked list of instances chained off of a multi instance UAVO. */
142  struct UAVOMultiInst * next;
143  uint8_t instance[];
144  /*
145  * Additional space will be malloc'd here to hold the
146  * the data for this instance.
147  */
148 } __attribute__((packed));
149 
150 /* Augmented type for Multi Instance Data UAVO */
151 struct UAVOMulti {
152  struct UAVOData uavo;
153 
154  uint16_t num_instances;
156  /*
157  * Additional space will be malloc'd here to hold the
158  * the data for instance 0.
159  */
160 } __attribute__((packed));
161 
163 #define MetaNumBytes sizeof(UAVObjMetadata)
164 
165 /* XXX TODO: All this reckless casting needs to die a horrific death! */
166 #define MetaBaseObjectPtr(obj) ((struct UAVOData *)((obj)-offsetof(struct UAVOData, metaObj)))
167 //#define MetaObjectPtr(obj) ((struct UAVOMeta*) &((obj)->metaObj))
168 #define MetaObjectPtr(obj) (&((obj)->metaObj.base))
169 #define MetaDataPtr(obj) ((UAVObjMetadata*)&((obj)->instance0))
170 #define LinkedMetaDataPtr(obj) ((UAVObjMetadata*)&((obj)->metaObj.instance0))
171 #define MetaObjectId(id) ((id)+1)
172 
174 #define ObjSingleInstanceDataOffset(obj) ((void*)(&(( (struct UAVOSingle*)obj )->instance0)))
175 #define InstanceDataOffset(inst) ((void*)&(( (struct UAVOMultiInst*)inst )->instance))
176 #define InstanceData(instance) (void*)instance
177 
178 // Private functions
179 static int32_t sendEvent(struct UAVOBase *obj, uint16_t instId,
180  UAVObjEventType event, void *obj_data, int len);
181 static InstanceHandle createInstance(struct UAVOData * obj, uint16_t instId);
182 static InstanceHandle getInstance(struct UAVOData * obj, uint16_t instId);
183 static int32_t connectObj(UAVObjHandle obj_handle, struct pios_queue *queue,
184  UAVObjEventCallback cb, void *cbCtx, uint8_t eventMask,
185  uint16_t interval);
186 static int32_t disconnectObj(UAVObjHandle obj_handle, struct pios_queue *queue,
187  UAVObjEventCallback cb, void *cbCtx);
188 
189 // Private variables
190 static struct UAVOData * uavo_list;
194 static const UAVObjMetadata defMetadata = {
201  .telemetryUpdatePeriod = 0,
202  .gcsTelemetryUpdatePeriod = 0,
203  .loggingUpdatePeriod = 0,
204 };
205 
208 
209 #define UAVO_CB_STACK_SIZE 512
210 
211 static void *cb_stack;
212 
219 {
220  // Initialize variables
221  uavo_list = NULL;
222  events_unused = NULL;
223  events_unused_throttled = NULL;
224 
225  // Allocate the stack used for callbacks.
227 
228  PIOS_Assert(cb_stack);
229 
230  // ARM stack grows down, so we should point to the "top valid" location
231  cb_stack += UAVO_CB_STACK_SIZE - 4;
232 
233  memset(&stats, 0, sizeof(UAVObjStats));
234 
235  // Create mutex
236  mutex = PIOS_Recursive_Mutex_Create();
237  if (mutex == NULL)
238  return -1;
239  // Done
240  return 0;
241 }
242 
243 /*****************
244  * Statistics
245  ****************/
246 
251 void UAVObjGetStats(UAVObjStats * statsOut)
252 {
254  memcpy(statsOut, &stats, sizeof(UAVObjStats));
256 }
257 
262 {
264  memset(&stats, 0, sizeof(UAVObjStats));
266 }
267 
268 /************************
269  * Object Initialization
270  ***********************/
271 
272 static void UAVObjInitMetaData (struct UAVOMeta * obj_meta)
273 {
274  /* Fill in the common part of the UAVO */
275  struct UAVOBase * uavo_base = &(obj_meta->base);
276  memset(uavo_base, 0, sizeof(*uavo_base));
277  uavo_base->flags.isMeta = true;
278  uavo_base->flags.isSingle = true;
279  uavo_base->next_event = NULL;
280 
281  /* Clear the instance data carried in the UAVO */
282  memset(&(obj_meta->instance0), 0, sizeof(obj_meta->instance0));
283 }
284 
285 static struct UAVOData * UAVObjAllocSingle(uint32_t num_bytes)
286 {
287  /* Compute the complete size of the object, including the data for a single embedded instance */
288  uint32_t object_size = sizeof(struct UAVOSingle) + num_bytes;
289 
290  /* Allocate the object from the heap */
291  struct UAVOSingle * uavo_single = (struct UAVOSingle *) PIOS_malloc_no_dma(object_size);
292  if (!uavo_single)
293  return (NULL);
294 
295  /* Fill in the common part of the UAVO */
296  struct UAVOBase * uavo_base = &(uavo_single->uavo.base);
297  memset(uavo_base, 0, sizeof(*uavo_base));
298  uavo_base->flags.isSingle = true;
299  uavo_base->next_event = NULL;
300 
301  /* Clear the instance data carried in the UAVO */
302  memset(&(uavo_single->instance0), 0, num_bytes);
303 
304  /* Give back the generic UAVO part */
305  return (&(uavo_single->uavo));
306 }
307 
308 static struct UAVOData * UAVObjAllocMulti(uint32_t num_bytes)
309 {
310  /* Compute the complete size of the object, including the data for a single embedded instance */
311  uint32_t object_size = sizeof(struct UAVOMulti) + num_bytes;
312 
313  /* Allocate the object from the heap */
314  struct UAVOMulti * uavo_multi = (struct UAVOMulti *) PIOS_malloc_no_dma(object_size);
315  if (!uavo_multi)
316  return (NULL);
317 
318  /* Fill in the common part of the UAVO */
319  struct UAVOBase * uavo_base = &(uavo_multi->uavo.base);
320  memset(uavo_base, 0, sizeof(*uavo_base));
321  uavo_base->flags.isSingle = false;
322  uavo_base->next_event = NULL;
323 
324  /* Set up the type-specific part of the UAVO */
325  uavo_multi->num_instances = 1;
326 
327  /* Clear the instance data carried in the UAVO */
328  uavo_multi->instance0.next = NULL;
329  memset (&(uavo_multi->instance0.instance), 0, num_bytes);
330 
331  /* Give back the generic UAVO part */
332  return (&(uavo_multi->uavo));
333 }
334 
335 /**************************
336  * UAVObject Database APIs
337  *************************/
338 
350  int32_t isSingleInstance, int32_t isSettings,
351  uint32_t num_bytes,
353 {
354  struct UAVOData * uavo_data = NULL;
355 
357 
358  /* Don't allow duplicate registrations */
359  if (UAVObjGetByID(id))
360  goto unlock_exit;
361 
362  /* Map the various flags to one of the UAVO types we understand */
363  if (isSingleInstance) {
364  uavo_data = UAVObjAllocSingle (num_bytes);
365  } else {
366  uavo_data = UAVObjAllocMulti (num_bytes);
367  }
368 
369  if (!uavo_data)
370  goto unlock_exit;
371 
372  /* Fill in the details about this UAVO */
373  uavo_data->id = id;
374  uavo_data->instance_size = num_bytes;
375  if (isSettings) {
376  uavo_data->base.flags.isSettings = true;
377  }
378 
379  /* Initialize the embedded meta UAVO */
380  UAVObjInitMetaData (&uavo_data->metaObj);
381 
382  /* Add the newly created object to the global list of objects */
383  LL_APPEND(uavo_list, uavo_data);
384 
385  /* Initialize object fields and metadata to default values */
386  if (initCb)
387  initCb((UAVObjHandle) uavo_data, 0);
388 
389  /* Always try to load the meta object from flash */
390  UAVObjLoad((UAVObjHandle) &(uavo_data->metaObj), 0);
391 
392  /* Attempt to load settings object from flash */
393  if (uavo_data->base.flags.isSettings)
394  UAVObjLoad((UAVObjHandle) uavo_data, 0);
395 
396  // fire events for outer object and its embedded meta object
397  UAVObjInstanceUpdated((UAVObjHandle) uavo_data, 0);
398  UAVObjInstanceUpdated((UAVObjHandle) &(uavo_data->metaObj), 0);
399 
400 unlock_exit:
402  return (UAVObjHandle) uavo_data;
403 }
404 
411 {
412  UAVObjHandle found_obj = NULL;
413 
414  // Get lock
416 
417  // Look for object
418  struct UAVOData * tmp_obj;
419  LL_FOREACH(uavo_list, tmp_obj) {
420  if (tmp_obj->id == id) {
421  found_obj = &tmp_obj->base;
422  goto unlock_exit;
423  }
424  if (MetaObjectId(tmp_obj->id) == id) {
425  found_obj = &(tmp_obj->metaObj.base);
426  goto unlock_exit;
427  }
428  }
429 
430 unlock_exit:
432  return found_obj;
433 }
434 
440 uint32_t UAVObjGetID(UAVObjHandle obj_handle)
441 {
442  PIOS_Assert(obj_handle);
443 
444  /* Recover the common object header */
445  struct UAVOBase * uavo_base = (struct UAVOBase *) obj_handle;
446 
447  if (UAVObjIsMetaobject(obj_handle)) {
448  /* We have a meta object, find our containing UAVO */
449  struct UAVOData * uavo_data = container_of ((struct UAVOMeta *)uavo_base, struct UAVOData, metaObj);
450 
451  return MetaObjectId (uavo_data->id);
452  } else {
453  /* We have a data object, augment our pointer */
454  struct UAVOData * uavo_data = (struct UAVOData *) uavo_base;
455 
456  return (uavo_data->id);
457  }
458 }
459 
466 {
467  PIOS_Assert(obj);
468 
469  uint32_t instance_size;
470 
471  /* Recover the common object header */
472  struct UAVOBase * uavo_base = (struct UAVOBase *) obj;
473 
474  if (uavo_base->flags.isMeta) {
475  instance_size = MetaNumBytes;
476  } else {
477  /* We have a data object, augment our pointer */
478  struct UAVOData * uavo = (struct UAVOData *) uavo_base;
479 
480  instance_size = uavo->instance_size;
481  }
482 
483  return (instance_size);
484 }
485 
494 {
495  PIOS_Assert(obj_handle);
496 
497  /* Recover the common object header */
498  struct UAVOBase * uavo_base = (struct UAVOBase *) obj_handle;
499 
500  if (UAVObjIsMetaobject(obj_handle)) {
501  /* We have a meta object, find our containing UAVO. */
502  struct UAVOData * uavo_data = container_of ((struct UAVOMeta *)uavo_base, struct UAVOData, metaObj);
503 
504  return (UAVObjHandle) uavo_data;
505  } else {
506  /* We have a data object, augment our pointer */
507  struct UAVOData * uavo_data = (struct UAVOData *) uavo_base;
508 
509  return (UAVObjHandle) &(uavo_data->metaObj);
510  }
511 }
512 
519 {
520  PIOS_Assert(obj_handle);
521 
522  if (UAVObjIsSingleInstance(obj_handle)) {
523  /* Only one instance is allowed */
524  return 1;
525  } else {
526  /* Multi-instance object. Inspect the object */
527  /* Augment our pointer to reflect the proper type */
528  struct UAVOMulti * uavo_multi = (struct UAVOMulti *) obj_handle;
529  return uavo_multi->num_instances;
530  }
531 }
532 
539 {
540  PIOS_Assert(obj_handle);
541  if (UAVObjIsMetaobject(obj_handle)) {
542  return 0;
543  }
544 
545  // Lock
547 
548  InstanceHandle instEntry;
549  uint16_t instId = 0;
550 
551  // Create new instance
552  instId = UAVObjGetNumInstances(obj_handle);
553  instEntry = createInstance((struct UAVOData *) obj_handle, instId);
554  if (instEntry == NULL) {
555  goto unlock_exit;
556  }
557 
558  // Initialize instance data
559  if (initCb) {
560  initCb(obj_handle, instId);
561  }
562 
563 unlock_exit:
565 
566  return instId;
567 }
568 
575 {
576  PIOS_Assert(obj_handle);
577 
578  return obj_handle->flags.isSingle;
579 }
580 
587 {
588  PIOS_Assert(obj_handle);
589 
590  /* Recover the common object header */
591  struct UAVOBase * uavo_base = (struct UAVOBase *) obj_handle;
592 
593  return uavo_base->flags.isMeta;
594 }
595 
602 {
603  PIOS_Assert(obj_handle);
604 
605  /* Recover the common object header */
606  struct UAVOBase * uavo_base = (struct UAVOBase *) obj_handle;
607 
608  return uavo_base->flags.isSettings;
609 }
610 
618 int32_t UAVObjUnpack(UAVObjHandle obj_handle, uint16_t instId,
619  const uint8_t * dataIn)
620 {
621  PIOS_Assert(obj_handle);
622 
623  // Lock
625 
626  int32_t rc = -1;
627 
628  void *target;
629  int len;
630 
631  if (UAVObjIsMetaobject(obj_handle)) {
632  if (instId != 0) {
633  goto unlock_exit;
634  }
635 
636  target = MetaDataPtr((struct UAVOMeta *)obj_handle);
637  len = MetaNumBytes;
638  memcpy(MetaDataPtr((struct UAVOMeta *)obj_handle), dataIn, MetaNumBytes);
639  } else {
640  struct UAVOData *obj;
641  InstanceHandle instEntry;
642 
643  // Cast handle to object
644  obj = (struct UAVOData *) obj_handle;
645 
646  // Get the instance
647  instEntry = getInstance(obj, instId);
648 
649  // If the instance does not exist create it and any other instances before it
650  if (instEntry == NULL) {
651  instEntry = createInstance(obj, instId);
652  if (instEntry == NULL) {
653  goto unlock_exit;
654  }
655  }
656  // Set the data
657 
658  target = InstanceData(instEntry);
659  len = obj->instance_size;
660  }
661 
662  memcpy(target, dataIn, len);
663 
664  // Fire event
665  sendEvent((struct UAVOBase*)obj_handle, instId, EV_UNPACKED,
666  target, len);
667 
668  rc = 0;
669 
670 unlock_exit:
672  return rc;
673 }
674 
682 int32_t UAVObjPack(UAVObjHandle obj_handle, uint16_t instId, uint8_t * dataOut)
683 {
684  PIOS_Assert(obj_handle);
685 
686  // Lock
688 
689  int32_t rc = -1;
690 
691  if (UAVObjIsMetaobject(obj_handle)) {
692  if (instId != 0) {
693  goto unlock_exit;
694  }
695  memcpy(dataOut, MetaDataPtr((struct UAVOMeta *)obj_handle), MetaNumBytes);
696  } else {
697  struct UAVOData *obj;
698  InstanceHandle instEntry;
699 
700  // Cast handle to object
701  obj = (struct UAVOData *) obj_handle;
702 
703  // Get the instance
704  instEntry = getInstance(obj, instId);
705  if (instEntry == NULL) {
706  goto unlock_exit;
707  }
708  // Pack data
709  memcpy(dataOut, InstanceData(instEntry), obj->instance_size);
710  }
711 
712  rc = 0;
713 
714 unlock_exit:
716  return rc;
717 }
718 
719 #if defined(PIOS_INCLUDE_FASTHEAP)
720 
726 static uint8_t uavobj_save_trampoline[256] __attribute__((aligned(4)));
727 #endif /* PIOS_INCLUDE_FASTHEAP */
728 
739 int32_t UAVObjSave(UAVObjHandle obj_handle, uint16_t instId)
740 {
741  PIOS_Assert(obj_handle);
742 
743  if (UAVObjIsMetaobject(obj_handle)) {
744  if (instId != 0)
745  return -1;
746 
747  // Save the object to the filesystem
748  int32_t rc;
749 #if defined(PIOS_INCLUDE_FASTHEAP)
750  memcpy(uavobj_save_trampoline,
751  MetaDataPtr((struct UAVOMeta *)obj_handle),
752  UAVObjGetNumBytes(obj_handle));
753 
755  UAVObjGetID(obj_handle),
756  instId,
757  uavobj_save_trampoline,
758  UAVObjGetNumBytes(obj_handle));
759 #else /* PIOS_INCLUDE_FASTHEAP */
761  UAVObjGetID(obj_handle),
762  instId,
763  (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle),
764  UAVObjGetNumBytes(obj_handle));
765 #endif /* PIOS_INCLUDE_FASTHEAP */
766 
767  if (rc != 0)
768  return -1;
769  } else {
770  InstanceHandle instEntry = getInstance( (struct UAVOData *)obj_handle, instId);
771 
772  if (instEntry == NULL)
773  return -1;
774 
775  if (InstanceData(instEntry) == NULL)
776  return -1;
777 
778  // Save the object to the filesystem
779  int32_t rc;
780 #if defined(PIOS_INCLUDE_FASTHEAP)
781  memcpy(uavobj_save_trampoline,
782  InstanceData(instEntry),
783  UAVObjGetNumBytes(obj_handle));
784 
786  UAVObjGetID(obj_handle),
787  instId,
788  uavobj_save_trampoline,
789  UAVObjGetNumBytes(obj_handle));
790 #else /* PIOS_INCLUDE_FASTHEAP */
792  UAVObjGetID(obj_handle),
793  instId,
794  InstanceData(instEntry),
795  UAVObjGetNumBytes(obj_handle));
796 #endif /* PIOS_INCLUDE_FASTHEAP */
797 
798  if (rc != 0)
799  return -1;
800  }
801 
802  return 0;
803 }
804 
805 #if defined(PIOS_INCLUDE_FASTHEAP)
806 
812 static uint8_t uavobj_load_trampoline[256] __attribute__((aligned(4)));
813 #endif /* PIOS_INCLUDE_FASTHEAP */
814 
823 int32_t UAVObjLoad(UAVObjHandle obj_handle, uint16_t instId)
824 {
825  PIOS_Assert(obj_handle);
826 
827  void *target;
828  int len;
829 
830  if (UAVObjIsMetaobject(obj_handle)) {
831  if (instId != 0)
832  return -1;
833 
834  target = MetaDataPtr((struct UAVOMeta *)obj_handle);
835  len = UAVObjGetNumBytes(obj_handle);
836  } else {
837 
838  InstanceHandle instEntry = getInstance( (struct UAVOData *)obj_handle, instId);
839 
840  if (instEntry == NULL)
841  return -1;
842 
843  target = InstanceData(instEntry);
844  len = UAVObjGetNumBytes(obj_handle);
845  }
846 
847  // Load the object from the filesystem
848  int32_t rc;
849 #if defined(PIOS_INCLUDE_FASTHEAP)
851  UAVObjGetID(obj_handle),
852  instId,
853  uavobj_load_trampoline,
854  len);
855 #else /* PIOS_INCLUDE_FASTHEAP */
857  UAVObjGetID(obj_handle),
858  instId,
859  target,
860  len);
861 #endif /* PIOS_INCLUDE_FASTHEAP */
862 
863  if (rc != 0)
864  return -1;
865 
866 #if defined(PIOS_INCLUDE_FASTHEAP)
867  memcpy(target, uavobj_load_trampoline, len);
868 #endif /* PIOS_INCLUDE_FASTHEAP */
869 
870  sendEvent((struct UAVOBase*)obj_handle, instId, EV_UNPACKED, target, len);
871  return 0;
872 }
873 
880 int32_t UAVObjDeleteById(uint32_t obj_id, uint16_t inst_id)
881 {
883 
884  return 0;
885 }
886 
892 {
893  struct UAVOData *obj;
894 
895  // Get lock
897 
898  int32_t rc = -1;
899 
900  // Save all settings objects
901  LL_FOREACH(uavo_list, obj) {
902  // Check if this is a settings object
903  if (UAVObjIsSettings(&obj->base)) {
904  // Save object
905  if (UAVObjSave(&obj->base, 0) ==
906  -1) {
907  goto unlock_exit;
908  }
909  }
910  }
911 
912  rc = 0;
913 
914 unlock_exit:
916  return rc;
917 }
918 
924 {
925  struct UAVOData *obj;
926 
927  // Get lock
929 
930  int32_t rc = -1;
931 
932  // Load all settings objects
933  LL_FOREACH(uavo_list, obj) {
934  // Check if this is a settings object
935  if (UAVObjIsSettings(&obj->base)) {
936  // Load object
937  if (UAVObjLoad((UAVObjHandle) obj, 0) ==
938  -1) {
939  goto unlock_exit;
940  }
941  }
942  }
943 
944  rc = 0;
945 
946 unlock_exit:
948  return rc;
949 }
950 
956 {
957  struct UAVOData *obj;
958 
959  // Get lock
961 
962  int32_t rc = -1;
963 
964  // Save all settings objects
965  LL_FOREACH(uavo_list, obj) {
966  // Check if this is a settings object
967  if (UAVObjIsSettings(&obj->base)) {
968  // Save object
969  if (UAVObjDeleteById(UAVObjGetID(&obj->base), 0)
970  == -1) {
971  goto unlock_exit;
972  }
973  }
974  }
975 
976  rc = 0;
977 
978 unlock_exit:
980  return rc;
981 }
982 
988 {
989  struct UAVOData *obj;
990 
991  // Get lock
993 
994  int32_t rc = -1;
995 
996  // Save all settings objects
997  LL_FOREACH(uavo_list, obj) {
998  // Save object
999  if (UAVObjSave(MetaObjectPtr(obj), 0) ==
1000  -1) {
1001  goto unlock_exit;
1002  }
1003  }
1004 
1005  rc = 0;
1006 
1007 unlock_exit:
1009  return rc;
1010 }
1011 
1017 {
1018  struct UAVOData *obj;
1019 
1020  // Get lock
1022 
1023  int32_t rc = -1;
1024 
1025  // Load all settings objects
1026  LL_FOREACH(uavo_list, obj) {
1027  // Load object
1028  if (UAVObjLoad((UAVObjHandle) MetaObjectPtr(obj), 0) ==
1029  -1) {
1030  goto unlock_exit;
1031  }
1032  }
1033 
1034  rc = 0;
1035 
1036 unlock_exit:
1038  return rc;
1039 }
1040 
1046 {
1047  struct UAVOData *obj;
1048 
1049  // Get lock
1051 
1052  int32_t rc = -1;
1053 
1054  // Load all settings objects
1055  LL_FOREACH(uavo_list, obj) {
1056  // Load object
1058  == -1) {
1059  goto unlock_exit;
1060  }
1061  }
1062 
1063  rc = 0;
1064 
1065 unlock_exit:
1067  return rc;
1068 }
1069 
1076 int32_t UAVObjSetData(UAVObjHandle obj_handle, const void *dataIn)
1077 {
1078  return UAVObjSetInstanceData(obj_handle, 0, dataIn);
1079 }
1080 
1087 int32_t UAVObjSetDataField(UAVObjHandle obj_handle, const void* dataIn, uint32_t offset, uint32_t size)
1088 {
1089  return UAVObjSetInstanceDataField(obj_handle, 0, dataIn, offset, size);
1090 }
1091 
1098 int32_t UAVObjGetData(UAVObjHandle obj_handle, void *dataOut)
1099 {
1100  return UAVObjGetInstanceData(obj_handle, 0, dataOut);
1101 }
1102 
1109 int32_t UAVObjGetDataField(UAVObjHandle obj_handle, void* dataOut, uint32_t offset, uint32_t size)
1110 {
1111  return UAVObjGetInstanceDataField(obj_handle, 0, dataOut, offset, size);
1112 }
1113 
1114 #define INSTANCE_COPY_ALL 0xffffffff
1115 
1123 int32_t UAVObjSetInstanceData(UAVObjHandle obj_handle, uint16_t instId,
1124  const void *dataIn)
1125 {
1126  return UAVObjSetInstanceDataField(obj_handle, instId, dataIn,
1127  0, INSTANCE_COPY_ALL);
1128 }
1129 
1137 int32_t UAVObjSetInstanceDataField(UAVObjHandle obj_handle, uint16_t instId, const void* dataIn, uint32_t offset, uint32_t size)
1138 {
1139  PIOS_Assert(obj_handle);
1140 
1141  // Lock
1143 
1144  int32_t rc = -1;
1145 
1146  void *target;
1147  int obj_len;
1148 
1149  if (UAVObjIsMetaobject(obj_handle)) {
1150  // Get instance information
1151  if (instId != 0) {
1152  goto unlock_exit;
1153  }
1154 
1155  obj_len = MetaNumBytes;
1156 
1157  target = MetaDataPtr((struct UAVOMeta *)obj_handle);
1158  } else {
1159  struct UAVOData * obj;
1160  InstanceHandle instEntry;
1161 
1162  // Cast to object info
1163  obj = (struct UAVOData *)obj_handle;
1164 
1165  // Check access level
1166  if (UAVObjReadOnly(obj_handle)) {
1167  goto unlock_exit;
1168  }
1169 
1170  // Get instance information
1171  instEntry = getInstance(obj, instId);
1172  if (instEntry == NULL) {
1173  goto unlock_exit;
1174  }
1175 
1176  obj_len = obj->instance_size;
1177 
1178  target = InstanceData(instEntry);
1179  }
1180 
1181  if (size == INSTANCE_COPY_ALL) {
1182  size = obj_len;
1183  }
1184 
1185  // Check for overrun
1186  if ((size + offset) > obj_len) {
1187  // XXX Should consider asserting!!!
1188  goto unlock_exit;
1189  }
1190 
1191  // Set data
1192  memcpy(target + offset, dataIn, size);
1193 
1194  // Fire event
1195  sendEvent((struct UAVOBase *)obj_handle, instId, EV_UPDATED,
1196  target, obj_len);
1197  rc = 0;
1198 
1199 unlock_exit:
1201  return rc;
1202 }
1203 
1211 int32_t UAVObjGetInstanceData(UAVObjHandle obj_handle, uint16_t instId,
1212  void *dataOut)
1213 {
1214  PIOS_Assert(obj_handle);
1215 
1216  // Lock
1218 
1219  int32_t rc = -1;
1220 
1221  if (UAVObjIsMetaobject(obj_handle)) {
1222  // Get instance information
1223  if (instId != 0) {
1224  goto unlock_exit;
1225  }
1226  // Set data
1227  memcpy(dataOut, MetaDataPtr((struct UAVOMeta *)obj_handle), MetaNumBytes);
1228  } else {
1229  struct UAVOData *obj;
1230  InstanceHandle instEntry;
1231 
1232  // Cast to object info
1233  obj = (struct UAVOData *) obj_handle;
1234 
1235  // Get instance information
1236  instEntry = getInstance(obj, instId);
1237  if (instEntry == NULL) {
1238  goto unlock_exit;
1239  }
1240  // Set data
1241  memcpy(dataOut, InstanceData(instEntry), obj->instance_size);
1242  }
1243 
1244  rc = 0;
1245 
1246 unlock_exit:
1248  return rc;
1249 }
1250 
1258 int32_t UAVObjGetInstanceDataField(UAVObjHandle obj_handle, uint16_t instId, void* dataOut, uint32_t offset, uint32_t size)
1259 {
1260  PIOS_Assert(obj_handle);
1261 
1262  // Lock
1264 
1265  int32_t rc = -1;
1266 
1267  if (UAVObjIsMetaobject(obj_handle)) {
1268  // Get instance information
1269  if (instId != 0) {
1270  goto unlock_exit;
1271  }
1272 
1273  // Check for overrun
1274  if ((size + offset) > MetaNumBytes) {
1275  goto unlock_exit;
1276  }
1277 
1278  // Set data
1279  memcpy(dataOut, MetaDataPtr((struct UAVOMeta *)obj_handle) + offset, size);
1280  } else {
1281  struct UAVOData * obj;
1282  InstanceHandle instEntry;
1283 
1284  // Cast to object info
1285  obj = (struct UAVOData *)obj_handle;
1286 
1287  // Get instance information
1288  instEntry = getInstance(obj, instId);
1289  if (instEntry == NULL) {
1290  goto unlock_exit;
1291  }
1292 
1293  // Check for overrun
1294  if ((size + offset) > obj->instance_size) {
1295  goto unlock_exit;
1296  }
1297 
1298  // Set data
1299  memcpy(dataOut, InstanceData(instEntry) + offset, size);
1300  }
1301 
1302  rc = 0;
1303 
1304 unlock_exit:
1306  return rc;
1307 }
1308 
1315 int32_t UAVObjSetMetadata(UAVObjHandle obj_handle, const UAVObjMetadata * dataIn)
1316 {
1317  PIOS_Assert(obj_handle);
1318 
1319  // Set metadata (metadata of metaobjects can not be modified)
1320  if (UAVObjIsMetaobject(obj_handle)) {
1321  return -1;
1322  }
1323 
1325 
1326  UAVObjSetData((UAVObjHandle) MetaObjectPtr((struct UAVOData *)obj_handle), dataIn);
1327 
1329  return 0;
1330 }
1331 
1338 int32_t UAVObjGetMetadata(UAVObjHandle obj_handle, UAVObjMetadata * dataOut)
1339 {
1340  PIOS_Assert(obj_handle);
1341 
1342  // Lock
1344 
1345  // Get metadata
1346  if (UAVObjIsMetaobject(obj_handle)) {
1347  memcpy(dataOut, &defMetadata, sizeof(UAVObjMetadata));
1348  } else {
1349  UAVObjGetData((UAVObjHandle) MetaObjectPtr( (struct UAVOData *)obj_handle ),
1350  dataOut);
1351  }
1352 
1353  // Unlock
1355  return 0;
1356 }
1357 
1358 /*******************************
1359  * Object Metadata Manipulation
1360  ******************************/
1361 
1367 UAVObjAccessType UAVObjGetAccess(const UAVObjMetadata* metadata)
1368 {
1369  PIOS_Assert(metadata);
1370  return (metadata->flags >> UAVOBJ_ACCESS_SHIFT) & 1;
1371 }
1372 
1378 void UAVObjSetAccess(UAVObjMetadata* metadata, UAVObjAccessType mode)
1379 {
1380  PIOS_Assert(metadata);
1381  SET_BITS(metadata->flags, UAVOBJ_ACCESS_SHIFT, mode, 1);
1382 }
1383 
1389 UAVObjAccessType UAVObjGetGcsAccess(const UAVObjMetadata* metadata)
1390 {
1391  PIOS_Assert(metadata);
1392  return (metadata->flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1;
1393 }
1394 
1400 void UAVObjSetGcsAccess(UAVObjMetadata* metadata, UAVObjAccessType mode) {
1401  PIOS_Assert(metadata);
1402  SET_BITS(metadata->flags, UAVOBJ_GCS_ACCESS_SHIFT, mode, 1);
1403 }
1404 
1410 uint8_t UAVObjGetTelemetryAcked(const UAVObjMetadata* metadata) {
1411  PIOS_Assert(metadata);
1412  return (metadata->flags >> UAVOBJ_TELEMETRY_ACKED_SHIFT) & 1;
1413 }
1414 
1420 void UAVObjSetTelemetryAcked(UAVObjMetadata* metadata, uint8_t val) {
1421  PIOS_Assert(metadata);
1422  SET_BITS(metadata->flags, UAVOBJ_TELEMETRY_ACKED_SHIFT, val, 1);
1423 }
1424 
1430 uint8_t UAVObjGetGcsTelemetryAcked(const UAVObjMetadata* metadata) {
1431  PIOS_Assert(metadata);
1432  return (metadata->flags >> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT) & 1;
1433 }
1434 
1440 void UAVObjSetGcsTelemetryAcked(UAVObjMetadata* metadata, uint8_t val) {
1441  PIOS_Assert(metadata);
1442  SET_BITS(metadata->flags, UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT, val, 1);
1443 }
1444 
1450 UAVObjUpdateMode UAVObjGetTelemetryUpdateMode(const UAVObjMetadata* metadata) {
1451  PIOS_Assert(metadata);
1452  return (metadata->flags >> UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT) & UAVOBJ_UPDATE_MODE_MASK;
1453 }
1454 
1460 void UAVObjSetTelemetryUpdateMode(UAVObjMetadata* metadata, UAVObjUpdateMode val) {
1461  PIOS_Assert(metadata);
1463 }
1464 
1470 UAVObjUpdateMode UAVObjGetGcsTelemetryUpdateMode(const UAVObjMetadata* metadata) {
1471  PIOS_Assert(metadata);
1473 }
1474 
1480 void UAVObjSetGcsTelemetryUpdateMode(UAVObjMetadata* metadata, UAVObjUpdateMode val) {
1481  PIOS_Assert(metadata);
1483 }
1484 
1485 
1494 int8_t UAVObjReadOnly(UAVObjHandle obj_handle)
1495 {
1496  PIOS_Assert(obj_handle);
1497  if (!UAVObjIsMetaobject(obj_handle)) {
1498  return UAVObjGetAccess(LinkedMetaDataPtr( (struct UAVOData *)obj_handle)) == ACCESS_READONLY;
1499  }
1500  return -1;
1501 }
1502 
1513  struct pios_queue *queue, uint8_t eventMask, uint16_t interval)
1514 {
1515  PIOS_Assert(obj_handle);
1516  PIOS_Assert(queue);
1517  int32_t res;
1519  res = connectObj(obj_handle, queue, NULL, NULL, eventMask, interval);
1521  return res;
1522 }
1523 
1524 int32_t UAVObjConnectQueue(UAVObjHandle obj_handle, struct pios_queue *queue,
1525  uint8_t eventMask) {
1526  return UAVObjConnectQueueThrottled(obj_handle, queue, eventMask, 0);
1527 }
1528 
1529 
1537 {
1538  PIOS_Assert(obj_handle);
1539  PIOS_Assert(queue);
1540  int32_t res;
1542  res = disconnectObj(obj_handle, queue, NULL, NULL);
1544  return res;
1545 }
1546 
1560 void UAVObjCbSetFlag(const UAVObjEvent *objEv, void *ctx, void *obj, int len)
1561 {
1562  volatile uint8_t *flag = ctx;
1563 
1564  *flag = 1;
1565 }
1566 
1579 void UAVObjCbCopyData(const UAVObjEvent *objEv, void *ctx, void *obj, int len)
1580 {
1581  memcpy(ctx, obj, len);
1582 }
1583 
1594  void *cbCtx, uint8_t eventMask, uint16_t interval)
1595 {
1596  PIOS_Assert(obj_handle);
1597  int32_t res;
1599  res = connectObj(obj_handle, 0, cb, cbCtx, eventMask, interval);
1601  return res;
1602 }
1603 
1605  void *cbCtx, uint8_t eventMask)
1606 {
1607  return UAVObjConnectCallbackThrottled(obj_handle, cb, cbCtx, eventMask, 0);
1608 }
1609 
1617  void *cbCtx)
1618 {
1619  PIOS_Assert(obj_handle);
1620  int32_t res;
1622  res = disconnectObj(obj_handle, 0, cb, cbCtx);
1624  return res;
1625 }
1626 
1631 void UAVObjUpdated(UAVObjHandle obj_handle)
1632 {
1634 }
1635 
1641 void UAVObjInstanceUpdated(UAVObjHandle obj_handle, uint16_t instId)
1642 {
1643  PIOS_Assert(obj_handle);
1645  sendEvent((struct UAVOBase *) obj_handle, instId, EV_UPDATED_MANUAL,
1646  NULL, 0);
1648 }
1649 
1655 void UAVObjIterate(void (*iterator) (UAVObjHandle obj))
1656 {
1657  PIOS_Assert(iterator);
1658 
1659  // Get lock
1661 
1662  // Iterate through the list and invoke iterator for each object
1663  struct UAVOData *obj;
1664  LL_FOREACH(uavo_list, obj) {
1665  (*iterator) ((UAVObjHandle) obj);
1666  (*iterator) ((UAVObjHandle) &obj->metaObj);
1667  }
1668 
1669  // Release lock
1671 }
1672 
1673 /* type signature must match invokeCallback below, with 4 or fewer args */
1674 static void __attribute__((used)) realInvokeCallback(
1675  const struct ObjectEventEntry *event,
1676  const UAVObjEvent *msg, void *obj_data, int len);
1677 
1678 static void realInvokeCallback(const struct ObjectEventEntry *event,
1679  const UAVObjEvent *msg, void *obj_data, int len) {
1680  event->cb(msg, event->cbInfo.cbCtx, obj_data, len);
1681 }
1682 
1683 #if (!defined(FLIGHT_POSIX)) && defined(__arm__)
1684 static void invokeCallback(const struct ObjectEventEntry *event,
1685  const UAVObjEvent *msg, void *obj_data, int len) {
1686  /* If we're inlined, we need to force these to the right parameter
1687  * slots. If we show up in a call they're already there. This
1688  * convinces gcc to do the right thing.
1689  */
1690  register const struct ObjectEventEntry *my_event asm("r0") = event;
1691  register const UAVObjEvent *my_msg asm("r1") = msg;
1692  register void *my_obj_data asm("r2") = obj_data;
1693  register int my_len asm("r3") = len;
1694 
1695  asm volatile (
1696  "mov r4, sp\n\t" // r4 = old stack pointer
1697  "mov r5, %0\n\t" // Get the new stack
1698  // Happens in two steps because of Cortex-M4 errata 752770
1699  "mov sp, r5\n\t" // set up the new stack
1700  "bl realInvokeCallback\n\t" // run realInvokeCallback--
1701  // with same args
1702  "mov sp, r4\n\t" // Put back the stack frame
1703 
1704  :
1705  "+r" (cb_stack),
1706  "+r" (my_event), "+r" (my_msg), "+r" (my_obj_data),
1707  "+r" (my_len) // mentioned as input and output
1708  // to guarantee that they don't
1709  // move under us and that the regs
1710  // are not used after this call
1711  // which might clobber r0-r3
1712  : // no pure read-only registers
1713  : "memory", // callback may clobber memory,
1714  "cc", // condition codes,
1715  "r4", "r5", "ip", "lr" // we clobber r4, r5, ip, and lr
1716  // And call-clobbered floating point registers
1717  , "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1718  "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15"
1719  );
1720 }
1721 #else
1722 #define invokeCallback realInvokeCallback
1723 #endif
1724 
1725 static int32_t pumpOneEvent(UAVObjEvent *msg, void *obj_data, int len) {
1726  // Go through each object and push the event message in the queue (if event is activated for the queue)
1727  struct ObjectEventEntry *event;
1728  LL_FOREACH(msg->obj->next_event, event) {
1729  if (event->eventMask == 0
1730  || (event->eventMask & msg->event) != 0) {
1731  struct ObjectEventEntryThrottled *throtInfo =
1732  (struct ObjectEventEntryThrottled *) event;
1733 
1734  if (event->hasThrottle) {
1735  // This is a throttled event
1736  // (triggered with a spacing of at least
1737  // "interval" ms). Also, it enforces "one in
1738  // queue" semantics.
1739  struct ObjectEventEntryThrottled *throtInfo =
1740  (struct ObjectEventEntryThrottled *) event;
1741 
1742  if (!PIOS_Thread_Period_Elapsed(throtInfo->when,
1743  throtInfo->interval)) {
1744  continue;
1745  }
1746 
1747  // Set time for next callback
1748  throtInfo->when = PIOS_Thread_Systime();
1749 
1750  if (throtInfo->inhibited) {
1751  continue;
1752  }
1753 
1754  msg->throttle = throtInfo;
1755  } else {
1756  msg->throttle = NULL;
1757  }
1758 
1759  // Invoke callback (from event task) if a valid one is registered
1760  if (event->cb) {
1761  // invoke callback directly; callbacks must be well behaved
1762  invokeCallback(event, msg, obj_data, len);
1763  } else if (event->cbInfo.queue) {
1764  if (event->hasThrottle) {
1765  throtInfo->inhibited = 1;
1766  }
1767  // Send to queue if a valid queue is registered
1768  // will not block
1769  if (PIOS_Queue_Send(event->cbInfo.queue, msg, 0) != true) {
1770  stats.lastQueueErrorID =
1771  UAVObjGetID(msg->obj);
1772  ++stats.eventQueueErrors;
1773  if (event->hasThrottle) {
1774  throtInfo->inhibited = 0;
1775  }
1776  }
1777  }
1778  }
1779  }
1780 
1781  return 0;
1782 }
1783 
1787 static int32_t sendEvent(struct UAVOBase * obj, uint16_t instId,
1788  UAVObjEventType triggered_event,
1789  void *obj_data, int len)
1790 {
1791  static uint8_t num_pending = 0;
1792 
1793  static struct PendEvent {
1794  UAVObjEvent msg;
1795  void *obj_data;
1796  int len;
1797  } pending_events[3];
1798 
1799  /* The logic to spool up callbacks here may be a little confusing.
1800  * basically, this relies on the fact that we are in a re-entrant
1801  * locked section. If we get in here and the static variable
1802  * in_progress is set, we are entering from a task that itself is
1803  * performing a parent callback.
1804  *
1805  * In other words, while executing a callback it did a uav object
1806  * update that will trigger in turn more callbacks.
1807  *
1808  * To handle this, we have a small buffer to store the pending
1809  * callbacks.
1810  *
1811  * We also make the point of disallowing a callback from generating
1812  * the exact same callback. This is relevant to things like
1813  * the session managing object in telemetry. While it is possible
1814  * to do this safely (by "stopping" the quasi-recursion) it seems
1815  * better to disallow it.
1816  *
1817  * However, infinite loops are still possible; callback A can
1818  * trigger callback B which triggers callback A. Don't do that.
1819  */
1820 
1821  if (num_pending >= 3) {
1822  /* Unable to pump event; backlog too long */
1823  stats.eventCallbackErrors++;
1824  stats.lastCallbackErrorID = UAVObjGetID(obj);
1825 
1826  return -1;
1827  }
1828 
1829  static struct UAVOBase *in_progress = NULL;
1830 
1831  if (num_pending) {
1832  if (in_progress == obj) {
1833  return -1; /* We don't fire events
1834  * of the same type generated by
1835  * an event callback. */
1836  }
1837  }
1838 
1839  pending_events[num_pending].msg = (UAVObjEvent) {
1840  .obj = obj,
1841  .event = triggered_event,
1842  .instId = instId
1843  };
1844 
1845  pending_events[num_pending].obj_data = obj_data;
1846  pending_events[num_pending].len = len;
1847 
1848  num_pending++;
1849 
1850  /* Only enter the section of pumping events if we are the "first event" */
1851  if (!in_progress) {
1852  /* While there are events to pump.. */
1853  while (num_pending) {
1854  /* Deallocate the top one.. */
1855  num_pending--;
1856 
1857  /* Mask off events of the same type resulting from
1858  * the callback... */
1859  in_progress = pending_events[num_pending].msg.obj;
1860 
1861  /* And pump the event. */
1862  pumpOneEvent(&pending_events[num_pending].msg,
1863  pending_events[num_pending].obj_data,
1864  pending_events[num_pending].len);
1865  }
1866  }
1867 
1868  in_progress = NULL;
1869 
1870  return 0;
1871 }
1872 
1876 static InstanceHandle createInstance(struct UAVOData * obj, uint16_t instId)
1877 {
1878  struct UAVOMultiInst *instEntry;
1879 
1880  /* Don't allow more than one instance for single instance objects */
1881  if (UAVObjIsSingleInstance(&(obj->base))) {
1882  PIOS_Assert(0);
1883  return NULL;
1884  }
1885 
1886  /* Don't create more than the allowed number of instances */
1887  if (instId >= UAVOBJ_MAX_INSTANCES) {
1888  return NULL;
1889  }
1890 
1891  /* Don't allow duplicate instances */
1892  if (instId < UAVObjGetNumInstances(&(obj->base))) {
1893  return NULL;
1894  }
1895 
1896  // Create any missing instances (all instance IDs must be sequential)
1897  for (uint16_t n = UAVObjGetNumInstances(&(obj->base)); n < instId; ++n) {
1898  if (createInstance(obj, n) == NULL) {
1899  return NULL;
1900  }
1901  }
1902 
1903  /* Create the actual instance */
1904  instEntry = (struct UAVOMultiInst *) PIOS_malloc_no_dma(sizeof(struct UAVOMultiInst)+obj->instance_size);
1905  if (!instEntry)
1906  return NULL;
1907  memset(InstanceDataOffset(instEntry), 0, obj->instance_size);
1908  LL_APPEND(( (struct UAVOMulti*)obj )->instance0.next, instEntry);
1909 
1910  ( (struct UAVOMulti*)obj )->num_instances++;
1911 
1912  // Fire event
1913  UAVObjInstanceUpdated((UAVObjHandle) obj, instId);
1914 
1915  // Done
1916  if (newUavObjInstanceCB) {
1917  newUavObjInstanceCB(obj->id, UAVObjGetNumInstances(&obj->base));
1918  }
1919  return InstanceDataOffset(instEntry);
1920 }
1921 
1925 static InstanceHandle getInstance(struct UAVOData * obj, uint16_t instId)
1926 {
1927  if (UAVObjIsMetaobject(&obj->base)) {
1928  /* Metadata Instance */
1929 
1930  if (instId != 0)
1931  return NULL;
1932 
1933  /* Augment our pointer to reflect the proper type */
1934  struct UAVOMeta * uavo_meta = (struct UAVOMeta *) obj;
1935  return (&(uavo_meta->instance0));
1936 
1937  } else if (UAVObjIsSingleInstance(&(obj->base))) {
1938  /* Single Instance */
1939 
1940  if (instId != 0)
1941  return NULL;
1942 
1943  /* Augment our pointer to reflect the proper type */
1944  struct UAVOSingle * uavo_single = (struct UAVOSingle *) obj;
1945  return (&(uavo_single->instance0));
1946  } else {
1947  /* Multi Instance */
1948  /* Augment our pointer to reflect the proper type */
1949  struct UAVOMulti * uavo_multi = (struct UAVOMulti *) obj;
1950  if (instId >= uavo_multi->num_instances)
1951  return NULL;
1952 
1953  // Look for specified instance ID
1954  uint16_t instance = 0;
1955  struct UAVOMultiInst *instEntry;
1956  LL_FOREACH(&(uavo_multi->instance0), instEntry) {
1957  if (instance++ == instId) {
1958  /* Found it */
1959  return &(instEntry->instance);
1960  }
1961  }
1962  /* Instance was not found */
1963  return NULL;
1964  }
1965 }
1966 
1976 static int32_t connectObj(UAVObjHandle obj_handle, struct pios_queue *queue,
1977  UAVObjEventCallback cb, void *cbCtx, uint8_t eventMask,
1978  uint16_t interval)
1979 {
1980  if (queue && cb) {
1981  return -1;
1982  }
1983 
1984  struct ObjectEventEntry *event;
1985  struct ObjectEventEntryThrottled *throttled;
1986  struct UAVOBase *obj;
1987 
1988  // Check that the queue is not already connected, if it is simply update event mask
1989  obj = (struct UAVOBase *) obj_handle;
1990  LL_FOREACH(obj->next_event, event) {
1991  if ((event->cb == cb && event->cbInfo.cbCtx == cbCtx) ||
1992  ((!event->cb) && event->cbInfo.queue == queue)) {
1993  // Already connected, update event mask and throttling (if possible)
1994  event->eventMask = eventMask;
1995  if (event->hasThrottle) {
1996  if (interval == 0) {
1997  event->hasThrottle = 0;
1998  }
1999  else {
2000  throttled = (struct ObjectEventEntryThrottled *) event;
2001  throttled->interval = interval;
2002  }
2003  return 0;
2004  }
2005  else {
2006  if (interval == 0) {
2007  // We don't need to do anything
2008  return 0;
2009  }
2010  else {
2011  // We are changing the callback from unthrottled to throttled,
2012  // need to allocate a new event (not ideal, as it leaks memory)
2013  LL_DELETE(obj->next_event, event);
2014  break;
2015  }
2016  }
2017  }
2018  }
2019 
2020  int mallocSize = sizeof(*event);
2021  struct ObjectEventEntry ** unused = &events_unused;
2022 
2023  if (interval) {
2024  mallocSize = sizeof(*throttled);
2025  unused = &events_unused_throttled;
2026  }
2027 
2029  if (*unused != NULL) {
2030  // We can re-use the memory of a previously disconnected event
2031  event = *unused;
2032  LL_DELETE(*unused, event);
2033  }
2034  else {
2035  event = (struct ObjectEventEntry *) PIOS_malloc_no_dma(mallocSize);
2036  if (event == NULL) {
2038  return -1;
2039  }
2040  }
2042 
2043  memset(event, 0, mallocSize);
2044  event->cb = cb;
2045 
2046  if (!cb) {
2047  event->cbInfo.queue = queue;
2048  } else {
2049  event->cbInfo.cbCtx = cbCtx;
2050  }
2051 
2052  event->eventMask = eventMask;
2053  event->hasThrottle = 0;
2054 
2055  if (interval) {
2056  event->hasThrottle = 1;
2057  throttled = (struct ObjectEventEntryThrottled *) event;
2058 
2059  throttled->interval = interval;
2060  throttled->when = PIOS_Thread_Systime() + randomize_int(throttled->interval);
2061  }
2062 
2063  LL_APPEND(obj->next_event, event);
2064 
2065  // Done
2066  return 0;
2067 }
2068 
2076 static int32_t disconnectObj(UAVObjHandle obj_handle, struct pios_queue *queue,
2077  UAVObjEventCallback cb, void *cbCtx)
2078 {
2079  struct ObjectEventEntry *event;
2080  struct UAVOBase *obj;
2081 
2082  // Find queue and remove it
2083  obj = (struct UAVOBase *) obj_handle;
2084  LL_FOREACH(obj->next_event, event) {
2085  if ((event->cb == cb && event->cbInfo.cbCtx == cbCtx) ||
2086  ((!event->cb) && event->cbInfo.queue == queue)) {
2087  LL_DELETE(obj->next_event, event);
2088  // store the unused memory for future reuse
2090  if (event->hasThrottle) {
2091  LL_APPEND(events_unused_throttled, event);
2092  }
2093  else {
2094  LL_APPEND(events_unused, event);
2095  }
2097  return 0;
2098  }
2099  }
2100 
2101  // If this point is reached the queue was not found
2102  return -1;
2103 }
2104 
2105 
2112 int32_t getEventMask(UAVObjHandle obj_handle, struct pios_queue *queue)
2113 {
2114  struct ObjectEventEntry *event;
2115  struct UAVOBase *obj;
2116 
2117  int32_t eventMask = EV_MASK_ALL;
2118 
2119  // Iterate over the event listeners, looking for the event matching the queue
2120  obj = (struct UAVOBase *) obj_handle;
2121  LL_FOREACH(obj->next_event, event) {
2122  if (event->cbInfo.queue == queue && event->cb == 0) {
2123  // Already connected, update event mask and return
2124  eventMask = event->eventMask;
2125  break;
2126  }
2127  }
2128 
2129  // Done
2130  return eventMask;
2131 }
2136 uint8_t UAVObjCount()
2137 {
2138  uint8_t count = 0;
2139  // Get lock
2141 
2142  // Look for object
2143  struct UAVOData * tmp_obj;
2144  LL_FOREACH(uavo_list, tmp_obj) {
2145  ++count;
2146  }
2147 
2148  // Release lock
2150  return count;
2151 }
2152 
2157 uint32_t UAVObjIDByIndex(uint8_t index)
2158 {
2159  uint8_t count = 0;
2160  // Get lock
2162 
2163  // Look for object
2164  struct UAVOData * tmp_obj;
2165  LL_FOREACH(uavo_list, tmp_obj) {
2166  if (count == index)
2167  {
2168  // Release lock
2170  return tmp_obj->id;
2171  }
2172  ++count;
2173  }
2174 
2175  // Release lock
2177  return 0;
2178 }
2179 
2185 {
2186  if (throttled) {
2187  throttled->inhibited = 0;
2188  }
2189 }
2190 
2195 {
2196  newUavObjInstanceCB = callback;
2197 }
int32_t UAVObjSaveMetaobjects()
uint8_t UAVObjCount()
void UAVObjSetTelemetryAcked(UAVObjMetadata *metadata, uint8_t val)
static int32_t sendEvent(struct UAVOBase *obj, uint16_t instId, UAVObjEventType event, void *obj_data, int len)
uint32_t UAVObjIDByIndex(uint8_t index)
#define LL_FOREACH(head, el)
Definition: utlist.h:263
struct UAVOData * next
void UAVObjClearStats()
uint32_t PIOS_Thread_Systime(void)
Definition: pios_thread.c:212
uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle, UAVObjInitializeCallback initCb)
UAVObjMetadata instance0
void UAVObjSetTelemetryUpdateMode(UAVObjMetadata *metadata, UAVObjUpdateMode val)
uint32_t lastCallbackErrorID
static struct UAVOData * uavo_list
struct pios_queue * queue
UAVObjHandle UAVObjGetByID(uint32_t id)
uint8_t hasThrottle
int32_t UAVObjSetInstanceData(UAVObjHandle obj_handle, uint16_t instId, const void *dataIn)
static int32_t disconnectObj(UAVObjHandle obj_handle, struct pios_queue *queue, UAVObjEventCallback cb, void *cbCtx)
uint32_t id
bool UAVObjIsMetaobject(UAVObjHandle obj_handle)
uint16_t interval
int32_t UAVObjDisconnectQueue(UAVObjHandle obj_handle, struct pios_queue *queue)
const uint8_t count
Definition: panel.c:515
uint8_t eventMask
static struct pios_recursive_mutex * mutex
UAVObjUpdateMode UAVObjGetGcsTelemetryUpdateMode(const UAVObjMetadata *metadata)
uint16_t instance_size
bool UAVObjIsSettings(UAVObjHandle obj_handle)
#define LinkedMetaDataPtr(obj)
struct UAVOBase::UAVOInfo flags
#define UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT
UAVObjUpdateMode
UAVObjAccessType
int32_t UAVObjLoadSettings()
int32_t UAVObjUnpack(UAVObjHandle obj_handle, uint16_t instId, const uint8_t *dataIn)
int32_t UAVObjSaveSettings()
uint32_t UAVObjGetNumBytes(UAVObjHandle obj)
#define UAVOBJ_ALL_INSTANCES
#define invokeCallback
#define UAVO_CB_STACK_SIZE
int32_t UAVObjPack(UAVObjHandle obj_handle, uint16_t instId, uint8_t *dataOut)
int32_t UAVObjConnectCallbackThrottled(UAVObjHandle obj_handle, UAVObjEventCallback cb, void *cbCtx, uint8_t eventMask, uint16_t interval)
bool PIOS_Queue_Send(struct pios_queue *queuep, const void *itemp, uint32_t timeout_ms)
Definition: pios_queue.c:141
static void UAVObjInitMetaData(struct UAVOMeta *obj_meta)
uintptr_t pios_uavo_settings_fs_id
Definition: pios_board.c:50
void UAVObjCbSetFlag(const UAVObjEvent *objEv, void *ctx, void *obj, int len)
UAVObjAccessType UAVObjGetGcsAccess(const UAVObjMetadata *metadata)
int32_t UAVObjSave(UAVObjHandle obj_handle, uint16_t instId)
int32_t UAVObjConnectQueueThrottled(UAVObjHandle obj_handle, struct pios_queue *queue, uint8_t eventMask, uint16_t interval)
uint32_t eventQueueErrors
static InstanceHandle getInstance(struct UAVOData *obj, uint16_t instId)
UAVObjAccessType UAVObjGetAccess(const UAVObjMetadata *metadata)
#define InstanceDataOffset(inst)
void * PIOS_malloc_no_dma(size_t size)
Definition: pios_heap.c:166
static void * cb_stack
uint8_t instance[]
uint8_t instance0[]
int32_t UAVObjSetDataField(UAVObjHandle obj_handle, const void *dataIn, uint32_t offset, uint32_t size)
UAVObjHandle obj
uint32_t lastQueueErrorID
void UAVObjGetStats(UAVObjStats *statsOut)
uint8_t UAVObjGetTelemetryAcked(const UAVObjMetadata *metadata)
void UAVObjSetGcsTelemetryUpdateMode(UAVObjMetadata *metadata, UAVObjUpdateMode val)
int32_t UAVObjGetInstanceDataField(UAVObjHandle obj_handle, uint16_t instId, void *dataOut, uint32_t offset, uint32_t size)
struct pios_recursive_mutex * PIOS_Recursive_Mutex_Create(void)
Definition: pios_mutex.c:115
static struct ObjectEventEntry * events_unused
static UAVObjStats stats
uint8_t UAVObjGetGcsTelemetryAcked(const UAVObjMetadata *metadata)
struct UAVOMultiInst instance0
uint32_t UAVObjGetID(UAVObjHandle obj_handle)
int32_t PIOS_FLASHFS_ObjDelete(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id)
Delete one instance of an object from the filesystem.
bool UAVObjIsSingleInstance(UAVObjHandle obj_handle)
struct UAVOData uavo
#define MetaObjectId(id)
#define UAVOBJ_GCS_ACCESS_SHIFT
void * cbCtx
#define SET_BITS(var, shift, value, mask)
uint16_t instance_size
bool PIOS_Recursive_Mutex_Lock(struct pios_recursive_mutex *mtx, uint32_t timeout_ms)
Definition: pios_mutex.c:139
struct ObjectEventEntry entry
static struct UAVOData * UAVObjAllocSingle(uint32_t num_bytes)
static int32_t connectObj(UAVObjHandle obj_handle, struct pios_queue *queue, UAVObjEventCallback cb, void *cbCtx, uint8_t eventMask, uint16_t interval)
static struct ObjectEventEntry * events_unused_throttled
#define InstanceData(instance)
int32_t UAVObjGetInstanceData(UAVObjHandle obj_handle, uint16_t instId, void *dataOut)
#define LL_APPEND(head, add)
Definition: utlist.h:234
void UAVObjInstanceUpdated(UAVObjHandle obj_handle, uint16_t instId)
uint32_t randomize_int(uint32_t interval)
Definition: misc_math.c:340
static struct UAVOData * UAVObjAllocMulti(uint32_t num_bytes)
void(* UAVObjInitializeCallback)(UAVObjHandle obj_handle, uint16_t instId)
UAVObjUpdateMode UAVObjGetTelemetryUpdateMode(const UAVObjMetadata *metadata)
enum channel_mode mode
Definition: pios_servo.c:58
int32_t UAVObjConnectCallback(UAVObjHandle obj_handle, UAVObjEventCallback cb, void *cbCtx, uint8_t eventMask)
uint32_t obj_id
struct UAVOData uavo
int32_t UAVObjSetInstanceDataField(UAVObjHandle obj_handle, uint16_t instId, const void *dataIn, uint32_t offset, uint32_t size)
uint32_t when
struct UAVOData uavo
void UAVObjUnblockThrottle(struct ObjectEventEntryThrottled *throttled)
bool PIOS_Thread_Period_Elapsed(const uint32_t prev_systime, const uint32_t increment_ms)
Determine if a period has elapsed since a datum.
Definition: pios_thread.c:281
static int32_t pumpOneEvent(UAVObjEvent *msg, void *obj_data, int len)
struct UAVOBase base
struct UAVOMultiInst * next
UAVObjEventType
struct UAVOBase * UAVObjHandle
int32_t UAVObjDeleteById(uint32_t obj_id, uint16_t inst_id)
static InstanceHandle createInstance(struct UAVOData *obj, uint16_t instId)
#define UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT
int32_t UAVObjSetMetadata(UAVObjHandle obj_handle, const UAVObjMetadata *dataIn)
void(* UAVObjEventCallback)(const UAVObjEvent *ev, void *cb_ctx, void *uavo_data, int uavo_len)
void UAVObjCbCopyData(const UAVObjEvent *objEv, void *ctx, void *obj, int len)
#define container_of(ptr, type, member)
int32_t UAVObjConnectQueue(UAVObjHandle obj_handle, struct pios_queue *queue, uint8_t eventMask)
#define UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT
uint32_t offset
Definition: uavtalk_priv.h:51
int32_t PIOS_FLASHFS_ObjSave(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t *obj_data, uint16_t obj_size)
Saves one object instance to the filesystem.
int32_t getEventMask(UAVObjHandle obj_handle, struct pios_queue *queue)
int32_t UAVObjLoadMetaobjects()
int32_t UAVObjGetMetadata(UAVObjHandle obj_handle, UAVObjMetadata *dataOut)
int32_t PIOS_FLASHFS_ObjLoad(uintptr_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t *obj_data, uint16_t obj_size)
Load one object instance from the filesystem.
union ObjectEventEntry::@25 cbInfo
struct UAVOMeta metaObj
void UAVObjSetGcsTelemetryAcked(UAVObjMetadata *metadata, uint8_t val)
UAVObjHandle UAVObjGetLinkedObj(UAVObjHandle obj_handle)
uint16_t num_instances
UAVObjMetadata instance0
void * InstanceHandle
uint32_t eventCallbackErrors
void UAVObjUpdated(UAVObjHandle obj_handle)
#define LL_DELETE(head, del)
Definition: utlist.h:247
UAVObjEventType event
#define UAVOBJ_TELEMETRY_ACKED_SHIFT
static const UAVObjMetadata defMetadata
Includes PiOS and core architecture components.
uint16_t UAVObjGetNumInstances(UAVObjHandle obj_handle)
int32_t UAVObjDeleteMetaobjects()
void(* new_uavo_instance_cb_t)(uint32_t, uint32_t)
#define UAVOBJ_UPDATE_MODE_MASK
uint8_t unused[4]
Definition: bl_messages.h:70
volatile uint8_t inhibited
int8_t UAVObjReadOnly(UAVObjHandle obj_handle)
#define EV_MASK_ALL
int32_t UAVObjLoad(UAVObjHandle obj_handle, uint16_t instId)
int32_t UAVObjSetData(UAVObjHandle obj_handle, const void *dataIn)
static struct pios_queue * queue
Definition: actuator.c:82
struct UAVOMeta metaObj
int32_t UAVObjInitialize()
uint32_t flag
Definition: msp_messages.h:99
UAVObjEventCallback cb
uint32_t id
int32_t UAVObjGetData(UAVObjHandle obj_handle, void *dataOut)
struct UAVOBase base
#define INSTANCE_COPY_ALL
#define UAVOBJ_ACCESS_SHIFT
static new_uavo_instance_cb_t newUavObjInstanceCB
UAVObjHandle UAVObjRegister(uint32_t id, int32_t isSingleInstance, int32_t isSettings, uint32_t num_bytes, UAVObjInitializeCallback initCb)
struct ObjectEventEntryThrottled * throttle
void UAVObjRegisterNewInstanceCB(new_uavo_instance_cb_t callback)
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t UAVObjGetDataField(UAVObjHandle obj_handle, void *dataOut, uint32_t offset, uint32_t size)
struct ObjectEventEntry * next
#define UAVOBJ_MAX_INSTANCES
#define MetaDataPtr(obj)
#define MetaNumBytes
bool PIOS_Recursive_Mutex_Unlock(struct pios_recursive_mutex *mtx)
Definition: pios_mutex.c:144
struct UAVOBase __attribute__((packed))
Definition: serial_4way.h:38
#define MetaObjectPtr(obj)
void UAVObjSetGcsAccess(UAVObjMetadata *metadata, UAVObjAccessType mode)
struct ObjectEventEntry * next_event
#define PIOS_MUTEX_TIMEOUT_MAX
Definition: pios_mutex.h:30
uint8_t instance[]
int32_t UAVObjDisconnectCallback(UAVObjHandle obj_handle, UAVObjEventCallback cb, void *cbCtx)
void UAVObjSetAccess(UAVObjMetadata *metadata, UAVObjAccessType mode)
void UAVObjIterate(void(*iterator)(UAVObjHandle obj))
int32_t UAVObjDeleteSettings()