1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-27 16:54:15 +01:00

Merge branch 'OP-499_216_Saving'

This commit is contained in:
James Cotton 2011-05-15 10:09:29 -05:00
commit eb2d094a66
8 changed files with 1981 additions and 1743 deletions

View File

@ -205,6 +205,7 @@ SRC += $(PIOSSTM32F10X)/pios_usb_hid_prop.c
SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c
## PIOS Hardware (Common) ## PIOS Hardware (Common)
SRC += $(PIOSCOMMON)/pios_flashfs_objlist.c
SRC += $(PIOSCOMMON)/pios_flash_w25x.c SRC += $(PIOSCOMMON)/pios_flash_w25x.c
SRC += $(PIOSCOMMON)/pios_adxl345.c SRC += $(PIOSCOMMON)/pios_adxl345.c
SRC += $(PIOSCOMMON)/pios_com.c SRC += $(PIOSCOMMON)/pios_com.c

View File

@ -681,6 +681,8 @@ void PIOS_Board_Init(void) {
PIOS_Flash_W25X_Init(pios_spi_flash_accel_id); PIOS_Flash_W25X_Init(pios_spi_flash_accel_id);
PIOS_ADXL345_Attach(pios_spi_flash_accel_id); PIOS_ADXL345_Attach(pios_spi_flash_accel_id);
PIOS_FLASHFS_Init();
#if defined(PIOS_INCLUDE_SPEKTRUM) #if defined(PIOS_INCLUDE_SPEKTRUM)
/* SPEKTRUM init must come before comms */ /* SPEKTRUM init must come before comms */
PIOS_SPEKTRUM_Init(); PIOS_SPEKTRUM_Init();

View File

@ -222,6 +222,14 @@ int8_t PIOS_Flash_W25X_WriteData(uint32_t addr, uint8_t * data, uint16_t len)
return 0; return 0;
} }
/**
* @brief Read data from a location in flash memory
* @param[in] addr Address in flash to write to
* @param[in] data Pointer to data to write from flash
* @param[in] len Length of data to write (max 256 bytes)
* @return Zero if success or error code
* @retval -1 Unable to claim SPI bus
*/
int8_t PIOS_Flash_W25X_ReadData(uint32_t addr, uint8_t * data, uint16_t len) int8_t PIOS_Flash_W25X_ReadData(uint32_t addr, uint8_t * data, uint16_t len)
{ {
if(PIOS_Flash_W25X_ClaimBus() == -1) if(PIOS_Flash_W25X_ClaimBus() == -1)

View File

@ -0,0 +1,294 @@
/**
******************************************************************************
*
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_FLASHFS_OBJLIST Object list based flash filesystem (low ram)
* @{
*
* @file pios_flashfs_objlist.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief A file system for storing UAVObject in flash chip
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "openpilot.h"
#include "uavobjectmanager.h"
// Private functions
static int32_t PIOS_FLASHFS_CleabObjectTableHeader();
static int32_t PIOS_FLASHFS_GetObjAddress(uint32_t objId, uint16_t instId);
static int32_t PIOS_FLASHFS_GetNewAddress(uint32_t objId, uint16_t instId);
// Private variables
static int32_t numObjects = -1;
// Private structures
// Header for objects in the file system table
struct objectHeader {
uint32_t objMagic;
uint32_t objId;
uint32_t instId;
uint32_t address;
} __attribute__((packed));;
struct fileHeader {
uint32_t id;
uint16_t instId;
uint16_t size;
} __attribute__((packed));
#define OBJECT_TABLE_MAGIC 0x85FB3C33
#define OBJ_MAGIC 0x3015AE71
#define OBJECT_TABLE_START 0x00000010
#define OBJECT_TABLE_END 0x00001000
#define SECTOR_SIZE 0x00001000
/**
* @brief Initialize the flash object setting FS
* @return 0 if success, -1 if failure
*/
int32_t PIOS_FLASHFS_Init()
{
// Check for valid object table or create one
uint32_t object_table_magic;
if (PIOS_Flash_W25X_ReadData(0, (uint8_t *)&object_table_magic, sizeof(object_table_magic)) != 0)
return -1;
if(object_table_magic != OBJECT_TABLE_MAGIC) {
if(PIOS_FLASHFS_CleabObjectTableHeader() < 0)
return -1;
}
int32_t addr = OBJECT_TABLE_START;
struct objectHeader header;
numObjects = 0;
// Loop through header area while objects detect to count how many saved
while(addr < OBJECT_TABLE_END) {
// Read the instance data
if (PIOS_Flash_W25X_ReadData(addr, (uint8_t *)&header, sizeof(header)) != 0)
return -1;
// Counting number of valid headers
if(header.objMagic != OBJ_MAGIC)
break;
numObjects++;
addr += sizeof(header);
}
return 0;
}
/**
* @brief Erase the headers for all objects in the flash chip
* @return 0 if successful, -1 if not
*/
static int32_t PIOS_FLASHFS_CleabObjectTableHeader()
{
if(PIOS_Flash_W25X_EraseSector(OBJECT_TABLE_START) != 0)
return -1;
uint32_t object_table_magic = OBJECT_TABLE_MAGIC;
if (PIOS_Flash_W25X_WriteData(0, (uint8_t *)&object_table_magic, sizeof(object_table_magic)) != 0)
return -1;
return 0;
}
/**
* @brief Get the address of an object
* @param obj UAVObjHandle for that object
* @parma instId Instance id for that object
* @return address if successful, -1 if not found
*/
static int32_t PIOS_FLASHFS_GetObjAddress(uint32_t objId, uint16_t instId)
{
int32_t addr = OBJECT_TABLE_START;
struct objectHeader header;
// Loop through header area while objects detect to count how many saved
while(addr < OBJECT_TABLE_END) {
// Read the instance data
if (PIOS_Flash_W25X_ReadData(addr, (uint8_t *) &header, sizeof(header)) != 0)
return -1;
if(header.objMagic != OBJ_MAGIC)
break; // stop searching once hit first non-object header
else if (header.objId == objId && header.instId == instId)
break;
addr += sizeof(header);
}
if (header.objId == objId && header.instId == instId)
return header.address;
return -1;
}
/**
* @brief Returns an address for a new object and creates entry into object table
* @param[in] obj Object handle for object to be saved
* @param[in] instId The instance id of object to be saved
* @return 0 if success or error code
* @retval -1 Object not found
* @retval -2 No room in object table
* @retval -3 Unable to write entry into object table
* @retval -4 FS not initialized
*/
int32_t PIOS_FLASHFS_GetNewAddress(uint32_t objId, uint16_t instId)
{
struct objectHeader header;
if(numObjects < 0)
return -4;
// Don't worry about max size of flash chip here, other code will catch that
header.objMagic = OBJ_MAGIC;
header.objId = objId;
header.instId = instId;
header.address = OBJECT_TABLE_END + SECTOR_SIZE * numObjects;
int32_t addr = OBJECT_TABLE_START + sizeof(header) * numObjects;
// No room for this header in object table
if((addr + sizeof(header)) > OBJECT_TABLE_END)
return -2;
if(PIOS_Flash_W25X_WriteData(addr, (uint8_t *) &header, sizeof(header)) != 0)
return -3;
// This numObejcts value must stay consistent or there will be a break in the table
// and later the table will have bad values in it
numObjects++;
return header.address;
}
/**
* @brief Saves one object instance per sector
* @param[in] obj UAVObjHandle the object to save
* @param[in] instId The instance of the object to save
* @return 0 if success or -1 if failure
* @note This uses one sector on the flash chip per object so that no buffering in ram
* must be done when erasing the sector before a save
*/
int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instId, uint8_t * data)
{
uint32_t objId = UAVObjGetID(obj);
int32_t addr = PIOS_FLASHFS_GetObjAddress(objId, instId);
// Object currently not saved
if(addr < 0)
addr = PIOS_FLASHFS_GetNewAddress(objId, instId);
// Could not allocate a sector
if(addr < 0)
return -1;
struct fileHeader header = {
.id = objId,
.instId = instId,
.size = UAVObjGetNumBytes(obj)
};
if(PIOS_Flash_W25X_EraseSector(addr) != 0)
return -2;
// Save header
// This information IS redundant with the object table id. Oh well. Better safe than sorry.
if(PIOS_Flash_W25X_WriteData(addr, (uint8_t *) &header, sizeof(header)) != 0)
return -3;
// Save data
if(PIOS_Flash_W25X_WriteData(addr + sizeof(header), data, UAVObjGetNumBytes(obj)) != 0)
return -4;
return 0;
}
/**
* @brief Load one object instance per sector
* @param[in] obj UAVObjHandle the object to save
* @param[in] instId The instance of the object to save
* @return 0 if success or error code
* @retval -1 if object not in file table
* @retval -2 if unable to retrieve object header
* @retval -3 if loaded data instId or objId don't match
* @retval -4 if unable to retrieve instance data
* @note This uses one sector on the flash chip per object so that no buffering in ram
* must be done when erasing the sector before a save
*/
int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instId, uint8_t * data)
{
uint32_t objId = UAVObjGetID(obj);
int32_t addr = PIOS_FLASHFS_GetObjAddress(objId, instId);
// Object currently not saved
if(addr < 0)
return -1;
struct fileHeader header;
// Load header
// This information IS redundant with the object table id. Oh well. Better safe than sorry.
if(PIOS_Flash_W25X_ReadData(addr, (uint8_t *) &header, sizeof(header)) != 0)
return -2;
if((header.id != objId) || (header.instId != instId))
return -3;
// Read the instance data
if (PIOS_Flash_W25X_ReadData(addr + sizeof(header), data, UAVObjGetNumBytes(obj)) != 0)
return -4;
return 0;
}
/**
* @brief Delete object from flash
* @param[in] obj UAVObjHandle the object to save
* @param[in] instId The instance of the object to save
* @return 0 if success or error code
* @retval -1 if object not in file table
* @retval -2 Erase failed
* @note To avoid buffering the file table (1k ram!) the entry in the file table
* remains but destination sector is erased. This will make the load fail as the
* file header won't match the object. At next save it goes back there.
*/
int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instId)
{
uint32_t objId = UAVObjGetID(obj);
int32_t addr = PIOS_FLASHFS_GetObjAddress(objId, instId);
// Object currently not saved
if(addr < 0)
return -1;
if(PIOS_Flash_W25X_EraseSector(addr) != 0)
return -2;
return 0;
}

