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

Merge remote-tracking branch 'origin/next' into thread/OP-935_Changes_Basic_Stab

This commit is contained in:
Fredrik Arvidsson 2013-05-01 16:16:16 +02:00
commit 11cb89930a
64 changed files with 1122 additions and 211 deletions

View File

@ -15,3 +15,6 @@
Makefile text eol=lf
Makefile.* text eol=lf
*.mk text eol=lf
*.h.template text eol=lf
*.c.template text eol=lf

View File

@ -17,8 +17,8 @@
65904F2614632C1700FD9482 /* board-info.mk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "board-info.mk"; sourceTree = "<group>"; };
65904F2714632C1700FD9482 /* board-info.mk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "board-info.mk"; sourceTree = "<group>"; };
65904F2814632C1700FD9482 /* version-info.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "version-info.py"; sourceTree = "<group>"; };
65904F2914632C1700FD9482 /* firmwareinfotemplate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = firmwareinfotemplate.c; sourceTree = "<group>"; };
65904F2A14632C1700FD9482 /* gcsversioninfotemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gcsversioninfotemplate.h; sourceTree = "<group>"; };
65904F2914632C1700FD9482 /* firmware_info.c.template */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = firmware_info.c.template; sourceTree = "<group>"; };
65904F2A14632C1700FD9482 /* gcs_version_info.h.template */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gcs_version_info.h.template; sourceTree = "<group>"; };
65904F2D14632C1700FD9482 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = "<group>"; };
65904F2E14632C1700FD9482 /* shell_script.reg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = shell_script.reg; sourceTree = "<group>"; };
65904F2F14632C1700FD9482 /* install */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = install; sourceTree = "<group>"; };
@ -79,8 +79,8 @@
65904F1A14632C1700FD9482 /* templates */ = {
isa = PBXGroup;
children = (
65904F2914632C1700FD9482 /* firmwareinfotemplate.c */,
65904F2A14632C1700FD9482 /* gcsversioninfotemplate.h */,
65904F2914632C1700FD9482 /* firmware_info.c.template */,
65904F2A14632C1700FD9482 /* gcs_version_info.h.template */,
);
path = templates;
sourceTree = "<group>";

View File

@ -0,0 +1,132 @@
/**
******************************************************************************
*
* @file callbacktest.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Example module to be used as a template for actual modules.
* Event callback version.
*
* @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
*/
/**
*
* This is a test suite to test the callback scheduler,
* including its forward scheduling ability
*
*/
#include "openpilot.h"
// Private constants
#define STACK_SIZE configMINIMAL_STACK_SIZE
#define CALLBACK_PRIORITY CALLBACK_PRIORITY_LOW
#define TASK_PRIORITY CALLBACK_TASKPRIORITY_AUXILIARY
// Private types
//#define DEBUGPRINT(...) fprintf (stderr, __VA_ARGS__)
#define DEBUGPRINT(...) xSemaphoreTakeRecursive(mutex, portMAX_DELAY); fprintf(stderr, __VA_ARGS__ ); xSemaphoreGiveRecursive(mutex);
static xSemaphoreHandle mutex;
// Private variables
static DelayedCallbackInfo *cbinfo[10];
static volatile int32_t counter[10]={0};
static void DelayedCb0();
static void DelayedCb1();
static void DelayedCb2();
static void DelayedCb3();
static void DelayedCb4();
static void DelayedCb5();
static void DelayedCb6();
/**
* Initialise the module, called on startup.
* \returns 0 on success or -1 if initialisation failed
*/
int32_t CallbackTestInitialize()
{
mutex = xSemaphoreCreateRecursiveMutex();
cbinfo[0] = DelayedCallbackCreate(&DelayedCb0,CALLBACK_PRIORITY_LOW,tskIDLE_PRIORITY+2,STACK_SIZE);
cbinfo[1] = DelayedCallbackCreate(&DelayedCb1,CALLBACK_PRIORITY_LOW,tskIDLE_PRIORITY+2,STACK_SIZE);
cbinfo[2] = DelayedCallbackCreate(&DelayedCb2,CALLBACK_PRIORITY_CRITICAL,tskIDLE_PRIORITY+2,STACK_SIZE);
cbinfo[3] = DelayedCallbackCreate(&DelayedCb3,CALLBACK_PRIORITY_CRITICAL,tskIDLE_PRIORITY+2,STACK_SIZE);
cbinfo[4] = DelayedCallbackCreate(&DelayedCb4,CALLBACK_PRIORITY_LOW,tskIDLE_PRIORITY+2,STACK_SIZE);
cbinfo[5] = DelayedCallbackCreate(&DelayedCb5,CALLBACK_PRIORITY_LOW,tskIDLE_PRIORITY+2,STACK_SIZE);
cbinfo[6] = DelayedCallbackCreate(&DelayedCb6,CALLBACK_PRIORITY_LOW,tskIDLE_PRIORITY+20,STACK_SIZE);
return 0;
}
int32_t CallbackTestStart() {
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
DelayedCallbackDispatch(cbinfo[3]);
DelayedCallbackDispatch(cbinfo[2]);
DelayedCallbackDispatch(cbinfo[1]);
DelayedCallbackDispatch(cbinfo[0]);
// different callback priorities within a taskpriority
DelayedCallbackSchedule(cbinfo[4],30000,CALLBACK_UPDATEMODE_NONE);
DelayedCallbackSchedule(cbinfo[4],5000,CALLBACK_UPDATEMODE_OVERRIDE);
DelayedCallbackSchedule(cbinfo[4],4000,CALLBACK_UPDATEMODE_SOONER);
DelayedCallbackSchedule(cbinfo[4],10000,CALLBACK_UPDATEMODE_SOONER);
DelayedCallbackSchedule(cbinfo[4],1000,CALLBACK_UPDATEMODE_LATER);
DelayedCallbackSchedule(cbinfo[4],4800,CALLBACK_UPDATEMODE_LATER);
DelayedCallbackSchedule(cbinfo[4],48000,CALLBACK_UPDATEMODE_NONE);
// should be at 4.8 seconds after this, allowing for exactly 9 prints of the following
DelayedCallbackSchedule(cbinfo[5],500,CALLBACK_UPDATEMODE_NONE);
// delayed counter with 500 ms
DelayedCallbackDispatch(cbinfo[6]);
// high task prio
xSemaphoreGiveRecursive(mutex);
return 0;
}
static void DelayedCb0() {
DEBUGPRINT("delayed counter low prio 0 updated: %i\n",counter[0]);
if (++counter[0]<10) DelayedCallbackDispatch(cbinfo[0]);
}
static void DelayedCb1() {
DEBUGPRINT("delayed counter low prio 1 updated: %i\n",counter[1]);
if (++counter[1]<10) DelayedCallbackDispatch(cbinfo[1]);
}
static void DelayedCb2() {
DEBUGPRINT("delayed counter high prio 2 updated: %i\n",counter[2]);
if (++counter[2]<10) DelayedCallbackDispatch(cbinfo[2]);
}
static void DelayedCb3() {
DEBUGPRINT("delayed counter high prio 3 updated: %i\n",counter[3]);
if (++counter[3]<10) DelayedCallbackDispatch(cbinfo[3]);
}
static void DelayedCb4() {
DEBUGPRINT("delayed scheduled callback 4 reached!\n");
exit(0);
}
static void DelayedCb5() {
DEBUGPRINT("delayed scheduled counter 5 updated: %i\n",counter[5]);
if (++counter[5]<10) DelayedCallbackSchedule(cbinfo[5],500,CALLBACK_UPDATEMODE_NONE);
// it will likely only reach 8 due to cb4 aborting the run
}
static void DelayedCb6() {
DEBUGPRINT("delayed counter 6 (high task prio) updated: %i\n",counter[6]);
if (++counter[6]<10) DelayedCallbackDispatch(cbinfo[6]);
}

View File

@ -0,0 +1,140 @@
/**
******************************************************************************
*
* @file examplemodcallback.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Example module to be used as a template for actual modules.
* Event callback version.
*
* @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
*/
/**
* Input objects: ExampleObject1, ExampleSettings
* Output object: ExampleObject2
*
* This module executes in response to ExampleObject1 updates. When the
* module is triggered it will update the data of ExampleObject2.
*
* No threads are used in this example.
*
* UAVObjects are automatically generated by the UAVObjectGenerator from
* the object definition XML file.
*
* Modules have no API, all communication to other modules is done through UAVObjects.
* However modules may use the API exposed by shared libraries.
* See the OpenPilot wiki for more details.
* http://www.openpilot.org/OpenPilot_Application_Architecture
*
*/
#include "openpilot.h"
#include "exampleobject1.h" // object the module will listen for updates (input)
#include "exampleobject2.h" // object the module will update (output)
#include "examplesettings.h" // object holding module settings (input)
// Private constants
#define STACK_SIZE configMINIMAL_STACK_SIZE
#define CALLBACK_PRIORITY CALLBACK_PRIORITY_LOW
#define CBTASK_PRIORITY CALLBACK_TASKPRIORITY_AUXILIARY
// Private types
// Private variables
static DelayedCallbackInfo *cbinfo;
// Private functions
static void ObjectUpdatedCb(UAVObjEvent *ev);
static void DelayedCb();
/**
* Initialise the module, called on startup.
* \returns 0 on success or -1 if initialisation failed
*/
int32_t ExampleModCallbackInitialize()
{
// Listen for ExampleObject1 updates, connect a callback function
ExampleObject1ConnectCallback(&ObjectUpdatedCb);
cbinfo = DelayedCallbackCreate(&DelayedCb, CALLBACK_PRIORITY, CBTASK_PRIORITY, STACK_SIZE);
return 0;
}
/**
* This function is called each time ExampleObject1 is updated, this could be
* a local update or a remote update from the GCS. In this example the module
* does not have its own thread, the callbacks are executed from within the
* event thread. Because of that the callback execution time must be kept to
* a minimum.
*/
static void ObjectUpdatedCb(UAVObjEvent * ev)
{
DelayedCallbackDispatch(cbinfo);
}
/**
* This function is called by the DelayedCallbackScheduler when its execution
* has been requested. Callbacks scheduled for execution are executed in the
* same thread in a round robin fashion. The Dispatch function to reschedule
* execution can be called from within the Callback itself, in which case the
* re-run will be scheduled after all other callback with equal or higher
* priority have been executed. Like event callbacks, delayed callbacks are
* executed in the same thread context one at a time, therefore blocking IO
* functions or very long lasting calculations are prohibited. Unlike Event
* callbacks these callbacks run with a standard (IDLE+1) thread priority and
* do not block regular threads. They are therefore saver to use.
*/
static void DelayedCb();
ExampleSettingsData settings;
ExampleObject1Data data1;
ExampleObject2Data data2;
int32_t step;
// Update settings with latest value
ExampleSettingsGet(&settings);
// Get the input object
ExampleObject1Get(&data1);
// Determine how to update the output object
if (settings.StepDirection == EXAMPLESETTINGS_STEPDIRECTION_UP) {
step = settings.StepSize;
} else {
step = -settings.StepSize;
}
// Update data
data2.Field1 = data1.Field1 + step;
data2.Field2 = data1.Field2 + step;
data2.Field3 = data1.Field3 + step;
data2.Field4[0] = data1.Field4[0] + step;
data2.Field4[1] = data1.Field4[1] + step;
// Update the ExampleObject2, after this function is called
// notifications to any other modules listening to that object
// will be sent and the GCS object will be updated through the
// telemetry link. All operations will take place asynchronously
// and the following call will return immediately.
ExampleObject2Set(&data2);
//call the module again 10 seconds later,
//even if the exampleobject has not been updated
DelayedCallbackSchedule(cbinfo, 10*1000, CALLBACK_UPDATEMODE_NONE);
}

