From 083e2b01a9dcc27b961a5f0a47233eedb7cff587 Mon Sep 17 00:00:00 2001 From: stac Date: Sun, 30 Jan 2011 22:46:48 +0000 Subject: [PATCH] uavobject: Use linker to produce uavobj initcalls The UAVObject initcall list is now automatically generated at link time based on the exact set of UAVObjects linked into the firmware image. This will allow any subset of UAVObjects to be used in any firmware image. The uavobj_initcall() macro automatically adds the marked function's address into the .initcalluavobj.init ELF section. The UAVObjectsInitializeAll() function now simply iterates over the functions listed in the .initcalluavobj.init section and calls them. You can see the contents of this section in the ELF file like this: ./tools/arm-2009q3/bin/arm-none-eabi-objdump \ --syms -j .initcalluavobj.init \ ./build/openpilot/OpenPilot.elf This is fundamentally the same mechanism that the Linux kernel uses to initialize the specific set of components that the user has selected in their kernel configuration. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2630 ebee16cc-31ac-478f-84a7-5cbb03baadba --- .../PiOS/STM32F10x/link_STM3210E_OP_HD_NB.ld | 10 +++ flight/PiOS/inc/pios_initcall.h | 65 +++++++++++++++++++ flight/PiOS/pios.h | 3 + flight/UAVObjects/uavobjectsinittemplate.c | 9 ++- flight/UAVObjects/uavobjecttemplate.c | 4 +- 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 flight/PiOS/inc/pios_initcall.h diff --git a/flight/PiOS/STM32F10x/link_STM3210E_OP_HD_NB.ld b/flight/PiOS/STM32F10x/link_STM3210E_OP_HD_NB.ld index c96c9e191..9c96c4ac3 100644 --- a/flight/PiOS/STM32F10x/link_STM3210E_OP_HD_NB.ld +++ b/flight/PiOS/STM32F10x/link_STM3210E_OP_HD_NB.ld @@ -218,6 +218,16 @@ SECTIONS } >FLASH + /* init sections */ + .initcalluavobj.init : + { + . = ALIGN(4); + __uavobj_initcall_start = .; + KEEP(*(.initcalluavobj.init)) + . = ALIGN(4); + __uavobj_initcall_end = .; + } >FLASH + /* the program code is stored in the .text section, which goes to Flash */ .text : { diff --git a/flight/PiOS/inc/pios_initcall.h b/flight/PiOS/inc/pios_initcall.h new file mode 100644 index 000000000..7edad6283 --- /dev/null +++ b/flight/PiOS/inc/pios_initcall.h @@ -0,0 +1,65 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Initcall infrastructure + * @{ + * @addtogroup PIOS_INITCALL Generic Initcall Macros + * @brief Initcall Macros + * @{ + * + * @file pios_initcall.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011. + * @brief Initcall header + * @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 PIOS_INITCALL_H +#define PIOS_INITCALL_H + +/* + * This implementation is heavily based on the Linux Kernel initcall + * infrastructure: + * http://lxr.linux.no/#linux/include/linux/init.h + * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=include/linux/init.h + */ + +/* + * Used for initialization calls.. + */ +typedef int32_t (*initcall_t)(void); + +/* initcalls are now grouped by functionality into separate + * subsections. Ordering inside the subsections is determined + * by link order. + * + * The `id' arg to __define_initcall() is needed so that multiple initcalls + * can point at the same handler without causing duplicate-symbol build errors. + */ + +#define __define_initcall(level,fn,id) \ + static initcall_t __initcall_##fn##id __attribute__((__used__)) \ + __attribute__((__section__(".initcall" level ".init"))) = fn + +#define uavobj_initcall(fn) __define_initcall("uavobj",fn,1) + +#endif /* PIOS_INITCALL_H */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/pios.h b/flight/PiOS/pios.h index 684084f57..88a5631c6 100644 --- a/flight/PiOS/pios.h +++ b/flight/PiOS/pios.h @@ -58,6 +58,9 @@ #include #endif +/* Generic initcall infrastructure */ +#include "pios_initcall.h" + /* PIOS Board Specific Device Configuration */ #include "pios_board.h" diff --git a/flight/UAVObjects/uavobjectsinittemplate.c b/flight/UAVObjects/uavobjectsinittemplate.c index 75a104d18..3d4abd7eb 100644 --- a/flight/UAVObjects/uavobjectsinittemplate.c +++ b/flight/UAVObjects/uavobjectsinittemplate.c @@ -28,13 +28,18 @@ */ #include "openpilot.h" -$(OBJINC) /** * Function used to initialize the first instance of each object. * This file is automatically updated by the UAVObjectGenerator. */ +extern initcall_t __uavobj_initcall_start[], __uavobj_initcall_end[]; + void UAVObjectsInitializeAll() { -$(OBJINIT) + initcall_t *fn; + int32_t ret; + + for (fn = __uavobj_initcall_start; fn < __uavobj_initcall_end; fn++) + ret = (*fn)(); } diff --git a/flight/UAVObjects/uavobjecttemplate.c b/flight/UAVObjects/uavobjecttemplate.c index 75b5c5a95..4ee7cc9b1 100644 --- a/flight/UAVObjects/uavobjecttemplate.c +++ b/flight/UAVObjects/uavobjecttemplate.c @@ -47,7 +47,7 @@ static UAVObjHandle handle; * \return 0 Success * \return -1 Failure */ -int32_t $(NAME)Initialize() +int32_t $(NAME)Initialize(void) { // Register object with the object manager handle = UAVObjRegister($(NAMEUC)_OBJID, $(NAMEUC)_NAME, $(NAMEUC)_METANAME, 0, @@ -64,6 +64,8 @@ int32_t $(NAME)Initialize() } } +uavobj_initcall($(NAME)Initialize); + /** * Initialize object fields and metadata with the default values. * If a default value is not specified the object fields