View File

@ -0,0 +1,37 @@
/**
******************************************************************************
*
* @addtogroup PIOS PIOS Core hardware abstraction layer
* @{
* @addtogroup PIOS_FLASHFS_OBJLIST Object list based flash filesystem (low ram)
* @{
*
* @file pios_flashfs_objlist.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief A file system for storing UAVObject in flash chip
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "openpilot.h"
#include "uavobjectmanager.h"
int32_t PIOS_FLASHFS_Init();
int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instId, uint8_t * data);
int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instId, uint8_t * data);
int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instId);

View File

@ -119,6 +119,7 @@
#if defined(PIOS_INCLUDE_FLASH) #if defined(PIOS_INCLUDE_FLASH)
#include <pios_flash_w25x.h> #include <pios_flash_w25x.h>
#include <pios_flashfs_objlist.h>
#endif #endif
#if defined(PIOS_INCLUDE_BL_HELPER) #if defined(PIOS_INCLUDE_BL_HELPER)

View File

@ -3171,6 +3171,8 @@
65FF4BE913791C3300146BE4 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; }; 65FF4BE913791C3300146BE4 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
65FF4BEA13791C3300146BE4 /* op_dfu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = op_dfu.c; sourceTree = "<group>"; }; 65FF4BEA13791C3300146BE4 /* op_dfu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = op_dfu.c; sourceTree = "<group>"; };
65FF4BEB13791C3300146BE4 /* pios_board.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pios_board.c; sourceTree = "<group>"; }; 65FF4BEB13791C3300146BE4 /* pios_board.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pios_board.c; sourceTree = "<group>"; };
65FF4D5E137EDEC100146BE4 /* pios_flashfs_objlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pios_flashfs_objlist.c; sourceTree = "<group>"; };
65FF4D61137EFA4F00146BE4 /* pios_flashfs_objlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pios_flashfs_objlist.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
@ -7657,6 +7659,7 @@
65E8F03711EFF25C00BBF654 /* printf-stdarg.c */, 65E8F03711EFF25C00BBF654 /* printf-stdarg.c */,
6528CCB412E406B800CF5144 /* pios_adxl345.c */, 6528CCB412E406B800CF5144 /* pios_adxl345.c */,
6512D60712ED4CB8008175E5 /* pios_flash_w25x.c */, 6512D60712ED4CB8008175E5 /* pios_flash_w25x.c */,
65FF4D5E137EDEC100146BE4 /* pios_flashfs_objlist.c */,
); );
name = Common; name = Common;
path = ../../PiOS/Common; path = ../../PiOS/Common;
@ -7681,6 +7684,7 @@
65E8F03E11EFF25C00BBF654 /* pios_debug.h */, 65E8F03E11EFF25C00BBF654 /* pios_debug.h */,
65E8F03F11EFF25C00BBF654 /* pios_delay.h */, 65E8F03F11EFF25C00BBF654 /* pios_delay.h */,
65E8F04011EFF25C00BBF654 /* pios_exti.h */, 65E8F04011EFF25C00BBF654 /* pios_exti.h */,
65FF4D61137EFA4F00146BE4 /* pios_flashfs_objlist.h */,
65E8F04111EFF25C00BBF654 /* pios_gpio.h */, 65E8F04111EFF25C00BBF654 /* pios_gpio.h */,
65E8F04211EFF25C00BBF654 /* pios_hmc5843.h */, 65E8F04211EFF25C00BBF654 /* pios_hmc5843.h */,
65E8F04311EFF25C00BBF654 /* pios_i2c.h */, 65E8F04311EFF25C00BBF654 /* pios_i2c.h */,

View File