View File

@ -30,31 +30,21 @@
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
from uavobject import *
$(DATAFIELDS)
# Object $(NAME) definition
class $(NAME)(UAVObject):
# Object constants
OBJID = $(UOBJID)
# Object constants
OBJID = $(UOBJID)
# Constructor
def __init__(self):
UAVObject.__init__(self, $(NAME).OBJID)
# Constructor
def __init__(self):
UAVObject.__init__(self, $(NAME).OBJID)
# Create object fields
# Create object fields
$(DATAFIELDINIT)
# Read field data
self.read()
self.metadata.read()
# Read field data
self.read()
self.metadata.read()

View File

@ -157,6 +157,9 @@ MODULE_INITCALL(SystemModInitialize, 0)
*/
static void systemTask(void *parameters)
{
/* start the delayed callback scheduler */
CallbackSchedulerStart();
/* create all modules thread */
MODULE_TASKCREATE_ALL;

View File

@ -66,6 +66,7 @@ ifndef TESTAPP
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
## UAVObjects
SRC += $(OPUAVSYNTHDIR)/accessorydesired.c

View File

@ -36,6 +36,7 @@
#include <utlist.h>
#include <uavobjectmanager.h>
#include <eventdispatcher.h>
#include <callbackscheduler.h>
#include <taskmonitor.h>
#include <uavtalk.h>

View File

@ -231,6 +231,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
/* Set up pulse timers */
PIOS_TIM_InitClock(&tim_1_cfg);
PIOS_TIM_InitClock(&tim_2_cfg);

View File

@ -48,6 +48,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
/* Initialize the PiOS library */
PIOS_COM_Init();

View File

@ -43,6 +43,7 @@ ifndef TESTAPP
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
## UAVObjects
SRC += $(OPUAVSYNTHDIR)/gcsreceiver.c

View File

@ -76,7 +76,7 @@ NVIC value of 255. */
#endif
/* Enable run time stats collection */
#if defined(DIAG_STACK)
#ifdef DIAG_TASKS
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configGENERATE_RUN_TIME_STATS 1
@ -91,9 +91,6 @@ do {\
#define configCHECK_FOR_STACK_OVERFLOW 1
#endif
void *pvPortMallocGeneric( size_t xWantedSize, size_t alignment);
#define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMallocGeneric( ( x ) , portBYTE_ALIGNMENT) ) : ( puxStackBuffer ) )
/**
* @}
*/

View File

@ -37,6 +37,7 @@
#include <utlist.h>
#include <uavobjectmanager.h>
#include <eventdispatcher.h>
#include <callbackscheduler.h>
#include <taskmonitor.h>
#include <uavtalk.h>

View File

@ -141,6 +141,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
#if defined(PIOS_INCLUDE_TIM)
/* Set up pulse timers */
PIOS_TIM_InitClock(&tim_1_cfg);

View File

@ -48,6 +48,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
/* Initialize the PiOS library */
PIOS_COM_Init();

View File

@ -52,6 +52,7 @@ ifndef TESTAPP
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
## OSD fonts
SRC += $(OPSYSTEM)/fonts.c

View File

@ -36,6 +36,7 @@
#include <utlist.h>
#include <uavobjectmanager.h>
#include <eventdispatcher.h>
#include <callbackscheduler.h>
#include <taskmonitor.h>
#include <uavtalk.h>

View File

@ -135,6 +135,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
/* IAP System Setup */
PIOS_IAP_Init();

View File

@ -70,6 +70,7 @@ ifndef TESTAPP
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
#ifeq ($(DEBUG), YES)
SRC += $(OPSYSTEM)/dcc_stdio.c

View File

@ -141,6 +141,7 @@ SRC += $(OPSYSTEM)/alarms.c
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
SRC += $(UAVOBJSYNTHDIR)/uavobjectsinit.c
else
## TESTCODE

View File

@ -37,6 +37,7 @@
#include <utlist.h>
#include <uavobjectmanager.h>
#include <eventdispatcher.h>
#include <callbackscheduler.h>
#include <taskmonitor.h>
#include <uavtalk.h>

View File

@ -382,6 +382,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
/* Set up pulse timers */
PIOS_TIM_InitClock(&tim_1_cfg);
PIOS_TIM_InitClock(&tim_3_cfg);

View File

@ -152,6 +152,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
#if defined(PIOS_INCLUDE_COM)
#if defined(PIOS_INCLUDE_TELEMETRY_RF) && 1
{

View File

@ -70,6 +70,7 @@ ifndef TESTAPP
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
#ifeq ($(DEBUG), YES)
SRC += $(OPSYSTEM)/dcc_stdio.c

View File

@ -145,6 +145,7 @@ SRC += $(OPSYSTEM)/alarms.c
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
SRC += $(UAVOBJSYNTHDIR)/uavobjectsinit.c

View File

@ -37,6 +37,7 @@
#include <utlist.h>
#include <uavobjectmanager.h>
#include <eventdispatcher.h>
#include <callbackscheduler.h>
#include <taskmonitor.h>
#include <uavtalk.h>

View File

@ -431,6 +431,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
/* Set up pulse timers */
PIOS_TIM_InitClock(&tim_1_cfg);
PIOS_TIM_InitClock(&tim_2_cfg);

View File

@ -152,6 +152,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
#if defined(PIOS_INCLUDE_COM)
#if defined(PIOS_INCLUDE_TELEMETRY_RF) && 1
{

View File

@ -79,6 +79,7 @@ SRC += $(FLIGHTLIB)/alarms.c
SRC += $(OPUAVTALK)/uavtalk.c
SRC += $(OPUAVOBJ)/uavobjectmanager.c
SRC += $(OPUAVOBJ)/eventdispatcher.c
SRC += $(OPUAVOBJ)/callbackscheduler.c
SRC += $(UAVOBJSYNTHDIR)/uavobjectsinit.c
SRC += $(FLIGHTLIB)/CoordinateConversions.c
@ -257,7 +258,7 @@ ALLSRC = $(ASRCARM) $(ASRC) $(SRCARM) $(SRC) $(CPPSRCARM) $(CPPSRC)
ALLSRCBASE = $(notdir $(basename $(ALLSRC)))
# Define all object files.
ALLOBJ = $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE) uavobjectsinit.o.firmwareinfo ))
ALLOBJ = $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE) uavobjectsinit.o.firmware_info ))
# Define all listing files (used for make clean).
LSTFILES = $(addprefix $(OUTDIR)/, $(addsuffix .lst, $(ALLSRCBASE)))

View File

@ -37,6 +37,7 @@
#include <utlist.h>
#include <uavobjectmanager.h>
#include <eventdispatcher.h>
#include <callbackscheduler.h>
#include <taskmonitor.h>
#include <uavtalk.h>

View File

