NuttX: fixes for NuttX build

In the upstream tree ringbuffer.h includes the method implementations
in the header file which causes multiple definitions in the link for
other targets. Changed so ringbuffer.cpp is build separately for other
platforms and is included by ringbuffer.h on NuttX.

uORB changes do not link without uORBTest_UnitTest.cpp enabled for
the NuttX build.

px4_getopt was not exported and wasn't visible in NuttX build.

The makefiles were restored to be as close as possible to upstream
so the NuttX build builtin's work again. The code will have to be
refactored after the merge.

Signed-off-by: Mark Charlebois <charlebm@gmail.com>
This commit is contained in:
Mark Charlebois
2015-05-15 12:56:18 -07:00
parent a3a0d0612c
commit 9f391b1867
12 changed files with 340 additions and 37 deletions
+135 -10
View File
@@ -97,8 +97,132 @@ upload:
endif
endif
ifeq ($(PX4_TARGET_OS),nuttx)
#
# Built products
#
DESIRED_FIRMWARES = $(foreach config,$(CONFIGS),$(IMAGE_DIR)$(config).px4)
STAGED_FIRMWARES = $(foreach config,$(KNOWN_CONFIGS),$(IMAGE_DIR)$(config).px4)
FIRMWARES = $(foreach config,$(KNOWN_CONFIGS),$(BUILD_DIR)$(config).build/firmware.px4)
all: $(DESIRED_FIRMWARES)
#
# Copy FIRMWARES into the image directory.
#
# XXX copying the .bin files is a hack to work around the PX4IO uploader
# not supporting .px4 files, and it should be deprecated onced that
# is taken care of.
#
$(STAGED_FIRMWARES): $(IMAGE_DIR)%.px4: $(BUILD_DIR)%.build/firmware.px4
@$(ECHO) %% Copying $@
$(Q) $(COPY) $< $@
$(Q) $(COPY) $(patsubst %.px4,%.bin,$<) $(patsubst %.px4,%.bin,$@)
#
# Generate FIRMWARES.
#
.PHONY: $(FIRMWARES)
$(BUILD_DIR)%.build/firmware.px4: config = $(patsubst $(BUILD_DIR)%.build/firmware.px4,%,$@)
$(BUILD_DIR)%.build/firmware.px4: work_dir = $(BUILD_DIR)$(config).build/
$(FIRMWARES): $(BUILD_DIR)%.build/firmware.px4: generateuorbtopicheaders checksubmodules
@$(ECHO) %%%%
@$(ECHO) %%%% Building $(config) in $(work_dir)
@$(ECHO) %%%%
$(Q) $(MKDIR) -p $(work_dir)
$(Q) $(MAKE) -r -C $(work_dir) \
-f $(PX4_MK_DIR)firmware.mk \
CONFIG=$(config) \
WORK_DIR=$(work_dir) \
$(FIRMWARE_GOAL)
#
# Make FMU firmwares depend on the corresponding IO firmware.
#
# This is a pretty vile hack, since it hard-codes knowledge of the FMU->IO dependency
# and forces the _default config in all cases. There has to be a better way to do this...
#
FMU_VERSION = $(patsubst px4fmu-%,%,$(word 1, $(subst _, ,$(1))))
define FMU_DEP
$(BUILD_DIR)$(1).build/firmware.px4: $(IMAGE_DIR)px4io-$(call FMU_VERSION,$(1))_default.px4
endef
FMU_CONFIGS := $(filter px4fmu%,$(CONFIGS))
$(foreach config,$(FMU_CONFIGS),$(eval $(call FMU_DEP,$(config))))
#
# Build the NuttX export archives.
#
# Note that there are no explicit dependencies extended from these
# archives. If NuttX is updated, the user is expected to rebuild the
# archives/build area manually. Likewise, when the 'archives' target is
# invoked, all archives are always rebuilt.
#
# XXX Should support fetching/unpacking from a separate directory to permit
# downloads of the prebuilt archives as well...
#
NUTTX_ARCHIVES = $(foreach board,$(BOARDS),$(ARCHIVE_DIR)$(board).export)
.PHONY: archives
archives: checksubmodules $(NUTTX_ARCHIVES)
# We cannot build these parallel; note that we also force -j1 for the
# sub-make invocations.
ifneq ($(filter archives,$(MAKECMDGOALS)),)
.NOTPARALLEL:
endif
J?=1
$(ARCHIVE_DIR)%.export: board = $(notdir $(basename $@))
$(ARCHIVE_DIR)%.export: configuration = nsh
$(NUTTX_ARCHIVES): $(ARCHIVE_DIR)%.export: $(NUTTX_SRC)
@$(ECHO) %% Configuring NuttX for $(board)
$(Q) (cd $(NUTTX_SRC) && $(RMDIR) nuttx-export)
$(Q) $(MAKE) -r -j$(J) -C $(NUTTX_SRC) -r $(MQUIET) distclean
$(Q) (cd $(NUTTX_SRC)/configs && $(COPYDIR) $(PX4_BASE)nuttx-configs/$(board) .)
$(Q) (cd $(NUTTX_SRC)tools && ./configure.sh $(board)/$(configuration))
@$(ECHO) %% Exporting NuttX for $(board)
$(Q) $(MAKE) -r -j$(J) -C $(NUTTX_SRC) -r $(MQUIET) CONFIG_ARCH_BOARD=$(board) export
$(Q) $(MKDIR) -p $(dir $@)
$(Q) $(COPY) $(NUTTX_SRC)nuttx-export.zip $@
$(Q) (cd $(NUTTX_SRC)/configs && $(RMDIR) $(board))
#
# The user can run the NuttX 'menuconfig' tool for a single board configuration with
# make BOARDS=<boardname> menuconfig
#
ifeq ($(MAKECMDGOALS),menuconfig)
ifneq ($(words $(BOARDS)),1)
$(error BOARDS must specify exactly one board for the menuconfig goal)
endif
BOARD = $(BOARDS)
menuconfig: $(NUTTX_SRC)
@$(ECHO) %% Configuring NuttX for $(BOARD)
$(Q) (cd $(NUTTX_SRC) && $(RMDIR) nuttx-export)
$(Q) $(MAKE) -r -j$(J) -C $(NUTTX_SRC) -r $(MQUIET) distclean
$(Q) (cd $(NUTTX_SRC)/configs && $(COPYDIR) $(PX4_BASE)nuttx-configs/$(BOARD) .)
$(Q) (cd $(NUTTX_SRC)tools && ./configure.sh $(BOARD)/nsh)
@$(ECHO) %% Running menuconfig for $(BOARD)
$(Q) $(MAKE) -r -j$(J) -C $(NUTTX_SRC) -r $(MQUIET) menuconfig
@$(ECHO) %% Saving configuration file
$(Q)$(COPY) $(NUTTX_SRC).config $(PX4_BASE)nuttx-configs/$(BOARD)/nsh/defconfig
else
menuconfig:
@$(ECHO) ""
@$(ECHO) "The menuconfig goal must be invoked without any other goal being specified"
@$(ECHO) ""
endif
$(NUTTX_SRC): checksubmodules
$(UAVCAN_DIR):
$(Q) (./Tools/check_submodules.sh)
endif
ifeq ($(PX4_TARGET_OS),nuttx)
include $(PX4_BASE)makefiles/firmware_nuttx.mk
# TODO
# Move the above nuttx specific rules into $(PX4_BASE)makefiles/firmware_nuttx.mk
endif
ifeq ($(PX4_TARGET_OS),posix)
include $(PX4_BASE)makefiles/firmware_posix.mk
@@ -107,6 +231,16 @@ ifeq ($(PX4_TARGET_OS),qurt)
include $(PX4_BASE)makefiles/firmware_qurt.mk
endif
.PHONY: checksubmodules
checksubmodules:
$(Q) ($(PX4_BASE)/Tools/check_submodules.sh)
.PHONY: updatesubmodules
updatesubmodules:
$(Q) (git submodule init)
$(Q) (git submodule update)
MSG_DIR = $(PX4_BASE)msg
UORB_TEMPLATE_DIR = $(PX4_BASE)msg/templates/uorb
MULTIPLATFORM_TEMPLATE_DIR = $(PX4_BASE)msg/templates/px4/uorb
@@ -117,15 +251,6 @@ TOPICHEADER_TEMP_DIR = $(BUILD_DIR)topics_temporary
GENMSG_PYTHONPATH = $(PX4_BASE)Tools/genmsg/src
GENCPP_PYTHONPATH = $(PX4_BASE)Tools/gencpp/src
.PHONY: checksubmodules
checksubmodules:
$(Q) ($(PX4_BASE)/Tools/check_submodules.sh)
.PHONY: updatesubmodules
updatesubmodules:
$(Q) (git submodule init)
$(Q) (git submodule update)
.PHONY: generateuorbtopicheaders
generateuorbtopicheaders: checksubmodules
@$(ECHO) "Generating uORB topic headers"
+189 -4
View File
@@ -213,7 +213,7 @@ endef
MODULE_MKFILES := $(foreach module,$(MODULES),$(call MODULE_SEARCH,$(module)))
MISSING_MODULES := $(subst MISSING_,,$(filter MISSING_%,$(MODULE_MKFILES)))
ifneq ($(MISSING_MODULES),)
$(error Can't find module(s): $(MISSING_MODULES))
$(error Cant find module(s): $(MISSING_MODULES))
endif
# Make a list of the object files we expect to build from modules
@@ -273,7 +273,7 @@ endef
LIBRARY_MKFILES := $(foreach library,$(LIBRARIES),$(call LIBRARY_SEARCH,$(library)))
MISSING_LIBRARIES := $(subst MISSING_,,$(filter MISSING_%,$(LIBRARY_MKFILES)))
ifneq ($(MISSING_LIBRARIES),)
$(error Can't find library(s): $(MISSING_LIBRARIES))
$(error Cant find library(s): $(MISSING_LIBRARIES))
endif
# Make a list of the archive files we expect to build from libraries
@@ -311,6 +311,132 @@ $(LIBRARY_CLEANS):
LIBRARY_MK=$(mkfile) \
clean
ifeq ($(PX4_TARGET_OS),nuttx)
################################################################################
# ROMFS generation
################################################################################
ifneq ($(ROMFS_ROOT),)
ifeq ($(wildcard $(ROMFS_ROOT)),)
$(error ROMFS_ROOT specifies a directory that does not exist)
endif
#
# Note that there is no support for more than one root directory or constructing
# a root from several templates. That would be a nice feature.
#
# Add dependencies on anything in the ROMFS root directory
ROMFS_FILES += $(wildcard \
$(ROMFS_ROOT)/* \
$(ROMFS_ROOT)/*/* \
$(ROMFS_ROOT)/*/*/* \
$(ROMFS_ROOT)/*/*/*/* \
$(ROMFS_ROOT)/*/*/*/*/* \
$(ROMFS_ROOT)/*/*/*/*/*/*)
ifeq ($(ROMFS_FILES),)
$(error ROMFS_ROOT $(ROMFS_ROOT) specifies a directory containing no files)
endif
ROMFS_DEPS += $(ROMFS_FILES)
# Extra files that may be copied into the ROMFS /extras directory
# ROMFS_EXTRA_FILES are required, ROMFS_OPTIONAL_FILES are optional
ROMFS_EXTRA_FILES += $(wildcard $(ROMFS_OPTIONAL_FILES))
ROMFS_DEPS += $(ROMFS_EXTRA_FILES)
ROMFS_IMG = romfs.img
ROMFS_SCRATCH = romfs_scratch
ROMFS_CSRC = $(ROMFS_IMG:.img=.c)
ROMFS_OBJ = $(ROMFS_CSRC:.c=.o)
LIBS += $(ROMFS_OBJ)
LINK_DEPS += $(ROMFS_OBJ)
# Remove all comments from startup and mixer files
ROMFS_PRUNER = $(PX4_BASE)/Tools/px_romfs_pruner.py
# Turn the ROMFS image into an object file
$(ROMFS_OBJ): $(ROMFS_IMG) $(GLOBAL_DEPS)
$(call BIN_TO_OBJ,$<,$@,romfs_img)
# Generate the ROMFS image from the root
$(ROMFS_IMG): $(ROMFS_SCRATCH) $(ROMFS_DEPS) $(GLOBAL_DEPS)
@$(ECHO) "ROMFS: $@"
$(Q) $(GENROMFS) -f $@ -d $(ROMFS_SCRATCH) -V "NSHInitVol"
# Construct the ROMFS scratch root from the canonical root
$(ROMFS_SCRATCH): $(ROMFS_DEPS) $(GLOBAL_DEPS)
$(Q) $(MKDIR) -p $(ROMFS_SCRATCH)
$(Q) $(COPYDIR) $(ROMFS_ROOT)/* $(ROMFS_SCRATCH)
# delete all files in ROMFS_SCRATCH which start with a . or end with a ~
$(Q) $(RM) $(ROMFS_SCRATCH)/*/.[!.]* $(ROMFS_SCRATCH)/*/*~
ifneq ($(ROMFS_EXTRA_FILES),)
$(Q) $(MKDIR) -p $(ROMFS_SCRATCH)/extras
$(Q) $(COPY) $(ROMFS_EXTRA_FILES) $(ROMFS_SCRATCH)/extras
endif
$(Q) $(PYTHON) -u $(ROMFS_PRUNER) --folder $(ROMFS_SCRATCH)
EXTRA_CLEANS += $(ROMGS_OBJ) $(ROMFS_IMG)
endif
################################################################################
# Builtin command list generation
################################################################################
#
# Builtin commands can be generated by the configuration, in which case they
# must refer to commands that already exist, or indirectly generated by modules
# when they are built.
#
# The configuration supplies builtin command information in the BUILTIN_COMMANDS
# variable. Applications make empty files in $(WORK_DIR)/builtin_commands whose
# filename contains the same information.
#
# In each case, the command information consists of four fields separated with a
# period. These fields are the command's name, its thread priority, its stack size
# and the name of the function to call when starting the thread.
#
BUILTIN_CSRC = $(WORK_DIR)builtin_commands.c
# command definitions from modules (may be empty at Makefile parsing time...)
MODULE_COMMANDS = $(subst COMMAND.,,$(notdir $(wildcard $(WORK_DIR)builtin_commands/COMMAND.*)))
# We must have at least one pre-defined builtin command in order to generate
# any of this.
#
ifneq ($(BUILTIN_COMMANDS),)
# (BUILTIN_PROTO,<cmdspec>,<outputfile>)
define BUILTIN_PROTO
$(ECHO) 'extern int $(word 4,$1)(int argc, char *argv[]);' >> $2;
endef
# (BUILTIN_DEF,<cmdspec>,<outputfile>)
define BUILTIN_DEF
$(ECHO) ' {"$(word 1,$1)", $(word 2,$1), $(word 3,$1), $(word 4,$1)},' >> $2;
endef
# Don't generate until modules have updated their command files
$(BUILTIN_CSRC): $(GLOBAL_DEPS) $(MODULE_OBJS) $(MODULE_MKFILES) $(BUILTIN_COMMAND_FILES)
@$(ECHO) "CMDS: $@"
$(Q) $(ECHO) '/* builtin command list - automatically generated, do not edit */' > $@
$(Q) $(ECHO) '#include <nuttx/config.h>' >> $@
$(Q) $(ECHO) '#include <nuttx/binfmt/builtin.h>' >> $@
$(Q) $(foreach spec,$(BUILTIN_COMMANDS),$(call BUILTIN_PROTO,$(subst ., ,$(spec)),$@))
$(Q) $(foreach spec,$(MODULE_COMMANDS),$(call BUILTIN_PROTO,$(subst ., ,$(spec)),$@))
$(Q) $(ECHO) 'const struct builtin_s g_builtins[] = {' >> $@
$(Q) $(foreach spec,$(BUILTIN_COMMANDS),$(call BUILTIN_DEF,$(subst ., ,$(spec)),$@))
$(Q) $(foreach spec,$(MODULE_COMMANDS),$(call BUILTIN_DEF,$(subst ., ,$(spec)),$@))
$(Q) $(ECHO) ' {NULL, 0, 0, NULL}' >> $@
$(Q) $(ECHO) '};' >> $@
$(Q) $(ECHO) 'const int g_builtin_count = $(words $(BUILTIN_COMMANDS) $(MODULE_COMMANDS));' >> $@
SRCS += $(BUILTIN_CSRC)
EXTRA_CLEANS += $(BUILTIN_CSRC)
endif
endif
################################################################################
# Default SRCS generation
@@ -329,9 +455,22 @@ SRCS += $(EMPTY_SRC)
endif
################################################################################
# Generic Build rules
# Build rules
################################################################################
ifeq ($(PX4_TARGET_OS),nuttx)
#
# What we're going to build.
#
PRODUCT_BUNDLE = $(WORK_DIR)firmware.px4
PRODUCT_BIN = $(WORK_DIR)firmware.bin
PRODUCT_ELF = $(WORK_DIR)firmware.elf
PRODUCT_PARAMXML = $(WORK_DIR)/parameters.xml
.PHONY: firmware
firmware: $(PRODUCT_BUNDLE)
endif
#
# Object files we will generate from sources
#
@@ -352,13 +491,59 @@ $(filter %.cpp.o,$(OBJS)): $(WORK_DIR)%.cpp.o: %.cpp $(GLOBAL_DEPS)
$(filter %.S.o,$(OBJS)): $(WORK_DIR)%.S.o: %.S $(GLOBAL_DEPS)
$(call ASSEMBLE,$<,$@)
ifeq ($(PX4_TARGET_OS),nuttx)
#
# Built product rules
#
$(PRODUCT_BUNDLE): $(PRODUCT_BIN)
@$(ECHO) %% Generating $@
ifdef GEN_PARAM_XML
$(Q) $(PYTHON) $(PX4_BASE)/Tools/px_process_params.py --src-path $(PX4_BASE)/src --board CONFIG_ARCH_BOARD_$(CONFIG_BOARD) --xml
$(Q) $(MKFW) --prototype $(IMAGE_DIR)/$(BOARD).prototype \
--git_identity $(PX4_BASE) \
--parameter_xml $(PRODUCT_PARAMXML) \
--image $< > $@
else
$(Q) $(MKFW) --prototype $(IMAGE_DIR)/$(BOARD).prototype \
--git_identity $(PX4_BASE) \
--image $< > $@
endif
$(PRODUCT_BIN): $(PRODUCT_ELF)
$(call SYM_TO_BIN,$<,$@)
$(PRODUCT_ELF): $(OBJS) $(MODULE_OBJS) $(LIBRARY_LIBS) $(GLOBAL_DEPS) $(LINK_DEPS) $(MODULE_MKFILES)
$(call LINK,$@,$(OBJS) $(MODULE_OBJS) $(LIBRARY_LIBS))
#
# Utility rules
#
.PHONY: upload
upload: $(PRODUCT_BUNDLE) $(PRODUCT_BIN)
$(Q) $(MAKE) -f $(PX4_MK_DIR)/upload.mk \
METHOD=serial \
CONFIG=$(CONFIG) \
BOARD=$(BOARD) \
BUNDLE=$(PRODUCT_BUNDLE) \
BIN=$(PRODUCT_BIN)
.PHONY: clean
clean: $(MODULE_CLEANS)
@$(ECHO) %% cleaning
$(Q) $(REMOVE) $(PRODUCT_BUNDLE) $(PRODUCT_BIN) $(PRODUCT_ELF)
$(Q) $(REMOVE) $(OBJS) $(DEP_INCLUDES) $(EXTRA_CLEANS)
$(Q) $(RMDIR) $(NUTTX_EXPORT_DIR)
endif
# Include the OS specific build rules
# The rules must define the "firmware" make target
#
ifeq ($(PX4_TARGET_OS),nuttx)
include $(MK_DIR)/nuttx_romfs.mk
# TODO
# Move above nuttx specific rules to $(MK_DIR)/nuttx_romfs.mk
endif
ifeq ($(PX4_TARGET_OS),posix)
include $(MK_DIR)/posix_elf.mk
+1 -1
View File
@@ -34,7 +34,7 @@
# building firmware.
#
#MODULES += platforms/nuttx/px4_layer
MODULES += platforms/nuttx/px4_layer platforms/common
#
# Check that the NuttX archive for the selected board is available.
+2 -3
View File
@@ -41,8 +41,7 @@ SRCS = \
cdev.cpp \
i2c_nuttx.cpp \
pio.cpp \
spi.cpp \
ringbuffer.cpp
spi.cpp
else
SRCS = \
device_posix.cpp \
@@ -51,5 +50,5 @@ SRCS = \
vdev_posix.cpp \
i2c_posix.cpp \
sim.cpp \
ringbuffer.cpp
ringbuffer.cpp
endif
+1 -1
View File
@@ -237,7 +237,7 @@ RingBuffer::force(double val)
// FIXME - clang crashes on this get() call
#ifdef __PX4_QURT
#define __PX4_SBCAP my_sync_bool_compare_and_swap
static bool my_sync_bool_compare_and_swap(volatile unsigned *a, unsigned b, unsigned c)
static inline bool my_sync_bool_compare_and_swap(volatile unsigned *a, unsigned b, unsigned c)
{
if (*a == b) {
*a = c;
+6
View File
@@ -172,3 +172,9 @@ private:
RingBuffer operator=(const RingBuffer&);
};
#ifdef __PX4_NUTTX
// Not sure why NuttX requires these to be defined in the header file
// but on other targets it causes a problem with multiple definitions
// at link time
#include "ringbuffer.cpp"
#endif
@@ -51,6 +51,8 @@ PublisherExample::PublisherExample() :
{
}
px4::AppState PublisherExample::appState;
int PublisherExample::main()
{
px4::Rate loop_rate(10);
@@ -361,7 +361,7 @@ main_state_transition(struct vehicle_status_s *status, main_state_t new_main_sta
return ret;
}
#ifdef PX4_NUTTX
#ifdef __PX4_NUTTX
static transition_result_t disable_publication(const int mavlink_fd)
{
transition_result_t ret;
+1
View File
@@ -41,6 +41,7 @@ MODULE_STACKSIZE = 2048
ifeq ($(PX4_TARGET_OS),nuttx)
SRCS = uORBDevices_nuttx.cpp \
uORBTest_UnitTest.cpp \
uORBManager_nuttx.cpp
else
+1
View File
@@ -35,6 +35,7 @@
#include "uORBCommon.hpp"
#include <px4_config.h>
#include <px4_time.h>
#include <stdio.h>
uORBTest::UnitTest &uORBTest::UnitTest::instance()
{
+1 -2
View File
@@ -121,7 +121,7 @@ static int reorder(int argc, char **argv, const char *options)
// Argv is changed to put all options and option args at the beginning,
// followed by non-options.
//
int px4_getopt(int argc, char *argv[], const char *options, int *myoptind, const char **myoptarg)
__EXPORT int px4_getopt(int argc, char *argv[], const char *options, int *myoptind, const char **myoptarg)
{
char *p;
char c;
@@ -149,4 +149,3 @@ int px4_getopt(int argc, char *argv[], const char *options, int *myoptind, const
}
return -1;
}
@@ -72,21 +72,6 @@ px4_systemreset(bool to_bootloader)
while(true);
}
static void kill_task(FAR struct tcb_s *tcb, FAR void *arg);
void px4_killall()
{
// printf("Sending SIGUSR1 to all processes now\n");
/* iterate through all tasks and send kill signal */
sched_foreach(kill_task, NULL);
}
static void kill_task(FAR struct tcb_s *tcb, FAR void *arg)
{
kill(tcb->pid, SIGUSR1);
}
int px4_task_spawn_cmd(const char *name, int scheduler, int priority, int stack_size, main_t entry, char * const argv[])
{
int pid;