@ -41,10 +41,10 @@
* List of event queues and the eventmask associated with the queue. * List of event queues and the eventmask associated with the queue.
*/ */
struct ObjectEventListStruct { struct ObjectEventListStruct {
xQueueHandle queue; xQueueHandle queue;
UAVObjEventCallback cb; UAVObjEventCallback cb;
int32_t eventMask; int32_t eventMask;
struct ObjectEventListStruct* next; struct ObjectEventListStruct *next;
}; };
typedef struct ObjectEventListStruct ObjectEventList; typedef struct ObjectEventListStruct ObjectEventList;
@ -52,9 +52,9 @@ typedef struct ObjectEventListStruct ObjectEventList;
* List of object instances, holds the actual data structure and instance ID * List of object instances, holds the actual data structure and instance ID
*/ */
struct ObjectInstListStruct { struct ObjectInstListStruct {
void* data; void *data;
uint16_t instId; uint16_t instId;
struct ObjectInstListStruct* next; struct ObjectInstListStruct *next;
}; };
typedef struct ObjectInstListStruct ObjectInstList; typedef struct ObjectInstListStruct ObjectInstList;
@ -62,34 +62,48 @@ typedef struct ObjectInstListStruct ObjectInstList;
* List of objects registered in the object manager * List of objects registered in the object manager
*/ */
struct ObjectListStruct { struct ObjectListStruct {
uint32_t id; /** The object ID */ uint32_t id;
const char* name; /** The object name */ /** The object ID */
int8_t isMetaobject; /** Set to 1 if this is a metaobject */ const char *name;
int8_t isSingleInstance; /** Set to 1 if this object has a single instance */ /** The object name */
int8_t isSettings; /** Set to 1 if this object is a settings object */ int8_t isMetaobject;
uint16_t numBytes; /** Number of data bytes contained in the object (for a single instance) */ /** Set to 1 if this is a metaobject */
uint16_t numInstances; /** Number of instances */ int8_t isSingleInstance;
struct ObjectListStruct* linkedObj; /** Linked object, for regular objects this is the metaobject and for metaobjects it is the parent object */ /** Set to 1 if this object has a single instance */
ObjectInstList instances; /** List of object instances, instance 0 always exists */ int8_t isSettings;
ObjectEventList* events; /** Event queues registered on the object */ /** Set to 1 if this object is a settings object */
struct ObjectListStruct* next; /** Needed by linked list library (utlist.h) */ uint16_t numBytes;
/** Number of data bytes contained in the object (for a single instance) */
uint16_t numInstances;
/** Number of instances */
struct ObjectListStruct *linkedObj;
/** Linked object, for regular objects this is the metaobject and for metaobjects it is the parent object */
ObjectInstList instances;
/** List of object instances, instance 0 always exists */
ObjectEventList *events;
/** Event queues registered on the object */
struct ObjectListStruct *next;
/** Needed by linked list library (utlist.h) */
}; };
typedef struct ObjectListStruct ObjectList; typedef struct ObjectListStruct ObjectList;
// Private functions // Private functions
static int32_t sendEvent(ObjectList* obj, uint16_t instId, UAVObjEventType event); static int32_t sendEvent(ObjectList * obj, uint16_t instId,
static ObjectInstList* createInstance(ObjectList* obj, uint16_t instId); UAVObjEventType event);
static ObjectInstList* getInstance(ObjectList* obj, uint16_t instId); static ObjectInstList *createInstance(ObjectList * obj, uint16_t instId);
static int32_t connectObj(UAVObjHandle obj, xQueueHandle queue, UAVObjEventCallback cb, int32_t eventMask); static ObjectInstList *getInstance(ObjectList * obj, uint16_t instId);
static int32_t disconnectObj(UAVObjHandle obj, xQueueHandle queue, UAVObjEventCallback cb); static int32_t connectObj(UAVObjHandle obj, xQueueHandle queue,
UAVObjEventCallback cb, int32_t eventMask);
static int32_t disconnectObj(UAVObjHandle obj, xQueueHandle queue,
UAVObjEventCallback cb);
#if defined(PIOS_INCLUDE_SDCARD) #if defined(PIOS_INCLUDE_SDCARD)
static void objectFilename(ObjectList* obj, uint8_t* filename); static void objectFilename(ObjectList * obj, uint8_t * filename);
static void customSPrintf(uint8_t* buffer, uint8_t* format, ...); static void customSPrintf(uint8_t * buffer, uint8_t * format, ...);
#endif #endif
// Private variables // Private variables
static ObjectList* objList; static ObjectList *objList;
static xSemaphoreHandle mutex; static xSemaphoreHandle mutex;
static UAVObjMetadata defMetadata; static UAVObjMetadata defMetadata;
static UAVObjStats stats; static UAVObjStats stats;
@ -101,40 +115,40 @@ static UAVObjStats stats;
*/ */
int32_t UAVObjInitialize() int32_t UAVObjInitialize()
{ {
// Initialize variables // Initialize variables
objList = NULL; objList = NULL;
memset(&stats, 0, sizeof(UAVObjStats)); memset(&stats, 0, sizeof(UAVObjStats));
// Create mutex // Create mutex
mutex = xSemaphoreCreateRecursiveMutex(); mutex = xSemaphoreCreateRecursiveMutex();
if (mutex == NULL) if (mutex == NULL)
return -1; return -1;
// Initialize default metadata structure (metadata of metaobjects) // Initialize default metadata structure (metadata of metaobjects)
defMetadata.access = ACCESS_READWRITE; defMetadata.access = ACCESS_READWRITE;
defMetadata.gcsAccess = ACCESS_READWRITE; defMetadata.gcsAccess = ACCESS_READWRITE;
defMetadata.telemetryAcked = 1; defMetadata.telemetryAcked = 1;
defMetadata.telemetryUpdateMode = UPDATEMODE_ONCHANGE; defMetadata.telemetryUpdateMode = UPDATEMODE_ONCHANGE;
defMetadata.telemetryUpdatePeriod = 0; defMetadata.telemetryUpdatePeriod = 0;
defMetadata.gcsTelemetryAcked = 1; defMetadata.gcsTelemetryAcked = 1;
defMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE; defMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
defMetadata.gcsTelemetryUpdatePeriod = 0; defMetadata.gcsTelemetryUpdatePeriod = 0;
defMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE; defMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE;
defMetadata.loggingUpdatePeriod = 0; defMetadata.loggingUpdatePeriod = 0;
// Done // Done
return 0; return 0;
} }
/** /**
* Get the statistics counters * Get the statistics counters
* @param[out] statsOut The statistics counters will be copied there * @param[out] statsOut The statistics counters will be copied there
*/ */
void UAVObjGetStats(UAVObjStats* statsOut) void UAVObjGetStats(UAVObjStats * statsOut)
{ {
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
memcpy(statsOut, &stats, sizeof(UAVObjStats)); memcpy(statsOut, &stats, sizeof(UAVObjStats));
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
} }
/** /**
@ -142,9 +156,9 @@ void UAVObjGetStats(UAVObjStats* statsOut)
*/ */
void UAVObjClearStats() void UAVObjClearStats()
{ {
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
memset(&stats, 0, sizeof(UAVObjStats)); memset(&stats, 0, sizeof(UAVObjStats));
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
} }
/** /**
@ -160,91 +174,85 @@ void UAVObjClearStats()
* \return Object handle, or NULL if failure. * \return Object handle, or NULL if failure.
* \return * \return
*/ */
UAVObjHandle UAVObjRegister(uint32_t id, const char* name, const char* metaName, int32_t isMetaobject, UAVObjHandle UAVObjRegister(uint32_t id, const char *name,
int32_t isSingleInstance, int32_t isSettings, uint32_t numBytes, UAVObjInitializeCallback initCb) const char *metaName, int32_t isMetaobject,
int32_t isSingleInstance, int32_t isSettings,
uint32_t numBytes,
UAVObjInitializeCallback initCb)
{ {
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
ObjectList* metaObj; ObjectList *metaObj;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Check that the object is not already registered // Check that the object is not already registered
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ if (objEntry->id == id) {
if (objEntry->id == id) // Already registered, ignore
{ xSemaphoreGiveRecursive(mutex);
// Already registered, ignore return NULL;
xSemaphoreGiveRecursive(mutex); }
return NULL; }
}
}
// Create and append entry // Create and append entry
objEntry = (ObjectList*)pvPortMalloc(sizeof(ObjectList)); objEntry = (ObjectList *) pvPortMalloc(sizeof(ObjectList));
if (objEntry == NULL) if (objEntry == NULL) {
{ xSemaphoreGiveRecursive(mutex);
xSemaphoreGiveRecursive(mutex); return NULL;
return NULL; }
} objEntry->id = id;
objEntry->id = id; objEntry->name = name;
objEntry->name = name; objEntry->isMetaobject = (int8_t) isMetaobject;
objEntry->isMetaobject = (int8_t)isMetaobject; objEntry->isSingleInstance = (int8_t) isSingleInstance;
objEntry->isSingleInstance = (int8_t)isSingleInstance; objEntry->isSettings = (int8_t) isSettings;
objEntry->isSettings = (int8_t)isSettings; objEntry->numBytes = numBytes;
objEntry->numBytes = numBytes; objEntry->events = NULL;
objEntry->events = NULL; objEntry->numInstances = 0;
objEntry->numInstances = 0; objEntry->instances.data = NULL;
objEntry->instances.data = NULL; objEntry->instances.instId = 0xFFFF;
objEntry->instances.instId = 0xFFFF; objEntry->instances.next = NULL;
objEntry->instances.next = NULL; objEntry->linkedObj = NULL; // will be set later
objEntry->linkedObj = NULL; // will be set later LL_APPEND(objList, objEntry);
LL_APPEND(objList, objEntry);
// Create instance zero // Create instance zero
instEntry = createInstance(objEntry, 0); instEntry = createInstance(objEntry, 0);
if ( instEntry == NULL ) if (instEntry == NULL) {
{ xSemaphoreGiveRecursive(mutex);
xSemaphoreGiveRecursive(mutex); return NULL;
return NULL; }
} // Create metaobject and update linkedObj
if (isMetaobject) {
objEntry->linkedObj = NULL; // will be set later
} else {
// Create metaobject
metaObj =
(ObjectList *) UAVObjRegister(id + 1, metaName,
NULL, 1, 1, 0,
sizeof
(UAVObjMetadata),
NULL);
// Link two objects
objEntry->linkedObj = metaObj;
metaObj->linkedObj = objEntry;
}
// Create metaobject and update linkedObj // Initialize object fields and metadata to default values
if (isMetaobject) if (initCb != NULL) {
{ initCb((UAVObjHandle) objEntry, 0);
objEntry->linkedObj = NULL; // will be set later }
} // Attempt to load object's metadata from the SD card (not done directly on the metaobject, but through the object)
else if (!objEntry->isMetaobject) {
{ UAVObjLoad((UAVObjHandle) objEntry->linkedObj, 0);
// Create metaobject }
metaObj = (ObjectList*)UAVObjRegister(id+1, metaName, NULL, 1, 1, 0, sizeof(UAVObjMetadata), NULL); // If this is a settings object, attempt to load from SD card
// Link two objects if (objEntry->isSettings) {
objEntry->linkedObj = metaObj; UAVObjLoad((UAVObjHandle) objEntry, 0);
metaObj->linkedObj = objEntry; }
} // Release lock
xSemaphoreGiveRecursive(mutex);
// Initialize object fields and metadata to default values return (UAVObjHandle) objEntry;
if ( initCb != NULL )
{
initCb((UAVObjHandle)objEntry, 0);
}
// Attempt to load object's metadata from the SD card (not done directly on the metaobject, but through the object)
if ( !objEntry->isMetaobject )
{
UAVObjLoad( (UAVObjHandle)objEntry->linkedObj, 0 );
}
// If this is a settings object, attempt to load from SD card
if ( objEntry->isSettings )
{
UAVObjLoad( (UAVObjHandle)objEntry, 0 );
}
// Release lock
xSemaphoreGiveRecursive(mutex);
return (UAVObjHandle)objEntry;
} }
/** /**
@ -254,26 +262,24 @@ UAVObjHandle UAVObjRegister(uint32_t id, const char* name, const char* metaName,
*/ */
UAVObjHandle UAVObjGetByID(uint32_t id) UAVObjHandle UAVObjGetByID(uint32_t id)
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Look for object // Look for object
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ if (objEntry->id == id) {
if (objEntry->id == id) // Release lock
{ xSemaphoreGiveRecursive(mutex);
// Release lock // Done, object found
xSemaphoreGiveRecursive(mutex); return (UAVObjHandle) objEntry;
// Done, object found }
return (UAVObjHandle)objEntry; }
}
}
// Object not found, release lock and return error // Object not found, release lock and return error
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return NULL; return NULL;
} }
/** /**
@ -281,28 +287,27 @@ UAVObjHandle UAVObjGetByID(uint32_t id)
* \param[in] name The name of the object * \param[in] name The name of the object
* \return The object or NULL if not found. * \return The object or NULL if not found.
*/ */
UAVObjHandle UAVObjGetByName(char* name) UAVObjHandle UAVObjGetByName(char *name)
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Look for object // Look for object
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ if (objEntry->name != NULL
if (objEntry->name != NULL && strcmp(objEntry->name, name) == 0) && strcmp(objEntry->name, name) == 0) {
{ // Release lock
// Release lock xSemaphoreGiveRecursive(mutex);
xSemaphoreGiveRecursive(mutex); // Done, object found
// Done, object found return (UAVObjHandle) objEntry;
return (UAVObjHandle)objEntry; }
} }
}
// Object not found, release lock and return error // Object not found, release lock and return error
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return NULL; return NULL;
} }
/** /**
@ -312,7 +317,7 @@ UAVObjHandle UAVObjGetByName(char* name)
*/ */
uint32_t UAVObjGetID(UAVObjHandle obj) uint32_t UAVObjGetID(UAVObjHandle obj)
{ {
return ((ObjectList*)obj)->id; return ((ObjectList *) obj)->id;
} }
/** /**
@ -320,9 +325,9 @@ uint32_t UAVObjGetID(UAVObjHandle obj)
* \param[in] obj The object handle * \param[in] obj The object handle
* \return The object's name * \return The object's name
*/ */
const char* UAVObjGetName(UAVObjHandle obj) const char *UAVObjGetName(UAVObjHandle obj)
{ {
return ((ObjectList*)obj)->name; return ((ObjectList *) obj)->name;
} }
/** /**
@ -332,7 +337,7 @@ const char* UAVObjGetName(UAVObjHandle obj)
*/ */
uint32_t UAVObjGetNumBytes(UAVObjHandle obj) uint32_t UAVObjGetNumBytes(UAVObjHandle obj)
{ {
return ((ObjectList*)obj)->numBytes; return ((ObjectList *) obj)->numBytes;
} }
/** /**
@ -344,7 +349,7 @@ uint32_t UAVObjGetNumBytes(UAVObjHandle obj)
*/ */
UAVObjHandle UAVObjGetLinkedObj(UAVObjHandle obj) UAVObjHandle UAVObjGetLinkedObj(UAVObjHandle obj)
{ {
return (UAVObjHandle)(((ObjectList*)obj)->linkedObj); return (UAVObjHandle) (((ObjectList *) obj)->linkedObj);
} }
/** /**
@ -354,11 +359,11 @@ UAVObjHandle UAVObjGetLinkedObj(UAVObjHandle obj)
*/ */
uint16_t UAVObjGetNumInstances(UAVObjHandle obj) uint16_t UAVObjGetNumInstances(UAVObjHandle obj)
{ {
uint32_t numInstances; uint32_t numInstances;
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
numInstances = ((ObjectList*)obj)->numInstances; numInstances = ((ObjectList *) obj)->numInstances;
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return numInstances; return numInstances;
} }
/** /**
@ -366,32 +371,29 @@ uint16_t UAVObjGetNumInstances(UAVObjHandle obj)
* \param[in] obj The object handle * \param[in] obj The object handle
* \return The instance ID or 0 if an error * \return The instance ID or 0 if an error
*/ */
uint16_t UAVObjCreateInstance(UAVObjHandle obj, UAVObjInitializeCallback initCb) uint16_t UAVObjCreateInstance(UAVObjHandle obj,
UAVObjInitializeCallback initCb)
{ {
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
// Lock // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Create new instance // Create new instance
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
instEntry = createInstance(objEntry, objEntry->numInstances); instEntry = createInstance(objEntry, objEntry->numInstances);
if ( instEntry == NULL ) if (instEntry == NULL) {
{ xSemaphoreGiveRecursive(mutex);
xSemaphoreGiveRecursive(mutex); return -1;
return -1; }
} // Initialize instance data
if (initCb != NULL) {
// Initialize instance data initCb(obj, instEntry->instId);
if ( initCb != NULL ) }
{ // Unlock
initCb(obj, instEntry->instId); xSemaphoreGiveRecursive(mutex);
} return instEntry->instId;
// Unlock
xSemaphoreGiveRecursive(mutex);
return instEntry->instId;
} }
/** /**
@ -401,7 +403,7 @@ uint16_t UAVObjCreateInstance(UAVObjHandle obj, UAVObjInitializeCallback initCb)
*/ */
int32_t UAVObjIsSingleInstance(UAVObjHandle obj) int32_t UAVObjIsSingleInstance(UAVObjHandle obj)
{ {
return ((ObjectList*)obj)->isSingleInstance; return ((ObjectList *) obj)->isSingleInstance;
} }
/** /**
@ -411,7 +413,7 @@ int32_t UAVObjIsSingleInstance(UAVObjHandle obj)
*/ */
int32_t UAVObjIsMetaobject(UAVObjHandle obj) int32_t UAVObjIsMetaobject(UAVObjHandle obj)
{ {
return ((ObjectList*)obj)->isMetaobject; return ((ObjectList *) obj)->isMetaobject;
} }
/** /**
@ -421,7 +423,7 @@ int32_t UAVObjIsMetaobject(UAVObjHandle obj)
*/ */
int32_t UAVObjIsSettings(UAVObjHandle obj) int32_t UAVObjIsSettings(UAVObjHandle obj)
{ {
return ((ObjectList*)obj)->isSettings; return ((ObjectList *) obj)->isSettings;
} }
/** /**
@ -431,41 +433,39 @@ int32_t UAVObjIsSettings(UAVObjHandle obj)
* \param[in] dataIn The byte array * \param[in] dataIn The byte array
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjUnpack(UAVObjHandle obj, uint16_t instId, const uint8_t* dataIn) int32_t UAVObjUnpack(UAVObjHandle obj, uint16_t instId,
const uint8_t * dataIn)
{ {
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
// Lock // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Cast handle to object // Cast handle to object
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
// Get the instance // Get the instance
instEntry = getInstance(objEntry, instId); instEntry = getInstance(objEntry, instId);
// If the instance does not exist create it and any other instances before it // If the instance does not exist create it and any other instances before it
if ( instEntry == NULL ) if (instEntry == NULL) {
{ instEntry = createInstance(objEntry, instId);
instEntry = createInstance(objEntry, instId); if (instEntry == NULL) {
if ( instEntry == NULL ) // Error, unlock and return
{ xSemaphoreGiveRecursive(mutex);
// Error, unlock and return return -1;
xSemaphoreGiveRecursive(mutex); }
return -1; }
} // Set the data
} memcpy(instEntry->data, dataIn, objEntry->numBytes);
// Set the data // Fire event
memcpy(instEntry->data, dataIn, objEntry->numBytes); sendEvent(objEntry, instId, EV_UNPACKED);
// Fire event // Unlock
sendEvent(objEntry, instId, EV_UNPACKED); xSemaphoreGiveRecursive(mutex);
return 0;
// Unlock
xSemaphoreGiveRecursive(mutex);
return 0;
} }
/** /**
@ -475,32 +475,30 @@ int32_t UAVObjUnpack(UAVObjHandle obj, uint16_t instId, const uint8_t* dataIn)
* \param[out] dataOut The byte array * \param[out] dataOut The byte array
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjPack(UAVObjHandle obj, uint16_t instId, uint8_t* dataOut) int32_t UAVObjPack(UAVObjHandle obj, uint16_t instId, uint8_t * dataOut)
{ {
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
// Lock // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Cast handle to object // Cast handle to object
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
// Get the instance // Get the instance
instEntry = getInstance(objEntry, instId); instEntry = getInstance(objEntry, instId);
if ( instEntry == NULL ) if (instEntry == NULL) {
{ // Error, unlock and return
// Error, unlock and return xSemaphoreGiveRecursive(mutex);
xSemaphoreGiveRecursive(mutex); return -1;
return -1; }
} // Pack data
memcpy(dataOut, instEntry->data, objEntry->numBytes);
// Pack data // Unlock
memcpy(dataOut, instEntry->data, objEntry->numBytes); xSemaphoreGiveRecursive(mutex);
return 0;
// Unlock
xSemaphoreGiveRecursive(mutex);
return 0;
} }
/** /**
@ -512,64 +510,52 @@ int32_t UAVObjPack(UAVObjHandle obj, uint16_t instId, uint8_t* dataOut)
* @param[in] file File to append to * @param[in] file File to append to
* @return 0 if success or -1 if failure * @return 0 if success or -1 if failure
*/ */
int32_t UAVObjSaveToFile(UAVObjHandle obj, uint16_t instId, FILEINFO* file) int32_t UAVObjSaveToFile(UAVObjHandle obj, uint16_t instId,
FILEINFO * file)
{ {
#if defined(PIOS_INCLUDE_SDCARD) #if defined(PIOS_INCLUDE_SDCARD)
uint32_t bytesWritten; uint32_t bytesWritten;
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
// Check for file system availability // Check for file system availability
if ( PIOS_SDCARD_IsMounted() == 0 ) if (PIOS_SDCARD_IsMounted() == 0) {
{ return -1;
return -1; }
} // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Lock // Cast to object
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); objEntry = (ObjectList *) obj;
// Cast to object // Get the instance information
objEntry = (ObjectList*)obj; instEntry = getInstance(objEntry, instId);
if (instEntry == NULL) {
xSemaphoreGiveRecursive(mutex);
return -1;
}
// Write the object ID
PIOS_FWRITE(file, &objEntry->id, sizeof(objEntry->id),
&bytesWritten);
// Get the instance information // Write the instance ID
instEntry = getInstance(objEntry, instId); if (!objEntry->isSingleInstance) {
if ( instEntry == NULL ) PIOS_FWRITE(file, &instEntry->instId,
{ sizeof(instEntry->instId), &bytesWritten);
xSemaphoreGiveRecursive(mutex); }
return -1; // Write the data and check that the write was successful
} PIOS_FWRITE(file, instEntry->data, objEntry->numBytes,
&bytesWritten);
// Write the object ID if (bytesWritten != objEntry->numBytes) {
PIOS_FWRITE(file,&objEntry->id,sizeof(objEntry->id),&bytesWritten); xSemaphoreGiveRecursive(mutex);
return -1;
// Write the instance ID }
if (!objEntry->isSingleInstance) // Done
{ xSemaphoreGiveRecursive(mutex);
PIOS_FWRITE(file,&instEntry->instId,sizeof(instEntry->instId),&bytesWritten);
}
// Write the data and check that the write was successful
PIOS_FWRITE(file,instEntry->data,objEntry->numBytes,&bytesWritten);
if ( bytesWritten != objEntry->numBytes )
{
xSemaphoreGiveRecursive(mutex);
return -1;
}
// Done
xSemaphoreGiveRecursive(mutex);
#endif /* PIOS_INCLUDE_SDCARD */ #endif /* PIOS_INCLUDE_SDCARD */
return 0; return 0;
} }
struct fileHeader {
uint32_t id;
uint16_t instId;
uint16_t size;
} __attribute__((packed));
#define FLASH_MASK 0x001ff000 /* Select a sector */
/** /**
* Save the data of the specified object to the file system (SD card). * Save the data of the specified object to the file system (SD card).
* If the object contains multiple instances, all of them will be saved. * If the object contains multiple instances, all of them will be saved.
@ -583,71 +569,56 @@ struct fileHeader {
int32_t UAVObjSave(UAVObjHandle obj, uint16_t instId) int32_t UAVObjSave(UAVObjHandle obj, uint16_t instId)
{ {
#if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS) #if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
ObjectList* objEntry = (ObjectList*)obj; ObjectList *objEntry = (ObjectList *) obj;
if(objEntry == NULL) if (objEntry == NULL)
return -1; return -1;
ObjectInstList* instEntry = getInstance(objEntry, instId); ObjectInstList *instEntry = getInstance(objEntry, instId);
if(instEntry == NULL) if (instEntry == NULL)
return -1; return -1;
if(instEntry->data == NULL) if (instEntry->data == NULL)
return -1; return -1;
if (PIOS_FLASHFS_ObjSave(obj, instId, instEntry->data) != 0)
struct fileHeader header = { return -1;
.id = objEntry->id,
.instId = instId,
.size = objEntry->numBytes
};
uint32_t addr = (objEntry->id & FLASH_MASK);
PIOS_Flash_W25X_EraseSector(addr);
PIOS_Flash_W25X_WriteData(addr, (uint8_t *) &header, sizeof(header));
PIOS_Flash_W25X_WriteData(addr + sizeof(header), instEntry->data,objEntry->numBytes);
#endif #endif
#if defined(PIOS_INCLUDE_SDCARD) #if defined(PIOS_INCLUDE_SDCARD)
FILEINFO file; FILEINFO file;
ObjectList* objEntry; ObjectList *objEntry;
uint8_t filename[14]; uint8_t filename[14];
// Check for file system availability // Check for file system availability
if ( PIOS_SDCARD_IsMounted() == 0 ) if (PIOS_SDCARD_IsMounted() == 0) {
{ return -1;
return -1; }
} // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Lock // Cast to object
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); objEntry = (ObjectList *) obj;
// Cast to object // Get filename
objEntry = (ObjectList*)obj; objectFilename(objEntry, filename);
// Get filename // Open file
objectFilename(objEntry, filename); if (PIOS_FOPEN_WRITE(filename, file)) {
xSemaphoreGiveRecursive(mutex);
// Open file return -1;
if ( PIOS_FOPEN_WRITE(filename,file) ) }
{ // Append object
xSemaphoreGiveRecursive(mutex); if (UAVObjSaveToFile(obj, instId, &file) == -1) {
return -1; PIOS_FCLOSE(file);
} xSemaphoreGiveRecursive(mutex);
return -1;
// Append object }
if ( UAVObjSaveToFile(obj, instId, &file) == -1 ) // Done, close file and unlock
{ PIOS_FCLOSE(file);
PIOS_FCLOSE(file); xSemaphoreGiveRecursive(mutex);
xSemaphoreGiveRecursive(mutex);
return -1;
}
// Done, close file and unlock
PIOS_FCLOSE(file);
xSemaphoreGiveRecursive(mutex);
#endif /* PIOS_INCLUDE_SDCARD */ #endif /* PIOS_INCLUDE_SDCARD */
return 0; return 0;
} }
/** /**
@ -655,82 +626,71 @@ int32_t UAVObjSave(UAVObjHandle obj, uint16_t instId)
* @param[in] file File to read from * @param[in] file File to read from
* @return The handle of the object loaded or NULL if a failure * @return The handle of the object loaded or NULL if a failure
*/ */
UAVObjHandle UAVObjLoadFromFile(FILEINFO* file) UAVObjHandle UAVObjLoadFromFile(FILEINFO * file)
{ {
#if defined(PIOS_INCLUDE_SDCARD) #if defined(PIOS_INCLUDE_SDCARD)
uint32_t bytesRead; uint32_t bytesRead;
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
uint32_t objId; uint32_t objId;
uint16_t instId; uint16_t instId;
UAVObjHandle obj; UAVObjHandle obj;
// Check for file system availability // Check for file system availability
if ( PIOS_SDCARD_IsMounted() == 0 ) if (PIOS_SDCARD_IsMounted() == 0) {
{ return NULL;
return NULL; }
} // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Lock // Read the object ID
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); if (PIOS_FREAD(file, &objId, sizeof(objId), &bytesRead)) {
xSemaphoreGiveRecursive(mutex);
return NULL;
}
// Get the object
obj = UAVObjGetByID(objId);
if (obj == 0) {
xSemaphoreGiveRecursive(mutex);
return NULL;
}
objEntry = (ObjectList *) obj;
// Read the object ID // Get the instance ID
if ( PIOS_FREAD(file,&objId,sizeof(objId),&bytesRead) ) instId = 0;
{ if (!objEntry->isSingleInstance) {
xSemaphoreGiveRecursive(mutex); if (PIOS_FREAD
return NULL; (file, &instId, sizeof(instId), &bytesRead)) {
} xSemaphoreGiveRecursive(mutex);
return NULL;
}
}
// Get the instance information
instEntry = getInstance(objEntry, instId);
// Get the object // If the instance does not exist create it and any other instances before it
obj = UAVObjGetByID(objId); if (instEntry == NULL) {
if ( obj == 0 ) instEntry = createInstance(objEntry, instId);
{ if (instEntry == NULL) {
xSemaphoreGiveRecursive(mutex); // Error, unlock and return
return NULL; xSemaphoreGiveRecursive(mutex);
} return NULL;
objEntry = (ObjectList*)obj; }
}
// Read the instance data
if (PIOS_FREAD
(file, instEntry->data, objEntry->numBytes, &bytesRead)) {
xSemaphoreGiveRecursive(mutex);
return NULL;
}
// Fire event
sendEvent(objEntry, instId, EV_UNPACKED);
// Get the instance ID // Unlock
instId = 0; xSemaphoreGiveRecursive(mutex);
if ( !objEntry->isSingleInstance ) return obj;
{
if ( PIOS_FREAD(file,&instId,sizeof(instId),&bytesRead) )
{
xSemaphoreGiveRecursive(mutex);
return NULL;
}
}
// Get the instance information
instEntry = getInstance(objEntry, instId);
// If the instance does not exist create it and any other instances before it
if ( instEntry == NULL )
{
instEntry = createInstance(objEntry, instId);
if ( instEntry == NULL )
{
// Error, unlock and return
xSemaphoreGiveRecursive(mutex);
return NULL;
}
}
// Read the instance data
if ( PIOS_FREAD(file,instEntry->data,objEntry->numBytes,&bytesRead) )
{
xSemaphoreGiveRecursive(mutex);
return NULL;
}
// Fire event
sendEvent(objEntry, instId, EV_UNPACKED);
// Unlock
xSemaphoreGiveRecursive(mutex);
return obj;
#else /* PIOS_INCLUDE_SDCARD */ #else /* PIOS_INCLUDE_SDCARD */
return NULL; return NULL;
#endif #endif
} }
@ -745,87 +705,70 @@ UAVObjHandle UAVObjLoadFromFile(FILEINFO* file)
int32_t UAVObjLoad(UAVObjHandle obj, uint16_t instId) int32_t UAVObjLoad(UAVObjHandle obj, uint16_t instId)
{ {
#if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS) #if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
ObjectList* objEntry = (ObjectList*)obj; ObjectList *objEntry = (ObjectList *) obj;
if(objEntry == NULL) if (objEntry == NULL)
return -1; return -1;
ObjectInstList* instEntry = getInstance(objEntry, instId); ObjectInstList *instEntry = getInstance(objEntry, instId);
if(instEntry == NULL) if (instEntry == NULL)
return -1; return -1;
if(instEntry->data == NULL) if (instEntry->data == NULL)
return -1; return -1;
struct fileHeader header; // Fire event on success
uint32_t addr = (objEntry->id & FLASH_MASK); if (PIOS_FLASHFS_ObjLoad(obj, instId, instEntry->data) == 0)
sendEvent(objEntry, instId, EV_UNPACKED);
PIOS_Flash_W25X_ReadData(addr, (uint8_t *) &header, sizeof(header)); else
return -1;
if(header.id != objEntry->id)
return -1;
// Read the instance data
if (PIOS_Flash_W25X_ReadData(addr + sizeof(header) ,instEntry->data, objEntry->numBytes) != 0)
return -1;
// Fire event
sendEvent(objEntry, instId, EV_UNPACKED);
#endif #endif
#if defined(PIOS_INCLUDE_SDCARD) #if defined(PIOS_INCLUDE_SDCARD)
FILEINFO file; FILEINFO file;
ObjectList* objEntry; ObjectList *objEntry;
UAVObjHandle loadedObj; UAVObjHandle loadedObj;
ObjectList* loadedObjEntry; ObjectList *loadedObjEntry;
uint8_t filename[14]; uint8_t filename[14];
// Check for file system availability // Check for file system availability
if ( PIOS_SDCARD_IsMounted() == 0 ) if (PIOS_SDCARD_IsMounted() == 0) {
{ return -1;
return -1; }
} // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Lock // Cast to object
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); objEntry = (ObjectList *) obj;
// Cast to object // Get filename
objEntry = (ObjectList*)obj; objectFilename(objEntry, filename);
// Get filename // Open file
objectFilename(objEntry, filename); if (PIOS_FOPEN_READ(filename, file)) {
xSemaphoreGiveRecursive(mutex);
// Open file return -1;
if ( PIOS_FOPEN_READ(filename,file) ) }
{ // Load object
xSemaphoreGiveRecursive(mutex); loadedObj = UAVObjLoadFromFile(&file);
return -1; if (loadedObj == 0) {
} PIOS_FCLOSE(file);
xSemaphoreGiveRecursive(mutex);
// Load object return -1;
loadedObj = UAVObjLoadFromFile(&file); }
if (loadedObj == 0) // Check that the IDs match
{ loadedObjEntry = (ObjectList *) loadedObj;
PIOS_FCLOSE(file); if (loadedObjEntry->id != objEntry->id) {
xSemaphoreGiveRecursive(mutex); PIOS_FCLOSE(file);
return -1; xSemaphoreGiveRecursive(mutex);
} return -1;
}
// Check that the IDs match // Done, close file and unlock
loadedObjEntry = (ObjectList*)loadedObj; PIOS_FCLOSE(file);
if ( loadedObjEntry->id != objEntry->id ) xSemaphoreGiveRecursive(mutex);
{
PIOS_FCLOSE(file);
xSemaphoreGiveRecursive(mutex);
return -1;
}
// Done, close file and unlock
PIOS_FCLOSE(file);
xSemaphoreGiveRecursive(mutex);
#endif /* PIOS_INCLUDE_SDCARD */ #endif /* PIOS_INCLUDE_SDCARD */
return 0; return 0;
} }
/** /**
@ -837,40 +780,32 @@ int32_t UAVObjLoad(UAVObjHandle obj, uint16_t instId)
int32_t UAVObjDelete(UAVObjHandle obj, uint16_t instId) int32_t UAVObjDelete(UAVObjHandle obj, uint16_t instId)
{ {
#if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS) #if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS)
ObjectList* objEntry = (ObjectList*)obj; PIOS_FLASHFS_ObjDelete(obj, instId);
if(objEntry == NULL)
return -1;
uint32_t addr = (objEntry->id & FLASH_MASK);
PIOS_Flash_W25X_EraseSector(addr);
#endif #endif
#if defined(PIOS_INCLUDE_SDCARD) #if defined(PIOS_INCLUDE_SDCARD)
ObjectList* objEntry; ObjectList *objEntry;
uint8_t filename[14]; uint8_t filename[14];
// Check for file system availability // Check for file system availability
if ( PIOS_SDCARD_IsMounted() == 0 ) if (PIOS_SDCARD_IsMounted() == 0) {
{ return -1;
return -1; }
} // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Lock // Cast to object
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); objEntry = (ObjectList *) obj;
// Cast to object // Get filename
objEntry = (ObjectList*)obj; objectFilename(objEntry, filename);
// Get filename // Delete file
objectFilename(objEntry, filename); PIOS_FUNLINK(filename);
// Delete file // Done
PIOS_FUNLINK(filename); xSemaphoreGiveRecursive(mutex);
// Done
xSemaphoreGiveRecursive(mutex);
#endif /* PIOS_INCLUDE_SDCARD */ #endif /* PIOS_INCLUDE_SDCARD */
return 0; return 0;
} }
/** /**
@ -879,29 +814,27 @@ int32_t UAVObjDelete(UAVObjHandle obj, uint16_t instId)
*/ */
int32_t UAVObjSaveSettings() int32_t UAVObjSaveSettings()
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Save all settings objects // Save all settings objects
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ // Check if this is a settings object
// Check if this is a settings object if (objEntry->isSettings) {
if ( objEntry->isSettings ) // Save object
{ if (UAVObjSave((UAVObjHandle) objEntry, 0) ==
// Save object -1) {
if ( UAVObjSave( (UAVObjHandle)objEntry, 0 ) == -1 ) xSemaphoreGiveRecursive(mutex);
{ return -1;
xSemaphoreGiveRecursive(mutex); }
return -1; }
} }
}
}
// Done // Done
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -910,29 +843,27 @@ int32_t UAVObjSaveSettings()
*/ */
int32_t UAVObjLoadSettings() int32_t UAVObjLoadSettings()
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Load all settings objects // Load all settings objects
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ // Check if this is a settings object
// Check if this is a settings object if (objEntry->isSettings) {
if ( objEntry->isSettings ) // Load object
{ if (UAVObjLoad((UAVObjHandle) objEntry, 0) ==
// Load object -1) {
if ( UAVObjLoad( (UAVObjHandle)objEntry, 0 ) == -1 ) xSemaphoreGiveRecursive(mutex);
{ return -1;
xSemaphoreGiveRecursive(mutex); }
return -1; }
} }
}
}
// Done // Done
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -941,29 +872,27 @@ int32_t UAVObjLoadSettings()
*/ */
int32_t UAVObjDeleteSettings() int32_t UAVObjDeleteSettings()
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Save all settings objects // Save all settings objects
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ // Check if this is a settings object
// Check if this is a settings object if (objEntry->isSettings) {
if ( objEntry->isSettings ) // Save object
{ if (UAVObjDelete((UAVObjHandle) objEntry, 0)
// Save object == -1) {
if ( UAVObjDelete( (UAVObjHandle)objEntry, 0 ) == -1 ) xSemaphoreGiveRecursive(mutex);
{ return -1;
xSemaphoreGiveRecursive(mutex); }
return -1; }
} }
}
}
// Done // Done
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -972,29 +901,27 @@ int32_t UAVObjDeleteSettings()
*/ */
int32_t UAVObjSaveMetaobjects() int32_t UAVObjSaveMetaobjects()
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Save all settings objects // Save all settings objects
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ // Check if this is a settings object
// Check if this is a settings object if (objEntry->isMetaobject) {
if ( objEntry->isMetaobject ) // Save object
{ if (UAVObjSave((UAVObjHandle) objEntry, 0) ==
// Save object -1) {
if ( UAVObjSave( (UAVObjHandle)objEntry, 0 ) == -1 ) xSemaphoreGiveRecursive(mutex);
{ return -1;
xSemaphoreGiveRecursive(mutex); }
return -1; }
} }
}
}
// Done // Done
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -1003,29 +930,27 @@ int32_t UAVObjSaveMetaobjects()
*/ */
int32_t UAVObjLoadMetaobjects() int32_t UAVObjLoadMetaobjects()
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Load all settings objects // Load all settings objects
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ // Check if this is a settings object
// Check if this is a settings object if (objEntry->isMetaobject) {
if ( objEntry->isMetaobject ) // Load object
{ if (UAVObjLoad((UAVObjHandle) objEntry, 0) ==
// Load object -1) {
if ( UAVObjLoad( (UAVObjHandle)objEntry, 0 ) == -1 ) xSemaphoreGiveRecursive(mutex);
{ return -1;
xSemaphoreGiveRecursive(mutex); }
return -1; }
} }
}
}
// Done // Done
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -1034,29 +959,27 @@ int32_t UAVObjLoadMetaobjects()
*/ */
int32_t UAVObjDeleteMetaobjects() int32_t UAVObjDeleteMetaobjects()
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Load all settings objects // Load all settings objects
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ // Check if this is a settings object
// Check if this is a settings object if (objEntry->isMetaobject) {
if ( objEntry->isMetaobject ) // Load object
{ if (UAVObjDelete((UAVObjHandle) objEntry, 0)
// Load object == -1) {
if ( UAVObjDelete( (UAVObjHandle)objEntry, 0 ) == -1 ) xSemaphoreGiveRecursive(mutex);
{ return -1;
xSemaphoreGiveRecursive(mutex); }
return -1; }
} }
}
}
// Done // Done
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -1065,9 +988,9 @@ int32_t UAVObjDeleteMetaobjects()
* \param[in] dataIn The object's data structure * \param[in] dataIn The object's data structure
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjSetData(UAVObjHandle obj, const void* dataIn) int32_t UAVObjSetData(UAVObjHandle obj, const void *dataIn)
{ {
return UAVObjSetInstanceData(obj, 0, dataIn); return UAVObjSetInstanceData(obj, 0, dataIn);
} }
/** /**
@ -1076,9 +999,9 @@ int32_t UAVObjSetData(UAVObjHandle obj, const void* dataIn)
* \param[out] dataOut The object's data structure * \param[out] dataOut The object's data structure
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjGetData(UAVObjHandle obj, void* dataOut) int32_t UAVObjGetData(UAVObjHandle obj, void *dataOut)
{ {
return UAVObjGetInstanceData(obj, 0, dataOut); return UAVObjGetInstanceData(obj, 0, dataOut);
} }
/** /**
@ -1088,47 +1011,45 @@ int32_t UAVObjGetData(UAVObjHandle obj, void* dataOut)
* \param[in] dataIn The object's data structure * \param[in] dataIn The object's data structure
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjSetInstanceData(UAVObjHandle obj, uint16_t instId, const void* dataIn) int32_t UAVObjSetInstanceData(UAVObjHandle obj, uint16_t instId,
const void *dataIn)
{ {
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
UAVObjMetadata* mdata; UAVObjMetadata *mdata;
// Lock // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Cast to object info // Cast to object info
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
// Check access level // Check access level
if ( !objEntry->isMetaobject ) if (!objEntry->isMetaobject) {
{ mdata =
mdata = (UAVObjMetadata*)(objEntry->linkedObj->instances.data); (UAVObjMetadata *) (objEntry->linkedObj->instances.
if ( mdata->access == ACCESS_READONLY ) data);
{ if (mdata->access == ACCESS_READONLY) {
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return -1; return -1;
} }
} }
// Get instance information
instEntry = getInstance(objEntry, instId);
if (instEntry == NULL) {
// Error, unlock and return
xSemaphoreGiveRecursive(mutex);
return -1;
}
// Set data
memcpy(instEntry->data, dataIn, objEntry->numBytes);
// Get instance information // Fire event
instEntry = getInstance(objEntry, instId); sendEvent(objEntry, instId, EV_UPDATED);
if ( instEntry == NULL )
{
// Error, unlock and return
xSemaphoreGiveRecursive(mutex);
return -1;
}
// Set data // Unlock
memcpy(instEntry->data, dataIn, objEntry->numBytes); xSemaphoreGiveRecursive(mutex);
return 0;
// Fire event
sendEvent(objEntry, instId, EV_UPDATED);
// Unlock
xSemaphoreGiveRecursive(mutex);
return 0;
} }
/** /**
@ -1138,32 +1059,31 @@ int32_t UAVObjSetInstanceData(UAVObjHandle obj, uint16_t instId, const void* dat
* \param[out] dataOut The object's data structure * \param[out] dataOut The object's data structure
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjGetInstanceData(UAVObjHandle obj, uint16_t instId, void* dataOut) int32_t UAVObjGetInstanceData(UAVObjHandle obj, uint16_t instId,
void *dataOut)
{ {
ObjectList* objEntry; ObjectList *objEntry;
ObjectInstList* instEntry; ObjectInstList *instEntry;
// Lock // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Cast to object info // Cast to object info
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
// Get instance information // Get instance information
instEntry = getInstance(objEntry, instId); instEntry = getInstance(objEntry, instId);
if ( instEntry == NULL ) if (instEntry == NULL) {
{ // Error, unlock and return
// Error, unlock and return xSemaphoreGiveRecursive(mutex);
xSemaphoreGiveRecursive(mutex); return -1;
return -1; }
} // Set data
memcpy(dataOut, instEntry->data, objEntry->numBytes);
// Set data // Unlock
memcpy(dataOut, instEntry->data, objEntry->numBytes); xSemaphoreGiveRecursive(mutex);
return 0;
// Unlock
xSemaphoreGiveRecursive(mutex);
return 0;
} }
/** /**
@ -1172,27 +1092,25 @@ int32_t UAVObjGetInstanceData(UAVObjHandle obj, uint16_t instId, void* dataOut)
* \param[in] dataIn The object's metadata structure * \param[in] dataIn The object's metadata structure
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjSetMetadata(UAVObjHandle obj, const UAVObjMetadata* dataIn) int32_t UAVObjSetMetadata(UAVObjHandle obj, const UAVObjMetadata * dataIn)
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Lock // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Set metadata (metadata of metaobjects can not be modified) // Set metadata (metadata of metaobjects can not be modified)
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
if (!objEntry->isMetaobject) if (!objEntry->isMetaobject) {
{ UAVObjSetData((UAVObjHandle) objEntry->linkedObj,
UAVObjSetData((UAVObjHandle)objEntry->linkedObj, dataIn); dataIn);
} } else {
else return -1;
{ }
return -1;
}
// Unlock // Unlock
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -1201,27 +1119,25 @@ int32_t UAVObjSetMetadata(UAVObjHandle obj, const UAVObjMetadata* dataIn)
* \param[out] dataOut The object's metadata structure * \param[out] dataOut The object's metadata structure
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjGetMetadata(UAVObjHandle obj, UAVObjMetadata* dataOut) int32_t UAVObjGetMetadata(UAVObjHandle obj, UAVObjMetadata * dataOut)
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Lock // Lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Get metadata // Get metadata
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
if (objEntry->isMetaobject) if (objEntry->isMetaobject) {
{ memcpy(dataOut, &defMetadata, sizeof(UAVObjMetadata));
memcpy(dataOut, &defMetadata, sizeof(UAVObjMetadata)); } else {
} UAVObjGetData((UAVObjHandle) objEntry->linkedObj,
else dataOut);
{ }
UAVObjGetData((UAVObjHandle)objEntry->linkedObj, dataOut);
}
// Unlock // Unlock
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return 0; return 0;
} }
/** /**
@ -1234,19 +1150,20 @@ int32_t UAVObjGetMetadata(UAVObjHandle obj, UAVObjMetadata* dataOut)
*/ */
int8_t UAVObjReadOnly(UAVObjHandle obj) int8_t UAVObjReadOnly(UAVObjHandle obj)
{ {
ObjectList* objEntry; ObjectList *objEntry;
UAVObjMetadata* mdata; UAVObjMetadata *mdata;
// Cast to object info // Cast to object info
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
// Check access level // Check access level
if ( !objEntry->isMetaobject ) if (!objEntry->isMetaobject) {
{ mdata =
mdata = (UAVObjMetadata*)(objEntry->linkedObj->instances.data); (UAVObjMetadata *) (objEntry->linkedObj->instances.
return mdata->access == ACCESS_READONLY; data);
} return mdata->access == ACCESS_READONLY;
return -1; }
return -1;
} }
/** /**
@ -1257,13 +1174,14 @@ int8_t UAVObjReadOnly(UAVObjHandle obj)
* \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL) * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjConnectQueue(UAVObjHandle obj, xQueueHandle queue, int32_t eventMask) int32_t UAVObjConnectQueue(UAVObjHandle obj, xQueueHandle queue,
int32_t eventMask)
{ {
int32_t res; int32_t res;
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
res = connectObj(obj, queue, 0, eventMask); res = connectObj(obj, queue, 0, eventMask);
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return res; return res;
} }
/** /**
@ -1274,11 +1192,11 @@ int32_t UAVObjConnectQueue(UAVObjHandle obj, xQueueHandle queue, int32_t eventMa
*/ */
int32_t UAVObjDisconnectQueue(UAVObjHandle obj, xQueueHandle queue) int32_t UAVObjDisconnectQueue(UAVObjHandle obj, xQueueHandle queue)
{ {
int32_t res; int32_t res;
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
res = disconnectObj(obj, queue, 0); res = disconnectObj(obj, queue, 0);
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return res; return res;
} }
/** /**
@ -1289,13 +1207,14 @@ int32_t UAVObjDisconnectQueue(UAVObjHandle obj, xQueueHandle queue)
* \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL) * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
int32_t UAVObjConnectCallback(UAVObjHandle obj, UAVObjEventCallback cb, int32_t eventMask) int32_t UAVObjConnectCallback(UAVObjHandle obj, UAVObjEventCallback cb,
int32_t eventMask)
{ {
int32_t res; int32_t res;
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
res = connectObj(obj, 0, cb, eventMask); res = connectObj(obj, 0, cb, eventMask);
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return res; return res;
} }
/** /**
@ -1306,14 +1225,13 @@ int32_t UAVObjConnectCallback(UAVObjHandle obj, UAVObjEventCallback cb, int32_t
*/ */
int32_t UAVObjDisconnectCallback(UAVObjHandle obj, UAVObjEventCallback cb) int32_t UAVObjDisconnectCallback(UAVObjHandle obj, UAVObjEventCallback cb)
{ {
int32_t res; int32_t res;
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
res = disconnectObj(obj, 0, cb); res = disconnectObj(obj, 0, cb);
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
return res; return res;
} }
/** /**
* Request an update of the object's data from the GCS. The call will not wait for the response, a EV_UPDATED event * Request an update of the object's data from the GCS. The call will not wait for the response, a EV_UPDATED event
* will be generated as soon as the object is updated. * will be generated as soon as the object is updated.
@ -1321,7 +1239,7 @@ int32_t UAVObjDisconnectCallback(UAVObjHandle obj, UAVObjEventCallback cb)
*/ */
void UAVObjRequestUpdate(UAVObjHandle obj) void UAVObjRequestUpdate(UAVObjHandle obj)
{ {
UAVObjRequestInstanceUpdate(obj, UAVOBJ_ALL_INSTANCES); UAVObjRequestInstanceUpdate(obj, UAVOBJ_ALL_INSTANCES);
} }
/** /**
@ -1332,9 +1250,9 @@ void UAVObjRequestUpdate(UAVObjHandle obj)
*/ */
void UAVObjRequestInstanceUpdate(UAVObjHandle obj, uint16_t instId) void UAVObjRequestInstanceUpdate(UAVObjHandle obj, uint16_t instId)
{ {
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
sendEvent((ObjectList*)obj, instId, EV_UPDATE_REQ); sendEvent((ObjectList *) obj, instId, EV_UPDATE_REQ);
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
} }
/** /**
@ -1343,7 +1261,7 @@ void UAVObjRequestInstanceUpdate(UAVObjHandle obj, uint16_t instId)
*/ */
void UAVObjUpdated(UAVObjHandle obj) void UAVObjUpdated(UAVObjHandle obj)
{ {
UAVObjInstanceUpdated(obj, UAVOBJ_ALL_INSTANCES); UAVObjInstanceUpdated(obj, UAVOBJ_ALL_INSTANCES);
} }
/** /**
@ -1353,9 +1271,9 @@ void UAVObjUpdated(UAVObjHandle obj)
*/ */
void UAVObjInstanceUpdated(UAVObjHandle obj, uint16_t instId) void UAVObjInstanceUpdated(UAVObjHandle obj, uint16_t instId)
{ {
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
sendEvent((ObjectList*)obj, instId, EV_UPDATED_MANUAL); sendEvent((ObjectList *) obj, instId, EV_UPDATED_MANUAL);
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
} }
/** /**
@ -1363,143 +1281,133 @@ void UAVObjInstanceUpdated(UAVObjHandle obj, uint16_t instId)
* \param iterator This function will be called once for each object, * \param iterator This function will be called once for each object,
* the object will be passed as a parameter * the object will be passed as a parameter
*/ */
void UAVObjIterate(void (*iterator)(UAVObjHandle obj)) void UAVObjIterate(void (*iterator) (UAVObjHandle obj))
{ {
ObjectList* objEntry; ObjectList *objEntry;
// Get lock // Get lock
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// Iterate through the list and invoke iterator for each object // Iterate through the list and invoke iterator for each object
LL_FOREACH(objList, objEntry) LL_FOREACH(objList, objEntry) {
{ (*iterator) ((UAVObjHandle) objEntry);
(*iterator)((UAVObjHandle)objEntry); }
}
// Release lock // Release lock
xSemaphoreGiveRecursive(mutex); xSemaphoreGiveRecursive(mutex);
} }
/** /**
* Send an event to all event queues registered on the object. * Send an event to all event queues registered on the object.
*/ */
static int32_t sendEvent(ObjectList* obj, uint16_t instId, UAVObjEventType event) static int32_t sendEvent(ObjectList * obj, uint16_t instId,
UAVObjEventType event)
{ {
ObjectEventList* eventEntry; ObjectEventList *eventEntry;
UAVObjEvent msg; UAVObjEvent msg;
// Setup event // Setup event
msg.obj = (UAVObjHandle)obj; msg.obj = (UAVObjHandle) obj;
msg.event = event; msg.event = event;
msg.instId = instId; msg.instId = instId;
// Go through each object and push the event message in the queue (if event is activated for the queue) // Go through each object and push the event message in the queue (if event is activated for the queue)
LL_FOREACH(obj->events, eventEntry) LL_FOREACH(obj->events, eventEntry) {
{ if (eventEntry->eventMask == 0
if ( eventEntry->eventMask == 0 || (eventEntry->eventMask & event) != 0 ) || (eventEntry->eventMask & event) != 0) {
{ // Send to queue if a valid queue is registered
// Send to queue if a valid queue is registered if (eventEntry->queue != 0) {
if (eventEntry->queue != 0) if (xQueueSend(eventEntry->queue, &msg, 0) != pdTRUE) // will not block
{ {
if ( xQueueSend(eventEntry->queue, &msg, 0) != pdTRUE ) // will not block ++stats.eventErrors;
{ }
++stats.eventErrors; }
} // Invoke callback (from event task) if a valid one is registered
} if (eventEntry->cb != 0) {
// Invoke callback (from event task) if a valid one is registered if (EventCallbackDispatch(&msg, eventEntry->cb) != pdTRUE) // invoke callback from the event task, will not block
if (eventEntry->cb != 0) {
{ ++stats.eventErrors;
if ( EventCallbackDispatch(&msg, eventEntry->cb) != pdTRUE ) // invoke callback from the event task, will not block }
{ }
++stats.eventErrors; }
} }
}
}
}
// Done // Done
return 0; return 0;
} }
/** /**
* Create a new object instance, return the instance info or NULL if failure. * Create a new object instance, return the instance info or NULL if failure.
*/ */
static ObjectInstList* createInstance(ObjectList* obj, uint16_t instId) static ObjectInstList *createInstance(ObjectList * obj, uint16_t instId)
{ {
ObjectInstList* instEntry; ObjectInstList *instEntry;
int32_t n; int32_t n;
// For single instance objects, only instance zero is allowed // For single instance objects, only instance zero is allowed
if (obj->isSingleInstance && instId != 0) if (obj->isSingleInstance && instId != 0) {
{ return NULL;
return NULL; }
} // Make sure that the instance ID is within limits
if (instId >= UAVOBJ_MAX_INSTANCES) {
return NULL;
}
// Check if the instance already exists
if (getInstance(obj, instId) != NULL) {
return NULL;
}
// Create any missing instances (all instance IDs must be sequential)
for (n = obj->numInstances; n < instId; ++n) {
if (createInstance(obj, n) == NULL) {
return NULL;
}
}
// Make sure that the instance ID is within limits if (instId == 0) { /* Instance 0 ObjectInstList allocated with ObjectList element */
if (instId >= UAVOBJ_MAX_INSTANCES) instEntry = &obj->instances;
{ instEntry->data = pvPortMalloc(obj->numBytes);
return NULL; if (instEntry->data == NULL)
} return NULL;
memset(instEntry->data, 0, obj->numBytes);
instEntry->instId = instId;
} else {
// Create the actual instance
instEntry =
(ObjectInstList *)
pvPortMalloc(sizeof(ObjectInstList));
if (instEntry == NULL)
return NULL;
instEntry->data = pvPortMalloc(obj->numBytes);
if (instEntry->data == NULL)
return NULL;
memset(instEntry->data, 0, obj->numBytes);
instEntry->instId = instId;
LL_APPEND(obj->instances.next, instEntry);
}
++obj->numInstances;
// Check if the instance already exists // Fire event
if ( getInstance(obj, instId) != NULL ) UAVObjInstanceUpdated((UAVObjHandle) obj, instId);
{
return NULL;
}
// Create any missing instances (all instance IDs must be sequential) // Done
for (n = obj->numInstances; n < instId; ++n) return instEntry;
{
if ( createInstance(obj, n) == NULL )
{
return NULL;
}
}
if(instId == 0) /* Instance 0 ObjectInstList allocated with ObjectList element */
{
instEntry = &obj->instances;
instEntry->data = pvPortMalloc(obj->numBytes);
if (instEntry->data == NULL) return NULL;
memset(instEntry->data, 0, obj->numBytes);
instEntry->instId = instId;
} else
{
// Create the actual instance
instEntry = (ObjectInstList*)pvPortMalloc(sizeof(ObjectInstList));
if (instEntry == NULL) return NULL;
instEntry->data = pvPortMalloc(obj->numBytes);
if (instEntry->data == NULL) return NULL;
memset(instEntry->data, 0, obj->numBytes);
instEntry->instId = instId;
LL_APPEND(obj->instances.next, instEntry);
}
++obj->numInstances;
// Fire event
UAVObjInstanceUpdated((UAVObjHandle)obj, instId);
// Done
return instEntry;
} }
/** /**
* Get the instance information or NULL if the instance does not exist * Get the instance information or NULL if the instance does not exist
*/ */
static ObjectInstList* getInstance(ObjectList* obj, uint16_t instId) static ObjectInstList *getInstance(ObjectList * obj, uint16_t instId)
{ {
ObjectInstList* instEntry; ObjectInstList *instEntry;
// Look for specified instance ID // Look for specified instance ID
LL_FOREACH(&(obj->instances), instEntry) LL_FOREACH(&(obj->instances), instEntry) {
{ if (instEntry->instId == instId) {
if (instEntry->instId == instId) return instEntry;
{ }
return instEntry; }
} // If this point is reached then instance id was not found
} return NULL;
// If this point is reached then instance id was not found
return NULL;
} }
/** /**
@ -1510,36 +1418,35 @@ static ObjectInstList* getInstance(ObjectList* obj, uint16_t instId)
* \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL) * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
static int32_t connectObj(UAVObjHandle obj, xQueueHandle queue, UAVObjEventCallback cb, int32_t eventMask) static int32_t connectObj(UAVObjHandle obj, xQueueHandle queue,
UAVObjEventCallback cb, int32_t eventMask)
{ {
ObjectEventList* eventEntry; ObjectEventList *eventEntry;
ObjectList* objEntry; ObjectList *objEntry;
// Check that the queue is not already connected, if it is simply update event mask // Check that the queue is not already connected, if it is simply update event mask
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
LL_FOREACH(objEntry->events, eventEntry) LL_FOREACH(objEntry->events, eventEntry) {
{ if (eventEntry->queue == queue && eventEntry->cb == cb) {
if ( eventEntry->queue == queue && eventEntry->cb == cb ) // Already connected, update event mask and return
{ eventEntry->eventMask = eventMask;
// Already connected, update event mask and return return 0;
eventEntry->eventMask = eventMask; }
return 0; }
}
}
// Add queue to list // Add queue to list
eventEntry = (ObjectEventList*)pvPortMalloc(sizeof(ObjectEventList)); eventEntry =
if (eventEntry == NULL) (ObjectEventList *) pvPortMalloc(sizeof(ObjectEventList));
{ if (eventEntry == NULL) {
return -1; return -1;
} }
eventEntry->queue = queue; eventEntry->queue = queue;
eventEntry->cb = cb; eventEntry->cb = cb;
eventEntry->eventMask = eventMask; eventEntry->eventMask = eventMask;
LL_APPEND(objEntry->events, eventEntry); LL_APPEND(objEntry->events, eventEntry);
// Done // Done
return 0; return 0;
} }
/** /**
@ -1549,59 +1456,43 @@ static int32_t connectObj(UAVObjHandle obj, xQueueHandle queue, UAVObjEventCallb
* \param[in] cb The event callback * \param[in] cb The event callback
* \return 0 if success or -1 if failure * \return 0 if success or -1 if failure
*/ */
static int32_t disconnectObj(UAVObjHandle obj, xQueueHandle queue, UAVObjEventCallback cb) static int32_t disconnectObj(UAVObjHandle obj, xQueueHandle queue,
UAVObjEventCallback cb)
{ {
ObjectEventList* eventEntry; ObjectEventList *eventEntry;
ObjectList* objEntry; ObjectList *objEntry;
// Find queue and remove it // Find queue and remove it
objEntry = (ObjectList*)obj; objEntry = (ObjectList *) obj;
LL_FOREACH(objEntry->events, eventEntry) LL_FOREACH(objEntry->events, eventEntry) {
{ if ((eventEntry->queue == queue
if ( ( eventEntry->queue == queue && eventEntry->cb == cb ) ) && eventEntry->cb == cb)) {
{ LL_DELETE(objEntry->events, eventEntry);
LL_DELETE(objEntry->events, eventEntry); vPortFree(eventEntry);
vPortFree(eventEntry); return 0;
return 0; }
} }
}
// If this point is reached the queue was not found // If this point is reached the queue was not found
return -1; return -1;
} }
#if defined(PIOS_INCLUDE_SDCARD) #if defined(PIOS_INCLUDE_SDCARD)
/** /**
* Wrapper for the sprintf function * Wrapper for the sprintf function
*/ */
static void customSPrintf(uint8_t* buffer, uint8_t* format, ...) static void customSPrintf(uint8_t * buffer, uint8_t * format, ...)
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
vsprintf((char *)buffer, (char *)format, args); vsprintf((char *)buffer, (char *)format, args);
} }
/** /**
* Get an 8 character (plus extension) filename for the object. * Get an 8 character (plus extension) filename for the object.
*/ */
static void objectFilename(ObjectList* obj, uint8_t* filename) static void objectFilename(ObjectList * obj, uint8_t * filename)
{ {
customSPrintf(filename, (uint8_t*)"%X.obj", obj->id); customSPrintf(filename, (uint8_t *) "%X.obj", obj->id);
} }
#endif /* PIOS_INCLUDE_SDCARD */ #endif /* PIOS_INCLUDE_SDCARD */