@ -129,6 +129,9 @@ void PIOS_Board_Init(void) {
/* Initialize the task monitor library */
TaskMonitorInitialize();
/* Initialize the delayed callback library */
CallbackSchedulerInitialize();
/* Configure IO ports */
/* Configure Telemetry port */

View File

@ -38,7 +38,7 @@ bin: $(OUTDIR)/$(TARGET).bin
BL_BIN = $(BUILD_DIR)/bl_$(BOARD_NAME)/bl_$(BOARD_NAME).bin
FW_BIN = $(BUILD_DIR)/fw_$(BOARD_NAME)/fw_$(BOARD_NAME).bin
FWINFO_BIN = $(FW_BIN).firmwareinfo.bin
FWINFO_BIN = $(FW_BIN).firmware_info.bin
$(OUTDIR)/$(TARGET).bin: $(BL_BIN) $(FW_BIN)
$(V0) @$(ECHO) $(MSG_FLASH_IMG) $@

View File

@ -0,0 +1,417 @@
/**
******************************************************************************
*
* @file callbackscheduler.c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
* @brief Scheduler to run callback functions from a shared context with given priorities.
*
* @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"
// Private constants
#define STACK_SIZE 128
#define MAX_SLEEP 1000
// Private types
/**
* task information
*/
struct DelayedCallbackTaskStruct {
DelayedCallbackInfo *callbackQueue[CALLBACK_PRIORITY_LOW + 1];
DelayedCallbackInfo *queueCursor[CALLBACK_PRIORITY_LOW + 1];
xTaskHandle callbackSchedulerTaskHandle;
signed char name[3];
uint32_t stackSize;
DelayedCallbackPriorityTask priorityTask;
xSemaphoreHandle signal;
struct DelayedCallbackTaskStruct *next;
};
/**
* callback information
*/
struct DelayedCallbackInfoStruct {
DelayedCallback cb;
bool volatile waiting;
uint32_t volatile scheduletime;
struct DelayedCallbackTaskStruct *task;
struct DelayedCallbackInfoStruct *next;
};
// Private variables
static struct DelayedCallbackTaskStruct *schedulerTasks;
static xSemaphoreHandle mutex;
static bool schedulerStarted;
// Private functions
static void CallbackSchedulerTask(void *task);
static int32_t runNextCallback(struct DelayedCallbackTaskStruct *task, DelayedCallbackPriority priority);
/**
* Initialize the scheduler
* must be called before any other functions are called
* \return Success (0), failure (-1)
*/
int32_t CallbackSchedulerInitialize()
{
// Initialize variables
schedulerTasks = NULL;
schedulerStarted = false;
// Create mutex
mutex = xSemaphoreCreateRecursiveMutex();
if (mutex == NULL) {
return -1;
}
// Done
return 0;
}
/**
* Start all scheduler tasks
* Will instantiate all scheduler tasks registered so far. Although new
* callbacks CAN be registered beyond that point, any further scheduling tasks
* will be started the moment of instantiation. It is not possible to increase
* the STACK requirements of a scheduler task after this function has been
* run. No callbacks will be run before this function is called, although
* they can be marked for later execution by executing the dispatch function.
* \return Success (0), failure (-1)
*/
int32_t CallbackSchedulerStart()
{
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// only call once
PIOS_Assert(schedulerStarted == false);
// start tasks
struct DelayedCallbackTaskStruct *cursor = NULL;
int t = 0;
LL_FOREACH(schedulerTasks, cursor) {
xTaskCreate(
CallbackSchedulerTask,
cursor->name,
cursor->stackSize/4,
cursor,
cursor->priorityTask,
&cursor->callbackSchedulerTaskHandle
);
if (TASKINFO_RUNNING_CALLBACKSCHEDULER0+t <= TASKINFO_RUNNING_CALLBACKSCHEDULER3) {
TaskMonitorAdd(TASKINFO_RUNNING_CALLBACKSCHEDULER0 + t, cursor->callbackSchedulerTaskHandle);
}
t++;
}
schedulerStarted = true;
xSemaphoreGiveRecursive(mutex);
return 0;
}
/**
* Schedule dispatching a callback at some point in the future. The function returns immediately.
* \param[in] *cbinfo the callback handle
* \param[in] milliseconds How far in the future to dispatch the callback
* \param[in] updatemode What to do if the callback is already scheduled but not dispatched yet.
* The options are:
* UPDATEMODE_NONE: An existing schedule will not be touched, the call will have no effect at all if there's an existing schedule.
* UPDATEMODE_SOONER: The callback will be rescheduled only if the new schedule triggers before the original one would have triggered.
* UPDATEMODE_LATER: The callback will be rescheduled only if the new schedule triggers after the original one would have triggered.
* UPDATEMODE_OVERRIDE: The callback will be rescheduled in any case, effectively overriding any previous schedule. (sooner+later=override)
* \return 0: not scheduled, previous schedule takes precedence, 1: new schedule, 2: previous schedule overridden
*/
int32_t DelayedCallbackSchedule(
DelayedCallbackInfo *cbinfo,
int32_t milliseconds,
DelayedCallbackUpdateMode updatemode
)
{
int32_t result = 0;
PIOS_Assert(cbinfo);
if (milliseconds <= 0) {
milliseconds = 0; // we can and will not schedule in the past since that ruins the wraparound of uint32_t
}
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
uint32_t new = xTaskGetTickCount() + (milliseconds/portTICK_RATE_MS);
if (!new) {
new = 1; // zero has a special meaning, schedule at time 1 instead
}
int32_t diff = new - cbinfo->scheduletime;
if ( (!cbinfo->scheduletime)
|| ((updatemode & CALLBACK_UPDATEMODE_SOONER) && diff < 0)
|| ((updatemode & CALLBACK_UPDATEMODE_LATER ) && diff > 0)
) {
// the scheduletime may be updated
if (!cbinfo->scheduletime) {
result = 1;
} else {
result = 2;
}
cbinfo->scheduletime = new;
// scheduler needs to be notified to adapt sleep times
xSemaphoreGive(cbinfo->task->signal);
}
xSemaphoreGiveRecursive(mutex);
return result;
}
/**
* Dispatch an event by invoking the supplied callback. The function
* returns immediately, the callback is invoked from the event task.
* \param[in] cbinfo the callback handle
* \return Success (-1), failure (0)
*/
int32_t DelayedCallbackDispatch(DelayedCallbackInfo *cbinfo)
{
PIOS_Assert(cbinfo);
// no semaphore needed for the callback
cbinfo->waiting = true;
// but the scheduler as a whole needs to be notified
return xSemaphoreGive(cbinfo->task->signal);
}
/**
* Dispatch an event by invoking the supplied callback. The function
* returns immediately, the callback is invoked from the event task.
* \param[in] cbinfo the callback handle
* \param[in] pxHigherPriorityTaskWoken
* xSemaphoreGiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE if
* giving the semaphore caused a task to unblock, and the unblocked task has a
* priority higher than the currently running task. If xSemaphoreGiveFromISR()
* sets this value to pdTRUE then a context switch should be requested before
* the interrupt is exited.
* From FreeRTOS Docu: Context switching from an ISR uses port specific syntax.
* Check the demo task for your port to find the syntax required.
* \return Success (-1), failure (0)
*/
int32_t DelayedCallbackDispatchFromISR(DelayedCallbackInfo *cbinfo, long *pxHigherPriorityTaskWoken)
{
PIOS_Assert(cbinfo);
// no semaphore needed for the callback
cbinfo->waiting = true;
// but the scheduler as a whole needs to be notified
return xSemaphoreGiveFromISR(cbinfo->task->signal, pxHigherPriorityTaskWoken);
}
/**
* Register a new callback to be called by a delayed callback scheduler task.
* If a scheduler task with the specified task priority does not exist yet, it
* will be created.
* \param[in] cb The callback to be invoked
* \param[in] priority Priority of the callback compared to other callbacks scheduled by the same delayed callback scheduler task.
* \param[in] priorityTask Task priority of the scheduler task. One scheduler task will be spawned for each distinct value specified, further callbacks created with the same priorityTask will all be handled by the same delayed callback scheduler task and scheduled according to their individual callback priorities
* \param[in] stacksize The stack requirements of the callback when called by the scheduler.
* \return CallbackInfo Pointer on success, NULL if failed.
*/
DelayedCallbackInfo *DelayedCallbackCreate(
DelayedCallback cb,
DelayedCallbackPriority priority,
DelayedCallbackPriorityTask priorityTask,
uint32_t stacksize
)
{
xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
// find appropriate scheduler task matching priorityTask
struct DelayedCallbackTaskStruct *task = NULL;
int t = 0;
LL_FOREACH(schedulerTasks, task) {
if (task->priorityTask == priorityTask) {
break; // found
}
t++;
}
// if given priorityTask does not exist, create it
if (!task) {
// allocate memory if possible
task = (struct DelayedCallbackTaskStruct*)pvPortMalloc(sizeof(struct DelayedCallbackTaskStruct));
if (!task) {
xSemaphoreGiveRecursive(mutex);
return NULL;
}
// initialize structure
for (DelayedCallbackPriority p = 0; p <= CALLBACK_PRIORITY_LOW; p++) {
task->callbackQueue[p] = NULL;
task->queueCursor[p] = NULL;
}
task->name[0] = 'C';
task->name[1] = 'a'+t;
task->name[2] = 0;
task->stackSize = ((STACK_SIZE>stacksize)?STACK_SIZE:stacksize);
task->priorityTask = priorityTask;
task->next = NULL;
// create the signaling semaphore
vSemaphoreCreateBinary( task->signal );
if (!task->signal) {
xSemaphoreGiveRecursive(mutex);
return NULL;
}
// add to list of scheduler tasks
LL_APPEND(schedulerTasks, task);
// Previously registered tasks are spawned when CallbackSchedulerStart() is called.
// Tasks registered afterwards need to spawn upon creation.
if (schedulerStarted) {
xTaskCreate(
CallbackSchedulerTask,
task->name,
task->stackSize/4,
task,
task->priorityTask,
&task->callbackSchedulerTaskHandle
);
if (TASKINFO_RUNNING_CALLBACKSCHEDULER0 + t <= TASKINFO_RUNNING_CALLBACKSCHEDULER3) {
TaskMonitorAdd(TASKINFO_RUNNING_CALLBACKSCHEDULER0 + t, task->callbackSchedulerTaskHandle);
}
}
}
if (!schedulerStarted && stacksize > task->stackSize) {
task->stackSize = stacksize; // previous to task initialisation we can still adapt to the maximum needed stack
}
if (stacksize > task->stackSize) {
xSemaphoreGiveRecursive(mutex);
return NULL; // error - not enough memory
}
// initialize callback scheduling info
DelayedCallbackInfo *info = (DelayedCallbackInfo*)pvPortMalloc(sizeof(DelayedCallbackInfo));
if (!info) {
xSemaphoreGiveRecursive(mutex);
return NULL; // error - not enough memory
}
info->next = NULL;
info->waiting = false;
info->scheduletime = 0;
info->task = task;
info->cb = cb;
// add to scheduling queue
LL_APPEND(task->callbackQueue[priority], info);
xSemaphoreGiveRecursive(mutex);
return info;
}
/**
* Scheduler subtask
* \param[in] task The scheduler task in question
* \param[in] priority The scheduling priority of the callback to search for
* \return wait time until next scheduled callback is due - 0 if a callback has just been executed
*/
static int32_t runNextCallback(struct DelayedCallbackTaskStruct *task, DelayedCallbackPriority priority)
{
int32_t result = MAX_SLEEP;
int32_t diff = 0;
// no such queue
if (priority > CALLBACK_PRIORITY_LOW) {
return result;
}
// queue is empty, search a lower priority queue
if (task->callbackQueue[priority] == NULL) {
return runNextCallback(task, priority + 1);
}
DelayedCallbackInfo *current = task->queueCursor[priority];
DelayedCallbackInfo *next;
do {
if (current == NULL) {
next = task->callbackQueue[priority]; // loop around the end of the list
// also attempt to run a callback that has lower priority
// every time the queue is completely traversed
diff = runNextCallback(task, priority + 1);
if (!diff) {
task->queueCursor[priority] = next; // the recursive call has executed a callback
return 0;
}
if (diff < result) {
result = diff; // adjust sleep time
}
} else {
next = current->next;
xSemaphoreTakeRecursive(mutex, portMAX_DELAY); // access to scheduletime should be mutex protected
if (current->scheduletime) {
diff = current->scheduletime - xTaskGetTickCount();
if (diff <= 0) {
current->waiting = true;
} else if (diff < result) {
result = diff; // adjust sleep time
}
}
if (current->waiting) {
task->queueCursor[priority] = next;
current->scheduletime = 0; // any schedules are reset
current->waiting = false; // the flag is reset just before execution.
xSemaphoreGiveRecursive(mutex);
current->cb(); // call the callback
return 0;
}
xSemaphoreGiveRecursive(mutex);
}
current = next;
} while (current != task->queueCursor[priority]);
// once the list has been traversed entirely without finding any to be executed task, abort (nothing to do)
return result;
}
/**
* Scheduler task, responsible of invoking callbacks.
* \param[in] task The scheduling task being run
*/
static void CallbackSchedulerTask(void *task)
{
uint32_t delay = 0;
while (1) {
delay = runNextCallback((struct DelayedCallbackTaskStruct*)task, CALLBACK_PRIORITY_CRITICAL);
if (delay) {
// nothing to do but sleep
xSemaphoreTake(((struct DelayedCallbackTaskStruct*)task)->signal, delay);
}
}
}

View File

@ -0,0 +1,189 @@
/**
******************************************************************************
*
* @file callbackscheduler.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Include files of the uavobjectlist library
* @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
*/
#ifndef CALLBACKSCHEDULER_H
#define CALLBACKSCHEDULER_H
// Public types
typedef enum{
CALLBACK_PRIORITY_CRITICAL = 0,
CALLBACK_PRIORITY_REGULAR = 1,
CALLBACK_PRIORITY_LOW = 2
} DelayedCallbackPriority;
// Use the CallbackPriority to define how frequent a callback needs to be
// called in relation to others in the same callback scheduling task.
// The scheduler will call callbacks waiting for execution with the same
// priority in a round robin way. However one slot in this queue is reserved
// for a chosen member of the next lower priority. This member will also be
// chosen in a round robin way.
// Example:
// Assume you have 6 callbacks in the same PriorityTask, all constantly wanting
// to be executed.
// A and B are priority CRITICAL,
// c and d are priority REGULAR,
// x and y are priority LOW.
// Then the execution schedule will look as follows:
// ...ABcABdABxABcABdAByABcABdABxABcABdABy...
// However if only the 3 callbacks, A, c and x want to execute, you will get:
// ...AcAxAcAxAcAxAcAxAcAxAcAxAcAxAcAxAcAx...
// And if onlz A and y need execution it will be:
// ...AyAyAyAyAyAyAyAyAyAyAyAyAyAyAyAyAyAy...
// despite their different priority they would get treated equally in this case.
//
// WARNING: Callbacks ALWAYS should return as quickly as possible. Otherwise
// a low priority callback can block a critical one from being executed.
// Callbacks MUST NOT block execution!
typedef enum{
CALLBACK_TASK_AUXILIARY = (tskIDLE_PRIORITY + 1),
CALLBACK_TASK_NAVIGATION = (tskIDLE_PRIORITY + 2),
CALLBACK_TASK_FLIGHTCONTROL = (tskIDLE_PRIORITY + 3),
CALLBACK_TASK_DEVICEDRIVER = (tskIDLE_PRIORITY + 4),
} DelayedCallbackPriorityTask;
// Use the PriorityTask to define the global importance of callback execution
// compared to other processes in the system.
// Callbacks dispatched in a higher PriorityTasks will halt the execution of
// any lower priority processes, including callbacks and even callback
// scheduling tasks until they are done!
// Assume you have two callbacks:
// A in priorityTask DEVICEDRIVER,
// b and c in priorityTask AUXILIARY,
// Then the execution schedule can look as follows: (| marks a task switch)
// <b ... /b><c ... |<A ... /A>| ... /c><b ...
// be aware that if A gets constantly dispatched this would look like this:
// <b ... |<A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A>...
//
// WARNING: Any higher priority task can prevent lower priority code from being
// executed! (This does not only apply to callbacks but to all FreeRTOS tasks!)
typedef enum{
CALLBACK_UPDATEMODE_NONE = 0,
CALLBACK_UPDATEMODE_SOONER = 1,
CALLBACK_UPDATEMODE_LATER = 2,
CALLBACK_UPDATEMODE_OVERRIDE = 3
} DelayedCallbackUpdateMode;
// When scheduling a callback for execution at a time in the future, use the
// update mode to define what should happen if the callback is already
// scheduled.
// With NONE, the schedule will not be updated and the callback will be
// executed at the original time.
// With SOONER, the closer of the two schedules will take precedence
// With LATER, the schedule more distant in the future will be used.
// With OVERRIDE, the original schedule will be discarded.
typedef void (*DelayedCallback)(void);
// Use this type for the callback function.
struct DelayedCallbackInfoStruct;
typedef struct DelayedCallbackInfoStruct DelayedCallbackInfo;
// Use a pointer to DelayedCallbackInfo as a handle to identify registered callbacks.
// be aware that the same callback function can be registered as a callback
// several times, even with different callback priorities and even
// priorityTasks, using different handles and as such different dispatch calls.
// Be aware that using different priorityTasks for the same callback function
// might cause your callback to be executed recursively in different task contexts!
// Public functions
//
/**
* Initialize the scheduler
* must be called before any other functions are called
* \return Success (0), failure (-1)
*/
int32_t CallbackSchedulerInitialize();
/**
* Start all scheduler tasks
* Will instantiate all scheduler tasks registered so far. Although new
* callbacks CAN be registered beyond that point, any further scheduling tasks
* will be started the moment of instantiation. It is not possible to increase
* the STACK requirements of a scheduler task after this function has been
* run. No callbacks will be run before this function is called, although
* they can be marked for later execution by executing the dispatch function.
* \return Success (0), failure (-1)
*/
int32_t CallbackSchedulerStart();
/**
* Register a new callback to be called by a delayed callback scheduler task.
* If a scheduler task with the specified task priority does not exist yet, it
* will be created.
* \param[in] cb The callback to be invoked
* \param[in] priority Priority of the callback compared to other callbacks scheduled by the same delayed callback scheduler task.
* \param[in] priorityTask Task priority of the scheduler task. One scheduler task will be spawned for each distinct value specified, further callbacks created with the same priorityTask will all be handled by the same delayed callback scheduler task and scheduled according to their individual callback priorities
* \param[in] stacksize The stack requirements of the callback when called by the scheduler.
* \return CallbackInfo Pointer on success, NULL if failed.
*/
DelayedCallbackInfo *DelayedCallbackCreate(
DelayedCallback cb,
DelayedCallbackPriority priority,
DelayedCallbackPriorityTask priorityTask,
uint32_t stacksize
);
/**
* Schedule dispatching a callback at some point in the future. The function returns immediately.
* \param[in] *cbinfo the callback handle
* \param[in] milliseconds How far in the future to dispatch the callback
* \param[in] updatemode What to do if the callback is already scheduled but not dispatched yet.
* The options are:
* UPDATEMODE_NONE: An existing schedule will not be touched, the call will have no effect at all if there's an existing schedule.
* UPDATEMODE_SOONER: The callback will be rescheduled only if the new schedule triggers before the original one would have triggered.
* UPDATEMODE_LATER: The callback will be rescheduled only if the new schedule triggers after the original one would have triggered.
* UPDATEMODE_OVERRIDE: The callback will be rescheduled in any case, effectively overriding any previous schedule. (sooner+later=override)
* \return 0: not scheduled, previous schedule takes precedence, 1: new schedule, 2: previous schedule overridden
*/
int32_t DelayedCallbackSchedule(
DelayedCallbackInfo *cbinfo,
int32_t milliseconds,
DelayedCallbackUpdateMode updatemode
);
/**
* Dispatch an event by invoking the supplied callback. The function
* returns immediately, the callback is invoked from the event task.
* \param[in] *cbinfo the callback handle
* \return Success (-1), failure (0)
*/
int32_t DelayedCallbackDispatch( DelayedCallbackInfo *cbinfo );
/**
* Dispatch an event by invoking the supplied callback. The function
* returns immediately, the callback is invoked from the event task.
* \param[in] *cbinfo the callback handle
* \param[in] pxHigherPriorityTaskWoken
* xSemaphoreGiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE if
* giving the semaphore caused a task to unblock, and the unblocked task has a
* priority higher than the currently running task. If xSemaphoreGiveFromISR()
* sets this value to pdTRUE then a context switch should be requested before
* the interrupt is exited.
* From FreeRTOS Docu: Context switching from an ISR uses port specific syntax.
* Check the demo task for your port to find the syntax required.
* \return Success (-1), failure (0)
*/
int32_t DelayedCallbackDispatchFromISR( DelayedCallbackInfo *cbinfo, long *pxHigherPriorityTaskWoken );
#endif // CALLBACKSCHEDULER_H

View File

@ -6,11 +6,11 @@
* @brief $(DESCRIPTION)
*
* Autogenerated files and functions for $(NAME) Object
*
* @{
*
* @file $(NAMELC).h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2013.
* @brief Implementation of the $(NAME) object. This file has been
* automatically generated by the UAVObjectGenerator.
*
@ -40,68 +40,51 @@
#ifndef $(NAMEUC)_H
#define $(NAMEUC)_H
// Object constants
/* Object constants */
#define $(NAMEUC)_OBJID $(OBJIDHEX)
#define $(NAMEUC)_ISSINGLEINST $(ISSINGLEINST)
#define $(NAMEUC)_ISSETTINGS $(ISSETTINGS)
#define $(NAMEUC)_NUMBYTES sizeof($(NAME)Data)
// Generic interface functions
/* Generic interface functions */
int32_t $(NAME)Initialize();
UAVObjHandle $(NAME)Handle();
void $(NAME)SetDefaults(UAVObjHandle obj, uint16_t instId);
// Packed Object data (unaligned).
// Should only be used where 4 byte alignment can be guaranteed
// (eg a single instance on the heap)
typedef struct {
$(DATAFIELDS)
} __attribute__((packed)) $(NAME)DataPacked;
// Packed Object data.
// Alignment is forced to 4 bytes so as to avoid the potential for CPU usage faults
// on Cortex M4F during load/store of float UAVO fields
typedef $(NAME)DataPacked __attribute__((aligned(4))) $(NAME)Data;
// Typesafe Object access functions
/**
* @function $(NAME)Get(dataOut)
* @brief Populate a $(NAME)Data object
* @param[out] dataOut
/*
* Packed Object data (unaligned).
* Should only be used where 4 byte alignment can be guaranteed
* (eg a single instance on the heap)
*/
typedef struct {
$(DATAFIELDS)} __attribute__((packed)) $(NAME)DataPacked;
/*
* Packed Object data.
* Alignment is forced to 4 bytes so as to avoid the potential for CPU usage faults
* on Cortex M4F during load/store of float UAVO fields
*/
typedef $(NAME)DataPacked __attribute__((aligned(4))) $(NAME)Data;
/* Typesafe Object access functions */
static inline int32_t $(NAME)Get($(NAME)Data *dataOut) { return UAVObjGetData($(NAME)Handle(), dataOut); }
static inline int32_t $(NAME)Set(const $(NAME)Data *dataIn) { return UAVObjSetData($(NAME)Handle(), dataIn); }
static inline int32_t $(NAME)InstGet(uint16_t instId, $(NAME)Data *dataOut) { return UAVObjGetInstanceData($(NAME)Handle(), instId, dataOut); }
static inline int32_t $(NAME)InstSet(uint16_t instId, const $(NAME)Data *dataIn) { return UAVObjSetInstanceData($(NAME)Handle(), instId, dataIn); }
static inline int32_t $(NAME)ConnectQueue(xQueueHandle queue) { return UAVObjConnectQueue($(NAME)Handle(), queue, EV_MASK_ALL_UPDATES); }
static inline int32_t $(NAME)ConnectCallback(UAVObjEventCallback cb) { return UAVObjConnectCallback($(NAME)Handle(), cb, EV_MASK_ALL_UPDATES); }
static inline uint16_t $(NAME)CreateInstance() { return UAVObjCreateInstance($(NAME)Handle(), &$(NAME)SetDefaults); }
static inline void $(NAME)RequestUpdate() { UAVObjRequestUpdate($(NAME)Handle()); }
static inline void $(NAME)RequestInstUpdate(uint16_t instId) { UAVObjRequestInstanceUpdate($(NAME)Handle(), instId); }
static inline void $(NAME)Updated() { UAVObjUpdated($(NAME)Handle()); }
static inline void $(NAME)InstUpdated(uint16_t instId) { UAVObjInstanceUpdated($(NAME)Handle(), instId); }
static inline int32_t $(NAME)GetMetadata(UAVObjMetadata *dataOut) { return UAVObjGetMetadata($(NAME)Handle(), dataOut); }
static inline int32_t $(NAME)SetMetadata(const UAVObjMetadata *dataIn) { return UAVObjSetMetadata($(NAME)Handle(), dataIn); }
static inline int8_t $(NAME)ReadOnly() { return UAVObjReadOnly($(NAME)Handle()); }
// Field information
$(DATAFIELDINFO)
// set/Get functions
/* Set/Get functions */
$(SETGETFIELDSEXTERN)
#endif // $(NAMEUC)_H

View File

@ -9,7 +9,7 @@
* @{
*
* @file $(NAMELC).c
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2013.
* @brief Implementation of the $(NAME) object. This file has been
* automatically generated by the UAVObjectGenerator.
*
@ -36,7 +36,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "openpilot.h"
#include <openpilot.h>
#include "$(NAMELC).h"
// Private variables
@ -53,28 +53,22 @@ static UAVObjHandle handle __attribute__((section("_uavo_handles")));
*/
int32_t $(NAME)Initialize(void)
{
// Compile time assertion that the $(NAME)DataPacked and $(NAME)Data structs
// have the same size (though instances of $(NAME)Data
// should be placed in memory by the linker/compiler on a 4 byte alignment).
PIOS_STATIC_ASSERT(sizeof($(NAME)DataPacked) == sizeof($(NAME)Data));
// Compile time assertion that the $(NAME)DataPacked and $(NAME)Data structs
// have the same size (though instances of $(NAME)Data
// should be placed in memory by the linker/compiler on a 4 byte alignment).
PIOS_STATIC_ASSERT(sizeof($(NAME)DataPacked) == sizeof($(NAME)Data));
// Don't set the handle to null if already registered
if(UAVObjGetByID($(NAMEUC)_OBJID) != NULL)
return -2;
// Register object with the object manager
handle = UAVObjRegister($(NAMEUC)_OBJID,
$(NAMEUC)_ISSINGLEINST, $(NAMEUC)_ISSETTINGS, $(NAMEUC)_NUMBYTES, &$(NAME)SetDefaults);
// Don't set the handle to null if already registered
if (UAVObjGetByID($(NAMEUC)_OBJID)) {
return -2;
}
// Done
if (handle != 0)
{
return 0;
}
else
{
return -1;
}
// Register object with the object manager
handle = UAVObjRegister($(NAMEUC)_OBJID,
$(NAMEUC)_ISSINGLEINST, $(NAMEUC)_ISSETTINGS, $(NAMEUC)_NUMBYTES, &$(NAME)SetDefaults);
// Done
return handle ? 0 : -1;
}
/**
@ -84,27 +78,27 @@ int32_t $(NAME)Initialize(void)
*/
void $(NAME)SetDefaults(UAVObjHandle obj, uint16_t instId)
{
$(NAME)Data data;
UAVObjMetadata metadata;
$(NAME)Data data;
UAVObjMetadata metadata;
// Initialize object fields to their default values
UAVObjGetInstanceData(obj, instId, &data);
memset(&data, 0, sizeof($(NAME)Data));
// Initialize object fields to their default values
UAVObjGetInstanceData(obj, instId, &data);
memset(&data, 0, sizeof($(NAME)Data));
$(INITFIELDS)
UAVObjSetInstanceData(obj, instId, &data);
UAVObjSetInstanceData(obj, instId, &data);
// Initialize object metadata to their default values
metadata.flags =
$(FLIGHTACCESS) << UAVOBJ_ACCESS_SHIFT |
$(GCSACCESS) << UAVOBJ_GCS_ACCESS_SHIFT |
$(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT |
$(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
$(FLIGHTTELEM_UPDATEMODE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
$(GCSTELEM_UPDATEMODE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
metadata.telemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
UAVObjSetMetadata(obj, &metadata);
// Initialize object metadata to their default values
metadata.flags =
$(FLIGHTACCESS) << UAVOBJ_ACCESS_SHIFT |
$(GCSACCESS) << UAVOBJ_GCS_ACCESS_SHIFT |
$(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT |
$(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
$(FLIGHTTELEM_UPDATEMODE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
$(GCSTELEM_UPDATEMODE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
metadata.telemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
UAVObjSetMetadata(obj, &metadata);
}
/**
@ -112,7 +106,7 @@ $(INITFIELDS)
*/
UAVObjHandle $(NAME)Handle()
{
return handle;
return handle;
}
/**
@ -123,4 +117,3 @@ $(SETGETFIELDS)
/**
* @}
*/

View File

@ -27,7 +27,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "openpilot.h"
#include <openpilot.h>
$(OBJINC)
/**

View File

@ -15,3 +15,7 @@
*.pri text eol=crlf
*.pro text eol=crlf
*.h.template text eol=crlf
*.c.template text eol=crlf
*.cpp.template text eol=crlf

View File

@ -34,7 +34,7 @@ PYTHON_DIR = python-2.7.4
VERSION_INFO_DIR = $$GCS_BUILD_TREE/../openpilotgcs-synthetics
VERSION_INFO_HEADER = $$VERSION_INFO_DIR/gcs_version_info.h
VERSION_INFO_SCRIPT = $$ROOT_DIR/make/scripts/version-info.py
VERSION_INFO_TEMPLATE = $$ROOT_DIR/make/templates/gcs_version_info_template.h
VERSION_INFO_TEMPLATE = $$ROOT_DIR/make/templates/gcs_version_info.h.template
VERSION_INFO_COMMAND = $$PYTHON \"$$VERSION_INFO_SCRIPT\"
UAVO_DEF_PATH = $$ROOT_DIR/shared/uavobjectdefinition

View File

@ -1,7 +1,7 @@
/**
******************************************************************************
*
* @file uavobjecttemplate.cpp
* @file $(NAME).java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Template for an uavobject in java
* $(GENERATEDWARNING)

View File

@ -2,7 +2,7 @@
******************************************************************************
*
*
* @file uavobjectsinittemplate.java
* @file UAVObjectsInitialize.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief the template for the uavobjects init part
* $(GENERATEDWARNING)

View File

@ -30,6 +30,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "$(NAMELC).h"
#include "uavobjectfield.h"
@ -43,10 +44,10 @@ const QString $(NAME)::CATEGORY = QString("$(CATEGORY)");
$(NAME)::$(NAME)(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS, NAME)
{
// Create fields
QList<UAVObjectField*> fields;
QList<UAVObjectField *> fields;
$(FIELDSINIT)
// Initialize object
initializeFields(fields, (quint8*)&data, NUMBYTES);
initializeFields(fields, (quint8 *)&data, NUMBYTES);
// Set the default field values
setDefaultFieldValues();
// Set the object description
@ -55,8 +56,7 @@ $(FIELDSINIT)
// Set the Category of this object type
setCategory(CATEGORY);
connect(this, SIGNAL(objectUpdated(UAVObject*)),
SLOT(emitNotifications()));
connect(this, SIGNAL(objectUpdated(UAVObject *)), SLOT(emitNotifications()));
}
/**
@ -66,12 +66,12 @@ UAVObject::Metadata $(NAME)::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.flags =
$(FLIGHTACCESS) << UAVOBJ_ACCESS_SHIFT |
$(GCSACCESS) << UAVOBJ_GCS_ACCESS_SHIFT |
$(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT |
$(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
$(FLIGHTTELEM_UPDATEMODE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
$(GCSTELEM_UPDATEMODE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
$(FLIGHTACCESS) << UAVOBJ_ACCESS_SHIFT |
$(GCSACCESS) << UAVOBJ_GCS_ACCESS_SHIFT |
$(FLIGHTTELEM_ACKED) << UAVOBJ_TELEMETRY_ACKED_SHIFT |
$(GCSTELEM_ACKED) << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
$(FLIGHTTELEM_UPDATEMODE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
$(GCSTELEM_UPDATEMODE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
@ -106,8 +106,7 @@ void $(NAME)::setData(const DataFields& data)
// Get metadata
Metadata mdata = getMetadata();
// Update object if the access mode permits
if ( UAVObject::GetGcsAccess(mdata) == ACCESS_READWRITE )
{
if (UAVObject::GetGcsAccess(mdata) == ACCESS_READWRITE) {
this->data = data;
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
@ -124,9 +123,9 @@ void $(NAME)::emitNotifications()
* Do not use this function directly to create new instances, the
* UAVObjectManager should be used instead.
*/
UAVDataObject* $(NAME)::clone(quint32 instID)
UAVDataObject *$(NAME)::clone(quint32 instID)
{
$(NAME)* obj = new $(NAME)();
$(NAME) *obj = new $(NAME)();
obj->initialize(instID, this->getMetaObject());
return obj;
}
@ -134,18 +133,18 @@ UAVDataObject* $(NAME)::clone(quint32 instID)
/**
* Create a clone of this object only to be used to retrieve defaults
*/
UAVDataObject* $(NAME)::dirtyClone()
UAVDataObject *$(NAME)::dirtyClone()
{
$(NAME)* obj = new $(NAME)();
$(NAME) *obj = new $(NAME)();
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
$(NAME)* $(NAME)::GetInstance(UAVObjectManager* objMngr, quint32 instID)
$(NAME) *$(NAME)::GetInstance(UAVObjectManager *objMngr, quint32 instID)
{
return dynamic_cast<$(NAME)*>(objMngr->getObject($(NAME)::OBJID, instID));
return dynamic_cast<$(NAME) *>(objMngr->getObject($(NAME)::OBJID, instID));
}
$(PROPERTIES_IMPL)

View File

@ -29,14 +29,16 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavobjectsinit.h"
$(OBJINC)
/**
* Function used to initialize the first instance of each object.
* This file is automatically updated by the UAVObjectGenerator.
*/
void UAVObjectsInitialize(UAVObjectManager* objMngr)
void UAVObjectsInitialize(UAVObjectManager *objMngr)
{
$(OBJINIT)
}

View File

@ -35,15 +35,15 @@ bool UAVObjectGeneratorFlight::generate(UAVObjectParser* parser,QString template
QString flightObjInit,objInc,objFileNames,objNames;
qint32 sizeCalc;
flightCodePath = QDir( templatepath + QString("flight/uavobjects"));
flightCodePath = QDir( templatepath + QString(FLIGHT_CODE_DIR));
flightOutputPath = QDir( outputpath + QString("flight") );
flightOutputPath.mkpath(flightOutputPath.absolutePath());
flightCodeTemplate = readFile( flightCodePath.absoluteFilePath("uavobjecttemplate.c") );
flightIncludeTemplate = readFile( flightCodePath.absoluteFilePath("inc/uavobjecttemplate.h") );
flightInitTemplate = readFile( flightCodePath.absoluteFilePath("uavobjectsinittemplate.c") );
flightInitIncludeTemplate = readFile( flightCodePath.absoluteFilePath("inc/uavobjectsinittemplate.h") );
flightMakeTemplate = readFile( flightCodePath.absoluteFilePath("Makefiletemplate.inc") );
flightCodeTemplate = readFile( flightCodePath.absoluteFilePath("uavobject.c.template") );
flightIncludeTemplate = readFile( flightCodePath.absoluteFilePath("inc/uavobject.h.template") );
flightInitTemplate = readFile( flightCodePath.absoluteFilePath("uavobjectsinit.c.template") );
flightInitIncludeTemplate = readFile( flightCodePath.absoluteFilePath("inc/uavobjectsinit.h.template") );
flightMakeTemplate = readFile( flightCodePath.absoluteFilePath("Makefile.inc.template") );
if ( flightCodeTemplate.isNull() || flightIncludeTemplate.isNull() || flightInitTemplate.isNull()) {
cerr << "Error: Could not open flight template files." << endl;
@ -54,10 +54,10 @@ bool UAVObjectGeneratorFlight::generate(UAVObjectParser* parser,QString template
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
ObjectInfo* info=parser->getObjectByIndex(objidx);
process_object(info);
flightObjInit.append("#ifdef UAVOBJ_INIT_" + info->namelc +"\r\n");
flightObjInit.append(" " + info->name + "Initialize();\r\n");
flightObjInit.append("#endif\r\n");
objInc.append("#include \"" + info->namelc + ".h\"\r\n");
flightObjInit.append("#ifdef UAVOBJ_INIT_" + info->namelc +"\n");
flightObjInit.append(" " + info->name + "Initialize();\n");
flightObjInit.append("#endif\n");
objInc.append("#include \"" + info->namelc + ".h\"\n");
objFileNames.append(" " + info->namelc);
objNames.append(" " + info->name);
if (parser->getNumBytes(objidx)>sizeCalc) {
@ -124,12 +124,12 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
// Append field
if ( info->fields[n]->numElements > 1 )
{
fields.append( QString(" %1 %2[%3];\r\n").arg(type)
fields.append( QString(" %1 %2[%3];\n").arg(type)
.arg(info->fields[n]->name).arg(info->fields[n]->numElements) );
}
else
{
fields.append( QString(" %1 %2;\r\n").arg(type).arg(info->fields[n]->name) );
fields.append( QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name) );
}
}
outInclude.replace(QString("$(DATAFIELDS)"), fields);
@ -138,16 +138,16 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
QString enums;
for (int n = 0; n < info->fields.length(); ++n)
{
enums.append(QString("// Field %1 information\r\n").arg(info->fields[n]->name));
enums.append(QString("/* Field %1 information */\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
enums.append(QString("/* Enumeration options for field %1 */\r\n").arg(info->fields[n]->name));
enums.append("typedef enum { ");
enums.append(QString("\n// Enumeration options for field %1\n").arg(info->fields[n]->name));
enums.append("typedef enum {\n");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
QString s = (m == (options.length()-1)) ? "%1_%2_%3=%4" : "%1_%2_%3=%4, ";
QString s = (m == (options.length()-1)) ? " %1_%2_%3=%4\n" : " %1_%2_%3=%4,\n";
enums.append( s
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
@ -155,20 +155,20 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
.arg(m) );
}
enums.append( QString(" } %1%2Options;\r\n")
enums.append( QString("} %1%2Options;\n")
.arg( info->name )
.arg( info->fields[n]->name ) );
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames)
{
enums.append(QString("/* Array element names for field %1 */\r\n").arg(info->fields[n]->name));
enums.append("typedef enum { ");
enums.append(QString("\n// Array element names for field %1\n").arg(info->fields[n]->name));
enums.append("typedef enum {\n");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
{
QString s = (m != (elemNames.length()-1)) ? "%1_%2_%3=%4, " : "%1_%2_%3=%4";
QString s = (m != (elemNames.length()-1)) ? " %1_%2_%3=%4,\n" : " %1_%2_%3=%4\n";
enums.append( s
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
@ -176,19 +176,21 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
.arg(m) );
}
enums.append( QString(" } %1%2Elem;\r\n")
enums.append( QString("} %1%2Elem;\n")
.arg( info->name )
.arg( info->fields[n]->name ) );
}
// Generate array information
if (info->fields[n]->numElements > 1)
{
enums.append(QString("/* Number of elements for field %1 */\r\n").arg(info->fields[n]->name));
enums.append( QString("#define %1_%2_NUMELEM %3\r\n")
enums.append(QString("\n// Number of elements for field %1\n").arg(info->fields[n]->name));
enums.append( QString("#define %1_%2_NUMELEM %3\n")
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
.arg( info->fields[n]->numElements ) );
}
enums.append(QString("\n"));
}
outInclude.replace(QString("$(DATAFIELDINFO)"), enums);
@ -203,19 +205,19 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString("\tdata.%1 = %2;\r\n")
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[0] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString("\tdata.%1 = %2;\r\n")
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toFloat() ) );
}
else
{
initfields.append( QString("\tdata.%1 = %2;\r\n")
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toInt() ) );
}
@ -227,21 +229,21 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString("\tdata.%1[%2] = %3;\r\n")
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[idx] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString("\tdata.%1[%2] = %3;\r\n")
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toFloat() ) );
}
else
{
initfields.append( QString("\tdata.%1[%2] = %3;\r\n")
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toInt() ) );
@ -263,58 +265,58 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
{
/* Set */
setgetfields.append( QString("void %2%3Set( %1 *New%3 )\r\n")
setgetfields.append( QString("void %2%3Set(%1 *New%3)\n")
.arg( fieldTypeStrC[info->fields[n]->type] )
.arg( info->name )
.arg( info->fields[n]->name ) );
setgetfields.append( QString("{\r\n") );
setgetfields.append( QString("\tUAVObjSetDataField(%1Handle(), (void*)New%2, offsetof( %1Data, %2), sizeof(%3));\r\n")
setgetfields.append( QString("{\n") );
setgetfields.append( QString(" UAVObjSetDataField(%1Handle(), (void *)New%2, offsetof(%1Data, %2), sizeof(%3));\n")
.arg( info->name )
.arg( info->fields[n]->name )
.arg( fieldTypeStrC[info->fields[n]->type] ) );
setgetfields.append( QString("}\r\n") );
setgetfields.append( QString("}\n") );
/* GET */
setgetfields.append( QString("void %2%3Get( %1 *New%3 )\r\n")
setgetfields.append( QString("void %2%3Get(%1 *New%3)\n")
.arg( fieldTypeStrC[info->fields[n]->type] )
.arg( info->name )
.arg( info->fields[n]->name ));
setgetfields.append( QString("{\r\n") );
setgetfields.append( QString("\tUAVObjGetDataField(%1Handle(), (void*)New%2, offsetof( %1Data, %2), sizeof(%3));\r\n")
setgetfields.append( QString("{\n") );
setgetfields.append( QString(" UAVObjGetDataField(%1Handle(), (void *)New%2, offsetof(%1Data, %2), sizeof(%3));\n")
.arg( info->name )
.arg( info->fields[n]->name )
.arg( fieldTypeStrC[info->fields[n]->type] ) );
setgetfields.append( QString("}\r\n") );
setgetfields.append( QString("}\n") );
}
else
{
/* SET */
setgetfields.append( QString("void %2%3Set( %1 *New%3 )\r\n")
setgetfields.append( QString("void %2%3Set( %1 *New%3 )\n")
.arg( fieldTypeStrC[info->fields[n]->type] )
.arg( info->name )
.arg( info->fields[n]->name ) );
setgetfields.append( QString("{\r\n") );
setgetfields.append( QString("\tUAVObjSetDataField(%1Handle(), (void*)New%2, offsetof( %1Data, %2), %3*sizeof(%4));\r\n")
setgetfields.append( QString("{\n") );
setgetfields.append( QString(" UAVObjSetDataField(%1Handle(), (void *)New%2, offsetof(%1Data, %2), %3*sizeof(%4));\n")
.arg( info->name )
.arg( info->fields[n]->name )
.arg( info->fields[n]->numElements )
.arg( fieldTypeStrC[info->fields[n]->type] ) );
setgetfields.append( QString("}\r\n") );
setgetfields.append( QString("}\n") );
/* GET */
setgetfields.append( QString("void %2%3Get( %1 *New%3 )\r\n")
setgetfields.append( QString("void %2%3Get( %1 *New%3 )\n")
.arg( fieldTypeStrC[info->fields[n]->type] )
.arg( info->name )
.arg( info->fields[n]->name ) );
setgetfields.append( QString("{\r\n") );
setgetfields.append( QString("\tUAVObjGetDataField(%1Handle(), (void*)New%2, offsetof( %1Data, %2), %3*sizeof(%4));\r\n")
setgetfields.append( QString("{\n") );
setgetfields.append( QString(" UAVObjGetDataField(%1Handle(), (void *)New%2, offsetof(%1Data, %2), %3*sizeof(%4));\n")
.arg( info->name )
.arg( info->fields[n]->name )
.arg( info->fields[n]->numElements )
.arg( fieldTypeStrC[info->fields[n]->type] ) );
setgetfields.append( QString("}\r\n") );
setgetfields.append( QString("}\n") );
}
}
}
@ -328,13 +330,13 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
{
/* SET */
setgetfieldsextern.append( QString("extern void %2%3Set( %1 *New%3 );\r\n")
setgetfieldsextern.append( QString("extern void %2%3Set(%1 *New%3);\n")
.arg( fieldTypeStrC[info->fields[n]->type] )
.arg( info->name )
.arg( info->fields[n]->name ) );
/* GET */
setgetfieldsextern.append( QString("extern void %2%3Get( %1 *New%3 );\r\n")
setgetfieldsextern.append( QString("extern void %2%3Get(%1 *New%3);\n")
.arg( fieldTypeStrC[info->fields[n]->type] )
.arg( info->name )
.arg( info->fields[n]->name ) );
@ -357,5 +359,3 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
return true;
}

View File

@ -27,6 +27,8 @@
#ifndef UAVOBJECTGENERATORFLIGHT_H
#define UAVOBJECTGENERATORFLIGHT_H
#define FLIGHT_CODE_DIR "flight/uavobjects"
#include "../generator_common.h"
class UAVObjectGeneratorFlight

View File

@ -39,9 +39,9 @@ bool UAVObjectGeneratorGCS::generate(UAVObjectParser* parser,QString templatepat
gcsOutputPath = QDir( outputpath + QString("gcs") );
gcsOutputPath.mkpath(gcsOutputPath.absolutePath());
gcsCodeTemplate = readFile( gcsCodePath.absoluteFilePath("uavobjecttemplate.cpp") );
gcsIncludeTemplate = readFile( gcsCodePath.absoluteFilePath("uavobjecttemplate.h") );
QString gcsInitTemplate = readFile( gcsCodePath.absoluteFilePath("uavobjectsinittemplate.cpp") );
gcsCodeTemplate = readFile( gcsCodePath.absoluteFilePath("uavobject.cpp.template") );
gcsIncludeTemplate = readFile( gcsCodePath.absoluteFilePath("uavobject.h.template") );
QString gcsInitTemplate = readFile( gcsCodePath.absoluteFilePath("uavobjectsinit.cpp.template") );
if (gcsCodeTemplate.isEmpty() || gcsIncludeTemplate.isEmpty() || gcsInitTemplate.isEmpty()) {
std::cerr << "Problem reading gcs code templates" << endl;

View File

@ -39,8 +39,8 @@ bool UAVObjectGeneratorJava::generate(UAVObjectParser* parser,QString templatepa
javaOutputPath = QDir( outputpath + QString("java") );
javaOutputPath.mkpath(javaOutputPath.absolutePath());
javaCodeTemplate = readFile( javaCodePath.absoluteFilePath("uavobjecttemplate.java") );
QString javaInitTemplate = readFile( javaCodePath.absoluteFilePath("uavobjectsinittemplate.java") );
javaCodeTemplate = readFile( javaCodePath.absoluteFilePath("uavobject.java.template") );
QString javaInitTemplate = readFile( javaCodePath.absoluteFilePath("uavobjectsinit.java.template") );
if (javaCodeTemplate.isEmpty() || javaInitTemplate.isEmpty()) {
std::cerr << "Problem reading java code templates" << endl;

View File

@ -35,11 +35,11 @@ bool UAVObjectGeneratorMatlab::generate(UAVObjectParser* parser,QString template
fieldSizeStrMatlab << "1" << "2" << "4"
<< "1" << "2" << "4" << "4" << "1";
QDir matlabTemplatePath = QDir( templatepath + QString("ground/openpilotgcs/src/plugins/uavobjects"));
QDir matlabTemplatePath = QDir( templatepath + QString(MATLAB_CODE_DIR));
QDir matlabOutputPath = QDir( outputpath + QString("matlab") );
matlabOutputPath.mkpath(matlabOutputPath.absolutePath());
QString matlabCodeTemplate = readFile( matlabTemplatePath.absoluteFilePath( "uavobjecttemplate.m") );
QString matlabCodeTemplate = readFile( matlabTemplatePath.absoluteFilePath( "uavobject.m.template") );
if (matlabCodeTemplate.isEmpty() ) {
std::cerr << "Problem reading matlab templates" << endl;

View File

@ -27,6 +27,8 @@
#ifndef UAVOBJECTGENERATORMATLAB_H
#define UAVOBJECTGENERATORMATLAB_H
#define MATLAB_CODE_DIR "ground/openpilotgcs/src/plugins/uavobjects"
#include "../generator_common.h"
class UAVObjectGeneratorMatlab

View File

@ -29,10 +29,10 @@ using namespace std;
bool UAVObjectGeneratorPython::generate(UAVObjectParser* parser,QString templatepath,QString outputpath) {
// Load template and setup output directory
pythonCodePath = QDir( templatepath + QString("flight/Modules/FlightPlan/lib"));
pythonCodePath = QDir( templatepath + QString("flight/modules/FlightPlan/lib"));
pythonOutputPath = QDir( outputpath + QString("python") );
pythonOutputPath.mkpath(pythonOutputPath.absolutePath());
pythonCodeTemplate = readFile( pythonCodePath.absoluteFilePath("uavobjecttemplate.pyt") );
pythonCodeTemplate = readFile( pythonCodePath.absoluteFilePath("uavobject.pyt.template") );
if (pythonCodeTemplate.isEmpty()) {
std::cerr << "Problem reading python templates" << endl;
return false;
@ -71,20 +71,20 @@ bool UAVObjectGeneratorPython::process_object(ObjectInfo* info)
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
datafields.append(QString("\t# Enumeration options\n"));
datafields.append(QString(" # Enumeration options\n"));
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
QString name = options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "");
if (name[0].isDigit())
name = QString("N%1").arg(name);
datafields.append(QString("\t%1 = %2\n").arg(name).arg(m));
datafields.append(QString(" %1 = %2\n").arg(name).arg(m));
}
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames)
{
datafields.append(QString("\t# Array element names\n"));
datafields.append(QString(" # Array element names\n"));
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
@ -92,12 +92,12 @@ bool UAVObjectGeneratorPython::process_object(ObjectInfo* info)
QString name = elemNames[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "");
if (name[0].isDigit())
name = QString("N%1").arg(name);
datafields.append(QString("\t%1 = %2\n").arg(name).arg(m));
datafields.append(QString(" %1 = %2\n").arg(name).arg(m));
}
}
// Constructor
datafields.append(QString("\tdef __init__(self):\n"));
datafields.append(QString("\t\tUAVObjectField.__init__(self, %1, %2)\n\n").arg(info->fields[n]->type).arg(info->fields[n]->numElements));
datafields.append(QString(" def __init__(self):\n"));
datafields.append(QString(" UAVObjectField.__init__(self, %1, %2)\n\n").arg(info->fields[n]->type).arg(info->fields[n]->numElements));
}
outCode.replace(QString("$(DATAFIELDS)"), datafields);
@ -105,8 +105,8 @@ bool UAVObjectGeneratorPython::process_object(ObjectInfo* info)
QString fields;
for (int n = 0; n < info->fields.length(); ++n)
{
fields.append(QString("\t\tself.%1 = %1Field()\n").arg(info->fields[n]->name));
fields.append(QString("\t\tself.addField(self.%1)\n").arg(info->fields[n]->name));
fields.append(QString(" self.%1 = %1Field()\n").arg(info->fields[n]->name));
fields.append(QString(" self.addField(self.%1)\n").arg(info->fields[n]->name));
}
outCode.replace(QString("$(DATAFIELDINIT)"), fields);
@ -119,4 +119,3 @@ bool UAVObjectGeneratorPython::process_object(ObjectInfo* info)
return true;
}

View File

@ -40,8 +40,8 @@ bool UAVObjectGeneratorWireshark::generate(UAVObjectParser* parser,QString templ
wiresharkOutputPath = QDir( outputpath + QString("wireshark") );
wiresharkOutputPath.mkpath(wiresharkOutputPath.absolutePath());
wiresharkCodeTemplate = readFile( wiresharkCodePath.absoluteFilePath("op-uavobjects/packet-op-uavobjects-template.c") );
wiresharkMakeTemplate = readFile( wiresharkCodePath.absoluteFilePath("op-uavobjects/Makefile.common-template") );
wiresharkCodeTemplate = readFile( wiresharkCodePath.absoluteFilePath("op-uavobjects/packet-op-uavobjects.c.template") );
wiresharkMakeTemplate = readFile( wiresharkCodePath.absoluteFilePath("op-uavobjects/Makefile.common.template") );
if ( wiresharkCodeTemplate.isNull() || wiresharkMakeTemplate.isNull()) {
cerr << "Error: Could not open wireshark template files." << endl;

4
make/.gitattributes vendored
View File

@ -7,7 +7,7 @@
*.sh text eol=lf
/doxygen/*.cfg text eol=lf
/templates/firmwareinfotemplate.c text eol=lf
/templates/gcs_version_info_template.h text eol=crlf
/templates/firmware_info.c.template text eol=lf
/templates/gcs_version_info.h.template text eol=crlf
/templates/*.txt text eol=crlf
/uncrustify/*.cfg text eol=lf

View File

@ -133,21 +133,21 @@ endef
define OPFW_TEMPLATE
FORCE:
$(1).firmwareinfo.c: $(1) $(ROOT_DIR)/make/templates/firmwareinfotemplate.c FORCE
$(1).firmware_info.c: $(1) $(ROOT_DIR)/make/templates/firmware_info.c.template FORCE
@$(ECHO) $(MSG_FWINFO) $$(call toprel, $$@)
$(V1) $(VERSION_INFO) \
--template=$(ROOT_DIR)/make/templates/firmwareinfotemplate.c \
--template=$(ROOT_DIR)/make/templates/firmware_info.c.template \
--outfile=$$@ \
--image=$(1) \
--type=$(2) \
--revision=$(3) \
--uavodir=$(ROOT_DIR)/shared/uavobjectdefinition
$(eval $(call COMPILE_C_TEMPLATE, $(1).firmwareinfo.c))
$(eval $(call COMPILE_C_TEMPLATE, $(1).firmware_info.c))
$(OUTDIR)/$(notdir $(basename $(1))).opfw : $(1) $(1).firmwareinfo.bin
$(OUTDIR)/$(notdir $(basename $(1))).opfw : $(1) $(1).firmware_info.bin
@$(ECHO) $(MSG_OPFIRMWARE) $$(call toprel, $$@)
$(V1) $(CAT) $(1) $(1).firmwareinfo.bin > $$@
$(V1) $(CAT) $(1) $(1).firmware_info.bin > $$@
endef
# Assemble: create object files from assembler source files.

View File

@ -102,7 +102,7 @@ indent_namespace_limit = 0 # number
indent_extern = false # false/true
# Whether the 'class' body is indented
indent_class = false # false/true
indent_class = true # false/true
# Whether to indent the stuff after a leading class colon
indent_class_colon = false # false/true
@ -164,7 +164,7 @@ indent_sing_line_comments = 0 # number
# If set, will indent trailing single line ('//') comments relative
# to the code instead of trying to keep the same absolute column
indent_relative_single_line_comments = false # false/true
indent_relative_single_line_comments = true # false/true
# Spaces to indent 'case' from 'switch'
# Usually 0 or indent_columns.
@ -397,7 +397,7 @@ sp_before_semi = remove # ignore/add/remove/force
sp_before_semi_for = remove # ignore/add/remove/force
# Add or remove space before a semicolon of an empty part of a for statement.
sp_before_semi_for_empty = force # ignore/add/remove/force
sp_before_semi_for_empty = remove # ignore/add/remove/force
# Add or remove space after ';', except when followed by a comment. Default=Add
sp_after_semi = force # ignore/add/remove/force
@ -1398,7 +1398,7 @@ mod_pawn_semicolon = false # false/true
mod_full_paren_if_bool = false # false/true
# Whether to remove superfluous semicolons
mod_remove_extra_semicolon = true # false/true
mod_remove_extra_semicolon = false # false/true
# If a function body exceeds the specified number of newlines and doesn't have a comment after
# the close brace, a comment will be added.

View File

@ -27,6 +27,10 @@
<elementname>ModemStat</elementname>
<elementname>Autotune</elementname>
<elementname>EventDispatcher</elementname>
<elementname>CallbackScheduler0</elementname>
<elementname>CallbackScheduler1</elementname>
<elementname>CallbackScheduler2</elementname>
<elementname>CallbackScheduler3</elementname>
</elementnames>
</field>
<field name="Running" units="bool" type="enum">
@ -55,6 +59,10 @@
<elementname>ModemStat</elementname>
<elementname>Autotune</elementname>
<elementname>EventDispatcher</elementname>
<elementname>CallbackScheduler0</elementname>
<elementname>CallbackScheduler1</elementname>
<elementname>CallbackScheduler2</elementname>
<elementname>CallbackScheduler3</elementname>
</elementnames>
<options>
<option>False</option>
@ -87,6 +95,10 @@
<elementname>ModemStat</elementname>
<elementname>Autotune</elementname>
<elementname>EventDispatcher</elementname>
<elementname>CallbackScheduler0</elementname>
<elementname>CallbackScheduler1</elementname>
<elementname>CallbackScheduler2</elementname>
<elementname>CallbackScheduler3</elementname>
</elementnames>
</field>
<access gcs="readwrite" flight="readwrite"/>