mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-29 07:24:13 +01:00
Merge remote-tracking branch 'origin/next' into brian/rfm22_FHSS
Conflicts: flight/targets/PipXtreme/System/inc/pios_config.h flight/targets/RevoMini/System/inc/pios_config.h
This commit is contained in:
commit
1cac81b3e8
104
.gitignore
vendored
104
.gitignore
vendored
@ -1,88 +1,54 @@
|
||||
# Exclude temporary and system files
|
||||
.DS_Store
|
||||
# Ignore artifacts of top-level Makefile
|
||||
/downloads
|
||||
/tools
|
||||
/build
|
||||
|
||||
# /flight/
|
||||
# Exclude temporary and system files
|
||||
Thumbs.db
|
||||
.DS_Store
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
|
||||
# flight
|
||||
/flight/*.pnproj
|
||||
/flight/*.pnps
|
||||
/flight/.cproject
|
||||
/flight/.metadata
|
||||
/flight/.project
|
||||
/flight/.settings
|
||||
/flight/Build
|
||||
|
||||
# /flight/AHRS/
|
||||
/flight/AHRS/Build
|
||||
|
||||
# /flight/Bootloaders/OpenPilot.old/
|
||||
/flight/Bootloaders/OpenPilot.old/Build
|
||||
|
||||
# /flight/OpenPilot/
|
||||
/flight/OpenPilot/Build
|
||||
/flight/OpenPilot/Build.win32
|
||||
|
||||
#flight/Project/OpenPilotOSX
|
||||
flight/Project/OpenPilotOSX/build
|
||||
|
||||
# /flight/PipBee/
|
||||
/flight/PipBee/Build
|
||||
|
||||
# /flight/Project/OpenPilotOSX/
|
||||
/flight/Project/OpenPilotOSX/build/
|
||||
|
||||
# /ground/
|
||||
/ground/Build
|
||||
|
||||
/ground/openpilotgcs/share/openpilotgcs/models/Easystar/Thumbs.db
|
||||
|
||||
/ground/openpilotgcs/share/openpilotgcs/sounds/normalize.exe
|
||||
|
||||
/ground/openpilotgcs/share/openpilotgcs/sounds/default/normalize.exe
|
||||
|
||||
/ground/openpilotgcs/share/openpilotgcs/translations/extract-mimetypes.xq
|
||||
|
||||
/ground/openpilotgcs/src/experimental/OPMapWidget/core/header.h
|
||||
|
||||
/ground/openpilotgcs/src/experimental/tools/DocumentationHelper/ui_mainwindow.h
|
||||
|
||||
/ground/openpilotgcs/src/libs/qextserialport/.hg
|
||||
/ground/openpilotgcs/src/libs/qextserialport/.hgtags
|
||||
|
||||
/ground/openpilotgcs/src/libs/qwt/qwt.prf
|
||||
/ground/openpilotgcs/src/libs/qwt/designer
|
||||
|
||||
/ground/openpilotgcs/src/plugins/ipconnection/ui_ipconnectionoptionspage.h
|
||||
|
||||
# Ignore artifacts of top-level Makefile
|
||||
/downloads
|
||||
/tools
|
||||
/build
|
||||
/flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/*.mode1v3
|
||||
/flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/*.pbxuser
|
||||
|
||||
# ground
|
||||
openpilotgcs-build-desktop
|
||||
flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/*.mode1v3
|
||||
flight/Project/OpenPilotOSX/OpenPilotOSX.xcodeproj/*.pbxuser
|
||||
|
||||
# Ignore some of the .pro.user files
|
||||
ground/openpilotgcs/openpilotgcs.pro.user
|
||||
ground/uavobjgenerator/uavobjgenerator.pro.user
|
||||
ground/uavobjects/uavobjects.pro.user
|
||||
ground/ground.pro.user
|
||||
/ground/openpilotgcs/openpilotgcs.pro.user
|
||||
/ground/uavobjgenerator/uavobjgenerator.pro.user
|
||||
/ground/uavobjects/uavobjects.pro.user
|
||||
/ground/ground.pro.user
|
||||
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
|
||||
plane
|
||||
quad
|
||||
# Misc artifacts
|
||||
/ground/openpilotgcs/share/openpilotgcs/sounds/normalize.exe
|
||||
/ground/openpilotgcs/share/openpilotgcs/sounds/default/normalize.exe
|
||||
/ground/openpilotgcs/share/openpilotgcs/translations/extract-mimetypes.xq
|
||||
/ground/openpilotgcs/src/experimental/tools/DocumentationHelper/ui_mainwindow.h
|
||||
/ground/openpilotgcs/src/libs/qextserialport/.hg
|
||||
/ground/openpilotgcs/src/libs/qextserialport/.hgtags
|
||||
/ground/openpilotgcs/src/libs/qwt/qwt.prf
|
||||
/ground/openpilotgcs/src/libs/qwt/designer
|
||||
/ground/openpilotgcs/src/plugins/ipconnection/ui_ipconnectionoptionspage.h
|
||||
|
||||
# Ignore intermediate files generated by command-line android builds
|
||||
# Couldn't figure out how to force these files into the ./build directory
|
||||
androidgcs/build.xml
|
||||
androidgcs/local.properties
|
||||
androidgcs/proguard-project.txt
|
||||
/androidgcs/build.xml
|
||||
/androidgcs/local.properties
|
||||
/androidgcs/proguard-project.txt
|
||||
|
||||
# Ignore build output from Eclipse android builds
|
||||
androidgcs/bin/
|
||||
androidgcs/gen/
|
||||
/androidgcs/bin/
|
||||
/androidgcs/gen/
|
||||
/.cproject
|
||||
/.project
|
||||
|
@ -172,7 +172,7 @@ By default a lot of diagnostic objects that were enabled by default are now
|
||||
disabled in the build. This include TaskInfo (and all the FreeRTOS options
|
||||
that provide that debugging information). Also MixerStatus, I2CStatus,
|
||||
WatchdogStatus and RateDesired. These can be reenabled for debugging with
|
||||
-DDIAGNOSTICS.
|
||||
-DDIAG_ALL.
|
||||
|
||||
2011-08-04
|
||||
Fixed packaging aesthetic issues. Also avoid runtime issues on OSX Lion by
|
||||
|
1156
Makefile
1156
Makefile
@ -1,11 +1,44 @@
|
||||
#
|
||||
# Top level Makefile for the OpenPilot project build system.
|
||||
# Copyright (c) 2010-2013, The OpenPilot Team, http://www.openpilot.org
|
||||
#
|
||||
# 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 top level Makefile passes down some variables to sub-makes through
|
||||
# the environment. They are explicitly exported using the export keyword.
|
||||
# Lower level makefiles assume that these variables are defined. To ensure
|
||||
# that a special magic variable is exported here. It must be checked for
|
||||
# existance by each sub-make.
|
||||
export OPENPILOT_IS_COOL := Fuck Yeah!
|
||||
|
||||
# Set up a default goal
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# Set up some macros for common directories within the tree
|
||||
ROOT_DIR=$(CURDIR)
|
||||
TOOLS_DIR=$(ROOT_DIR)/tools
|
||||
BUILD_DIR=$(ROOT_DIR)/build
|
||||
DL_DIR=$(ROOT_DIR)/downloads
|
||||
export ROOT_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
export TOOLS_DIR := $(ROOT_DIR)/tools
|
||||
export BUILD_DIR := $(ROOT_DIR)/build
|
||||
export DL_DIR := $(ROOT_DIR)/downloads
|
||||
export PACKAGE_DIR := $(ROOT_DIR)/build/package
|
||||
|
||||
# Set up default build configurations (debug | release)
|
||||
GCS_BUILD_CONF := release
|
||||
UAVOGEN_BUILD_CONF := release
|
||||
ANDROIDGCS_BUILD_CONF := debug
|
||||
GOOGLE_API_VERSION := 14
|
||||
|
||||
# Function for converting an absolute path to one relative
|
||||
# to the top of the source tree.
|
||||
@ -15,10 +48,10 @@ toprel = $(subst $(realpath $(ROOT_DIR))/,,$(abspath $(1)))
|
||||
# to remove the chance that they will cause problems with our build
|
||||
define SANITIZE_VAR
|
||||
$(if $(filter-out undefined,$(origin $(1))),
|
||||
$(info *NOTE* Sanitized $(2) variable '$(1)' from $(origin $(1)))
|
||||
MAKEOVERRIDES = $(filter-out $(1)=%,$(MAKEOVERRIDES))
|
||||
override $(1) :=
|
||||
unexport $(1)
|
||||
$(info *NOTE* Sanitized $(2) variable '$(1)' from $(origin $(1)))
|
||||
MAKEOVERRIDES = $(filter-out $(1)=%,$(MAKEOVERRIDES))
|
||||
override $(1) :=
|
||||
unexport $(1)
|
||||
)
|
||||
endef
|
||||
|
||||
@ -31,144 +64,117 @@ $(foreach var, $(SANITIZE_GCC_VARS), $(eval $(call SANITIZE_VAR,$(var),disallowe
|
||||
SANITIZE_DEPRECATED_VARS := USE_BOOTLOADER
|
||||
$(foreach var, $(SANITIZE_DEPRECATED_VARS), $(eval $(call SANITIZE_VAR,$(var),deprecated)))
|
||||
|
||||
# Deal with unreasonable requests
|
||||
# See: http://xkcd.com/149/
|
||||
ifeq ($(MAKECMDGOALS),me a sandwich)
|
||||
ifeq ($(shell whoami),root)
|
||||
$(error Okay)
|
||||
else
|
||||
$(error What? Make it yourself)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Make sure this isn't being run as root
|
||||
ifeq ($(shell whoami),root)
|
||||
$(error You should not be running this as root)
|
||||
# Make sure this isn't being run as root (no whoami on Windows, but that is ok here)
|
||||
ifeq ($(shell whoami 2>/dev/null),root)
|
||||
$(error You should not be running this as root)
|
||||
endif
|
||||
|
||||
# Decide on a verbosity level based on the V= parameter
|
||||
export AT := @
|
||||
|
||||
ifndef V
|
||||
export V0 :=
|
||||
export V1 := $(AT)
|
||||
export V0 :=
|
||||
export V1 := $(AT)
|
||||
else ifeq ($(V), 0)
|
||||
export V0 := $(AT)
|
||||
export V1 := $(AT)
|
||||
export V0 := $(AT)
|
||||
export V1 := $(AT)
|
||||
else ifeq ($(V), 1)
|
||||
endif
|
||||
|
||||
# Make sure we know a few things about the architecture before including
|
||||
# Make sure we know few things about the architecture before including
|
||||
# the tools.mk to ensure that we download/install the right tools.
|
||||
UNAME := $(shell uname)
|
||||
ARCH := $(shell uname -m)
|
||||
|
||||
include $(ROOT_DIR)/make/tools.mk
|
||||
|
||||
# We almost need to consider autoconf/automake instead of this
|
||||
# I don't know if windows supports uname :-(
|
||||
QT_SPEC=win32-g++
|
||||
UAVOBJGENERATOR="$(BUILD_DIR)/ground/uavobjgenerator/debug/uavobjgenerator.exe"
|
||||
ifeq ($(UNAME), Linux)
|
||||
QT_SPEC=linux-g++
|
||||
UAVOBJGENERATOR="$(BUILD_DIR)/ground/uavobjgenerator/uavobjgenerator"
|
||||
ARCH := $(shell uname -m)
|
||||
# Here and everywhere if not Linux or OSX then assume Windows
|
||||
ifeq ($(filter Linux Darwin, $(UNAME)), )
|
||||
UNAME := Windows
|
||||
endif
|
||||
ifeq ($(UNAME), Darwin)
|
||||
QT_SPEC=macx-g++
|
||||
UAVOBJGENERATOR="$(BUILD_DIR)/ground/uavobjgenerator/uavobjgenerator"
|
||||
endif
|
||||
|
||||
# OpenPilot GCS build configuration (debug | release)
|
||||
GCS_BUILD_CONF ?= debug
|
||||
|
||||
# Set up misc host tools
|
||||
RM=rm
|
||||
export ECHO := echo
|
||||
export MKDIR := mkdir
|
||||
export CP := cp
|
||||
export RM := rm
|
||||
export LN := ln
|
||||
export CAT := cat
|
||||
export SED := sed
|
||||
export TAR := tar
|
||||
export ANT := ant
|
||||
export JAVAC := javac
|
||||
export JAR := jar
|
||||
export GIT := git
|
||||
export PYTHON := python
|
||||
export INSTALL := install
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo
|
||||
@echo " This Makefile is known to work on Linux and Mac in a standard shell environment."
|
||||
@echo " It also works on Windows by following the instructions in make/winx86/README.txt."
|
||||
@echo
|
||||
@echo " Here is a summary of the available targets:"
|
||||
@echo
|
||||
@echo " [Tool Installers]"
|
||||
@echo " qt_sdk_install - Install the QT v4.7.3 tools"
|
||||
@echo " arm_sdk_install - Install the GNU ARM gcc toolchain"
|
||||
@echo " openocd_install - Install the OpenOCD JTAG daemon"
|
||||
@echo " stm32flash_install - Install the stm32flash tool for unbricking boards"
|
||||
@echo " dfuutil_install - Install the dfu-util tool for unbricking F4-based boards"
|
||||
@echo " android_sdk_install - Install the Android SDK tools"
|
||||
@echo
|
||||
@echo " [Big Hammer]"
|
||||
@echo " all - Generate UAVObjects, build openpilot firmware and gcs"
|
||||
@echo " all_flight - Build all firmware, bootloaders and bootloader updaters"
|
||||
@echo " all_fw - Build only firmware for all boards"
|
||||
@echo " all_bl - Build only bootloaders for all boards"
|
||||
@echo " all_bu - Build only bootloader updaters for all boards"
|
||||
@echo
|
||||
@echo " all_clean - Remove your build directory ($(BUILD_DIR))"
|
||||
@echo " all_flight_clean - Remove all firmware, bootloaders and bootloader updaters"
|
||||
@echo " all_fw_clean - Remove firmware for all boards"
|
||||
@echo " all_bl_clean - Remove bootlaoders for all boards"
|
||||
@echo " all_bu_clean - Remove bootloader updaters for all boards"
|
||||
@echo
|
||||
@echo " all_<board> - Build all available images for <board>"
|
||||
@echo " all_<board>_clean - Remove all available images for <board>"
|
||||
@echo
|
||||
@echo " all_ut - Build all unit tests"
|
||||
@echo " all_ut_tap - Run all unit tests and capture all TAP output to files"
|
||||
@echo " all_ut_run - Run all unit tests and dump TAP output to console"
|
||||
@echo
|
||||
@echo " [Firmware]"
|
||||
@echo " <board> - Build firmware for <board>"
|
||||
@echo " supported boards are ($(ALL_BOARDS))"
|
||||
@echo " fw_<board> - Build firmware for <board>"
|
||||
@echo " supported boards are ($(FW_BOARDS))"
|
||||
@echo " fw_<board>_clean - Remove firmware for <board>"
|
||||
@echo " fw_<board>_program - Use OpenOCD + JTAG to write firmware to <board>"
|
||||
@echo
|
||||
@echo " [Bootloader]"
|
||||
@echo " bl_<board> - Build bootloader for <board>"
|
||||
@echo " supported boards are ($(BL_BOARDS))"
|
||||
@echo " bl_<board>_clean - Remove bootloader for <board>"
|
||||
@echo " bl_<board>_program - Use OpenOCD + JTAG to write bootloader to <board>"
|
||||
@echo
|
||||
@echo " [Bootloader Updater]"
|
||||
@echo " bu_<board> - Build bootloader updater for <board>"
|
||||
@echo " supported boards are ($(BU_BOARDS))"
|
||||
@echo " bu_<board>_clean - Remove bootloader updater for <board>"
|
||||
@echo
|
||||
@echo " [Unbrick a board]"
|
||||
@echo " unbrick_<board> - Use the STM32's built in boot ROM to write a bootloader to <board>"
|
||||
@echo " supported boards are ($(BL_BOARDS))"
|
||||
@echo " [Unittests]"
|
||||
@echo " ut_<test> - Build unit test <test>"
|
||||
@echo " ut_<test>_tap - Run test and capture TAP output into a file"
|
||||
@echo " ut_<test>_run - Run test and dump TAP output to console"
|
||||
@echo
|
||||
@echo " [Simulation]"
|
||||
@echo " sim_osx - Build OpenPilot simulation firmware for OSX"
|
||||
@echo " sim_osx_clean - Delete all build output for the osx simulation"
|
||||
@echo " sim_win32 - Build OpenPilot simulation firmware for"
|
||||
@echo " Windows using mingw and msys"
|
||||
@echo " sim_win32_clean - Delete all build output for the win32 simulation"
|
||||
@echo
|
||||
@echo " [GCS]"
|
||||
@echo " gcs - Build the Ground Control System (GCS) application"
|
||||
@echo " gcs_clean - Remove the Ground Control System (GCS) application"
|
||||
@echo
|
||||
@echo " [UAVObjects]"
|
||||
@echo " uavobjects - Generate source files from the UAVObject definition XML files"
|
||||
@echo " uavobjects_test - parse xml-files - check for valid, duplicate ObjId's, ... "
|
||||
@echo " uavobjects_<group> - Generate source files from a subset of the UAVObject definition XML files"
|
||||
@echo " supported groups are ($(UAVOBJ_TARGETS))"
|
||||
@echo
|
||||
@echo " Hint: Add V=1 to your command line to see verbose build output."
|
||||
@echo
|
||||
@echo " Note: All tools will be installed into $(TOOLS_DIR)"
|
||||
@echo " All build output will be placed in $(BUILD_DIR)"
|
||||
@echo
|
||||
# Command to extract version info data from the repository and source tree
|
||||
export VERSION_INFO := $(PYTHON) "$(ROOT_DIR)/make/scripts/version-info.py" --path="$(ROOT_DIR)"
|
||||
|
||||
# Test if quotes are needed for the echo-command
|
||||
ifeq (${shell $(ECHO) "test"}, test)
|
||||
export QUOTE := '
|
||||
# This line is just to clear out the single quote above '
|
||||
else
|
||||
export QUOTE :=
|
||||
endif
|
||||
|
||||
# The tools.mk uses wget to fetch tarballs or packages
|
||||
ifeq ($(shell [ -x "$(TOOLS_DIR)/bin/wget" ] && $(ECHO) "exists"), exists)
|
||||
WGET := $(TOOLS_DIR)/bin/wget
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
WGET ?= wget
|
||||
endif
|
||||
|
||||
# Include tools installers
|
||||
include $(ROOT_DIR)/make/tools.mk
|
||||
|
||||
# Set up paths to tools
|
||||
ifeq ($(shell [ -d "$(QT_SDK_DIR)" ] && $(ECHO) "exists"), exists)
|
||||
QMAKE := $(QT_SDK_QMAKE_PATH)
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
QMAKE ?= qmake
|
||||
endif
|
||||
|
||||
ifeq ($(shell [ -d "$(ARM_SDK_DIR)" ] && $(ECHO) "exists"), exists)
|
||||
export ARM_SDK_PREFIX := $(ARM_SDK_DIR)/bin/arm-none-eabi-
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
export ARM_SDK_PREFIX ?= arm-none-eabi-
|
||||
endif
|
||||
|
||||
ifeq ($(shell [ -d "$(OPENOCD_DIR)" ] && $(ECHO) "exists"), exists)
|
||||
export OPENOCD := $(OPENOCD_DIR)/bin/openocd
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
export OPENOCD ?= openocd
|
||||
endif
|
||||
|
||||
ifeq ($(shell [ -d "$(ANDROID_SDK_DIR)" ] && $(ECHO) "exists"), exists)
|
||||
ANDROID := $(ANDROID_SDK_DIR)/tools/android
|
||||
ANDROID_DX := $(ANDROID_SDK_DIR)/platform-tools/dx
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
ANDROID ?= android
|
||||
ANDROID_DX ?= dx
|
||||
endif
|
||||
|
||||
# We almost need to consider autoconf/automake instead of this
|
||||
ifeq ($(UNAME), Linux)
|
||||
QT_SPEC = linux-g++
|
||||
UAVOBJGENERATOR = "$(BUILD_DIR)/ground/uavobjgenerator/uavobjgenerator"
|
||||
else ifeq ($(UNAME), Darwin)
|
||||
QT_SPEC = macx-g++
|
||||
UAVOBJGENERATOR = "$(BUILD_DIR)/ground/uavobjgenerator/uavobjgenerator"
|
||||
else
|
||||
QT_SPEC = win32-g++
|
||||
UAVOBJGENERATOR = "$(BUILD_DIR)/ground/uavobjgenerator/$(UAVOGEN_BUILD_CONF)/uavobjgenerator.exe"
|
||||
endif
|
||||
|
||||
##############################
|
||||
#
|
||||
# All targets
|
||||
#
|
||||
##############################
|
||||
|
||||
.PHONY: all
|
||||
all: uavobjects all_ground all_flight
|
||||
@ -178,268 +184,57 @@ all_clean:
|
||||
[ ! -d "$(BUILD_DIR)" ] || $(RM) -rf "$(BUILD_DIR)"
|
||||
|
||||
$(DL_DIR):
|
||||
mkdir -p $@
|
||||
$(MKDIR) -p $@
|
||||
|
||||
$(TOOLS_DIR):
|
||||
mkdir -p $@
|
||||
$(MKDIR) -p $@
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
$(MKDIR) -p $@
|
||||
|
||||
##############################
|
||||
#
|
||||
# Set up paths to tools
|
||||
# UAVObjects
|
||||
#
|
||||
##############################
|
||||
|
||||
ifeq ($(shell [ -d "$(QT_SDK_DIR)" ] && echo "exists"), exists)
|
||||
QMAKE = $(QT_SDK_QMAKE_PATH)
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
QMAKE = qmake
|
||||
endif
|
||||
|
||||
ifeq ($(shell [ -d "$(ARM_SDK_DIR)" ] && echo "exists"), exists)
|
||||
ARM_SDK_PREFIX := $(ARM_SDK_DIR)/bin/arm-none-eabi-
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
ARM_SDK_PREFIX ?= arm-none-eabi-
|
||||
endif
|
||||
|
||||
ifeq ($(shell [ -d "$(OPENOCD_DIR)" ] && echo "exists"), exists)
|
||||
OPENOCD := $(OPENOCD_DIR)/bin/openocd
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
OPENOCD ?= openocd
|
||||
endif
|
||||
|
||||
ifeq ($(shell [ -d "$(ANDROID_SDK_DIR)" ] && echo "exists"), exists)
|
||||
ANDROID := $(ANDROID_SDK_DIR)/tools/android
|
||||
ANDROID_DX := $(ANDROID_SDK_DIR)/platform-tools/dx
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
ANDROID ?= android
|
||||
ANDROID_DX ?= dx
|
||||
endif
|
||||
|
||||
##############################
|
||||
#
|
||||
# GCS related components
|
||||
#
|
||||
##############################
|
||||
|
||||
.PHONY: all_ground
|
||||
all_ground: openpilotgcs
|
||||
|
||||
# Convenience target for the GCS
|
||||
.PHONY: gcs gcs_clean
|
||||
gcs: openpilotgcs
|
||||
gcs_clean: openpilotgcs_clean
|
||||
|
||||
ifeq ($(V), 1)
|
||||
GCS_SILENT :=
|
||||
UAVOGEN_SILENT :=
|
||||
else
|
||||
GCS_SILENT := silent
|
||||
endif
|
||||
|
||||
.PHONY: openpilotgcs
|
||||
openpilotgcs: uavobjects_gcs
|
||||
$(V1) mkdir -p $(BUILD_DIR)/ground/$@
|
||||
$(V1) ( cd $(BUILD_DIR)/ground/$@ && \
|
||||
$(QMAKE) $(ROOT_DIR)/ground/openpilotgcs/openpilotgcs.pro -spec $(QT_SPEC) -r CONFIG+="$(GCS_BUILD_CONF) $(GCS_SILENT)" $(GCS_QMAKE_OPTS) && \
|
||||
$(MAKE) -w ; \
|
||||
)
|
||||
|
||||
.PHONY: openpilotgcs_clean
|
||||
openpilotgcs_clean:
|
||||
$(V0) @echo " CLEAN $@"
|
||||
$(V1) [ ! -d "$(BUILD_DIR)/ground/openpilotgcs" ] || $(RM) -r "$(BUILD_DIR)/ground/openpilotgcs"
|
||||
|
||||
ifeq ($(V), 1)
|
||||
UAVOGEN_SILENT :=
|
||||
else
|
||||
UAVOGEN_SILENT := silent
|
||||
UAVOGEN_SILENT := silent
|
||||
endif
|
||||
|
||||
.PHONY: uavobjgenerator
|
||||
uavobjgenerator:
|
||||
$(V1) mkdir -p $(BUILD_DIR)/ground/$@
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/ground/$@
|
||||
$(V1) ( cd $(BUILD_DIR)/ground/$@ && \
|
||||
$(QMAKE) $(ROOT_DIR)/ground/uavobjgenerator/uavobjgenerator.pro -spec $(QT_SPEC) -r CONFIG+="debug $(UAVOGEN_SILENT)" && \
|
||||
$(MAKE) --no-print-directory -w ; \
|
||||
$(QMAKE) $(ROOT_DIR)/ground/uavobjgenerator/uavobjgenerator.pro -spec $(QT_SPEC) -r CONFIG+="$(UAVOGEN_BUILD_CONF) $(UAVOGEN_SILENT)" && \
|
||||
$(MAKE) --no-print-directory -w ; \
|
||||
)
|
||||
|
||||
UAVOBJ_TARGETS := gcs flight python matlab java wireshark
|
||||
.PHONY:uavobjects
|
||||
|
||||
.PHONY: uavobjects
|
||||
uavobjects: $(addprefix uavobjects_, $(UAVOBJ_TARGETS))
|
||||
|
||||
UAVOBJ_XML_DIR := $(ROOT_DIR)/shared/uavobjectdefinition
|
||||
UAVOBJ_OUT_DIR := $(BUILD_DIR)/uavobject-synthetics
|
||||
|
||||
$(UAVOBJ_OUT_DIR):
|
||||
$(V1) mkdir -p $@
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
uavobjects_%: $(UAVOBJ_OUT_DIR) uavobjgenerator
|
||||
$(V1) ( cd $(UAVOBJ_OUT_DIR) && \
|
||||
$(UAVOBJGENERATOR) -$* $(UAVOBJ_XML_DIR) $(ROOT_DIR) ; \
|
||||
$(UAVOBJGENERATOR) -$* $(UAVOBJ_XML_DIR) $(ROOT_DIR) ; \
|
||||
)
|
||||
|
||||
uavobjects_test: $(UAVOBJ_OUT_DIR) uavobjgenerator
|
||||
$(V1) $(UAVOBJGENERATOR) -v -none $(UAVOBJ_XML_DIR) $(ROOT_DIR)
|
||||
|
||||
uavobjects_clean:
|
||||
$(V0) @echo " CLEAN $@"
|
||||
$(V0) @$(ECHO) " CLEAN $@"
|
||||
$(V1) [ ! -d "$(UAVOBJ_OUT_DIR)" ] || $(RM) -r "$(UAVOBJ_OUT_DIR)"
|
||||
|
||||
################################
|
||||
#
|
||||
# Android GCS related components
|
||||
#
|
||||
################################
|
||||
|
||||
ANDROIDGCS_BUILD_CONF ?= debug
|
||||
|
||||
# Build the output directory for the Android GCS build
|
||||
ANDROIDGCS_OUT_DIR := $(BUILD_DIR)/androidgcs
|
||||
$(ANDROIDGCS_OUT_DIR):
|
||||
$(V1) mkdir -p $@
|
||||
|
||||
# Build the asset directory for the android assets
|
||||
ANDROIDGCS_ASSETS_DIR := $(ANDROIDGCS_OUT_DIR)/assets
|
||||
$(ANDROIDGCS_ASSETS_DIR)/uavos:
|
||||
$(V1) mkdir -p $@
|
||||
|
||||
ifeq ($(V), 1)
|
||||
ANT_QUIET :=
|
||||
ANDROID_SILENT :=
|
||||
else
|
||||
ANT_QUIET := -q
|
||||
ANDROID_SILENT := -s
|
||||
endif
|
||||
.PHONY: androidgcs
|
||||
androidgcs: uavo-collections_java
|
||||
$(V0) @echo " ANDROID $(call toprel, $(ANDROIDGCS_OUT_DIR))"
|
||||
$(V1) mkdir -p $(ANDROIDGCS_OUT_DIR)
|
||||
$(V1) $(ANDROID) $(ANDROID_SILENT) update project --target 'Google Inc.:Google APIs:14' --name androidgcs --path ./androidgcs
|
||||
$(V1) ant -f ./androidgcs/build.xml \
|
||||
$(ANT_QUIET) \
|
||||
-Dout.dir="../$(call toprel, $(ANDROIDGCS_OUT_DIR)/bin)" \
|
||||
-Dgen.absolute.dir="$(ANDROIDGCS_OUT_DIR)/gen" \
|
||||
$(ANDROIDGCS_BUILD_CONF)
|
||||
|
||||
.PHONY: androidgcs_clean
|
||||
androidgcs_clean:
|
||||
$(V0) @echo " CLEAN $@"
|
||||
$(V1) [ ! -d "$(ANDROIDGCS_OUT_DIR)" ] || $(RM) -r "$(ANDROIDGCS_OUT_DIR)"
|
||||
|
||||
# We want to take snapshots of the UAVOs at each point that they change
|
||||
# to allow the GCS to be compatible with as many versions as possible.
|
||||
#
|
||||
# Find the git hashes of each commit that changes uavobjects with:
|
||||
# git log --format=%h -- shared/uavobjectdefinition/ | head -n 2
|
||||
UAVO_GIT_VERSIONS := 5e14f53
|
||||
|
||||
# All versions includes a pseudo collection called "working" which represents
|
||||
# the UAVOs in the source tree
|
||||
UAVO_ALL_VERSIONS := $(UAVO_GIT_VERSIONS) srctree
|
||||
|
||||
# This is where the UAVO collections are stored
|
||||
UAVO_COLLECTION_DIR := $(BUILD_DIR)/uavo-collections
|
||||
|
||||
# $(1) git hash of a UAVO snapshot
|
||||
define UAVO_COLLECTION_GIT_TEMPLATE
|
||||
|
||||
# Make the output directory that will contain all of the synthetics for the
|
||||
# uavo collection referenced by the git hash $(1)
|
||||
$$(UAVO_COLLECTION_DIR)/$(1):
|
||||
$$(V1) mkdir -p $$(UAVO_COLLECTION_DIR)/$(1)
|
||||
|
||||
# Extract the snapshot of shared/uavobjectdefinition from git hash $(1)
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar: | $$(UAVO_COLLECTION_DIR)/$(1)
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar:
|
||||
$$(V0) @echo " UAVOTAR $(1)"
|
||||
$$(V1) git archive $(1) -o $$@ -- shared/uavobjectdefinition/
|
||||
|
||||
# Extract the uavo xml files from our snapshot
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml: $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar
|
||||
$$(V0) @echo " UAVOUNTAR $(1)"
|
||||
$$(V1) rm -rf $$@
|
||||
$$(V1) mkdir -p $$@
|
||||
$$(V1) tar -C $$(call toprel, $$@) -xf $$(call toprel, $$<) || rm -rf $$@
|
||||
endef
|
||||
|
||||
# Map the current working directory into the set of UAVO collections
|
||||
$(UAVO_COLLECTION_DIR)/srctree:
|
||||
$(V1) mkdir -p $@
|
||||
|
||||
$(UAVO_COLLECTION_DIR)/srctree/uavo-xml: | $(UAVO_COLLECTION_DIR)/srctree
|
||||
$(UAVO_COLLECTION_DIR)/srctree/uavo-xml: $(UAVOBJ_XML_DIR)
|
||||
$(V1) ln -sf $(ROOT_DIR) $(UAVO_COLLECTION_DIR)/srctree/uavo-xml
|
||||
|
||||
# $(1) git hash (or symbolic name) of a UAVO snapshot
|
||||
define UAVO_COLLECTION_BUILD_TEMPLATE
|
||||
|
||||
# This leaves us with a (broken) symlink that points to the full sha1sum of the collection
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavohash: $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml
|
||||
# Compute the sha1 hash for this UAVO collection
|
||||
# The sed bit truncates the UAVO hash to 16 hex digits
|
||||
$$(V1) python $$(ROOT_DIR)/make/scripts/version-info.py \
|
||||
--path=$$(ROOT_DIR) \
|
||||
--uavodir=$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml/shared/uavobjectdefinition \
|
||||
--format='$$$${UAVOSHA1TXT}' | \
|
||||
sed -e 's|\(................\).*|\1|' > $$@
|
||||
|
||||
$$(V0) @echo " UAVOHASH $(1) ->" $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash)
|
||||
|
||||
# Generate the java uavobjects for this UAVO collection
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/java-build/java: $$(UAVO_COLLECTION_DIR)/$(1)/uavohash
|
||||
$$(V0) @echo " UAVOJAVA $(1) " $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash)
|
||||
$$(V1) mkdir -p $$@
|
||||
$$(V1) ( \
|
||||
cd $$(UAVO_COLLECTION_DIR)/$(1)/java-build && \
|
||||
$$(UAVOBJGENERATOR) -java $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml/shared/uavobjectdefinition $$(ROOT_DIR) ; \
|
||||
)
|
||||
|
||||
# Build a jar file for this UAVO collection
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/java-build/uavobjects.jar: | $$(ANDROIDGCS_ASSETS_DIR)/uavos
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/java-build/uavobjects.jar: $$(UAVO_COLLECTION_DIR)/$(1)/java-build/java
|
||||
$$(V0) @echo " UAVOJAR $(1) " $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash)
|
||||
$$(V1) ( \
|
||||
HASH=$$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash) && \
|
||||
cd $$(UAVO_COLLECTION_DIR)/$(1)/java-build && \
|
||||
javac java/*.java \
|
||||
$$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java \
|
||||
$$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVObject*.java \
|
||||
$$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java \
|
||||
-d . && \
|
||||
find ./org/openpilot/uavtalk/uavobjects -type f -name '*.class' > classlist.txt && \
|
||||
jar cf tmp_uavobjects.jar @classlist.txt && \
|
||||
$$(ANDROID_DX) \
|
||||
--dex \
|
||||
--output $$(ANDROIDGCS_ASSETS_DIR)/uavos/$$$${HASH}.jar \
|
||||
tmp_uavobjects.jar && \
|
||||
ln -sf $$(ANDROIDGCS_ASSETS_DIR)/uavos/$$$${HASH}.jar uavobjects.jar \
|
||||
)
|
||||
|
||||
endef
|
||||
|
||||
# One of these for each element of UAVO_GIT_VERSIONS so we can extract the UAVOs from git
|
||||
$(foreach githash, $(UAVO_GIT_VERSIONS), $(eval $(call UAVO_COLLECTION_GIT_TEMPLATE,$(githash))))
|
||||
|
||||
# One of these for each UAVO_ALL_VERSIONS which includes the ones in the srctree
|
||||
$(foreach githash, $(UAVO_ALL_VERSIONS), $(eval $(call UAVO_COLLECTION_BUILD_TEMPLATE,$(githash))))
|
||||
|
||||
.PHONY: uavo-collections_java
|
||||
uavo-collections_java: $(foreach githash, $(UAVO_ALL_VERSIONS), $(UAVO_COLLECTION_DIR)/$(githash)/java-build/uavobjects.jar)
|
||||
|
||||
.PHONY: uavo-collections
|
||||
uavo-collections: uavo-collections_java
|
||||
|
||||
.PHONY: uavo-collections_clean
|
||||
uavo-collections_clean:
|
||||
$(V0) @echo " CLEAN $(UAVO_COLLECTION_DIR)"
|
||||
$(V1) [ ! -d "$(UAVO_COLLECTION_DIR)" ] || $(RM) -r $(UAVO_COLLECTION_DIR)
|
||||
|
||||
##############################
|
||||
#
|
||||
# Flight related components
|
||||
@ -448,14 +243,75 @@ uavo-collections_clean:
|
||||
|
||||
# Define some pointers to the various important pieces of the flight code
|
||||
# to prevent these being repeated in every sub makefile
|
||||
PIOS := $(ROOT_DIR)/flight/PiOS
|
||||
FLIGHTLIB := $(ROOT_DIR)/flight/Libraries
|
||||
OPMODULEDIR := $(ROOT_DIR)/flight/Modules
|
||||
OPUAVOBJ := $(ROOT_DIR)/flight/targets/UAVObjects
|
||||
OPUAVTALK := $(ROOT_DIR)/flight/targets/UAVTalk
|
||||
HWDEFS := $(ROOT_DIR)/flight/targets/board_hw_defs
|
||||
DOXYGENDIR := $(ROOT_DIR)/flight/Doc/Doxygen
|
||||
OPUAVSYNTHDIR := $(BUILD_DIR)/uavobject-synthetics/flight
|
||||
export PIOS := $(ROOT_DIR)/flight/PiOS
|
||||
export FLIGHTLIB := $(ROOT_DIR)/flight/Libraries
|
||||
export OPMODULEDIR := $(ROOT_DIR)/flight/Modules
|
||||
export OPUAVOBJ := $(ROOT_DIR)/flight/targets/UAVObjects
|
||||
export OPUAVTALK := $(ROOT_DIR)/flight/targets/UAVTalk
|
||||
export HWDEFS := $(ROOT_DIR)/flight/targets/board_hw_defs
|
||||
export DOXYGENDIR := $(ROOT_DIR)/flight/Doc/Doxygen
|
||||
export OPUAVSYNTHDIR := $(BUILD_DIR)/uavobject-synthetics/flight
|
||||
|
||||
# Define supported board lists
|
||||
ALL_BOARDS := coptercontrol pipxtreme revolution revomini osd simposix
|
||||
ALL_BOARDS_BU := coptercontrol pipxtreme simposix
|
||||
|
||||
# Friendly names of each board (used to find source tree)
|
||||
coptercontrol_friendly := CopterControl
|
||||
pipxtreme_friendly := PipXtreme
|
||||
revolution_friendly := Revolution
|
||||
revomini_friendly := RevoMini
|
||||
osd_friendly := OSD
|
||||
simposix_friendly := SimPosix
|
||||
|
||||
# Short names of each board (used to display board name in parallel builds)
|
||||
coptercontrol_short := 'cc '
|
||||
pipxtreme_short := 'pipx'
|
||||
revolution_short := 'revo'
|
||||
revomini_short := 'rm '
|
||||
osd_short := 'osd '
|
||||
simposix_short := 'posx'
|
||||
|
||||
# SimPosix only builds on Linux so drop it from the list for
|
||||
# all other platforms.
|
||||
ifneq ($(UNAME), Linux)
|
||||
ALL_BOARDS := $(filter-out simposix, $(ALL_BOARDS))
|
||||
ALL_BOARDS_BU := $(filter-out simposix, $(ALL_BOARDS_BU))
|
||||
endif
|
||||
|
||||
# Start out assuming that we'll build fw, bl and bu for all boards
|
||||
FW_BOARDS := $(ALL_BOARDS)
|
||||
BL_BOARDS := $(ALL_BOARDS)
|
||||
BU_BOARDS := $(ALL_BOARDS_BU)
|
||||
EF_BOARDS := $(ALL_BOARDS)
|
||||
|
||||
# SimPosix doesn't have a BL, BU or EF target so we need to
|
||||
# filter them out to prevent errors on the all_flight target.
|
||||
BL_BOARDS := $(filter-out simposix, $(BL_BOARDS))
|
||||
BU_BOARDS := $(filter-out simposix, $(BU_BOARDS))
|
||||
EF_BOARDS := $(filter-out simposix, $(EF_BOARDS))
|
||||
|
||||
# Generate the targets for whatever boards are left in each list
|
||||
FW_TARGETS := $(addprefix fw_, $(FW_BOARDS))
|
||||
BL_TARGETS := $(addprefix bl_, $(BL_BOARDS))
|
||||
BU_TARGETS := $(addprefix bu_, $(BU_BOARDS))
|
||||
EF_TARGETS := $(addprefix ef_, $(EF_BOARDS))
|
||||
|
||||
# When building any of the "all_*" targets, tell all sub makefiles to display
|
||||
# additional details on each line of output to describe which build and target
|
||||
# that each line applies to. The same applies also to all, opfw_resource,
|
||||
# package and clean_package targets
|
||||
ifneq ($(strip $(filter all_% all opfw_resource package clean_package,$(MAKECMDGOALS))),)
|
||||
export ENABLE_MSG_EXTRA := yes
|
||||
endif
|
||||
|
||||
# When building more than one goal in a single make invocation, also
|
||||
# enable the extra context for each output line
|
||||
ifneq ($(word 2,$(MAKECMDGOALS)),)
|
||||
export ENABLE_MSG_EXTRA := yes
|
||||
endif
|
||||
|
||||
# TEMPLATES (used to generate build rules)
|
||||
|
||||
# $(1) = Canonical board name all in lower case (e.g. coptercontrol)
|
||||
# $(2) = Name of board used in source tree (e.g. CopterControl)
|
||||
@ -466,33 +322,22 @@ $(1): fw_$(1)_opfw
|
||||
fw_$(1): fw_$(1)_opfw
|
||||
|
||||
fw_$(1)_%: uavobjects_flight
|
||||
$(V1) mkdir -p $(BUILD_DIR)/fw_$(1)/dep
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/fw_$(1)/dep
|
||||
$(V1) cd $(ROOT_DIR)/flight/targets/$(2) && \
|
||||
$$(MAKE) -r --no-print-directory \
|
||||
BOARD_NAME=$(1) \
|
||||
BOARD_SHORT_NAME=$(3) \
|
||||
BUILD_TYPE=fw \
|
||||
TCHAIN_PREFIX="$(ARM_SDK_PREFIX)" \
|
||||
REMOVE_CMD="$(RM)" OOCD_EXE="$(OPENOCD)" \
|
||||
\
|
||||
TARGET=fw_$(1) \
|
||||
OUTDIR=$(BUILD_DIR)/fw_$(1) \
|
||||
\
|
||||
PIOS=$(PIOS) \
|
||||
FLIGHTLIB=$(FLIGHTLIB) \
|
||||
OPMODULEDIR=$(OPMODULEDIR) \
|
||||
OPUAVOBJ=$(OPUAVOBJ) \
|
||||
OPUAVTALK=$(OPUAVTALK) \
|
||||
HWDEFSINC=$(HWDEFS)/$(1) \
|
||||
DOXYGENDIR=$(DOXYGENDIR) \
|
||||
OPUAVSYNTHDIR=$(OPUAVSYNTHDIR) \
|
||||
\
|
||||
TOPDIR=$(ROOT_DIR)/flight/targets/$(2) \
|
||||
OUTDIR=$(BUILD_DIR)/fw_$(1) \
|
||||
TARGET=fw_$(1) \
|
||||
$$*
|
||||
|
||||
.PHONY: $(1)_clean
|
||||
$(1)_clean: fw_$(1)_clean
|
||||
fw_$(1)_clean:
|
||||
$(V0) @echo " CLEAN $$@"
|
||||
$(V0) @$(ECHO) " CLEAN $$@"
|
||||
$(V1) $(RM) -fr $(BUILD_DIR)/fw_$(1)
|
||||
endef
|
||||
|
||||
@ -504,46 +349,35 @@ bl_$(1): bl_$(1)_bin
|
||||
bl_$(1)_bino: bl_$(1)_bin
|
||||
|
||||
bl_$(1)_%:
|
||||
$(V1) mkdir -p $(BUILD_DIR)/bl_$(1)/dep
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/bl_$(1)/dep
|
||||
$(V1) cd $(ROOT_DIR)/flight/targets/Bootloaders/$(2) && \
|
||||
$$(MAKE) -r --no-print-directory \
|
||||
BOARD_NAME=$(1) \
|
||||
BOARD_SHORT_NAME=$(3) \
|
||||
BUILD_TYPE=bl \
|
||||
TCHAIN_PREFIX="$(ARM_SDK_PREFIX)" \
|
||||
REMOVE_CMD="$(RM)" OOCD_EXE="$(OPENOCD)" \
|
||||
\
|
||||
TARGET=bl_$(1) \
|
||||
OUTDIR=$(BUILD_DIR)/bl_$(1) \
|
||||
\
|
||||
PIOS=$(PIOS) \
|
||||
FLIGHTLIB=$(FLIGHTLIB) \
|
||||
OPMODULEDIR=$(OPMODULEDIR) \
|
||||
OPUAVOBJ=$(OPUAVOBJ) \
|
||||
OPUAVTALK=$(OPUAVTALK) \
|
||||
HWDEFSINC=$(HWDEFS)/$(1) \
|
||||
OPUAVSYNTHDIR=$(OPUAVSYNTHDIR) \
|
||||
DOXYGENDIR=$(DOXYGENDIR) \
|
||||
\
|
||||
TOPDIR=$(ROOT_DIR)/flight/targets/Bootloaders/$(2) \
|
||||
OUTDIR=$(BUILD_DIR)/bl_$(1) \
|
||||
TARGET=bl_$(1) \
|
||||
$$*
|
||||
|
||||
.PHONY: unbrick_$(1)
|
||||
unbrick_$(1): bl_$(1)_hex
|
||||
$(if $(filter-out undefined,$(origin UNBRICK_TTY)),
|
||||
$(V0) @echo " UNBRICK $(1) via $$(UNBRICK_TTY)"
|
||||
$(V0) @$(ECHO) " UNBRICK $(1) via $$(UNBRICK_TTY)"
|
||||
$(V1) $(STM32FLASH_DIR)/stm32flash \
|
||||
-w $(BUILD_DIR)/bl_$(1)/bl_$(1).hex \
|
||||
-g 0x0 \
|
||||
$$(UNBRICK_TTY)
|
||||
,
|
||||
$(V0) @echo
|
||||
$(V0) @echo "ERROR: You must specify UNBRICK_TTY=<serial-device> to use for unbricking."
|
||||
$(V0) @echo " eg. $$(MAKE) $$@ UNBRICK_TTY=/dev/ttyUSB0"
|
||||
$(V0) @$(ECHO)
|
||||
$(V0) @$(ECHO) "ERROR: You must specify UNBRICK_TTY=<serial-device> to use for unbricking."
|
||||
$(V0) @$(ECHO) " eg. $$(MAKE) $$@ UNBRICK_TTY=/dev/ttyUSB0"
|
||||
)
|
||||
|
||||
.PHONY: bl_$(1)_clean
|
||||
bl_$(1)_clean:
|
||||
$(V0) @echo " CLEAN $$@"
|
||||
$(V0) @$(ECHO) " CLEAN $$@"
|
||||
$(V1) $(RM) -fr $(BUILD_DIR)/bl_$(1)
|
||||
endef
|
||||
|
||||
@ -553,32 +387,21 @@ define BU_TEMPLATE
|
||||
bu_$(1): bu_$(1)_opfw
|
||||
|
||||
bu_$(1)_%: bl_$(1)_bino
|
||||
$(V1) mkdir -p $(BUILD_DIR)/bu_$(1)/dep
|
||||
$(V1) cd $(ROOT_DIR)/flight/targets/Bootloaders/BootloaderUpdater && \
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/bu_$(1)/dep
|
||||
$(V1) cd $(ROOT_DIR)/flight/targets/BootloaderUpdater && \
|
||||
$$(MAKE) -r --no-print-directory \
|
||||
BOARD_NAME=$(1) \
|
||||
BOARD_SHORT_NAME=$(3) \
|
||||
BUILD_TYPE=bu \
|
||||
TCHAIN_PREFIX="$(ARM_SDK_PREFIX)" \
|
||||
REMOVE_CMD="$(RM)" OOCD_EXE="$(OPENOCD)" \
|
||||
\
|
||||
TARGET=bu_$(1) \
|
||||
OUTDIR=$(BUILD_DIR)/bu_$(1) \
|
||||
\
|
||||
PIOS=$(PIOS) \
|
||||
FLIGHTLIB=$(FLIGHTLIB) \
|
||||
OPMODULEDIR=$(OPMODULEDIR) \
|
||||
OPUAVOBJ=$(OPUAVOBJ) \
|
||||
OPUAVTALK=$(OPUAVTALK) \
|
||||
HWDEFSINC=$(HWDEFS)/$(1) \
|
||||
OPUAVSYNTHDIR=$(OPUAVSYNTHDIR) \
|
||||
DOXYGENDIR=$(DOXYGENDIR) \
|
||||
\
|
||||
TOPDIR=$(ROOT_DIR)/flight/targets/BootloaderUpdater \
|
||||
OUTDIR=$(BUILD_DIR)/bu_$(1) \
|
||||
TARGET=bu_$(1) \
|
||||
$$*
|
||||
|
||||
.PHONY: bu_$(1)_clean
|
||||
bu_$(1)_clean:
|
||||
$(V0) @echo " CLEAN $$@"
|
||||
$(V0) @$(ECHO) " CLEAN $$@"
|
||||
$(V1) $(RM) -fr $(BUILD_DIR)/bu_$(1)
|
||||
endef
|
||||
|
||||
@ -588,39 +411,24 @@ define EF_TEMPLATE
|
||||
ef_$(1): ef_$(1)_bin
|
||||
|
||||
ef_$(1)_%: bl_$(1)_bin fw_$(1)_opfw
|
||||
$(V1) mkdir -p $(BUILD_DIR)/ef_$(1)/dep
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/ef_$(1)
|
||||
$(V1) cd $(ROOT_DIR)/flight/targets/EntireFlash && \
|
||||
$$(MAKE) -r --no-print-directory \
|
||||
BOARD_NAME=$(1) \
|
||||
BOARD_SHORT_NAME=$(3) \
|
||||
BUILD_TYPE=ef \
|
||||
TCHAIN_PREFIX="$(ARM_SDK_PREFIX)" \
|
||||
DFU_CMD="$(DFUUTIL_DIR)/bin/dfu-util" \
|
||||
\
|
||||
TARGET=ef_$(1) \
|
||||
TOPDIR=$(ROOT_DIR)/flight/targets/EntireFlash \
|
||||
OUTDIR=$(BUILD_DIR)/ef_$(1) \
|
||||
\
|
||||
TARGET=ef_$(1) \
|
||||
$$*
|
||||
|
||||
.PHONY: ef_$(1)_clean
|
||||
ef_$(1)_clean:
|
||||
$(V0) @echo " CLEAN $$@"
|
||||
$(V0) @$(ECHO) " CLEAN $$@"
|
||||
$(V1) $(RM) -fr $(BUILD_DIR)/ef_$(1)
|
||||
endef
|
||||
|
||||
# When building any of the "all_*" targets, tell all sub makefiles to display
|
||||
# additional details on each line of output to describe which build and target
|
||||
# that each line applies to.
|
||||
ifneq ($(strip $(filter all_%,$(MAKECMDGOALS))),)
|
||||
export ENABLE_MSG_EXTRA := yes
|
||||
endif
|
||||
|
||||
# When building more than one goal in a single make invocation, also
|
||||
# enable the extra context for each output line
|
||||
ifneq ($(word 2,$(MAKECMDGOALS)),)
|
||||
export ENABLE_MSG_EXTRA := yes
|
||||
endif
|
||||
|
||||
# $(1) = Canonical board name all in lower case (e.g. coptercontrol)
|
||||
define BOARD_PHONY_TEMPLATE
|
||||
.PHONY: all_$(1)
|
||||
@ -636,54 +444,7 @@ all_$(1)_clean: $$(addsuffix _clean, $$(filter bu_$(1), $$(BU_TARGETS)))
|
||||
all_$(1)_clean: $$(addsuffix _clean, $$(filter ef_$(1), $$(EF_TARGETS)))
|
||||
endef
|
||||
|
||||
ALL_BOARDS := coptercontrol pipxtreme revolution revomini simposix osd
|
||||
ALL_BOARDS_BU := coptercontrol pipxtreme simposix
|
||||
|
||||
# SimPosix only builds on Linux so drop it from the list for
|
||||
# all other platforms.
|
||||
ifneq ($(UNAME), Linux)
|
||||
ALL_BOARDS := $(filter-out simposix, $(ALL_BOARDS))
|
||||
ALL_BOARDS_BU := $(filter-out simposix, $(ALL_BOARDS_BU))
|
||||
endif
|
||||
|
||||
# Friendly names of each board (used to find source tree)
|
||||
coptercontrol_friendly := CopterControl
|
||||
pipxtreme_friendly := PipXtreme
|
||||
revolution_friendly := Revolution
|
||||
revomini_friendly := RevoMini
|
||||
simposix_friendly := SimPosix
|
||||
osd_friendly := OSD
|
||||
|
||||
# Short names of each board (used to display board name in parallel builds)
|
||||
coptercontrol_short := 'cc '
|
||||
pipxtreme_short := 'pipx'
|
||||
revolution_short := 'revo'
|
||||
revomini_short := 'rm '
|
||||
simposix_short := 'posx'
|
||||
osd_short := 'osd '
|
||||
|
||||
# Start out assuming that we'll build fw, bl and bu for all boards
|
||||
FW_BOARDS := $(ALL_BOARDS)
|
||||
BL_BOARDS := $(ALL_BOARDS)
|
||||
BU_BOARDS := $(ALL_BOARDS_BU)
|
||||
EF_BOARDS := $(ALL_BOARDS)
|
||||
|
||||
# FIXME: The BU image doesn't work for F4 boards so we need to
|
||||
# filter them out to prevent errors.
|
||||
BU_BOARDS := $(filter-out revolution osd, $(BU_BOARDS))
|
||||
|
||||
# SimPosix doesn't have a BL, BU or EF target so we need to
|
||||
# filter them out to prevent errors on the all_flight target.
|
||||
BL_BOARDS := $(filter-out simposix, $(BL_BOARDS))
|
||||
BU_BOARDS := $(filter-out simposix, $(BU_BOARDS))
|
||||
EF_BOARDS := $(filter-out simposix, $(EF_BOARDS))
|
||||
|
||||
# Generate the targets for whatever boards are left in each list
|
||||
FW_TARGETS := $(addprefix fw_, $(FW_BOARDS))
|
||||
BL_TARGETS := $(addprefix bl_, $(BL_BOARDS))
|
||||
BU_TARGETS := $(addprefix bu_, $(BU_BOARDS))
|
||||
EF_TARGETS := $(addprefix ef_, $(EF_BOARDS))
|
||||
|
||||
# Generate flight build rules
|
||||
.PHONY: all_fw all_fw_clean
|
||||
all_fw: $(addsuffix _opfw, $(FW_TARGETS))
|
||||
all_fw_clean: $(addsuffix _clean, $(FW_TARGETS))
|
||||
@ -707,15 +468,15 @@ all_flight_clean: all_fw_clean all_bl_clean all_bu_clean all_ef_clean
|
||||
# Expand the groups of targets for each board
|
||||
$(foreach board, $(ALL_BOARDS), $(eval $(call BOARD_PHONY_TEMPLATE,$(board))))
|
||||
|
||||
# Expand the bootloader updater rules
|
||||
$(foreach board, $(ALL_BOARDS), $(eval $(call BU_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short))))
|
||||
|
||||
# Expand the firmware rules
|
||||
$(foreach board, $(ALL_BOARDS), $(eval $(call FW_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short))))
|
||||
|
||||
# Expand the bootloader rules
|
||||
$(foreach board, $(ALL_BOARDS), $(eval $(call BL_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short))))
|
||||
|
||||
# Expand the bootloader updater rules
|
||||
$(foreach board, $(ALL_BOARDS), $(eval $(call BU_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short))))
|
||||
|
||||
# Expand the entire-flash rules
|
||||
$(foreach board, $(ALL_BOARDS), $(eval $(call EF_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short))))
|
||||
|
||||
@ -723,7 +484,7 @@ $(foreach board, $(ALL_BOARDS), $(eval $(call EF_TEMPLATE,$(board),$($(board)_fr
|
||||
sim_win32: sim_win32_exe
|
||||
|
||||
sim_win32_%: uavobjects_flight
|
||||
$(V1) mkdir -p $(BUILD_DIR)/sitl_win32
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/sitl_win32
|
||||
$(V1) $(MAKE) --no-print-directory \
|
||||
-C $(ROOT_DIR)/flight/targets/OpenPilot --file=$(ROOT_DIR)/flight/targets/OpenPilot/Makefile.win32 $*
|
||||
|
||||
@ -731,10 +492,202 @@ sim_win32_%: uavobjects_flight
|
||||
sim_osx: sim_osx_elf
|
||||
|
||||
sim_osx_%: uavobjects_flight
|
||||
$(V1) mkdir -p $(BUILD_DIR)/sim_osx
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/sim_osx
|
||||
$(V1) $(MAKE) --no-print-directory \
|
||||
-C $(ROOT_DIR)/flight/targets/Revolution --file=$(ROOT_DIR)/flight/targets/Revolution/Makefile.osx $*
|
||||
|
||||
##############################
|
||||
#
|
||||
# GCS related components
|
||||
#
|
||||
##############################
|
||||
|
||||
.PHONY: all_ground
|
||||
all_ground: openpilotgcs
|
||||
|
||||
# Convenience target for the GCS
|
||||
.PHONY: gcs gcs_clean gcs_all_clean
|
||||
gcs: openpilotgcs
|
||||
gcs_clean: openpilotgcs_clean
|
||||
gcs_all_clean: openpilotgcs_all_clean
|
||||
|
||||
ifeq ($(V), 1)
|
||||
GCS_SILENT :=
|
||||
else
|
||||
GCS_SILENT := silent
|
||||
endif
|
||||
|
||||
.PHONY: openpilotgcs
|
||||
openpilotgcs: uavobjects_gcs
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/ground/$@/$(GCS_BUILD_CONF)
|
||||
$(V1) ( cd $(BUILD_DIR)/ground/$@/$(GCS_BUILD_CONF) && \
|
||||
$(QMAKE) $(ROOT_DIR)/ground/openpilotgcs/openpilotgcs.pro -spec $(QT_SPEC) -r CONFIG+="$(GCS_BUILD_CONF) $(GCS_SILENT)" $(GCS_QMAKE_OPTS) && \
|
||||
$(MAKE) -w ; \
|
||||
)
|
||||
|
||||
.PHONY: openpilotgcs_clean
|
||||
openpilotgcs_clean:
|
||||
$(V0) @$(ECHO) " CLEAN $@"
|
||||
$(V1) [ ! -d "$(BUILD_DIR)/ground/openpilotgcs/$(GCS_BUILD_CONF)" ] || $(RM) -r "$(BUILD_DIR)/ground/openpilotgcs/$(GCS_BUILD_CONF)"
|
||||
|
||||
.PHONY: openpilotgcs_all_clean
|
||||
openpilotgcs_all_clean:
|
||||
$(V0) @$(ECHO) " CLEAN $@"
|
||||
$(V1) [ ! -d "$(BUILD_DIR)/ground/openpilotgcs" ] || $(RM) -r "$(BUILD_DIR)/ground/openpilotgcs"
|
||||
|
||||
################################
|
||||
#
|
||||
# Android GCS related components
|
||||
#
|
||||
################################
|
||||
|
||||
# Build the output directory for the Android GCS build
|
||||
ANDROIDGCS_OUT_DIR := $(BUILD_DIR)/androidgcs
|
||||
$(ANDROIDGCS_OUT_DIR):
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
# Build the asset directory for the android assets
|
||||
ANDROIDGCS_ASSETS_DIR := $(ANDROIDGCS_OUT_DIR)/assets
|
||||
$(ANDROIDGCS_ASSETS_DIR)/uavos:
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
ifeq ($(V), 1)
|
||||
ANT_QUIET :=
|
||||
ANDROID_SILENT :=
|
||||
else
|
||||
ANT_QUIET := -q
|
||||
ANDROID_SILENT := -s
|
||||
endif
|
||||
|
||||
.PHONY: androidgcs
|
||||
androidgcs: uavo-collections_java
|
||||
$(V0) @$(ECHO) " ANDROID $(call toprel, $(ANDROIDGCS_OUT_DIR))"
|
||||
$(V1) $(MKDIR) -p $(ANDROIDGCS_OUT_DIR)
|
||||
$(V1) $(ANDROID) $(ANDROID_SILENT) update project \
|
||||
--target "Google Inc.:Google APIs:$(GOOGLE_API_VERSION)" \
|
||||
--name androidgcs \
|
||||
--path ./androidgcs
|
||||
$(V1) $(ANT) -f ./androidgcs/build.xml \
|
||||
$(ANT_QUIET) \
|
||||
-Dout.dir="../$(call toprel, $(ANDROIDGCS_OUT_DIR)/bin)" \
|
||||
-Dgen.absolute.dir="$(ANDROIDGCS_OUT_DIR)/gen" \
|
||||
$(ANDROIDGCS_BUILD_CONF)
|
||||
|
||||
.PHONY: androidgcs_clean
|
||||
androidgcs_clean:
|
||||
$(V0) @$(ECHO) " CLEAN $@"
|
||||
$(V1) [ ! -d "$(ANDROIDGCS_OUT_DIR)" ] || $(RM) -r "$(ANDROIDGCS_OUT_DIR)"
|
||||
|
||||
# We want to take snapshots of the UAVOs at each point that they change
|
||||
# to allow the GCS to be compatible with as many versions as possible.
|
||||
# We always include a pseudo collection called "srctree" which represents
|
||||
# the UAVOs in the source tree. So not necessary to add current tree UAVO
|
||||
# hash here, it is always included.
|
||||
|
||||
# Find the git hashes of each commit that changes uavobjects with:
|
||||
# git log --format=%h -- shared/uavobjectdefinition/ | head -n 2
|
||||
# List only UAVO hashes of past releases, do not list current hash.
|
||||
# Past compatible versions are so far: RELEASE-12.10.2
|
||||
UAVO_GIT_VERSIONS := 5e14f53
|
||||
|
||||
# All versions includes also the current source tree UAVO hash
|
||||
UAVO_ALL_VERSIONS := $(UAVO_GIT_VERSIONS) srctree
|
||||
|
||||
# This is where the UAVO collections are stored
|
||||
UAVO_COLLECTION_DIR := $(BUILD_DIR)/uavo-collections
|
||||
|
||||
# $(1) git hash of a UAVO snapshot
|
||||
define UAVO_COLLECTION_GIT_TEMPLATE
|
||||
|
||||
# Make the output directory that will contain all of the synthetics for the
|
||||
# uavo collection referenced by the git hash $(1)
|
||||
$$(UAVO_COLLECTION_DIR)/$(1):
|
||||
$$(V1) $(MKDIR) -p $$(UAVO_COLLECTION_DIR)/$(1)
|
||||
|
||||
# Extract the snapshot of shared/uavobjectdefinition from git hash $(1)
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar: | $$(UAVO_COLLECTION_DIR)/$(1)
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar:
|
||||
$$(V0) @$(ECHO) " UAVOTAR $(1)"
|
||||
$$(V1) $(GIT) archive $(1) -o $$@ -- shared/uavobjectdefinition/
|
||||
|
||||
# Extract the uavo xml files from our snapshot
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml: $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar
|
||||
$$(V0) @$(ECHO) " UAVOUNTAR $(1)"
|
||||
$$(V1) $(RM) -rf $$@
|
||||
$$(V1) $(MKDIR) -p $$@
|
||||
$$(V1) $(TAR) -C $$(call toprel, $$@) -xf $$(call toprel, $$<) || $(RM) -rf $$@
|
||||
endef
|
||||
|
||||
# Map the current working directory into the set of UAVO collections
|
||||
$(UAVO_COLLECTION_DIR)/srctree:
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
$(UAVO_COLLECTION_DIR)/srctree/uavo-xml: | $(UAVO_COLLECTION_DIR)/srctree
|
||||
$(UAVO_COLLECTION_DIR)/srctree/uavo-xml: $(UAVOBJ_XML_DIR)
|
||||
$(V1) $(LN) -sf $(ROOT_DIR) $(UAVO_COLLECTION_DIR)/srctree/uavo-xml
|
||||
|
||||
# $(1) git hash (or symbolic name) of a UAVO snapshot
|
||||
define UAVO_COLLECTION_BUILD_TEMPLATE
|
||||
|
||||
# This leaves us with a (broken) symlink that points to the full sha1sum of the collection
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/uavohash: $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml
|
||||
# Compute the sha1 hash for this UAVO collection
|
||||
# The sed bit truncates the UAVO hash to 16 hex digits
|
||||
$$(V1) $$(VERSION_INFO) \
|
||||
--uavodir=$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml/shared/uavobjectdefinition \
|
||||
--format='$$$${UAVOSHA1TXT}' | \
|
||||
$(SED) -e 's|\(................\).*|\1|' > $$@
|
||||
|
||||
$$(V0) @$(ECHO) " UAVOHASH $(1) ->" $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash)
|
||||
|
||||
# Generate the java uavobjects for this UAVO collection
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/java-build/java: $$(UAVO_COLLECTION_DIR)/$(1)/uavohash
|
||||
$$(V0) @$(ECHO) " UAVOJAVA $(1) " $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash)
|
||||
$$(V1) $(MKDIR) -p $$@
|
||||
$$(V1) ( \
|
||||
cd $$(UAVO_COLLECTION_DIR)/$(1)/java-build && \
|
||||
$$(UAVOBJGENERATOR) -java $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml/shared/uavobjectdefinition $$(ROOT_DIR) ; \
|
||||
)
|
||||
|
||||
# Build a jar file for this UAVO collection
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/java-build/uavobjects.jar: | $$(ANDROIDGCS_ASSETS_DIR)/uavos
|
||||
$$(UAVO_COLLECTION_DIR)/$(1)/java-build/uavobjects.jar: $$(UAVO_COLLECTION_DIR)/$(1)/java-build/java
|
||||
$$(V0) @$(ECHO) " UAVOJAR $(1) " $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash)
|
||||
$$(V1) ( \
|
||||
HASH=$$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash) && \
|
||||
cd $$(UAVO_COLLECTION_DIR)/$(1)/java-build && \
|
||||
$(JAVAC) java/*.java \
|
||||
$$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java \
|
||||
$$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVObject*.java \
|
||||
$$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java \
|
||||
-d . && \
|
||||
find ./org/openpilot/uavtalk/uavobjects -type f -name '*.class' > classlist.txt && \
|
||||
$(JAR) cf tmp_uavobjects.jar @classlist.txt && \
|
||||
$$(ANDROID_DX) \
|
||||
--dex \
|
||||
--output $$(ANDROIDGCS_ASSETS_DIR)/uavos/$$$${HASH}.jar \
|
||||
tmp_uavobjects.jar && \
|
||||
$(LN) -sf $$(ANDROIDGCS_ASSETS_DIR)/uavos/$$$${HASH}.jar uavobjects.jar \
|
||||
)
|
||||
|
||||
endef
|
||||
|
||||
# One of these for each element of UAVO_GIT_VERSIONS so we can extract the UAVOs from git
|
||||
$(foreach githash, $(UAVO_GIT_VERSIONS), $(eval $(call UAVO_COLLECTION_GIT_TEMPLATE,$(githash))))
|
||||
|
||||
# One of these for each UAVO_ALL_VERSIONS which includes the ones in the srctree
|
||||
$(foreach githash, $(UAVO_ALL_VERSIONS), $(eval $(call UAVO_COLLECTION_BUILD_TEMPLATE,$(githash))))
|
||||
|
||||
.PHONY: uavo-collections_java
|
||||
uavo-collections_java: $(foreach githash, $(UAVO_ALL_VERSIONS), $(UAVO_COLLECTION_DIR)/$(githash)/java-build/uavobjects.jar)
|
||||
|
||||
.PHONY: uavo-collections
|
||||
uavo-collections: uavo-collections_java
|
||||
|
||||
.PHONY: uavo-collections_clean
|
||||
uavo-collections_clean:
|
||||
$(V0) @$(ECHO) " CLEAN $(UAVO_COLLECTION_DIR)"
|
||||
$(V1) [ ! -d "$(UAVO_COLLECTION_DIR)" ] || $(RM) -r $(UAVO_COLLECTION_DIR)
|
||||
|
||||
##############################
|
||||
#
|
||||
@ -744,10 +697,10 @@ sim_osx_%: uavobjects_flight
|
||||
|
||||
ALL_UNITTESTS := logfs
|
||||
|
||||
# Build the directory for the unit tests
|
||||
UT_OUT_DIR := $(BUILD_DIR)/unit_tests
|
||||
|
||||
$(UT_OUT_DIR):
|
||||
$(V1) mkdir -p $@
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
.PHONY: all_ut
|
||||
all_ut: $(addsuffix _elf, $(addprefix ut_, $(ALL_UNITTESTS)))
|
||||
@ -760,7 +713,7 @@ all_ut_run: $(addsuffix _run, $(addprefix ut_, $(ALL_UNITTESTS)))
|
||||
|
||||
.PHONY: all_ut_clean
|
||||
all_ut_clean:
|
||||
$(V0) @echo " CLEAN $@"
|
||||
$(V0) @$(ECHO) " CLEAN $@"
|
||||
$(V1) [ ! -d "$(UT_OUT_DIR)" ] || $(RM) -r "$(UT_OUT_DIR)"
|
||||
|
||||
# $(1) = Unit test name
|
||||
@ -769,7 +722,7 @@ define UT_TEMPLATE
|
||||
ut_$(1): ut_$(1)_run
|
||||
|
||||
ut_$(1)_%: $$(UT_OUT_DIR)
|
||||
$(V1) mkdir -p $(UT_OUT_DIR)/$(1)
|
||||
$(V1) $(MKDIR) -p $(UT_OUT_DIR)/$(1)
|
||||
$(V1) cd $(ROOT_DIR)/flight/tests/$(1) && \
|
||||
$$(MAKE) -r --no-print-directory \
|
||||
BUILD_TYPE=ut \
|
||||
@ -791,9 +744,8 @@ ut_$(1)_%: $$(UT_OUT_DIR)
|
||||
|
||||
.PHONY: ut_$(1)_clean
|
||||
ut_$(1)_clean:
|
||||
$(V0) @echo " CLEAN $(1)"
|
||||
$(V0) @$(ECHO) " CLEAN $(1)"
|
||||
$(V1) [ ! -d "$(UT_OUT_DIR)/$(1)" ] || $(RM) -r "$(UT_OUT_DIR)/$(1)"
|
||||
|
||||
endef
|
||||
|
||||
# Expand the unittest rules
|
||||
@ -803,7 +755,7 @@ $(foreach ut, $(ALL_UNITTESTS), $(eval $(call UT_TEMPLATE,$(ut))))
|
||||
# output is interleaved with the rest of the make output.
|
||||
ifneq ($(strip $(filter all_ut_run,$(MAKECMDGOALS))),)
|
||||
.NOTPARALLEL:
|
||||
$(info *NOTE* Parallel make disabled by all_ut_run target so we have sane console output)
|
||||
$(info *NOTE* Parallel make disabled by all_ut_run target so we have sane console output)
|
||||
endif
|
||||
|
||||
##############################
|
||||
@ -812,19 +764,213 @@ endif
|
||||
#
|
||||
##############################
|
||||
|
||||
.PHONY: package
|
||||
package:
|
||||
$(V1) cd $@ && $(MAKE) --no-print-directory $@
|
||||
# Firmware files to package
|
||||
PACKAGE_FW_TARGETS := $(filter-out fw_simposix, $(FW_TARGETS))
|
||||
PACKAGE_ELF_TARGETS := $(filter fw_simposix, $(FW_TARGETS))
|
||||
|
||||
.PHONY: package_resources
|
||||
package_resources:
|
||||
$(V1) cd package && $(MAKE) --no-print-directory opfw_resource
|
||||
# Rules to generate GCS resources used to embed firmware binaries into the GCS.
|
||||
# They are used later by the vehicle setup wizard to update board firmware.
|
||||
# To open a firmware image use ":/firmware/fw_coptercontrol.opfw"
|
||||
OPFW_RESOURCE := $(BUILD_DIR)/ground/opfw_resource/opfw_resource.qrc
|
||||
OPFW_RESOURCE_PREFIX := ../../../
|
||||
OPFW_FILES := $(foreach fw_targ, $(PACKAGE_FW_TARGETS), $(call toprel, $(BUILD_DIR)/$(fw_targ)/$(fw_targ).opfw))
|
||||
OPFW_CONTENTS := \
|
||||
<!DOCTYPE RCC><RCC version="1.0"> \
|
||||
<qresource prefix="/firmware"> \
|
||||
$(foreach fw_file, $(OPFW_FILES), <file alias="$(notdir $(fw_file))">$(OPFW_RESOURCE_PREFIX)$(fw_file)</file>) \
|
||||
</qresource> \
|
||||
</RCC>
|
||||
|
||||
.PHONY: opfw_resource
|
||||
opfw_resource: $(OPFW_RESOURCE)
|
||||
|
||||
$(OPFW_RESOURCE): $(FW_TARGETS)
|
||||
@$(ECHO) Generating OPFW resource file $(call toprel, $@)
|
||||
$(V1) $(MKDIR) -p $(dir $@)
|
||||
$(V1) $(ECHO) $(QUOTE)$(OPFW_CONTENTS)$(QUOTE) > $@
|
||||
|
||||
# If opfw_resource is requested, GCS should depend on it
|
||||
ifneq ($(strip $(filter opfw_resource,$(MAKECMDGOALS))),)
|
||||
$(eval openpilotgcs: | opfw_resource)
|
||||
endif
|
||||
|
||||
# Packaging targets: package, clean_package
|
||||
# - removes build directory (clean_package only)
|
||||
# - builds all firmware, opfw_resource, gcs
|
||||
# - copies firmware into a package directory
|
||||
# - calls paltform-specific packaging script
|
||||
|
||||
# Do some checks and define some values if package is requested
|
||||
ifneq ($(strip $(filter package clean_package,$(MAKECMDGOALS))),)
|
||||
# Define some variables
|
||||
export PACKAGE_LBL := $(shell $(VERSION_INFO) --format=\$${LABEL})
|
||||
export PACKAGE_NAME := OpenPilot
|
||||
export PACKAGE_SEP := -
|
||||
|
||||
# We can only package release builds
|
||||
ifneq ($(GCS_BUILD_CONF),release)
|
||||
$(error Packaging is currently supported for release builds only)
|
||||
endif
|
||||
|
||||
# Packaged GCS should depend on opfw_resource
|
||||
ifneq ($(strip $(filter package clean_package,$(MAKECMDGOALS))),)
|
||||
$(eval openpilotgcs: | opfw_resource)
|
||||
endif
|
||||
|
||||
# Clean the build directory if clean_package is requested
|
||||
ifneq ($(strip $(filter clean_package,$(MAKECMDGOALS))),)
|
||||
$(info Cleaning build directory before packaging...)
|
||||
ifneq ($(shell $(MAKE) all_clean >/dev/null 2>&1 && $(ECHO) "clean"), clean)
|
||||
$(error Cannot clean build directory)
|
||||
endif
|
||||
|
||||
.PHONY: clean_package
|
||||
clean_package: package
|
||||
endif
|
||||
endif
|
||||
|
||||
# Copy file template. Empty line before the endef is required, do not remove
|
||||
# $(1) = copy file name without extension
|
||||
# $(2) = source file extension
|
||||
# $(3) = destination file extension
|
||||
define COPY_FW_FILES
|
||||
$(V1) $(CP) "$(BUILD_DIR)/$(1)/$(1)$(2)" "$(PACKAGE_DIR)/firmware/$(1)$(PACKAGE_SEP)$(PACKAGE_LBL)$(3)"
|
||||
|
||||
endef
|
||||
|
||||
# Build and copy package files into the package directory
|
||||
# and call platform-specific packaging script
|
||||
.PHONY: package
|
||||
package: all_fw all_ground uavobjects_matlab
|
||||
@$(ECHO) "Packaging for $(UNAME) $(ARCH) into $(call toprel, $(PACKAGE_DIR)) directory"
|
||||
$(V1) [ ! -d "$(PACKAGE_DIR)" ] || $(RM) -rf "$(PACKAGE_DIR)"
|
||||
$(V1) $(MKDIR) -p "$(PACKAGE_DIR)/firmware"
|
||||
$(foreach fw_targ, $(PACKAGE_FW_TARGETS), $(call COPY_FW_FILES,$(fw_targ),.opfw,.opfw))
|
||||
$(foreach fw_targ, $(PACKAGE_ELF_TARGETS), $(call COPY_FW_FILES,$(fw_targ),.elf,))
|
||||
$(MAKE) --no-print-directory -C $(ROOT_DIR)/package --file=$(UNAME).mk $@
|
||||
|
||||
##############################
|
||||
#
|
||||
# Build info
|
||||
#
|
||||
##############################
|
||||
|
||||
.PHONY: build-info
|
||||
build-info:
|
||||
$(V1) mkdir -p $(BUILD_DIR)
|
||||
$(V1) python $(ROOT_DIR)/make/scripts/version-info.py \
|
||||
--path=$(ROOT_DIR) \
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)
|
||||
$(V1) $(VERSION_INFO) \
|
||||
--uavodir=$(ROOT_DIR)/shared/uavobjectdefinition \
|
||||
--template="make/templates/$@.txt" \
|
||||
--outfile="$(BUILD_DIR)/$@.txt"
|
||||
|
||||
##############################
|
||||
#
|
||||
# Help message, the default Makefile goal
|
||||
#
|
||||
##############################
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@$(ECHO)
|
||||
@$(ECHO) " This Makefile is known to work on Linux and Mac in a standard shell environment."
|
||||
@$(ECHO) " It also works on Windows by following the instructions in make/winx86/README.txt."
|
||||
@$(ECHO)
|
||||
@$(ECHO) " Here is a summary of the available targets:"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Tool Installers]"
|
||||
@$(ECHO) " qt_sdk_install - Install the QT development tools"
|
||||
@$(ECHO) " arm_sdk_install - Install the GNU ARM gcc toolchain"
|
||||
@$(ECHO) " openocd_install - Install the OpenOCD JTAG daemon"
|
||||
@$(ECHO) " stm32flash_install - Install the stm32flash tool for unbricking F1-based boards"
|
||||
@$(ECHO) " dfuutil_install - Install the dfu-util tool for unbricking F4-based boards"
|
||||
@$(ECHO) " android_sdk_install - Install the Android SDK tools"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Big Hammer]"
|
||||
@$(ECHO) " all - Generate UAVObjects, build openpilot firmware and gcs"
|
||||
@$(ECHO) " all_flight - Build all firmware, bootloaders and bootloader updaters"
|
||||
@$(ECHO) " all_fw - Build only firmware for all boards"
|
||||
@$(ECHO) " all_bl - Build only bootloaders for all boards"
|
||||
@$(ECHO) " all_bu - Build only bootloader updaters for all boards"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " all_clean - Remove your build directory ($(BUILD_DIR))"
|
||||
@$(ECHO) " all_flight_clean - Remove all firmware, bootloaders and bootloader updaters"
|
||||
@$(ECHO) " all_fw_clean - Remove firmware for all boards"
|
||||
@$(ECHO) " all_bl_clean - Remove bootlaoders for all boards"
|
||||
@$(ECHO) " all_bu_clean - Remove bootloader updaters for all boards"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " all_<board> - Build all available images for <board>"
|
||||
@$(ECHO) " all_<board>_clean - Remove all available images for <board>"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " all_ut - Build all unit tests"
|
||||
@$(ECHO) " all_ut_tap - Run all unit tests and capture all TAP output to files"
|
||||
@$(ECHO) " all_ut_run - Run all unit tests and dump TAP output to console"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Firmware]"
|
||||
@$(ECHO) " <board> - Build firmware for <board>"
|
||||
@$(ECHO) " supported boards are ($(ALL_BOARDS))"
|
||||
@$(ECHO) " fw_<board> - Build firmware for <board>"
|
||||
@$(ECHO) " supported boards are ($(FW_BOARDS))"
|
||||
@$(ECHO) " fw_<board>_clean - Remove firmware for <board>"
|
||||
@$(ECHO) " fw_<board>_program - Use OpenOCD + JTAG to write firmware to <board>"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Bootloader]"
|
||||
@$(ECHO) " bl_<board> - Build bootloader for <board>"
|
||||
@$(ECHO) " supported boards are ($(BL_BOARDS))"
|
||||
@$(ECHO) " bl_<board>_clean - Remove bootloader for <board>"
|
||||
@$(ECHO) " bl_<board>_program - Use OpenOCD + JTAG to write bootloader to <board>"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Entire Flash]"
|
||||
@$(ECHO) " ef_<board> - Build entire flash image for <board>"
|
||||
@$(ECHO) " supported boards are ($(EF_BOARDS))"
|
||||
@$(ECHO) " ef_<board>_clean - Remove entire flash image for <board>"
|
||||
@$(ECHO) " ef_<board>_program - Use OpenOCD + JTAG to write entire flash image to <board>"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Bootloader Updater]"
|
||||
@$(ECHO) " bu_<board> - Build bootloader updater for <board>"
|
||||
@$(ECHO) " supported boards are ($(BU_BOARDS))"
|
||||
@$(ECHO) " bu_<board>_clean - Remove bootloader updater for <board>"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Unbrick a board]"
|
||||
@$(ECHO) " unbrick_<board> - Use the STM32's built in boot ROM to write a bootloader to <board>"
|
||||
@$(ECHO) " supported boards are ($(BL_BOARDS))"
|
||||
@$(ECHO) " [Unittests]"
|
||||
@$(ECHO) " ut_<test> - Build unit test <test>"
|
||||
@$(ECHO) " ut_<test>_xml - Run test and capture XML output into a file"
|
||||
@$(ECHO) " ut_<test>_run - Run test and dump output to console"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Simulation]"
|
||||
@$(ECHO) " sim_osx - Build OpenPilot simulation firmware for OSX"
|
||||
@$(ECHO) " sim_osx_clean - Delete all build output for the osx simulation"
|
||||
@$(ECHO) " sim_win32 - Build OpenPilot simulation firmware for"
|
||||
@$(ECHO) " Windows using mingw and msys"
|
||||
@$(ECHO) " sim_win32_clean - Delete all build output for the win32 simulation"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [GCS]"
|
||||
@$(ECHO) " gcs - Build the Ground Control System (GCS) application (debug|release)"
|
||||
@$(ECHO) " gcs_clean - Remove the Ground Control System (GCS) application (debug|release)"
|
||||
@$(ECHO) " supported build configurations: GCS_BUILD_CONF=debug|release (default is $(GCS_BUILD_CONF))"
|
||||
@$(ECHO) " gcs_all_clean - Remove the Ground Control System (GCS) application (all build confgurations)"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [AndroidGCS]"
|
||||
@$(ECHO) " androidgcs - Build the Android Ground Control System (GCS) application"
|
||||
@$(ECHO) " androidgcs_install - Use ADB to install the Android GCS application"
|
||||
@$(ECHO) " androidgcs_run - Run the Android GCS application"
|
||||
@$(ECHO) " androidgcs_clean - Remove the Android GCS application"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [UAVObjects]"
|
||||
@$(ECHO) " uavobjects - Generate source files from the UAVObject definition XML files"
|
||||
@$(ECHO) " uavobjects_test - parse xml-files - check for valid, duplicate ObjId's, ... "
|
||||
@$(ECHO) " uavobjects_<group> - Generate source files from a subset of the UAVObject definition XML files"
|
||||
@$(ECHO) " supported groups are ($(UAVOBJ_TARGETS))"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Packaging]"
|
||||
@$(ECHO) " opfw_resource - Generate resources to embed firmware binaries into the GCS"
|
||||
@$(ECHO) " clean_package - Clean, build and package the OpenPilot platform-dependent package"
|
||||
@$(ECHO) " package - Build and package the OpenPilot platform-dependent package"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " Hint: Add V=1 to your command line to see verbose build output."
|
||||
@$(ECHO)
|
||||
@$(ECHO) " Note: All tools will be installed into $(TOOLS_DIR)"
|
||||
@$(ECHO) " All build output will be placed in $(BUILD_DIR)"
|
||||
@$(ECHO) " Package will be placed into $(PACKAGE_DIR)"
|
||||
@$(ECHO)
|
||||
|
@ -1,90 +0,0 @@
|
||||
// Regenerate using graphviz/dotty with this command
|
||||
// dot -Tjpg ./flight/Doc/Architecture/ahrs_spi_link_fsm.dot > ./flight/Doc/Architecture/ahrs_spi_link_fsm.jpg
|
||||
|
||||
digraph ahrs_spi_protocol {
|
||||
label="AHRS SPI Link State Machine"
|
||||
labelloc=t
|
||||
labeljust = l
|
||||
|
||||
// Stopped -- Undefined Wire State
|
||||
{
|
||||
node [ style=filled,color=lightgray ]
|
||||
|
||||
stopped [ shape="doublecircle" ]
|
||||
stopping
|
||||
}
|
||||
|
||||
// Wire State Inactive
|
||||
{
|
||||
node [ style=filled,color=lightblue ]
|
||||
|
||||
inactive
|
||||
}
|
||||
|
||||
// Wire State Busy
|
||||
{
|
||||
node [ style=filled,color=red ]
|
||||
|
||||
user_busy
|
||||
user_busy_tx_pending
|
||||
user_busy_rx_pending
|
||||
user_busy_rxtx_pending
|
||||
}
|
||||
{
|
||||
node [ style=filled,color=yellow ]
|
||||
|
||||
user_tx_pending
|
||||
user_rx_pending
|
||||
user_rxtx_pending
|
||||
}
|
||||
|
||||
// Wire State Ready
|
||||
{
|
||||
node [ style=filled,color=green ]
|
||||
|
||||
user_rx_active
|
||||
user_tx_active
|
||||
user_rxtx_active
|
||||
}
|
||||
|
||||
//
|
||||
// State transitions driven by the user
|
||||
//
|
||||
stopped -> inactive [ label="init link" ]
|
||||
|
||||
inactive -> stopping [ label="stop" ]
|
||||
inactive -> user_busy_rx_pending [ label="user set rx" ]
|
||||
inactive -> user_busy_tx_pending [ label="user set tx" ]
|
||||
|
||||
user_busy -> user_busy_tx_pending [ label="user set tx" ]
|
||||
user_busy -> user_busy_rx_pending [ label="user set rx" ]
|
||||
user_busy -> inactive [ label="user done" ]
|
||||
user_busy -> stopping [ label="stop" ]
|
||||
|
||||
user_busy_tx_pending -> user_busy_rxtx_pending [ label="user set rx" ]
|
||||
user_busy_tx_pending -> user_tx_pending [ label="user done" ]
|
||||
|
||||
user_busy_rx_pending -> user_busy_rxtx_pending [ label="user set tx" ]
|
||||
user_busy_rx_pending -> user_rx_pending [ label="user done" ]
|
||||
|
||||
user_busy_rxtx_pending -> user_rxtx_pending [ label="user done" ]
|
||||
|
||||
//
|
||||
// State transitions driven by messaging from the OP board
|
||||
//
|
||||
stopping -> stopped [ label="rx any" ]
|
||||
|
||||
user_tx_pending -> user_tx_active [ label="rx any" ]
|
||||
user_rx_pending -> user_rx_active [ label="rx any" ]
|
||||
|
||||
user_rxtx_pending -> user_rxtx_active [ label="rx any" ]
|
||||
|
||||
// Active -> Busy
|
||||
user_rx_active -> user_busy [ label="rx user" ]
|
||||
|
||||
user_tx_active -> inactive [ label="rx any" ]
|
||||
|
||||
user_rxtx_active -> user_busy [ label="rx user" ]
|
||||
user_rxtx_active -> user_rx_active [ label="rx link" ]
|
||||
user_rxtx_active -> user_rx_active [ label="rx unknown" ]
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 104 KiB |
@ -1,41 +1,75 @@
|
||||
#
|
||||
# Rules to add PYMite to a PiOS target
|
||||
# Rules to add PyMite flight plan interpreter
|
||||
#
|
||||
|
||||
PYMITE = $(FLIGHTLIB)/PyMite
|
||||
PYMITELIB = $(PYMITE)/lib
|
||||
PYMITEPLAT = $(PYMITE)/platform/openpilot
|
||||
PYMITETOOLS = $(PYMITE)/tools
|
||||
PYMITEVM = $(PYMITE)/vm
|
||||
PYMITEINC = $(PYMITEVM)
|
||||
PYMITEINC += $(PYMITEPLAT)
|
||||
PYMITEINC += $(OUTDIR)
|
||||
# Paths
|
||||
PYMITE := $(FLIGHTLIB)/PyMite
|
||||
PYMITELIB := $(PYMITE)/lib
|
||||
PYMITEPLAT := $(PYMITE)/platform/openpilot
|
||||
PYMITETOOLS := $(PYMITE)/tools
|
||||
PYMITEVM := $(PYMITE)/vm
|
||||
PYMITEINC := $(PYMITEVM)
|
||||
PYMITEINC += $(PYMITEPLAT)
|
||||
PYMITEINC += $(OUTDIR)
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
# use file-extension c for "c-only"-files
|
||||
# Flight plans
|
||||
FLIGHTPLANLIB ?= $(OPMODULEDIR)/FlightPlan/lib
|
||||
FLIGHTPLANS ?= $(OPMODULEDIR)/FlightPlan/flightplans
|
||||
|
||||
## PyMite files and modules
|
||||
SRC += $(OUTDIR)/pmlib_img.c
|
||||
SRC += $(OUTDIR)/pmlib_nat.c
|
||||
SRC += $(OUTDIR)/pmlibusr_img.c
|
||||
SRC += $(OUTDIR)/pmlibusr_nat.c
|
||||
PYSRC += $(wildcard ${PYMITEVM}/*.c)
|
||||
PYSRC += $(wildcard ${PYMITEPLAT}/*.c)
|
||||
PYSRC += ${foreach MOD, ${PYMODULES}, ${wildcard ${OPMODULEDIR}/${MOD}/*.c}}
|
||||
SRC += $(PYSRC)
|
||||
# Extra modules
|
||||
PYMODULES ?= FlightPlan
|
||||
|
||||
EXTRAINCDIRS += $(PYMITEINC)
|
||||
# Modules
|
||||
PYSRC += $(foreach mod, $(PYMODULES), $(wildcard $(OPMODULEDIR)/$(mod)/*.c))
|
||||
|
||||
# Generate intermediate code
|
||||
gencode: ${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h
|
||||
# PyMite virtual machine and platform files
|
||||
PYSRC += $(wildcard $(PYMITEVM)/*.c)
|
||||
PYSRC += $(wildcard $(PYMITEPLAT)/*.c)
|
||||
|
||||
$(PYSRC): gencode
|
||||
# Autogenerated files
|
||||
PYLIB += $(addprefix $(OUTDIR)/, pmlib_img.c pmlib_nat.c)
|
||||
PYLIB += $(addprefix $(OUTDIR)/, pmlibusr_img.c pmlibusr_nat.c)
|
||||
|
||||
PYTHON = python
|
||||
# Scripts
|
||||
PYSCRIPTS += $(wildcard $(PYMITELIB)/*.py)
|
||||
PYSCRIPTS += $(wildcard $(PYMITEPLAT)/*.py)
|
||||
PYSCRIPTS += $(wildcard $(FLIGHTPLANLIB)/*.py)
|
||||
PYSCRIPTS += $(wildcard $(FLIGHTPLANS)/*.py)
|
||||
|
||||
# Generate code for PyMite
|
||||
${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h: $(wildcard ${PYMITELIB}/*.py) $(wildcard ${PYMITEPLAT}/*.py) $(wildcard ${FLIGHTPLANLIB}/*.py) $(wildcard ${FLIGHTPLANS}/*.py)
|
||||
@echo $(MSG_PYMITEINIT) $(call toprel, $@)
|
||||
@$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -s --memspace=flash -o $(OUTDIR)/pmlib_img.c --native-file=$(OUTDIR)/pmlib_nat.c $(PYMITELIB)/list.py $(PYMITELIB)/dict.py $(PYMITELIB)/__bi.py $(PYMITELIB)/sys.py $(PYMITELIB)/string.py $(wildcard $(FLIGHTPLANLIB)/*.py)
|
||||
@$(PYTHON) $(PYMITETOOLS)/pmGenPmFeatures.py $(PYMITEPLAT)/pmfeatures.py > $(OUTDIR)/pmfeatures.h
|
||||
@$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -u -o $(OUTDIR)/pmlibusr_img.c --native-file=$(OUTDIR)/pmlibusr_nat.c $(FLIGHTPLANS)/test.py
|
||||
$(PYSRC): | $(PYLIB) $(OUTDIR)/pmfeatures.h
|
||||
|
||||
$(OUTDIR)/pmfeatures.h: $(PYSCRIPTS)
|
||||
@$(ECHO) $(MSG_PYMITEINIT) $(call toprel, $@)
|
||||
$(V1) $(PYTHON) $(PYMITETOOLS)/pmGenPmFeatures.py $(PYMITEPLAT)/pmfeatures.py > $@
|
||||
|
||||
$(OUTDIR)/pmlib_img.c: | $(OUTDIR)/pmlib_nat.c
|
||||
|
||||
$(OUTDIR)/pmlib_nat.c: $(PYSCRIPTS)
|
||||
@$(ECHO) $(MSG_PYMITEINIT) $(call toprel, $@)
|
||||
$(V1) $(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -c -s --memspace=flash \
|
||||
-f $(PYMITEPLAT)/pmfeatures.py \
|
||||
-o $(OUTDIR)/pmlib_img.c \
|
||||
--native-file=$(OUTDIR)/pmlib_nat.c \
|
||||
$(PYMITELIB)/list.py \
|
||||
$(PYMITELIB)/dict.py \
|
||||
$(PYMITELIB)/__bi.py \
|
||||
$(PYMITELIB)/sys.py \
|
||||
$(PYMITELIB)/string.py \
|
||||
$(wildcard $(FLIGHTPLANLIB)/*.py)
|
||||
|
||||
$(OUTDIR)/pmlibusr_img.c: | $(OUTDIR)/pmlibusr_nat.c
|
||||
|
||||
$(OUTDIR)/pmlibusr_nat.c: $(PYSCRIPTS)
|
||||
@$(ECHO) $(MSG_PYMITEINIT) $(call toprel, $@)
|
||||
$(V1) $(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -c -u \
|
||||
-f $(PYMITEPLAT)/pmfeatures.py \
|
||||
-o $(OUTDIR)/pmlibusr_img.c \
|
||||
--native-file=$(OUTDIR)/pmlibusr_nat.c \
|
||||
$(FLIGHTPLANS)/test.py
|
||||
|
||||
# Add to the source and include lists
|
||||
SRC += $(PYSRC)
|
||||
SRC += $(PYLIB)
|
||||
EXTRAINCDIRS += $(PYMITEINC)
|
||||
EXTRAINCDIRS += $(foreach mod, $(PYMODULES), $(OPMODULEDIR)/$(mod)/inc)
|
||||
|
@ -1,164 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ahrs_comm_objects.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief AHRS comms AUVObjects. This file defined teh objects to be used.
|
||||
*
|
||||
* @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 "pios.h"
|
||||
#include "ahrs_spi_comm.h"
|
||||
#include "pios_debug.h"
|
||||
|
||||
static AttitudeRawData AttitudeRaw;
|
||||
static AttitudeActualData AttitudeActual;
|
||||
static BaroAltitudeData BaroAltitude;
|
||||
static GPSPositionData GPSPosition;
|
||||
static HomeLocationData HomeLocation;
|
||||
static InsStatusData InsStatus;
|
||||
static InsSettingsData InsSettings;
|
||||
static FirmwareIAPObjData FirmwareIAPObj;
|
||||
static PositionActualData PositionActual;
|
||||
static VelocityActualData VelocityActual;
|
||||
static GPSSatellitesData GPSSatellites;
|
||||
static GPSTimeData GPSTime;
|
||||
|
||||
AhrsSharedObject objectHandles[MAX_AHRS_OBJECTS];
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#ifdef IN_AHRS
|
||||
|
||||
//slightly hacky - implement our own version of the xxxHandle() functions
|
||||
#define CREATEHANDLE(n,obj) \
|
||||
void * obj##Handle() {return (&objectHandles[n]);}
|
||||
|
||||
CREATEHANDLE(0, AttitudeRaw);
|
||||
CREATEHANDLE(1, AttitudeActual);
|
||||
CREATEHANDLE(2, InsSettings);
|
||||
CREATEHANDLE(3, InsStatus);
|
||||
CREATEHANDLE(4, BaroAltitude);
|
||||
CREATEHANDLE(5, GPSPosition);
|
||||
CREATEHANDLE(6, PositionActual);
|
||||
CREATEHANDLE(7, VelocityActual);
|
||||
CREATEHANDLE(8, HomeLocation);
|
||||
CREATEHANDLE(9, FirmwareIAPObj);
|
||||
CREATEHANDLE(10, GPSSatellites);
|
||||
CREATEHANDLE(11, GPSTime);
|
||||
|
||||
#if 12 != MAX_AHRS_OBJECTS //sanity check
|
||||
#error We did not create the correct number of xxxHandle() functions
|
||||
#endif
|
||||
|
||||
#define ADDHANDLE(idx,obj) {\
|
||||
int n = idx;\
|
||||
objectHandles[n].data = &obj;\
|
||||
objectHandles[n].size = sizeof(obj);\
|
||||
objectHandles[n].index = n;\
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void ObjectUpdatedCb(UAVObjEvent * ev);
|
||||
|
||||
#define ADDHANDLE(idx,obj) {\
|
||||
obj##Initialize();\
|
||||
int n = idx;\
|
||||
objectHandles[n].data = &obj;\
|
||||
objectHandles[n].uavHandle = obj##Handle();\
|
||||
objectHandles[n].size = sizeof(obj);\
|
||||
objectHandles[n].index = n;\
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void AhrsInitHandles(void)
|
||||
{
|
||||
int idx = 0;
|
||||
//Note: the first item in this list has the highest priority
|
||||
//the last has the lowest priority
|
||||
ADDHANDLE(idx++, AttitudeRaw);
|
||||
ADDHANDLE(idx++, AttitudeActual);
|
||||
ADDHANDLE(idx++, InsSettings);
|
||||
ADDHANDLE(idx++, InsStatus);
|
||||
ADDHANDLE(idx++, BaroAltitude);
|
||||
ADDHANDLE(idx++, GPSPosition);
|
||||
ADDHANDLE(idx++, PositionActual);
|
||||
ADDHANDLE(idx++, VelocityActual);
|
||||
ADDHANDLE(idx++, HomeLocation);
|
||||
ADDHANDLE(idx++, FirmwareIAPObj);
|
||||
ADDHANDLE(idx++, GPSSatellites);
|
||||
ADDHANDLE(idx++, GPSTime);
|
||||
|
||||
if (idx != MAX_AHRS_OBJECTS) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
//Note: Only connect objects that the AHRS needs to read
|
||||
//When the AHRS writes to these the data does a round trip
|
||||
//AHRS->OP->AHRS due to these events
|
||||
#ifndef IN_AHRS
|
||||
InsSettingsConnectCallback(ObjectUpdatedCb);
|
||||
HomeLocationConnectCallback(ObjectUpdatedCb);
|
||||
FirmwareIAPObjConnectCallback(ObjectUpdatedCb);
|
||||
#endif
|
||||
}
|
||||
|
||||
AhrsObjHandle AhrsFromIndex(uint8_t index)
|
||||
{
|
||||
if (index >= MAX_AHRS_OBJECTS) {
|
||||
return (NULL);
|
||||
}
|
||||
return (&objectHandles[index]);
|
||||
}
|
||||
|
||||
#ifndef IN_AHRS
|
||||
|
||||
AhrsObjHandle AhrsFromUAV(UAVObjHandle obj)
|
||||
{
|
||||
if (objectHandles[0].uavHandle == NULL) { //Oops - we haven't been initialised!
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
for (int ct = 0; ct < MAX_AHRS_OBJECTS; ct++) {
|
||||
if (objectHandles[ct].uavHandle == obj) {
|
||||
return (&objectHandles[ct]);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/** Callback to update AHRS from UAVObjects
|
||||
*/
|
||||
static void ObjectUpdatedCb(UAVObjEvent * ev)
|
||||
{
|
||||
if (!(ev->event & EV_MASK_ALL_UPDATES)) {
|
||||
return;
|
||||
}
|
||||
AhrsObjHandle hdl = AhrsFromUAV(ev->obj);
|
||||
if (hdl) {
|
||||
AhrsSharedData data; //this is guaranteed to be big enough
|
||||
UAVObjGetData(ev->obj, &data);
|
||||
AhrsSetData(hdl, &data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,452 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ahrs_spi_comm.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief AHRS SPI communications.
|
||||
*
|
||||
* @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 <pios.h>
|
||||
#include "ahrs_spi_comm.h"
|
||||
#include "ahrs_spi_program.h"
|
||||
|
||||
#ifdef IN_AHRS
|
||||
#include <string.h>
|
||||
#include "pios_debug.h"
|
||||
#include "pios_spi.h"
|
||||
#include "pios_irq.h"
|
||||
#include "ahrs_spi_program_slave.h"
|
||||
//#include "STM32103CB_AHRS.h"
|
||||
#endif
|
||||
|
||||
/*transmit and receive packet magic numbers.
|
||||
These numbers are chosen to be very unlikely to occur due to noise.
|
||||
CRC8 does not always catch noise from cross-coupling between data lines.
|
||||
*/
|
||||
#ifdef IN_AHRS
|
||||
#define TXMAGIC 0xA55AF0C3
|
||||
#define RXMAGIC 0x3C5AA50F
|
||||
#else
|
||||
#define RXMAGIC 0xA55AF0C3
|
||||
#define TXMAGIC 0x3C5AA50F
|
||||
#endif
|
||||
|
||||
//packet types
|
||||
typedef enum { COMMS_NULL, COMMS_OBJECT } COMMSCOMMAND;
|
||||
|
||||
//The maximum number of objects that can be updated in one cycle.
|
||||
//Currently the link is capable of sending 3 packets per cycle but 2 is enough
|
||||
#define MAX_UPDATE_OBJECTS 2
|
||||
|
||||
//Number of transmissions + 1 before we expect to see the data acknowledge
|
||||
//This is controlled by the SPI hardware.
|
||||
#define ACK_LATENCY 4
|
||||
|
||||
/** All data for one object
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t done;
|
||||
uint8_t index;
|
||||
AhrsSharedData object;
|
||||
} ObjectPacketData;
|
||||
|
||||
/** One complete packet.
|
||||
Other packet types are allowed for. The frame size will be the size of this
|
||||
structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t magicNumber;
|
||||
COMMSCOMMAND command;
|
||||
AhrsEndStatus status;
|
||||
union { //allow for expansion to other packet types.
|
||||
ObjectPacketData objects[MAX_UPDATE_OBJECTS];
|
||||
};
|
||||
uint8_t dummy; //For some reason comms trashes the last byte
|
||||
} CommsDataPacket;
|
||||
|
||||
static void FillObjectPacket();
|
||||
static void CommsCallback(uint8_t crc_ok, uint8_t crc_val);
|
||||
static void SetObjectDirty(const int idx);
|
||||
static void HandleObjectPacket();
|
||||
static void HandleRxPacket();
|
||||
static void PollEvents();
|
||||
#ifndef IN_AHRS
|
||||
static void SendPacket(void);
|
||||
static void AhrsUpdatedCb(AhrsObjHandle handle);
|
||||
#endif
|
||||
|
||||
/** Receive data buffer
|
||||
*/
|
||||
static CommsDataPacket rxPacket;
|
||||
|
||||
/** Transmit data buffer
|
||||
*/
|
||||
|
||||
static CommsDataPacket txPacket;
|
||||
/** Objects that have changed and so should be transmitted
|
||||
*/
|
||||
static unsigned int dirtyObjects[MAX_AHRS_OBJECTS];
|
||||
|
||||
/** Objects that have been updated at startup
|
||||
*/
|
||||
static bool readyObjects[MAX_AHRS_OBJECTS];
|
||||
|
||||
/** List of event callbacks
|
||||
*/
|
||||
static AhrsEventCallback objCallbacks[MAX_AHRS_OBJECTS];
|
||||
|
||||
/** True for objects for which new data is received and callback needs to be called
|
||||
*/
|
||||
static bool callbackPending[MAX_AHRS_OBJECTS];
|
||||
|
||||
//More than this number of errors in a row will indicate the link is down
|
||||
#define MAX_CRC_ERRORS 50
|
||||
//At least this number of good frames are needed to indicate the link is up.
|
||||
#define MIN_OK_FRAMES 50
|
||||
//At least this number of empty objects are needed before the initial flood of events is over.
|
||||
#define MIN_EMPTY_OBJECTS 10
|
||||
|
||||
static uint8_t linkOk = false;
|
||||
static int okCount = MIN_OK_FRAMES;
|
||||
static int emptyCount = MIN_EMPTY_OBJECTS;
|
||||
static bool programReceive = false;
|
||||
|
||||
void AhrsInitComms(void)
|
||||
{
|
||||
programReceive = false;
|
||||
AhrsInitHandles();
|
||||
memset(objCallbacks, 0, sizeof(AhrsEventCallback) * MAX_AHRS_OBJECTS);
|
||||
memset(callbackPending, 0, sizeof(bool) * MAX_AHRS_OBJECTS);
|
||||
memset(dirtyObjects, 0, sizeof(unsigned int) * MAX_AHRS_OBJECTS);
|
||||
memset(&txPacket, 0, sizeof(txPacket));
|
||||
memset(&rxPacket, 0, sizeof(rxPacket));
|
||||
memset(&readyObjects, 0, sizeof(bool) * MAX_AHRS_OBJECTS);
|
||||
txPacket.command = COMMS_NULL;
|
||||
rxPacket.command = COMMS_NULL;
|
||||
}
|
||||
|
||||
static uint32_t opahrs_spi_id;
|
||||
void AhrsConnect(uint32_t spi_id)
|
||||
{
|
||||
/* Bind this comms layer to the appropriate SPI id */
|
||||
opahrs_spi_id = spi_id;
|
||||
#ifndef IN_AHRS
|
||||
/* Comms already init in OP code */
|
||||
for (int ct = 0; ct < MAX_AHRS_OBJECTS; ct++) {
|
||||
AhrsObjHandle hdl = AhrsFromIndex(ct);
|
||||
if (hdl) {
|
||||
AhrsConnectCallBack(hdl, AhrsUpdatedCb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t AhrsSetData(AhrsObjHandle obj, const void *dataIn)
|
||||
{
|
||||
if (obj == NULL || dataIn == NULL || obj->data == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
if (memcmp(obj->data, dataIn, obj->size) == 0) { //nothing to do, don't generate an event
|
||||
return (0);
|
||||
}
|
||||
memcpy(obj->data, dataIn, obj->size);
|
||||
SetObjectDirty(obj->index);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int32_t AhrsGetData(AhrsObjHandle obj, void *dataOut)
|
||||
{
|
||||
|
||||
if (obj == NULL || dataOut == NULL || obj->data == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
memcpy(dataOut, obj->data, obj->size);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/** Mark an object to be sent
|
||||
*/
|
||||
void SetObjectDirty(const int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= MAX_AHRS_OBJECTS) {
|
||||
return;
|
||||
}
|
||||
dirtyObjects[idx] = ACK_LATENCY;
|
||||
}
|
||||
/** Work out what data needs to be sent.
|
||||
If an object was not sent it will be retried 4 frames later
|
||||
*/
|
||||
static void FillObjectPacket()
|
||||
{
|
||||
txPacket.command = COMMS_OBJECT;
|
||||
txPacket.magicNumber = TXMAGIC;
|
||||
int idx = 0;
|
||||
for (int ct = 0; ct < MAX_UPDATE_OBJECTS; ct++) {
|
||||
txPacket.objects[ct].index = AHRS_NO_OBJECT;
|
||||
for (; idx < MAX_AHRS_OBJECTS; idx++) {
|
||||
if (dirtyObjects[idx] > 0) {
|
||||
if (dirtyObjects[idx] == ACK_LATENCY) {
|
||||
dirtyObjects[idx]--;
|
||||
txPacket.objects[ct].index = idx;
|
||||
AhrsObjHandle hdl = AhrsFromIndex(idx);
|
||||
if (hdl) {
|
||||
memcpy(&txPacket.objects[ct].object, hdl->data, hdl->size);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
dirtyObjects[idx]--;
|
||||
if (dirtyObjects[idx] == 0) { //timed out
|
||||
dirtyObjects[idx] = ACK_LATENCY;
|
||||
txPacket.status.retries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; idx < MAX_AHRS_OBJECTS; idx++) {
|
||||
if (dirtyObjects[idx] > 0 && dirtyObjects[idx] != ACK_LATENCY) {
|
||||
dirtyObjects[idx]--;
|
||||
if (dirtyObjects[idx] == 0) { //timed out
|
||||
dirtyObjects[idx] = ACK_LATENCY;
|
||||
txPacket.status.retries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Process a received packet
|
||||
*/
|
||||
static void HandleRxPacket()
|
||||
{
|
||||
switch (rxPacket.command) {
|
||||
case COMMS_NULL:
|
||||
// Empty packet, nothing to do
|
||||
break;
|
||||
|
||||
case COMMS_OBJECT:
|
||||
HandleObjectPacket();
|
||||
break;
|
||||
|
||||
default:
|
||||
txPacket.status.invalidPacket++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Process a received UAVObject packet
|
||||
*/
|
||||
static void HandleObjectPacket()
|
||||
{
|
||||
for (int ct = 0; ct < MAX_UPDATE_OBJECTS; ct++) {
|
||||
uint8_t idx;
|
||||
|
||||
// Flag objects that have been successfully received at the other end
|
||||
idx = rxPacket.objects[ct].done;
|
||||
txPacket.objects[ct].done = AHRS_NO_OBJECT;
|
||||
if (idx < MAX_AHRS_OBJECTS) {
|
||||
|
||||
if (dirtyObjects[idx] == 1) { //this ack is the correct one for the last send
|
||||
dirtyObjects[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle received object if there is one in this packet
|
||||
idx = rxPacket.objects[ct].index;
|
||||
if (idx == AHRS_NO_OBJECT) {
|
||||
if (emptyCount > 0) {
|
||||
emptyCount--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
AhrsObjHandle obj = AhrsFromIndex(idx);
|
||||
if (obj) {
|
||||
memcpy(obj->data, &rxPacket.objects[ct].object, obj->size);
|
||||
txPacket.objects[ct].done = idx;
|
||||
callbackPending[idx] = true; // New data available, call callback
|
||||
readyObjects[idx] = true;
|
||||
} else {
|
||||
txPacket.status.invalidPacket++;
|
||||
}
|
||||
}
|
||||
#ifdef IN_AHRS
|
||||
FillObjectPacket(); //ready for the next frame
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t AhrsConnectCallBack(AhrsObjHandle obj, AhrsEventCallback cb)
|
||||
{
|
||||
if (obj == NULL || obj->data == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
objCallbacks[obj->index] = cb;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void AhrsGetStatus(AhrsCommStatus * status)
|
||||
{
|
||||
status->remote = rxPacket.status;
|
||||
status->local = txPacket.status;
|
||||
status->linkOk = linkOk;
|
||||
}
|
||||
|
||||
|
||||
/** Function called after an SPI transfer
|
||||
*/
|
||||
static void CommsCallback(uint8_t crc_ok, uint8_t crc_val)
|
||||
{
|
||||
#ifndef IN_AHRS
|
||||
PIOS_SPI_RC_PinSet(opahrs_spi_id, 1); //signal the end of the transfer
|
||||
#endif
|
||||
txPacket.command = COMMS_NULL; //we must send something so default to null
|
||||
|
||||
// While the crc is ok, there is a magic value in the received data for extra security
|
||||
if (rxPacket.magicNumber != RXMAGIC) {
|
||||
crc_ok = false;
|
||||
}
|
||||
|
||||
|
||||
if (crc_ok) {
|
||||
// The received data is OK, update link state and handle data
|
||||
if (!linkOk && okCount > 0) {
|
||||
okCount--;
|
||||
if (okCount == 0) {
|
||||
linkOk = true;
|
||||
okCount = MAX_CRC_ERRORS;
|
||||
emptyCount = MIN_EMPTY_OBJECTS;
|
||||
}
|
||||
}
|
||||
HandleRxPacket();
|
||||
} else {
|
||||
// The received data is incorrect, update state
|
||||
#ifdef IN_AHRS //AHRS - do we neeed to enter program mode?
|
||||
if (memcmp(&rxPacket, SPI_PROGRAM_REQUEST, SPI_PROGRAM_REQUEST_LENGTH) == 0)
|
||||
{
|
||||
rxPacket.magicNumber = 0;
|
||||
programReceive = true; //flag it to be executed in program space
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
txPacket.status.crcErrors++;
|
||||
if (linkOk && okCount > 0) {
|
||||
okCount--;
|
||||
if (okCount == 0) {
|
||||
linkOk = false;
|
||||
okCount = MIN_OK_FRAMES;
|
||||
}
|
||||
}
|
||||
}
|
||||
rxPacket.magicNumber = 0;
|
||||
#ifdef IN_AHRS
|
||||
/*queue next frame
|
||||
If PIOS_SPI_TransferBlock() fails for any reason, comms will stop working.
|
||||
In that case, AhrsPoll() should kick start things again.
|
||||
*/
|
||||
PIOS_SPI_TransferBlock(opahrs_spi_id, (uint8_t *) & txPacket, (uint8_t *) & rxPacket, sizeof(CommsDataPacket), &CommsCallback);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Call callbacks for object where new data is received
|
||||
*/
|
||||
static void PollEvents(void)
|
||||
{
|
||||
for (int idx = 0; idx < MAX_AHRS_OBJECTS; idx++) {
|
||||
if (objCallbacks[idx]) {
|
||||
PIOS_IRQ_Disable();
|
||||
if (callbackPending[idx]) {
|
||||
callbackPending[idx] = false;
|
||||
PIOS_IRQ_Enable();
|
||||
objCallbacks[idx] (AhrsFromIndex(idx));
|
||||
} else {
|
||||
PIOS_IRQ_Enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IN_AHRS
|
||||
void AhrsPoll()
|
||||
{
|
||||
if(programReceive)
|
||||
{
|
||||
AhrsProgramReceive(opahrs_spi_id);
|
||||
programReceive = false;
|
||||
}
|
||||
PollEvents();
|
||||
if (PIOS_SPI_Busy(opahrs_spi_id) != 0) { //Everything is working correctly
|
||||
return;
|
||||
}
|
||||
txPacket.status.kickStarts++;
|
||||
//comms have broken down - try kick starting it.
|
||||
txPacket.command = COMMS_NULL; //we must send something so default to null
|
||||
PIOS_SPI_TransferBlock(opahrs_spi_id, (uint8_t *) & txPacket, (uint8_t *) & rxPacket, sizeof(CommsDataPacket), &CommsCallback);
|
||||
}
|
||||
|
||||
bool AhrsLinkReady(void)
|
||||
{
|
||||
|
||||
for (int ct = 0; ct < MAX_AHRS_OBJECTS; ct++) {
|
||||
if (!readyObjects[ct]) {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
return (linkOk);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void AhrsSendObjects(void)
|
||||
{
|
||||
static bool oldLink = false;
|
||||
|
||||
PollEvents();
|
||||
|
||||
if (oldLink != linkOk) {
|
||||
oldLink = linkOk;
|
||||
if (linkOk) {
|
||||
for (int ct = 0; ct < MAX_AHRS_OBJECTS; ct++) {
|
||||
AhrsObjHandle hdl = AhrsFromIndex(ct);
|
||||
if (!hdl) { //paranoid - shouldn't ever happen
|
||||
continue;
|
||||
}
|
||||
AhrsSharedData data;
|
||||
UAVObjGetData(hdl->uavHandle, &data);
|
||||
AhrsSetData(hdl, &data);
|
||||
SetObjectDirty(ct); //force even unchanged data to be sent
|
||||
}
|
||||
}
|
||||
}
|
||||
FillObjectPacket();
|
||||
SendPacket();
|
||||
}
|
||||
|
||||
void SendPacket(void)
|
||||
{
|
||||
#ifndef IN_AHRS
|
||||
PIOS_SPI_RC_PinSet(opahrs_spi_id, 0);
|
||||
#endif
|
||||
//no point checking if this failed. There isn't much we could do about it if it did fail
|
||||
PIOS_SPI_TransferBlock(opahrs_spi_id, (uint8_t *) & txPacket, (uint8_t *) & rxPacket, sizeof(CommsDataPacket), &CommsCallback);
|
||||
}
|
||||
|
||||
static void AhrsUpdatedCb(AhrsObjHandle handle)
|
||||
{
|
||||
UAVObjSetData(handle->uavHandle, handle->data);
|
||||
return;
|
||||
}
|
||||
#endif
|
@ -1,95 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ahrs_comm_objects.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief AHRS SPI comms UAVObject definitions.
|
||||
*
|
||||
* @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 AHRS_COMM_OBJECTS_H
|
||||
#define AHRS_COMM_OBJECTS_H
|
||||
|
||||
#include "attitudeactual.h"
|
||||
#include "attituderaw.h"
|
||||
#include "baroaltitude.h"
|
||||
#include "gpsposition.h"
|
||||
#include "homelocation.h"
|
||||
#include "insstatus.h"
|
||||
#include "inssettings.h"
|
||||
#include "positionactual.h"
|
||||
#include "velocityactual.h"
|
||||
#include "firmwareiapobj.h"
|
||||
#include "gpsposition.h"
|
||||
#include "gpssatellites.h"
|
||||
#include "gpstime.h"
|
||||
/** union that will fit any UAVObject.
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
AttitudeRawData AttitudeRaw;
|
||||
AttitudeActualData AttitudeActual;
|
||||
InsStatusData AhrsStatus;
|
||||
BaroAltitudeData BaroAltitude;
|
||||
GPSPositionData GPSPosition;
|
||||
PositionActualData PositionActual;
|
||||
VelocityActualData VelocityActual;
|
||||
HomeLocationData HomeLocation;
|
||||
InsSettingsData InsSettings;
|
||||
FirmwareIAPObjData FirmwareIAPObj;
|
||||
GPSSatellitesData GPSSatellites;
|
||||
GPSTimeData GPSTime;
|
||||
} __attribute__ ((packed)) AhrsSharedData;
|
||||
|
||||
/** The number of UAVObjects we will be dealing with.
|
||||
*/
|
||||
#define MAX_AHRS_OBJECTS 12
|
||||
|
||||
/** Our own version of a UAVObject.
|
||||
*/
|
||||
typedef struct {
|
||||
void *data;
|
||||
int size;
|
||||
uint8_t index;
|
||||
#ifndef IN_AHRS
|
||||
UAVObjHandle uavHandle;
|
||||
#endif
|
||||
} AhrsSharedObject;
|
||||
|
||||
typedef AhrsSharedObject *AhrsObjHandle;
|
||||
|
||||
/** Initialise the object mapping.
|
||||
It is important that this is called before any of the following functions.
|
||||
*/
|
||||
void AhrsInitHandles(void);
|
||||
|
||||
/** the AHRS object related to the given index.
|
||||
Returns the AHRS object or NULL if not found
|
||||
*/
|
||||
AhrsObjHandle AhrsFromIndex(uint8_t index);
|
||||
|
||||
#ifndef IN_AHRS
|
||||
/** Get the AHRS object associated with the UAVObject.
|
||||
Returns the AHRS object or NULL if not found
|
||||
*/
|
||||
AhrsObjHandle AhrsFromUAV(UAVObjHandle obj);
|
||||
#endif
|
||||
|
||||
#endif //#ifndef AHRS_COMMS_OBJECTS_H
|
@ -1,136 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ahrs_spi_comm.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Include file of the AHRS SPI comms exposed functionality.
|
||||
*
|
||||
* @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 AHRS_SPI_COMM_H_INCLUDED
|
||||
#define AHRS_SPI_COMM_H_INCLUDED
|
||||
|
||||
#ifdef IN_AHRS //AHRS only
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/** Redirect UAVObjGetData call
|
||||
*/
|
||||
#define UAVObjGetData(obj, data) AhrsGetData(obj, data)
|
||||
|
||||
/** Redirect UAVObjSetData call
|
||||
*/
|
||||
#define UAVObjSetData(obj, data) AhrsSetData(obj, data)
|
||||
|
||||
/** Redirect UAVObjConnectCallback call
|
||||
Note: in AHRS, mask is unused because there is only one event type
|
||||
*/
|
||||
#define UAVObjConnectCallback(obj, callback, mask) AhrsConnectCallBack(obj,callback)
|
||||
|
||||
/** define our own UAVObjHandle
|
||||
*/
|
||||
typedef void *UAVObjHandle;
|
||||
|
||||
#else
|
||||
|
||||
#include "openpilot.h"
|
||||
#include "uavobjectmanager.h"
|
||||
|
||||
#endif
|
||||
|
||||
#define AHRS_NO_OBJECT 0xff
|
||||
|
||||
#include "ahrs_comm_objects.h"
|
||||
|
||||
/** Status of each end of the link
|
||||
*/
|
||||
typedef struct { //try to keep this short and in multiples of 4 bytes
|
||||
uint8_t kickStarts; //AHRS end only
|
||||
uint8_t crcErrors;
|
||||
uint8_t retries;
|
||||
uint8_t invalidPacket;
|
||||
} AhrsEndStatus;
|
||||
|
||||
/** AHRS comms status
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t linkOk;
|
||||
AhrsEndStatus remote;
|
||||
AhrsEndStatus local;
|
||||
} AhrsCommStatus;
|
||||
|
||||
/** Event callback, this function is called when an object changes.
|
||||
*/
|
||||
typedef void (*AhrsEventCallback) (AhrsObjHandle obj);
|
||||
|
||||
/** Initialise comms.
|
||||
Note: this must be called before you do anything else.
|
||||
Comms will not start until the first call to AhrsPoll() or
|
||||
AhrsSendObjects()
|
||||
*/
|
||||
void AhrsInitComms(void);
|
||||
|
||||
/** Connect Comms to a specific SPI interface instance.
|
||||
*/
|
||||
void AhrsConnect(uint32_t spi_id);
|
||||
|
||||
/** AHRS version of UAVObject xxxSetData.
|
||||
Returns: 0 if ok, -1 if an error
|
||||
*/
|
||||
int32_t AhrsSetData(AhrsObjHandle obj, const void *dataIn);
|
||||
|
||||
/** AHRS version of UAVObject xxxGetData.
|
||||
Returns: 0 if ok, -1 if an error
|
||||
*/
|
||||
int32_t AhrsGetData(AhrsObjHandle obj, void *dataOut);
|
||||
|
||||
/** Connect a callback for any changes to AHRS data.
|
||||
Returns: 0 if ok, -1 if an error
|
||||
*/
|
||||
int32_t AhrsConnectCallBack(AhrsObjHandle obj, AhrsEventCallback cb);
|
||||
|
||||
/** Get the current link status.
|
||||
Returns: the status.
|
||||
Note: the remote status will only be valid if the link is up and running
|
||||
*/
|
||||
void AhrsGetStatus(AhrsCommStatus * status);
|
||||
|
||||
#ifdef IN_AHRS //slave only
|
||||
/** Send the latest objects to the OP
|
||||
This also polls any pending events and kick starts the DMA
|
||||
if needed
|
||||
*/
|
||||
void AhrsPoll();
|
||||
|
||||
/** Check if the link is up and we have received the first batch of updates
|
||||
Returns: True if the link is up and all objects are up to date
|
||||
*/
|
||||
bool AhrsLinkReady();
|
||||
|
||||
#else //master only
|
||||
|
||||
/** Send the latest objects to the AHRS
|
||||
This also polls any pending events
|
||||
*/
|
||||
void AhrsSendObjects(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif //#ifndef AHRS_SPI_COMM_H_INCLUDED
|
@ -80,7 +80,7 @@ void VelBaroCorrection(float Vel[3], float BaroAlt);
|
||||
uint16_t ins_get_num_states();
|
||||
|
||||
// Nav structure containing current solution
|
||||
struct NavStruct {
|
||||
extern struct NavStruct {
|
||||
float Pos[3]; // Position in meters and relative to a local NED frame
|
||||
float Vel[3]; // Velocity in meters and in NED
|
||||
float q[4]; // unit quaternion rotation relative to NED
|
||||
|
@ -66,6 +66,9 @@ float P[NUMX][NUMX], X[NUMX]; // covariance matrix and state vector
|
||||
float Q[NUMW], R[NUMV]; // input noise and measurement noise variances
|
||||
float K[NUMX][NUMV]; // feedback gain matrix
|
||||
|
||||
// Global variables
|
||||
struct NavStruct Nav;
|
||||
|
||||
// ************* Exposed Functions ****************
|
||||
// *************************************************
|
||||
|
||||
|
@ -3,26 +3,26 @@
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
*
|
||||
* @file printf-stdarg.c
|
||||
* @file printf-stdarg.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief Formatted print functions
|
||||
* @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
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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.,
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
9
flight/Libraries/rscode/library.mk
Normal file
9
flight/Libraries/rscode/library.mk
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Rules to add RSCODE to a PiOS target
|
||||
#
|
||||
|
||||
RSCODE_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
RSCODE_SRC := berlekamp.c crcgen.c galois.c rs.c
|
||||
|
||||
SRC += $(addprefix $(RSCODE_DIR),$(RSCODE_SRC))
|
||||
EXTRAINCDIRS += $(RSCODE_DIR)
|
@ -47,7 +47,7 @@ int32_t TaskMonitorInitialize(void)
|
||||
lock = xSemaphoreCreateRecursiveMutex();
|
||||
memset(handles, 0, sizeof(xTaskHandle)*TASKINFO_RUNNING_NUMELEM);
|
||||
lastMonitorTime = 0;
|
||||
#if defined(DIAG_TASKS)
|
||||
#ifdef DIAG_TASKS
|
||||
lastMonitorTime = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
#endif
|
||||
return 0;
|
||||
@ -104,7 +104,7 @@ bool TaskMonitorQueryRunning(TaskInfoRunningElem task)
|
||||
*/
|
||||
void TaskMonitorUpdateAll(void)
|
||||
{
|
||||
#if defined(DIAG_TASKS)
|
||||
#ifdef DIAG_TASKS
|
||||
TaskInfoData data;
|
||||
int n;
|
||||
|
||||
|
@ -1,143 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup OpenPilotModules OpenPilot Modules
|
||||
* @{
|
||||
* @addtogroup AHRSCommsModule AHRSComms Module
|
||||
* @brief Handles communication with AHRS and updating position
|
||||
* Specifically updates the the @ref AttitudeActual "AttitudeActual" and @ref AttitudeRaw "AttitudeRaw" settings objects
|
||||
* @{
|
||||
*
|
||||
* @file ahrs_comms.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Module to handle all comms to the AHRS on a periodic basis.
|
||||
*
|
||||
* @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: As defined in PiOS/inc/pios_ahrs_comms.h
|
||||
* Output objects: As defined in PiOS/inc/pios_ahrs_comms.h
|
||||
*
|
||||
* This module will periodically update the values of latest attitude solution
|
||||
* and other objects that are transferred to and from the AHRS
|
||||
* The module settings can configure how often AHRS is polled for a new solution.
|
||||
*
|
||||
* The module executes in its own thread.
|
||||
*
|
||||
* 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 "ahrs_comms.h"
|
||||
#include "ahrs_spi_comm.h"
|
||||
#include "insstatus.h"
|
||||
|
||||
// Private constants
|
||||
#define STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
#define TASK_PRIORITY (tskIDLE_PRIORITY+4)
|
||||
|
||||
// Private types
|
||||
|
||||
// Private variables
|
||||
static xTaskHandle taskHandle;
|
||||
|
||||
// Private functions
|
||||
static void ahrscommsTask(void *parameters);
|
||||
|
||||
/**
|
||||
* Initialise the module, called on startup
|
||||
* \returns 0 on success or -1 if initialisation failed
|
||||
*/
|
||||
int32_t AHRSCommsStart(void)
|
||||
{
|
||||
// Start main task
|
||||
xTaskCreate(ahrscommsTask, (signed char *)"AHRSComms", STACK_SIZE, NULL, TASK_PRIORITY, &taskHandle);
|
||||
TaskMonitorAdd(TASKINFO_RUNNING_AHRSCOMMS, taskHandle);
|
||||
PIOS_WDG_RegisterFlag(PIOS_WDG_AHRS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the module, called on startup
|
||||
* \returns 0 on success or -1 if initialisation failed
|
||||
*/
|
||||
int32_t AHRSCommsInitialize(void)
|
||||
{
|
||||
InsStatusInitialize();
|
||||
InsSettingsInitialize();
|
||||
AttitudeRawInitialize();
|
||||
AttitudeActualInitialize();
|
||||
VelocityActualInitialize();
|
||||
PositionActualInitialize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
MODULE_INITCALL(AHRSCommsInitialize, AHRSCommsStart)
|
||||
|
||||
/**
|
||||
* Module thread, should not return.
|
||||
*/
|
||||
static void ahrscommsTask(void *parameters)
|
||||
{
|
||||
portTickType lastSysTime;
|
||||
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_AHRSCOMMS, SYSTEMALARMS_ALARM_CRITICAL);
|
||||
|
||||
// Main task loop
|
||||
while (1) {
|
||||
PIOS_WDG_UpdateFlag(PIOS_WDG_AHRS);
|
||||
AhrsCommStatus stat;
|
||||
|
||||
AhrsSendObjects();
|
||||
AhrsGetStatus(&stat);
|
||||
if (stat.linkOk) {
|
||||
AlarmsClear(SYSTEMALARMS_ALARM_AHRSCOMMS);
|
||||
} else {
|
||||
AlarmsSet(SYSTEMALARMS_ALARM_AHRSCOMMS, SYSTEMALARMS_ALARM_WARNING);
|
||||
}
|
||||
InsStatusData sData;
|
||||
InsStatusGet(&sData);
|
||||
|
||||
sData.LinkRunning = stat.linkOk;
|
||||
sData.AhrsKickstarts = stat.remote.kickStarts;
|
||||
sData.AhrsCrcErrors = stat.remote.crcErrors;
|
||||
sData.AhrsRetries = stat.remote.retries;
|
||||
sData.AhrsInvalidPackets = stat.remote.invalidPacket;
|
||||
sData.OpCrcErrors = stat.local.crcErrors;
|
||||
sData.OpRetries = stat.local.retries;
|
||||
sData.OpInvalidPackets = stat.local.invalidPacket;
|
||||
|
||||
InsStatusSet(&sData);
|
||||
/* Wait for the next update interval */
|
||||
vTaskDelayUntil(&lastSysTime, 2 / portTICK_RATE_MS);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
@ -1,37 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup OpenPilotModules OpenPilot Modules
|
||||
* @{
|
||||
* @addtogroup AHRSCommsModule AHRSComms Module
|
||||
* @{
|
||||
*
|
||||
* @file ahrs_comms.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Module to handle all comms to the AHRS on a periodic basis.
|
||||
*
|
||||
* @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 AHRS_COMMS_H
|
||||
#define AHRS_COMMS_H
|
||||
|
||||
#include "openpilot.h"
|
||||
|
||||
int32_t AHRSCommsInitialize(void);
|
||||
|
||||
#endif // AHRS_COMMS_H
|
@ -128,7 +128,7 @@ int32_t ActuatorInitialize()
|
||||
// Primary output of this module
|
||||
ActuatorCommandInitialize();
|
||||
|
||||
#if defined(MIXERSTATUS_DIAGNOSTICS)
|
||||
#ifdef DIAG_MIXERSTATUS
|
||||
// UAVO only used for inspecting the internal status of the mixer during debug
|
||||
MixerStatusInitialize();
|
||||
#endif
|
||||
@ -218,7 +218,7 @@ static void actuatorTask(void* parameters)
|
||||
ActuatorDesiredGet(&desired);
|
||||
ActuatorCommandGet(&command);
|
||||
|
||||
#if defined(MIXERSTATUS_DIAGNOSTICS)
|
||||
#ifdef DIAG_MIXERSTATUS
|
||||
MixerStatusGet(&mixerStatus);
|
||||
#endif
|
||||
int nMixers = 0;
|
||||
@ -379,7 +379,7 @@ static void actuatorTask(void* parameters)
|
||||
// Update in case read only (eg. during servo configuration)
|
||||
ActuatorCommandGet(&command);
|
||||
|
||||
#if defined(MIXERSTATUS_DIAGNOSTICS)
|
||||
#ifdef DIAG_MIXERSTATUS
|
||||
MixerStatusSet(&mixerStatus);
|
||||
#endif
|
||||
|
||||
|
@ -92,7 +92,7 @@ int32_t AltitudeStart()
|
||||
*/
|
||||
int32_t AltitudeInitialize()
|
||||
{
|
||||
#ifdef MODULE_Altitude_BUILTIN
|
||||
#ifdef MODULE_ALTITUDE_BUILTIN
|
||||
altitudeEnabled = 1;
|
||||
#else
|
||||
HwSettingsInitialize();
|
||||
|
@ -94,7 +94,7 @@ int32_t CameraStabInitialize(void)
|
||||
{
|
||||
bool cameraStabEnabled;
|
||||
|
||||
#ifdef MODULE_CameraStab_BUILTIN
|
||||
#ifdef MODULE_CAMERASTAB_BUILTIN
|
||||
cameraStabEnabled = true;
|
||||
#else
|
||||
uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM];
|
||||
|
@ -94,7 +94,7 @@ static int32_t comUsbBridgeInitialize(void)
|
||||
usart_port = PIOS_COM_BRIDGE;
|
||||
vcp_port = PIOS_COM_VCP;
|
||||
|
||||
#ifdef MODULE_ComUsbBridge_BUILTIN
|
||||
#ifdef MODULE_COMUSBBRIDGE_BUILTIN
|
||||
bridge_enabled = true;
|
||||
#else
|
||||
HwSettingsInitialize();
|
||||
|
@ -87,7 +87,7 @@ int32_t MagBaroStart()
|
||||
*/
|
||||
int32_t MagBaroInitialize()
|
||||
{
|
||||
#ifdef MODULE_MagBaro_BUILTIN
|
||||
#ifdef MODULE_MAGBARO_BUILTIN
|
||||
magbaroEnabled = 1;
|
||||
#else
|
||||
HwSettingsInitialize();
|
||||
|
@ -40,7 +40,7 @@ static uint8_t active_fault;
|
||||
|
||||
static int32_t fault_initialize(void)
|
||||
{
|
||||
#ifdef MODULE_Fault_BUILTIN
|
||||
#ifdef MODULE_FAULT_BUILTIN
|
||||
module_enabled = true;
|
||||
#else
|
||||
HwSettingsInitialize();
|
||||
|
@ -75,7 +75,7 @@ struct overosync *overosync;
|
||||
int32_t OveroSyncInitialize(void)
|
||||
{
|
||||
|
||||
#ifdef MODULE_OVERO_BUILTIN
|
||||
#ifdef MODULE_OVEROSYNC_BUILTIN
|
||||
overoEnabled = true;
|
||||
#else
|
||||
|
||||
|
@ -120,7 +120,7 @@ int32_t StabilizationInitialize()
|
||||
// Initialize variables
|
||||
StabilizationSettingsInitialize();
|
||||
ActuatorDesiredInitialize();
|
||||
#if defined(RATEDESIRED_DIAGNOSTICS)
|
||||
#ifdef DIAG_RATEDESIRED
|
||||
RateDesiredInitialize();
|
||||
#endif
|
||||
|
||||
@ -173,7 +173,7 @@ static void stabilizationTask(void* parameters)
|
||||
StabilizationDesiredGet(&stabDesired);
|
||||
AttitudeActualGet(&attitudeActual);
|
||||
GyrosGet(&gyrosData);
|
||||
#if defined(RATEDESIRED_DIAGNOSTICS)
|
||||
#ifdef DIAG_RATEDESIRED
|
||||
RateDesiredGet(&rateDesired);
|
||||
#endif
|
||||
|
||||
@ -350,7 +350,7 @@ static void stabilizationTask(void* parameters)
|
||||
if (settings.VbarPiroComp == STABILIZATIONSETTINGS_VBARPIROCOMP_TRUE)
|
||||
stabilization_virtual_flybar_pirocomp(gyro_filtered[2], dT);
|
||||
|
||||
#if defined(RATEDESIRED_DIAGNOSTICS)
|
||||
#ifdef DIAG_RATEDESIRED
|
||||
RateDesiredSet(&rateDesired);
|
||||
#endif
|
||||
|
||||
|
@ -92,7 +92,7 @@ static void hwSettingsUpdatedCb(UAVObjEvent * ev);
|
||||
static void updateStats();
|
||||
static void updateSystemAlarms();
|
||||
static void systemTask(void *parameters);
|
||||
#if defined(I2C_WDG_STATS_DIAGNOSTICS)
|
||||
#ifdef DIAG_I2C_WDG_STATS
|
||||
static void updateI2Cstats();
|
||||
static void updateWDGstats();
|
||||
#endif
|
||||
@ -125,10 +125,10 @@ int32_t SystemModInitialize(void)
|
||||
SystemStatsInitialize();
|
||||
FlightStatusInitialize();
|
||||
ObjectPersistenceInitialize();
|
||||
#if defined(DIAG_TASKS)
|
||||
#ifdef DIAG_TASKS
|
||||
TaskInfoInitialize();
|
||||
#endif
|
||||
#if defined(I2C_WDG_STATS_DIAGNOSTICS)
|
||||
#ifdef DIAG_I2C_WDG_STATS
|
||||
I2CStatsInitialize();
|
||||
WatchdogStatusInitialize();
|
||||
#endif
|
||||
@ -181,12 +181,12 @@ static void systemTask(void *parameters)
|
||||
|
||||
// Update the system alarms
|
||||
updateSystemAlarms();
|
||||
#if defined(I2C_WDG_STATS_DIAGNOSTICS)
|
||||
#ifdef DIAG_I2C_WDG_STATS
|
||||
updateI2Cstats();
|
||||
updateWDGstats();
|
||||
#endif
|
||||
|
||||
#if defined(DIAG_TASKS)
|
||||
#ifdef DIAG_TASKS
|
||||
// Update the task status object
|
||||
TaskMonitorUpdateAll();
|
||||
#endif
|
||||
@ -334,7 +334,7 @@ static void hwSettingsUpdatedCb(UAVObjEvent * ev)
|
||||
/**
|
||||
* Called periodically to update the I2C statistics
|
||||
*/
|
||||
#if defined(I2C_WDG_STATS_DIAGNOSTICS)
|
||||
#ifdef DIAG_I2C_WDG_STATS
|
||||
static void updateI2Cstats()
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_I2C)
|
||||
|
@ -1,243 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_board.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Defines board hardware for the OpenPilot Version 1.1 hardware.
|
||||
* @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 STM32103CB_AHRS_H_
|
||||
#define STM32103CB_AHRS_H_
|
||||
|
||||
//------------------------
|
||||
// Timers and Channels Used
|
||||
//------------------------
|
||||
/*
|
||||
Timer | Channel 1 | Channel 2 | Channel 3 | Channel 4
|
||||
------+-----------+-----------+-----------+----------
|
||||
TIM1 | | | |
|
||||
TIM2 | --------------- PIOS_DELAY -----------------
|
||||
TIM3 | | | |
|
||||
TIM4 | | | |
|
||||
TIM5 | | | |
|
||||
TIM6 | | | |
|
||||
TIM7 | | | |
|
||||
TIM8 | | | |
|
||||
------+-----------+-----------+-----------+----------
|
||||
*/
|
||||
|
||||
//------------------------
|
||||
// DMA Channels Used
|
||||
//------------------------
|
||||
/* Channel 1 - */
|
||||
/* Channel 2 - */
|
||||
/* Channel 3 - */
|
||||
/* Channel 4 - */
|
||||
/* Channel 5 - */
|
||||
/* Channel 6 - */
|
||||
/* Channel 7 - */
|
||||
/* Channel 8 - */
|
||||
/* Channel 9 - */
|
||||
/* Channel 10 - */
|
||||
/* Channel 11 - */
|
||||
/* Channel 12 - */
|
||||
|
||||
|
||||
//------------------------
|
||||
// BOOTLOADER_SETTINGS
|
||||
//------------------------
|
||||
#define BOARD_READABLE TRUE
|
||||
#define BOARD_WRITABLE TRUE
|
||||
#define MAX_DEL_RETRYS 3
|
||||
|
||||
//------------------------
|
||||
// PIOS_LED
|
||||
//------------------------
|
||||
#define PIOS_LED_HEARTBEAT 0
|
||||
|
||||
//-------------------------
|
||||
// System Settings
|
||||
//-------------------------
|
||||
#define PIOS_MASTER_CLOCK 72000000
|
||||
#define PIOS_PERIPHERAL_CLOCK (PIOS_MASTER_CLOCK / 2)
|
||||
|
||||
//-------------------------
|
||||
// Interrupt Priorities
|
||||
//-------------------------
|
||||
#define PIOS_IRQ_PRIO_LOW 12 // lower than RTOS
|
||||
#define PIOS_IRQ_PRIO_MID 8 // higher than RTOS
|
||||
#define PIOS_IRQ_PRIO_HIGH 5 // for SPI, ADC, I2C etc...
|
||||
#define PIOS_IRQ_PRIO_HIGHEST 4 // for USART etc...
|
||||
|
||||
//------------------------
|
||||
// PIOS_I2C
|
||||
// See also pios_board.c
|
||||
//------------------------
|
||||
#define PIOS_I2C_MAX_DEVS 1
|
||||
extern uint32_t pios_i2c_main_adapter_id;
|
||||
#define PIOS_I2C_MAIN_ADAPTER (pios_i2c_main_adapter_id)
|
||||
|
||||
//-------------------------
|
||||
// SPI
|
||||
//
|
||||
// See also pios_board.c
|
||||
//-------------------------
|
||||
#define PIOS_SPI_MAX_DEVS 1
|
||||
|
||||
//-------------------------
|
||||
// PIOS_USART
|
||||
//-------------------------
|
||||
#define PIOS_USART_MAX_DEVS 2
|
||||
|
||||
//-------------------------
|
||||
// PIOS_COM
|
||||
//
|
||||
// See also pios_board.c
|
||||
//-------------------------
|
||||
#define PIOS_COM_MAX_DEVS 2
|
||||
|
||||
extern uint32_t pios_com_aux_id;
|
||||
#define PIOS_COM_AUX (pios_com_aux_id)
|
||||
#define PIOS_COM_DEBUG PIOS_COM_AUX
|
||||
|
||||
//-------------------------
|
||||
// ADC
|
||||
// PIOS_ADC_PinGet(0) = Accel Z
|
||||
// PIOS_ADC_PinGet(2) = Accel Y
|
||||
// PIOS_ADC_PinGet(4) = Accel X
|
||||
// PIOS_ADC_PinGet(1) = Gyro X
|
||||
// PIOS_ADC_PinGet(3) = Gyro Y
|
||||
// PIOS_ADC_PinGet(5) = Gyro Z
|
||||
// PIOS_ADC_PinGet(6) = XY Temp
|
||||
// PIOS_ADC_PinGet(7) = Z Temp
|
||||
//-------------------------
|
||||
//#define PIOS_ADC_OVERSAMPLING_RATE 1
|
||||
#define PIOS_ADC_USE_TEMP_SENSOR 0
|
||||
#define PIOS_ADC_TEMP_SENSOR_ADC ADC1
|
||||
#define PIOS_ADC_TEMP_SENSOR_ADC_CHANNEL 1
|
||||
|
||||
#define PIOS_ADC_PIN1_GPIO_PORT GPIOA // PA2 (Accel X)
|
||||
#define PIOS_ADC_PIN1_GPIO_PIN GPIO_Pin_2 // ADC12_IN2
|
||||
#define PIOS_ADC_PIN1_GPIO_CHANNEL ADC_Channel_2
|
||||
#define PIOS_ADC_PIN1_ADC ADC1
|
||||
#define PIOS_ADC_PIN1_ADC_NUMBER 1
|
||||
|
||||
#define PIOS_ADC_PIN2_GPIO_PORT GPIOA // PA1 (Accel Y)
|
||||
#define PIOS_ADC_PIN2_GPIO_PIN GPIO_Pin_1 // ADC123_IN1
|
||||
#define PIOS_ADC_PIN2_GPIO_CHANNEL ADC_Channel_1
|
||||
#define PIOS_ADC_PIN2_ADC ADC1
|
||||
#define PIOS_ADC_PIN2_ADC_NUMBER 2
|
||||
|
||||
#define PIOS_ADC_PIN3_GPIO_PORT GPIOA // PA0 (Accel Z)
|
||||
#define PIOS_ADC_PIN3_GPIO_PIN GPIO_Pin_0 // ADC12_IN0
|
||||
#define PIOS_ADC_PIN3_GPIO_CHANNEL ADC_Channel_0
|
||||
#define PIOS_ADC_PIN3_ADC ADC1
|
||||
#define PIOS_ADC_PIN3_ADC_NUMBER 3
|
||||
|
||||
#define PIOS_ADC_PIN4_GPIO_PORT GPIOA // PA6 (Temp_XY)
|
||||
#define PIOS_ADC_PIN4_GPIO_PIN GPIO_Pin_6 // ADC12_IN6
|
||||
#define PIOS_ADC_PIN4_GPIO_CHANNEL ADC_Channel_6
|
||||
#define PIOS_ADC_PIN4_ADC ADC1
|
||||
#define PIOS_ADC_PIN4_ADC_NUMBER 4
|
||||
|
||||
#define PIOS_ADC_PIN5_GPIO_PORT GPIOA // PA4 (Gyro X)
|
||||
#define PIOS_ADC_PIN5_GPIO_PIN GPIO_Pin_4 // ADC12_IN4
|
||||
#define PIOS_ADC_PIN5_GPIO_CHANNEL ADC_Channel_4
|
||||
#define PIOS_ADC_PIN5_ADC ADC2
|
||||
#define PIOS_ADC_PIN5_ADC_NUMBER 1
|
||||
|
||||
#define PIOS_ADC_PIN6_GPIO_PORT GPIOA // PA5 (Gyro Y)
|
||||
#define PIOS_ADC_PIN6_GPIO_PIN GPIO_Pin_5 // ADC12_IN5
|
||||
#define PIOS_ADC_PIN6_GPIO_CHANNEL ADC_Channel_5
|
||||
#define PIOS_ADC_PIN6_ADC ADC2
|
||||
#define PIOS_ADC_PIN6_ADC_NUMBER 2
|
||||
|
||||
#define PIOS_ADC_PIN7_GPIO_PORT GPIOA // PA7 (Gyro Z)
|
||||
#define PIOS_ADC_PIN7_GPIO_PIN GPIO_Pin_7 // ADC12_IN7
|
||||
#define PIOS_ADC_PIN7_GPIO_CHANNEL ADC_Channel_7
|
||||
#define PIOS_ADC_PIN7_ADC ADC2
|
||||
#define PIOS_ADC_PIN7_ADC_NUMBER 3
|
||||
|
||||
#define PIOS_ADC_PIN8_GPIO_PORT GPIOB // PB1 (Z Temp)
|
||||
#define PIOS_ADC_PIN8_GPIO_PIN GPIO_Pin_1 // ADC12_IN9
|
||||
#define PIOS_ADC_PIN8_GPIO_CHANNEL ADC_Channel_9
|
||||
#define PIOS_ADC_PIN8_ADC ADC2
|
||||
#define PIOS_ADC_PIN8_ADC_NUMBER 4
|
||||
|
||||
#define PIOS_ADC_NUM_PINS 8
|
||||
|
||||
#define PIOS_ADC_PORTS { PIOS_ADC_PIN1_GPIO_PORT, PIOS_ADC_PIN2_GPIO_PORT, PIOS_ADC_PIN3_GPIO_PORT, PIOS_ADC_PIN4_GPIO_PORT, PIOS_ADC_PIN5_GPIO_PORT, PIOS_ADC_PIN6_GPIO_PORT, PIOS_ADC_PIN7_GPIO_PORT, PIOS_ADC_PIN8_GPIO_PORT }
|
||||
#define PIOS_ADC_PINS { PIOS_ADC_PIN1_GPIO_PIN, PIOS_ADC_PIN2_GPIO_PIN, PIOS_ADC_PIN3_GPIO_PIN, PIOS_ADC_PIN4_GPIO_PIN, PIOS_ADC_PIN5_GPIO_PIN, PIOS_ADC_PIN6_GPIO_PIN, PIOS_ADC_PIN7_GPIO_PIN, PIOS_ADC_PIN8_GPIO_PIN }
|
||||
#define PIOS_ADC_CHANNELS { PIOS_ADC_PIN1_GPIO_CHANNEL, PIOS_ADC_PIN2_GPIO_CHANNEL, PIOS_ADC_PIN3_GPIO_CHANNEL, PIOS_ADC_PIN4_GPIO_CHANNEL, PIOS_ADC_PIN5_GPIO_CHANNEL, PIOS_ADC_PIN6_GPIO_CHANNEL, PIOS_ADC_PIN7_GPIO_CHANNEL, PIOS_ADC_PIN8_GPIO_CHANNEL }
|
||||
#define PIOS_ADC_MAPPING { PIOS_ADC_PIN1_ADC, PIOS_ADC_PIN2_ADC, PIOS_ADC_PIN3_ADC, PIOS_ADC_PIN4_ADC, PIOS_ADC_PIN5_ADC, PIOS_ADC_PIN6_ADC, PIOS_ADC_PIN7_ADC, PIOS_ADC_PIN8_ADC }
|
||||
#define PIOS_ADC_CHANNEL_MAPPING { PIOS_ADC_PIN1_ADC_NUMBER, PIOS_ADC_PIN2_ADC_NUMBER, PIOS_ADC_PIN3_ADC_NUMBER, PIOS_ADC_PIN4_ADC_NUMBER, PIOS_ADC_PIN5_ADC_NUMBER, PIOS_ADC_PIN6_ADC_NUMBER, PIOS_ADC_PIN7_ADC_NUMBER, PIOS_ADC_PIN8_ADC_NUMBER }
|
||||
#define PIOS_ADC_NUM_CHANNELS (PIOS_ADC_NUM_PINS + PIOS_ADC_USE_TEMP_SENSOR)
|
||||
#define PIOS_ADC_NUM_ADC_CHANNELS 2
|
||||
#define PIOS_ADC_USE_ADC2 1
|
||||
#define PIOS_ADC_ADCCLK RCC_PCLK2_Div2
|
||||
#define PIOS_ADC_PCLK2 RCC_HCLK_Div16
|
||||
#define PIOS_ADC_CLOCK_FUNCTION RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE); RCC_PCLK2Config(PIOS_ADC_PCLK2);
|
||||
/* RCC_PCLK2_Div2: ADC clock = PCLK2/2 */
|
||||
/* RCC_PCLK2_Div4: ADC clock = PCLK2/4 */
|
||||
/* RCC_PCLK2_Div6: ADC clock = PCLK2/6 */
|
||||
/* RCC_PCLK2_Div8: ADC clock = PCLK2/8 */
|
||||
#define PIOS_ADC_SAMPLE_TIME ADC_SampleTime_239Cycles5
|
||||
/* Sample time: */
|
||||
/* With an ADCCLK = 14 MHz and a sampling time of 239.5 cycles: */
|
||||
/* Tconv = 239.5 + 12.5 = 252 cycles = 18<31>s */
|
||||
/* (1 / (ADCCLK / CYCLES)) = Sample Time (<28>S) */
|
||||
#define PIOS_ADC_IRQ_PRIO PIOS_IRQ_PRIO_LOW
|
||||
|
||||
// Currently analog acquistion hard coded at 480 Hz
|
||||
// PCKL2 = HCLK / 16
|
||||
// ADCCLK = PCLK2 / 2
|
||||
#define PIOS_ADC_RATE (72.0e6 / 16 / 2 / 252 / (PIOS_ADC_NUM_PINS / 2))
|
||||
#define EKF_RATE (PIOS_ADC_RATE / adc_oversampling / 2)
|
||||
#define PIOS_ADC_MAX_OVERSAMPLING 50
|
||||
|
||||
//-------------------------
|
||||
// GPIO
|
||||
//-------------------------
|
||||
#define PIOS_GPIO_1_PORT GPIOB
|
||||
#define PIOS_GPIO_1_PIN GPIO_Pin_9
|
||||
#define PIOS_GPIO_1_GPIO_CLK RCC_APB2Periph_GPIOB
|
||||
#define PIOS_GPIO_PORTS { PIOS_GPIO_1_PORT }
|
||||
#define PIOS_GPIO_PINS { PIOS_GPIO_1_PIN }
|
||||
#define PIOS_GPIO_CLKS { PIOS_GPIO_1_GPIO_CLK }
|
||||
#define PIOS_GPIO_NUM 1
|
||||
#define SET_ACCEL_2G PIOS_GPIO_On(0);
|
||||
#define SET_ACCEL_6G PIOS_GPIO_Off(0)
|
||||
|
||||
//------------------------
|
||||
// PIOS_HMC5843
|
||||
//------------------------
|
||||
#define PIOS_HMC5843_DRDY_GPIO_PORT GPIOB
|
||||
#define PIOS_HMC5843_DRDY_GPIO_PIN GPIO_Pin_8
|
||||
#define PIOS_HMC5843_DRDY_PORT_SOURCE GPIO_PortSourceGPIOB
|
||||
#define PIOS_HMC5843_DRDY_PIN_SOURCE GPIO_PinSource8
|
||||
#define PIOS_HMC5843_DRDY_CLK RCC_APB2Periph_GPIOB
|
||||
#define PIOS_HMC5843_DRDY_EXTI_LINE EXTI_Line8
|
||||
#define PIOS_HMC5843_DRDY_IRQn EXTI9_5_IRQn
|
||||
#define PIOS_HMC5843_DRDY_PRIO PIOS_IRQ_PRIO_HIGH
|
||||
|
||||
|
||||
|
||||
#endif /* STM32103CB_AHRS_H_ */
|
@ -275,4 +275,4 @@ extern uint32_t pios_com_debug_id;
|
||||
#define PIOS_USB_DETECT_GPIO_PORT GPIOC
|
||||
#define PIOS_USB_MAX_DEVS 1
|
||||
#define PIOS_USB_DETECT_GPIO_PIN GPIO_Pin_15
|
||||
#endif /* STM32103CB_AHRS_H_ */
|
||||
#endif /* STM32103CB_CC_H_ */
|
||||
|
@ -193,12 +193,6 @@ extern uint32_t pios_ppm_out_id;
|
||||
#define PIOS_PPM_RECEIVER (pios_ppm_rcvr_id)
|
||||
#define PIOS_PPM_OUTPUT (pios_ppm_out_id)
|
||||
|
||||
#define DEBUG_LEVEL 2
|
||||
#if DEBUG_LEVEL > 1000
|
||||
#define DEBUG_PRINTF(level, ...) {if(level <= DEBUG_LEVEL && PIOS_COM_DEBUG > 0) { PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_DEBUG, __VA_ARGS__); }}
|
||||
#else
|
||||
#define DEBUG_PRINTF(...)
|
||||
#endif
|
||||
#define RFM22_DEBUG 1
|
||||
|
||||
//-------------------------
|
||||
@ -296,26 +290,12 @@ extern uint32_t pios_rfm22b_id;
|
||||
//-------------------------
|
||||
// Packet Handler
|
||||
//-------------------------
|
||||
#if defined(PIOS_INCLUDE_PACKET_HANDLER)
|
||||
extern uint32_t pios_packet_handler;
|
||||
#define PIOS_PACKET_HANDLER (pios_packet_handler)
|
||||
#define PIOS_PH_MAX_PACKET 255
|
||||
#define PIOS_PH_WIN_SIZE 3
|
||||
#define PIOS_PH_MAX_CONNECTIONS 1
|
||||
#define RS_ECC_NPARITY 4
|
||||
#endif /* PIOS_INCLUDE_PACKET_HANDLER */
|
||||
|
||||
//-------------------------
|
||||
// Packet Handler
|
||||
//-------------------------
|
||||
|
||||
#if defined(PIOS_INCLUDE_PACKET_HANDLER)
|
||||
uint32_t pios_packet_handler;
|
||||
#define PIOS_PACKET_HANDLER (pios_packet_handler)
|
||||
#define PIOS_PH_MAX_PACKET 255
|
||||
#define PIOS_PH_WIN_SIZE 3
|
||||
#define PIOS_PH_MAX_CONNECTIONS 1
|
||||
#endif /* PIOS_INCLUDE_PACKET_HANDLER */
|
||||
|
||||
//-------------------------
|
||||
// Reed-Solomon ECC
|
||||
|
@ -186,7 +186,7 @@ extern uint32_t pios_com_telem_usb_id;
|
||||
#define PIOS_COM_GPS (pios_com_gps_id)
|
||||
#define PIOS_COM_TELEM_USB (pios_com_telem_usb_id)
|
||||
#define PIOS_COM_TELEM_RF (pios_com_telem_rf_id)
|
||||
#define PIOS_COM_DEBUG PIOS_COM_AUX
|
||||
#define PIOS_COM_DEBUG (PIOS_COM_AUX)
|
||||
#define PIOS_COM_OSD (pios_com_aux_id)
|
||||
|
||||
//extern uint32_t pios_com_serial_id;
|
||||
@ -202,13 +202,6 @@ extern uint32_t pios_com_telem_usb_id;
|
||||
#define PIOS_COM_TELEM_USB (pios_com_telem_usb_id)
|
||||
#endif
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
// #define DEBUG_PRINTF(...) PIOS_COM_SendFormattedString(PIOS_COM_DEBUG, __VA_ARGS__)
|
||||
#define DEBUG_PRINTF(...) PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINTF(...)
|
||||
#endif
|
||||
|
||||
// *****************************************************************
|
||||
// ADC
|
||||
|
||||
|
@ -31,13 +31,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(PIOS_INCLUDE_DEBUG_CONSOLE)
|
||||
#define DEBUG_LEVEL 0
|
||||
#define DEBUG_PRINTF(level, ...) {if(level <= DEBUG_LEVEL && pios_com_debug_id > 0) { PIOS_COM_SendFormattedStringNonBlocking(pios_com_debug_id, __VA_ARGS__); }}
|
||||
#else
|
||||
#define DEBUG_PRINTF(level, ...)
|
||||
#endif /* PIOS_INCLUDE_DEBUG_CONSOLE */
|
||||
|
||||
//------------------------
|
||||
// Timers and Channels Used
|
||||
//------------------------
|
||||
|
@ -1,9 +1,7 @@
|
||||
#ifndef PIOS_BOARD_H_
|
||||
#define PIOS_BOARD_H_
|
||||
|
||||
#ifdef USE_STM32103CB_AHRS
|
||||
#include "STM32103CB_AHRS.h"
|
||||
#elif USE_STM3210E_OP
|
||||
#ifdef USE_STM3210E_OP
|
||||
#include "STM3210E_OP.h"
|
||||
#elif USE_STM32103CB_PIPXTREME
|
||||
#include "STM32103CB_PIPXTREME_Rev1.h"
|
||||
|
@ -2,28 +2,26 @@
|
||||
# Rules to add CMSIS2 to a PiOS target
|
||||
#
|
||||
|
||||
CMSIS2_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
EXTRAINCDIRS += $(CMSIS2_DIR)/Include
|
||||
CMSIS2_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
EXTRAINCDIRS += $(CMSIS2_DIR)Include
|
||||
|
||||
# Rules to build the ARM DSP library
|
||||
ifeq ($(USE_DSP_LIB), YES)
|
||||
DSPLIB_NAME := dsp
|
||||
CMSIS_DSPLIB := $(CMSIS2_DIR)DSP_Lib/Source
|
||||
|
||||
DSPLIB_NAME := dsp
|
||||
CMSIS_DSPLIB := $(CMSIS2_DIR)/DSP_Lib/Source
|
||||
# Compile all files into output directory
|
||||
DSPLIB_SRC := $(wildcard $(CMSIS_DSPLIB)/*/*.c)
|
||||
DSPLIB_SRCBASE := $(notdir $(basename $(DSPLIB_SRC)))
|
||||
$(foreach src, $(DSPLIB_SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src))))
|
||||
|
||||
# Compile all files into output directory
|
||||
DSPLIB_SRC := $(wildcard $(CMSIS_DSPLIB)/*/*.c)
|
||||
DSPLIB_SRCBASE := $(notdir $(basename $(DSPLIB_SRC)))
|
||||
$(foreach src, $(DSPLIB_SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src))))
|
||||
# Define the object files directory and a list of object files for the library
|
||||
DSPLIB_OBJDIR = $(OUTDIR)
|
||||
DSPLIB_OBJ = $(addprefix $(DSPLIB_OBJDIR)/, $(addsuffix .o, $(DSPLIB_SRCBASE)))
|
||||
|
||||
# Define the object files directory and a list of object files for the library
|
||||
DSPLIB_OBJDIR = $(OUTDIR)
|
||||
DSPLIB_OBJ = $(addprefix $(DSPLIB_OBJDIR)/, $(addsuffix .o, $(DSPLIB_SRCBASE)))
|
||||
|
||||
# Create a library file
|
||||
$(eval $(call ARCHIVE_TEMPLATE, $(OUTDIR)/lib$(DSPLIB_NAME).a, $(DSPLIB_OBJ), $(DSPLIB_OBJDIR)))
|
||||
|
||||
# Add library to the list of linked objects
|
||||
ALLLIB += $(OUTDIR)/lib$(DSPLIB_NAME).a
|
||||
# Create a library file
|
||||
$(eval $(call ARCHIVE_TEMPLATE, $(OUTDIR)/lib$(DSPLIB_NAME).a, $(DSPLIB_OBJ), $(DSPLIB_OBJDIR)))
|
||||
|
||||
# Add library to the list of linked objects
|
||||
ALLLIB += $(OUTDIR)/lib$(DSPLIB_NAME).a
|
||||
endif
|
||||
|
@ -5,7 +5,6 @@
|
||||
# has been defined and add in the target-specific pieces separately.
|
||||
#
|
||||
|
||||
FREERTOS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))/Source
|
||||
SRC += $(wildcard $(FREERTOS_DIR)/*.c)
|
||||
EXTRAINCDIRS += $(FREERTOS_DIR)/include
|
||||
|
||||
FREERTOS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))/Source
|
||||
SRC += $(wildcard $(FREERTOS_DIR)/*.c)
|
||||
EXTRAINCDIRS += $(FREERTOS_DIR)/include
|
||||
|
@ -2,7 +2,6 @@
|
||||
# Rules to add DOSFS to a PiOS target
|
||||
#
|
||||
|
||||
DOSFS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
SRC += $(wildcard $(DOSFS_DIR)*.c)
|
||||
EXTRAINCDIRS += $(DOSFS_DIR)
|
||||
|
||||
DOSFS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
SRC += $(wildcard $(DOSFS_DIR)*.c)
|
||||
EXTRAINCDIRS += $(DOSFS_DIR)
|
||||
|
@ -2,7 +2,6 @@
|
||||
# Rules to add the MSHeap allocator to a PiOS target
|
||||
#
|
||||
|
||||
MSHEAP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
SRC += $(wildcard $(MSHEAP_DIR)*.c)
|
||||
EXTRAINCDIRS += $(MSHEAP_DIR)
|
||||
|
||||
MSHEAP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
SRC += $(wildcard $(MSHEAP_DIR)*.c)
|
||||
EXTRAINCDIRS += $(MSHEAP_DIR)
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_ADXL345
|
||||
|
||||
enum pios_adxl345_dev_magic {
|
||||
PIOS_ADXL345_DEV_MAGIC = 0xcb55aa55,
|
||||
};
|
||||
@ -306,3 +308,5 @@ uint8_t PIOS_ADXL345_Read(struct pios_adxl345_data * data)
|
||||
|
||||
return rec[8] & 0x7F; // return number of remaining entries
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_ADXL345 */
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_BMA180)
|
||||
#ifdef PIOS_INCLUDE_BMA180
|
||||
|
||||
#include "fifo_buffer.h"
|
||||
|
||||
@ -475,6 +475,7 @@ bool PIOS_BMA180_IRQHandler(void)
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_BMA180 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
@ -28,15 +28,13 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_BMP085)
|
||||
#if !defined(PIOS_INCLUDE_EXTI)
|
||||
#error PIOS_EXTI Must be included in the project!
|
||||
#endif /* PIOS_INCLUDE_EXTI */
|
||||
#ifdef PIOS_INCLUDE_BMP085
|
||||
|
||||
#include <pios_exti.h>
|
||||
#ifndef PIOS_INCLUDE_EXTI
|
||||
#error PIOS_EXTI must be included in the project
|
||||
#endif /* PIOS_INCLUDE_EXTI */
|
||||
|
||||
/* Glocal Variables */
|
||||
ConversionTypeTypeDef CurrentRead;
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <pios.h>
|
||||
#include <pios_board.h>
|
||||
|
||||
#include "pios_board_info.h"
|
||||
|
||||
const struct pios_board_info __attribute__((__used__)) __attribute__((__section__(".boardinfo"))) pios_board_info_blob = {
|
||||
|
@ -28,15 +28,14 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_COM)
|
||||
#ifdef PIOS_INCLUDE_COM
|
||||
|
||||
#include "fifo_buffer.h"
|
||||
#include <pios_com_priv.h>
|
||||
|
||||
#if !defined(PIOS_INCLUDE_FREERTOS)
|
||||
#ifndef PIOS_INCLUDE_FREERTOS
|
||||
#include "pios_delay.h" /* PIOS_DELAY_WaitmS */
|
||||
#endif
|
||||
|
||||
@ -524,7 +523,7 @@ bool PIOS_COM_Available(uint32_t com_id)
|
||||
return (com_dev->driver->available)(com_dev->lower_id);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_COM */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,10 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_COM_MSG)
|
||||
#ifdef PIOS_INCLUDE_COM_MSG
|
||||
|
||||
#include "pios_com.h"
|
||||
|
||||
|
@ -28,12 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_ETASV3)
|
||||
|
||||
#include "pios_etasv3.h"
|
||||
#ifdef PIOS_INCLUDE_ETASV3
|
||||
|
||||
static bool PIOS_ETASV3_Read(uint8_t * buffer, uint8_t len)
|
||||
{
|
||||
|
@ -28,7 +28,11 @@
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH
|
||||
|
||||
#include "pios_flash_jedec_priv.h"
|
||||
|
||||
#define JEDEC_WRITE_ENABLE 0x06
|
||||
@ -562,3 +566,4 @@ const struct pios_flash_driver pios_jedec_flash_driver = {
|
||||
.read_data = PIOS_Flash_Jedec_ReadData,
|
||||
};
|
||||
|
||||
#endif /* PIOS_INCLUDE_FLASH */
|
||||
|
@ -24,6 +24,11 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH
|
||||
|
||||
#include "openpilot.h"
|
||||
|
||||
#include "pios_flashfs_logfs_priv.h"
|
||||
@ -1020,6 +1025,8 @@ out_exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_FLASH */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
@ -28,12 +28,11 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#include "uavobjectmanager.h"
|
||||
#ifdef PIOS_INCLUDE_GCSRCVR
|
||||
|
||||
#if defined(PIOS_INCLUDE_GCSRCVR)
|
||||
#include "uavobjectmanager.h"
|
||||
|
||||
#include "pios_gcsrcvr_priv.h"
|
||||
|
||||
@ -168,7 +167,7 @@ static void PIOS_gcsrcvr_Supervisor(uint32_t gcsrcvr_id) {
|
||||
gcsrcvr_dev->Fresh = false;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_GCSRCVR */
|
||||
#endif /* PIOS_INCLUDE_GCSRCVR */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,12 +28,12 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_HCSR04)
|
||||
#ifdef PIOS_INCLUDE_HCSR04
|
||||
|
||||
#if !(defined(PIOS_INCLUDE_DSM) || defined(PIOS_INCLUDE_SBUS))
|
||||
#error Only supported with Spektrum/JR DSM or S.Bus interface!
|
||||
#error Only supported with Spektrum/JR DSM or S.Bus interface
|
||||
#endif
|
||||
|
||||
/* Local Variables */
|
||||
@ -206,5 +206,5 @@ void TIM3_IRQHandler(void)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_HCSR04 */
|
||||
|
||||
#endif
|
||||
|
@ -29,10 +29,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_HMC5843)
|
||||
#ifdef PIOS_INCLUDE_HMC5843
|
||||
|
||||
#include <pios_exti.h>
|
||||
|
||||
@ -376,7 +375,7 @@ static bool PIOS_HMC5843_Write(uint8_t address, uint8_t buffer)
|
||||
return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_HMC5843 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,10 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_HMC5883)
|
||||
#ifdef PIOS_INCLUDE_HMC5883
|
||||
|
||||
/* Global Variables */
|
||||
|
||||
|
@ -29,12 +29,11 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_I2C_ESC)
|
||||
#ifdef PIOS_INCLUDE_I2C_ESC
|
||||
|
||||
/* HMC5843 Addresses */
|
||||
/* Known i2c ESC addresses */
|
||||
#define MK_I2C_ADDR 0x29
|
||||
#define ASTEC4_I2C_ADDR 0x02
|
||||
|
||||
@ -164,7 +163,7 @@ bool PIOS_SetAstec4Speed(uint8_t motornum, uint8_t speed) {
|
||||
return PIOS_I2C_Transfer(PIOS_I2C_ESC_ADAPTER, txn_list, NELEMENTS(txn_list));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_I2C_ESC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -29,10 +29,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_L3GD20)
|
||||
#ifdef PIOS_INCLUDE_L3GD20
|
||||
|
||||
#include "fifo_buffer.h"
|
||||
|
||||
@ -381,7 +380,7 @@ bool PIOS_L3GD20_IRQHandler(void)
|
||||
return xHigherPriorityTaskWoken == pdTRUE;
|
||||
}
|
||||
|
||||
#endif /* L3GD20 */
|
||||
#endif /* PIOS_INCLUDE_L3GD20 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -29,9 +29,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
#if defined(PIOS_INCLUDE_MPU6000)
|
||||
|
||||
#ifdef PIOS_INCLUDE_MPU6000
|
||||
|
||||
#include "fifo_buffer.h"
|
||||
|
||||
@ -551,7 +551,7 @@ bool PIOS_MPU6000_IRQHandler(void)
|
||||
return xHigherPriorityTaskWoken == pdTRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_MPU6000 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -30,10 +30,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_MPXV)
|
||||
#ifdef PIOS_INCLUDE_MPXV
|
||||
|
||||
#define A0 340.27f //speed of sound at standard sea level in [m/s]
|
||||
#define P0 101.325f //static air pressure at standard sea level in kPa
|
||||
|
@ -28,13 +28,14 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_MS5611
|
||||
|
||||
|
||||
// TODO: Clean this up. Getting around old constant.
|
||||
#define PIOS_MS5611_OVERSAMPLING oversampling
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_MS5611)
|
||||
|
||||
/* Glocal Variables */
|
||||
ConversionTypeTypeDef CurrentRead;
|
||||
@ -261,7 +262,7 @@ int32_t PIOS_MS5611_Test()
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_MS5611 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -1,343 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_OPAHRS OPAHRS Functions
|
||||
* @brief HAL code to interface to the OpenPilot AHRS module
|
||||
* @{
|
||||
*
|
||||
* @file pios_opahrs.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Hardware commands to communicate with the AHRS
|
||||
* @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
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_OPAHRS)
|
||||
|
||||
#include "pios_opahrs_proto.h"
|
||||
#include "pios_opahrs.h"
|
||||
|
||||
/**
|
||||
* Initialise the OpenPilot AHRS
|
||||
*/
|
||||
void PIOS_OPAHRS_Init(void)
|
||||
{
|
||||
PIOS_SPI_SetClockSpeed(PIOS_OPAHRS_SPI, PIOS_SPI_PRESCALER_8);
|
||||
}
|
||||
|
||||
static int32_t opahrs_msg_txrx(const uint8_t * tx, uint8_t * rx, uint32_t len)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 0);
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(20);
|
||||
#endif
|
||||
rc = PIOS_SPI_TransferBlock(PIOS_OPAHRS_SPI, tx, rx, len, NULL);
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 1);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static enum opahrs_result opahrs_msg_v1_send_req(const struct opahrs_msg_v1 *req)
|
||||
{
|
||||
int32_t rc;
|
||||
struct opahrs_msg_v1 link_rx;
|
||||
|
||||
for (uint8_t retries = 0; retries < 20; retries++) {
|
||||
struct opahrs_msg_v1 *rsp = &link_rx;
|
||||
|
||||
if ((rc = opahrs_msg_txrx((const uint8_t *)req, (uint8_t *) rsp, sizeof(*rsp))) < 0) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
/* Make sure we got a sane response by checking the magic */
|
||||
if ((rsp->head.magic != OPAHRS_MSG_MAGIC_HEAD) || (rsp->tail.magic != OPAHRS_MSG_MAGIC_TAIL)) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
switch (rsp->head.type) {
|
||||
case OPAHRS_MSG_TYPE_LINK:
|
||||
switch (rsp->payload.link.state) {
|
||||
case OPAHRS_MSG_LINK_STATE_BUSY:
|
||||
case OPAHRS_MSG_LINK_STATE_INACTIVE:
|
||||
/* Wait for a small delay and retry */
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(20);
|
||||
#endif
|
||||
continue;
|
||||
case OPAHRS_MSG_LINK_STATE_READY:
|
||||
/* Peer was ready when we Tx'd so they have now Rx'd our message */
|
||||
return OPAHRS_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case OPAHRS_MSG_TYPE_USER_V0:
|
||||
case OPAHRS_MSG_TYPE_USER_V1:
|
||||
/* Wait for a small delay and retry */
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(50);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return OPAHRS_RESULT_TIMEOUT;
|
||||
}
|
||||
|
||||
static enum opahrs_result opahrs_msg_v1_recv_rsp(enum opahrs_msg_v1_tag tag, struct opahrs_msg_v1 *rsp)
|
||||
{
|
||||
struct opahrs_msg_v1 link_tx;
|
||||
|
||||
opahrs_msg_v1_init_link_tx(&link_tx, OPAHRS_MSG_LINK_TAG_NOP);
|
||||
|
||||
for (uint8_t retries = 0; retries < 20; retries++) {
|
||||
if (opahrs_msg_txrx((const uint8_t *)&link_tx, (uint8_t *) rsp, sizeof(*rsp)) < 0) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
/* Make sure we got a sane response by checking the magic */
|
||||
if ((rsp->head.magic != OPAHRS_MSG_MAGIC_HEAD) || (rsp->tail.magic != OPAHRS_MSG_MAGIC_TAIL)) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
switch (rsp->head.type) {
|
||||
case OPAHRS_MSG_TYPE_LINK:
|
||||
switch (rsp->payload.link.state) {
|
||||
case OPAHRS_MSG_LINK_STATE_BUSY:
|
||||
/* Wait for a small delay and retry */
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(20);
|
||||
#endif
|
||||
continue;
|
||||
case OPAHRS_MSG_LINK_STATE_INACTIVE:
|
||||
case OPAHRS_MSG_LINK_STATE_READY:
|
||||
/* somehow, we've missed our response */
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
break;
|
||||
case OPAHRS_MSG_TYPE_USER_V0:
|
||||
/* This isn't the type we expected */
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
break;
|
||||
case OPAHRS_MSG_TYPE_USER_V1:
|
||||
if (rsp->payload.user.t == tag) {
|
||||
return OPAHRS_RESULT_OK;
|
||||
} else {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return OPAHRS_RESULT_TIMEOUT;
|
||||
}
|
||||
|
||||
static enum opahrs_result PIOS_OPAHRS_v1_simple_req(enum opahrs_msg_v1_tag req_type, struct opahrs_msg_v1 *rsp, enum opahrs_msg_v1_tag rsp_type)
|
||||
{
|
||||
struct opahrs_msg_v1 req;
|
||||
enum opahrs_result rc;
|
||||
|
||||
/* Make up an empty request */
|
||||
opahrs_msg_v1_init_user_tx(&req, req_type);
|
||||
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v1_send_req(&req);
|
||||
if ((rc == OPAHRS_RESULT_OK) && rsp) {
|
||||
/* We need a specific kind of reply, go get it */
|
||||
return opahrs_msg_v1_recv_rsp(rsp_type, rsp);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_GetSerial(struct opahrs_msg_v1 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
return (PIOS_OPAHRS_v1_simple_req(OPAHRS_MSG_V1_REQ_SERIAL, rsp, OPAHRS_MSG_V1_RSP_SERIAL));
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_resync(void)
|
||||
{
|
||||
struct opahrs_msg_v1 req;
|
||||
struct opahrs_msg_v1 rsp;
|
||||
|
||||
enum opahrs_result rc = OPAHRS_RESULT_FAILED;
|
||||
|
||||
opahrs_msg_v1_init_link_tx(&req, OPAHRS_MSG_LINK_TAG_NOP);
|
||||
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 0);
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(20);
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < sizeof(req); i++) {
|
||||
/* Tx a shortened (by one byte) message to walk through all byte positions */
|
||||
opahrs_msg_v1_init_rx(&rsp);
|
||||
PIOS_SPI_TransferBlock(PIOS_OPAHRS_SPI, (uint8_t *) & req, (uint8_t *) & rsp, sizeof(req) - 1, NULL);
|
||||
|
||||
/* Good magic means we're sync'd */
|
||||
if ((rsp.head.magic == OPAHRS_MSG_MAGIC_HEAD) && (rsp.tail.magic == OPAHRS_MSG_MAGIC_TAIL)) {
|
||||
/* We need to shift out one more byte to compensate for the short tx */
|
||||
PIOS_SPI_TransferByte(PIOS_OPAHRS_SPI, 0x00);
|
||||
rc = OPAHRS_RESULT_OK;
|
||||
break;
|
||||
}
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(10);
|
||||
#endif
|
||||
}
|
||||
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 1);
|
||||
//vTaskDelay(5 / portTICK_RATE_MS);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_GetAttitudeRaw(struct opahrs_msg_v1 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
return (PIOS_OPAHRS_v1_simple_req(OPAHRS_MSG_V1_REQ_ATTITUDERAW, rsp, OPAHRS_MSG_V1_RSP_ATTITUDERAW));
|
||||
}
|
||||
|
||||
extern enum opahrs_result PIOS_OPAHRS_SetAlgorithm(struct opahrs_msg_v1 *req)
|
||||
{
|
||||
struct opahrs_msg_v1 rsp;
|
||||
enum opahrs_result rc;
|
||||
|
||||
if (!req)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v1_init_user_tx(req, OPAHRS_MSG_V1_REQ_ALGORITHM);
|
||||
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v1_send_req(req);
|
||||
if (rc != OPAHRS_RESULT_OK) {
|
||||
/* Failed to send the request, bail out */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return opahrs_msg_v1_recv_rsp(OPAHRS_MSG_V1_RSP_ALGORITHM, &rsp);
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_SetMagNorth(struct opahrs_msg_v1 *req)
|
||||
{
|
||||
struct opahrs_msg_v1 rsp;
|
||||
enum opahrs_result rc;
|
||||
|
||||
if (!req)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v1_init_user_tx(req, OPAHRS_MSG_V1_REQ_NORTH);
|
||||
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v1_send_req(req);
|
||||
if (rc != OPAHRS_RESULT_OK) {
|
||||
/* Failed to send the request, bail out */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return opahrs_msg_v1_recv_rsp(OPAHRS_MSG_V1_RSP_NORTH, &rsp);
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_SetGetUpdate(struct opahrs_msg_v1 *req, struct opahrs_msg_v1 *rsp)
|
||||
{
|
||||
enum opahrs_result rc;
|
||||
|
||||
if (!req)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v1_init_user_tx(req, OPAHRS_MSG_V1_REQ_UPDATE);
|
||||
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v1_send_req(req);
|
||||
if (rc != OPAHRS_RESULT_OK) {
|
||||
/* Failed to send the request, bail out */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return opahrs_msg_v1_recv_rsp(OPAHRS_MSG_V1_RSP_UPDATE, rsp);
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_SetGetCalibration(struct opahrs_msg_v1 *req, struct opahrs_msg_v1 *rsp)
|
||||
{
|
||||
enum opahrs_result rc;
|
||||
|
||||
if (!req)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v1_init_user_tx(req, OPAHRS_MSG_V1_REQ_CALIBRATION);
|
||||
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v1_send_req(req);
|
||||
if (rc != OPAHRS_RESULT_OK) {
|
||||
/* Failed to send the request, bail out */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return opahrs_msg_v1_recv_rsp(OPAHRS_MSG_V1_RSP_CALIBRATION, rsp);
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_SetGetInitialized(struct opahrs_msg_v1 *req, struct opahrs_msg_v1 *rsp)
|
||||
{
|
||||
enum opahrs_result rc;
|
||||
|
||||
if (!req)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v1_init_user_tx(req, OPAHRS_MSG_V1_REQ_INITIALIZED);
|
||||
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v1_send_req(req);
|
||||
if (rc != OPAHRS_RESULT_OK) {
|
||||
/* Failed to send the request, bail out */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return opahrs_msg_v1_recv_rsp(OPAHRS_MSG_V1_RSP_INITIALIZED, rsp);
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_OPAHRS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
@ -1,76 +0,0 @@
|
||||
/**
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_OPAHRS OPAHRS Functions
|
||||
* @{
|
||||
*
|
||||
* @file pios_opahrs_proto.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief PPM Input functions
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pios_opahrs_proto.h"
|
||||
#include <string.h> /* memset */
|
||||
|
||||
void opahrs_msg_v0_init_rx(struct opahrs_msg_v0 *msg)
|
||||
{
|
||||
/* Make sure we start with bad magic in the rx buffer */
|
||||
msg->head.magic = 0;
|
||||
msg->head.type = 0;
|
||||
msg->tail.magic = 0;
|
||||
}
|
||||
|
||||
void opahrs_msg_v0_init_user_tx(struct opahrs_msg_v0 *msg, enum opahrs_msg_v0_tag tag)
|
||||
{
|
||||
msg->head.magic = OPAHRS_MSG_MAGIC_HEAD;
|
||||
msg->head.type = OPAHRS_MSG_TYPE_USER_V0;
|
||||
|
||||
msg->payload.user.t = tag;
|
||||
|
||||
msg->tail.magic = OPAHRS_MSG_MAGIC_TAIL;
|
||||
}
|
||||
|
||||
void opahrs_msg_v0_init_link_tx(struct opahrs_msg_v0 *msg, enum opahrs_msg_link_tag tag)
|
||||
{
|
||||
msg->head.magic = OPAHRS_MSG_MAGIC_HEAD;
|
||||
msg->head.type = OPAHRS_MSG_TYPE_LINK;
|
||||
|
||||
msg->payload.link.t = tag;
|
||||
|
||||
msg->tail.magic = OPAHRS_MSG_MAGIC_TAIL;
|
||||
}
|
||||
|
||||
void opahrs_msg_v1_init_rx(struct opahrs_msg_v1 *msg)
|
||||
{
|
||||
/* Make sure we start with bad magic in the rx buffer */
|
||||
msg->head.magic = 0;
|
||||
msg->head.type = 0;
|
||||
msg->tail.magic = 0;
|
||||
}
|
||||
|
||||
void opahrs_msg_v1_init_user_tx(struct opahrs_msg_v1 *msg, enum opahrs_msg_v1_tag tag)
|
||||
{
|
||||
msg->head.magic = OPAHRS_MSG_MAGIC_HEAD;
|
||||
msg->head.type = OPAHRS_MSG_TYPE_USER_V1;
|
||||
|
||||
msg->payload.user.t = tag;
|
||||
|
||||
msg->tail.magic = OPAHRS_MSG_MAGIC_TAIL;
|
||||
}
|
||||
|
||||
void opahrs_msg_v1_init_link_tx(struct opahrs_msg_v1 *msg, enum opahrs_msg_link_tag tag)
|
||||
{
|
||||
msg->head.magic = OPAHRS_MSG_MAGIC_HEAD;
|
||||
msg->head.type = OPAHRS_MSG_TYPE_LINK;
|
||||
|
||||
msg->payload.link.t = tag;
|
||||
|
||||
msg->tail.magic = OPAHRS_MSG_MAGIC_TAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
@ -1,330 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_OPAHRS OPAHRS Functions
|
||||
* @brief HAL code to interface to the OpenPilot AHRS module's bootloader
|
||||
* @{
|
||||
*
|
||||
* @file pios_opahrs_download.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Hardware commands to communicate with the AHRS bootloader
|
||||
* @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
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_OPAHRS)
|
||||
|
||||
#include "pios_opahrs_proto.h"
|
||||
#include "pios_opahrs.h"
|
||||
|
||||
static uint32_t PIOS_OPAHRS_SPI;
|
||||
|
||||
void PIOS_OPAHRS_Attach(uint32_t spi_id)
|
||||
{
|
||||
PIOS_OPAHRS_SPI = spi_id;
|
||||
}
|
||||
|
||||
void PIOS_OPAHRS_ForceSlaveSelected(bool selected)
|
||||
{
|
||||
if (selected) {
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 0);
|
||||
} else {
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t opahrs_msg_txrx(const uint8_t * tx, uint8_t * rx, uint32_t len)
|
||||
{
|
||||
int32_t rc;
|
||||
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 0);
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(20 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(1);
|
||||
#endif
|
||||
rc = PIOS_SPI_TransferBlock(PIOS_OPAHRS_SPI, tx, rx, len, NULL);
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 1);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static enum opahrs_result opahrs_msg_v0_send_req(const struct opahrs_msg_v0 *req)
|
||||
{
|
||||
int32_t rc;
|
||||
struct opahrs_msg_v0 link_rx;
|
||||
|
||||
for (uint8_t retries = 0; retries < 20; retries++) {
|
||||
struct opahrs_msg_v0 *rsp = &link_rx;
|
||||
|
||||
if ((rc = opahrs_msg_txrx((const uint8_t *)req, (uint8_t *) rsp, sizeof(*rsp))) < 0) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
/* Make sure we got a sane response by checking the magic */
|
||||
if ((rsp->head.magic != OPAHRS_MSG_MAGIC_HEAD) || (rsp->tail.magic != OPAHRS_MSG_MAGIC_TAIL)) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
switch (rsp->head.type) {
|
||||
case OPAHRS_MSG_TYPE_LINK:
|
||||
switch (rsp->payload.link.state) {
|
||||
case OPAHRS_MSG_LINK_STATE_BUSY:
|
||||
case OPAHRS_MSG_LINK_STATE_INACTIVE:
|
||||
/* Wait for a small delay and retry */
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(20 / portTICK_RATE_MS);
|
||||
#else
|
||||
//PIOS_DELAY_WaitmS(1);
|
||||
#endif
|
||||
continue;
|
||||
case OPAHRS_MSG_LINK_STATE_READY:
|
||||
/* Peer was ready when we Tx'd so they have now Rx'd our message */
|
||||
return OPAHRS_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case OPAHRS_MSG_TYPE_USER_V0:
|
||||
case OPAHRS_MSG_TYPE_USER_V1:
|
||||
/* Wait for a small delay and retry */
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(50 / portTICK_RATE_MS);
|
||||
#else
|
||||
//PIOS_DELAY_WaitmS(1);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return OPAHRS_RESULT_TIMEOUT;
|
||||
}
|
||||
|
||||
static enum opahrs_result opahrs_msg_v0_recv_rsp(enum opahrs_msg_v0_tag tag, struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
struct opahrs_msg_v0 link_tx;
|
||||
|
||||
opahrs_msg_v0_init_link_tx(&link_tx, OPAHRS_MSG_LINK_TAG_NOP);
|
||||
|
||||
for (uint8_t retries = 0; retries < 20; retries++) {
|
||||
if (opahrs_msg_txrx((const uint8_t *)&link_tx, (uint8_t *) rsp, sizeof(*rsp)) < 0) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
/* Make sure we got a sane response by checking the magic */
|
||||
if ((rsp->head.magic != OPAHRS_MSG_MAGIC_HEAD) || (rsp->tail.magic != OPAHRS_MSG_MAGIC_TAIL)) {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
switch (rsp->head.type) {
|
||||
case OPAHRS_MSG_TYPE_LINK:
|
||||
switch (rsp->payload.link.state) {
|
||||
case OPAHRS_MSG_LINK_STATE_BUSY:
|
||||
/* Wait for a small delay and retry */
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(20 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(1);
|
||||
#endif
|
||||
continue;
|
||||
case OPAHRS_MSG_LINK_STATE_INACTIVE:
|
||||
case OPAHRS_MSG_LINK_STATE_READY:
|
||||
/* somehow, we've missed our response */
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
break;
|
||||
case OPAHRS_MSG_TYPE_USER_V0:
|
||||
if (rsp->payload.user.t == tag) {
|
||||
return OPAHRS_RESULT_OK;
|
||||
} else {
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
}
|
||||
break;
|
||||
case OPAHRS_MSG_TYPE_USER_V1:
|
||||
/* This isn't the type we expected */
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return OPAHRS_RESULT_TIMEOUT;
|
||||
}
|
||||
|
||||
static enum opahrs_result PIOS_OPAHRS_v0_simple_req(enum opahrs_msg_v0_tag req_type, struct opahrs_msg_v0 *rsp, enum opahrs_msg_v0_tag rsp_type)
|
||||
{
|
||||
struct opahrs_msg_v0 req;
|
||||
enum opahrs_result rc;
|
||||
|
||||
/* Make up an empty request */
|
||||
opahrs_msg_v0_init_user_tx(&req, req_type);
|
||||
|
||||
/* Send the message until it is received */
|
||||
|
||||
rc = opahrs_msg_v0_send_req(&req);
|
||||
if ((rc == OPAHRS_RESULT_OK) && rsp) {
|
||||
/* We need a specific kind of reply, go get it */
|
||||
return opahrs_msg_v0_recv_rsp(rsp_type, rsp);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_GetVersions(struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
return (PIOS_OPAHRS_v0_simple_req(OPAHRS_MSG_V0_REQ_VERSIONS, rsp, OPAHRS_MSG_V0_RSP_VERSIONS));
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_GetMemMap(struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
return (PIOS_OPAHRS_v0_simple_req(OPAHRS_MSG_V0_REQ_MEM_MAP, rsp, OPAHRS_MSG_V0_RSP_MEM_MAP));
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_GetSerial(struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
return (PIOS_OPAHRS_v0_simple_req(OPAHRS_MSG_V0_REQ_SERIAL, rsp, OPAHRS_MSG_V0_RSP_SERIAL));
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_FwupStart(struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
return (PIOS_OPAHRS_v0_simple_req(OPAHRS_MSG_V0_REQ_FWUP_START, rsp, OPAHRS_MSG_V0_RSP_FWUP_STATUS));
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_FwupStatus(struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
return (PIOS_OPAHRS_v0_simple_req(OPAHRS_MSG_V0_REQ_FWUP_STATUS, rsp, OPAHRS_MSG_V0_RSP_FWUP_STATUS));
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_FwupData(struct opahrs_msg_v0 *req, struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!req || !rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v0_init_user_tx(req, OPAHRS_MSG_V0_REQ_FWUP_DATA);
|
||||
enum opahrs_result rc;
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v0_send_req(req);
|
||||
if (rc != OPAHRS_RESULT_OK) {
|
||||
/* Failed to send the request, bail out */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return opahrs_msg_v0_recv_rsp(OPAHRS_MSG_V0_RSP_FWUP_STATUS, rsp);
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_FwDlData(struct opahrs_msg_v0 *req, struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!req || !rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v0_init_user_tx(req, OPAHRS_MSG_V0_REQ_FWDN_DATA);
|
||||
enum opahrs_result rc;
|
||||
/* Send the message until it is received */
|
||||
rc = opahrs_msg_v0_send_req(req);
|
||||
if (rc != OPAHRS_RESULT_OK) {
|
||||
/* Failed to send the request, bail out */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return opahrs_msg_v0_recv_rsp(OPAHRS_MSG_V0_RSP_FWDN_DATA, rsp);
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_FwupVerify(struct opahrs_msg_v0 *rsp)
|
||||
{
|
||||
if (!rsp)
|
||||
return OPAHRS_RESULT_FAILED;
|
||||
|
||||
return (PIOS_OPAHRS_v0_simple_req(OPAHRS_MSG_V0_REQ_FWUP_VERIFY, rsp, OPAHRS_MSG_V0_RSP_FWUP_STATUS));
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_resync(void)
|
||||
{
|
||||
struct opahrs_msg_v0 req;
|
||||
struct opahrs_msg_v0 rsp;
|
||||
|
||||
enum opahrs_result rc = OPAHRS_RESULT_FAILED;
|
||||
|
||||
opahrs_msg_v0_init_link_tx(&req, OPAHRS_MSG_LINK_TAG_NOP);
|
||||
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 0);
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(20 / portTICK_RATE_MS);
|
||||
#else
|
||||
//PIOS_DELAY_WaitmS(1);
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < sizeof(req); i++) {
|
||||
/* Tx a shortened (by one byte) message to walk through all byte positions */
|
||||
opahrs_msg_v0_init_rx(&rsp);
|
||||
PIOS_SPI_TransferBlock(PIOS_OPAHRS_SPI, (uint8_t *) & req, (uint8_t *) & rsp, sizeof(req) - 1, NULL);
|
||||
|
||||
/* Good magic means we're sync'd */
|
||||
if ((rsp.head.magic == OPAHRS_MSG_MAGIC_HEAD) && (rsp.tail.magic == OPAHRS_MSG_MAGIC_TAIL)) {
|
||||
/* We need to shift out one more byte to compensate for the short tx */
|
||||
PIOS_SPI_TransferByte(PIOS_OPAHRS_SPI, 0x00);
|
||||
rc = OPAHRS_RESULT_OK;
|
||||
break;
|
||||
}
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
vTaskDelay(10 / portTICK_RATE_MS);
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
PIOS_SPI_RC_PinSet(PIOS_OPAHRS_SPI, 1);
|
||||
//vTaskDelay(5 / portTICK_RATE_MS);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_reset(uint32_t delay)
|
||||
{
|
||||
struct opahrs_msg_v0 req;
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v0_init_user_tx(&req, OPAHRS_MSG_V0_REQ_RESET);
|
||||
req.payload.user.v.req.reset.reset_delay_in_ms = delay;
|
||||
/* Send the message until it is received */
|
||||
return opahrs_msg_v0_send_req(&req);
|
||||
}
|
||||
|
||||
enum opahrs_result PIOS_OPAHRS_bl_boot(uint32_t delay)
|
||||
{
|
||||
struct opahrs_msg_v0 req;
|
||||
/* Make up an attituderaw request */
|
||||
opahrs_msg_v0_init_user_tx(&req, OPAHRS_MSG_V0_REQ_BOOT);
|
||||
req.payload.user.v.req.boot.boot_delay_in_ms = delay;
|
||||
/* Send the message until it is received */
|
||||
return opahrs_msg_v0_send_req(&req);
|
||||
}
|
||||
#endif /* PIOS_INCLUDE_OPAHRS */
|
@ -1,7 +1,6 @@
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_RCVR)
|
||||
#ifdef PIOS_INCLUDE_RCVR
|
||||
|
||||
#include <pios_rcvr_priv.h>
|
||||
|
||||
@ -108,7 +107,7 @@ int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel)
|
||||
return rcvr_dev->driver->read(rcvr_dev->lower_id, channel);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_RCVR */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -46,10 +46,9 @@
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_RFM22B)
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
|
||||
#include <pios_spi_priv.h>
|
||||
#include <packet_handler.h>
|
||||
@ -2615,7 +2614,7 @@ static enum pios_rfm22b_event rfm22_fatal_error(struct pios_rfm22b_dev *rfm22b_d
|
||||
|
||||
// ************************************
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_RFM22B */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,9 +28,10 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include <pios.h>
|
||||
|
||||
#ifdef PIOS_INCLUDE_RFM22B_COM
|
||||
|
||||
#include <pios_rfm22b_priv.h>
|
||||
|
||||
/* Provide a COM driver */
|
||||
@ -125,3 +126,5 @@ static bool PIOS_RFM22B_COM_Available(uint32_t rfm22b_id)
|
||||
{
|
||||
return PIOS_RFM22B_LinkStatus(rfm22b_id);
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_RFM22B_COM */
|
||||
|
@ -28,10 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_RFM22B_RCVR)
|
||||
#ifdef PIOS_INCLUDE_RFM22B_RCVR
|
||||
|
||||
#include "pios_rfm22b_priv.h"
|
||||
|
||||
@ -91,7 +90,7 @@ static void PIOS_RFM22B_RCVR_Supervisor(uint32_t rcvr_id) {
|
||||
rfm22b_dev->ppm_fresh = false;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_GCSRCVR */
|
||||
#endif /* PIOS_INCLUDE_RFM22B_RCVR */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,11 +28,11 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
#include "pios_sbus_priv.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_SBUS)
|
||||
#ifdef PIOS_INCLUDE_SBUS
|
||||
|
||||
#include "pios_sbus_priv.h"
|
||||
|
||||
/* Forward Declarations */
|
||||
static int32_t PIOS_SBus_Get(uint32_t rcvr_id, uint8_t channel);
|
||||
@ -332,7 +332,7 @@ static void PIOS_SBus_Supervisor(uint32_t sbus_id)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_SBUS */
|
||||
#endif /* PIOS_INCLUDE_SBUS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -29,10 +29,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_SDCARD)
|
||||
#ifdef PIOS_INCLUDE_SDCARD
|
||||
|
||||
/* Global Variables */
|
||||
VOLINFO PIOS_SDCARD_VolInfo;
|
||||
@ -1000,7 +999,7 @@ int32_t PIOS_SDCARD_FileDelete(char *Filename)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_SDCARD */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,6 +28,10 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_USB
|
||||
|
||||
#include "pios_usb_desc_hid_cdc_priv.h" /* exported API */
|
||||
#include "pios_usb_defs.h" /* struct usb_*, USB_* */
|
||||
#include "pios_usb_board_data.h" /* PIOS_USB_BOARD_* */
|
||||
@ -324,3 +328,5 @@ int32_t PIOS_USB_DESC_HID_CDC_Init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_USB */
|
||||
|
@ -28,6 +28,10 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_USB
|
||||
|
||||
#include "pios_usb_desc_hid_only_priv.h" /* exported API */
|
||||
#include "pios_usb_defs.h" /* struct usb_*, USB_* */
|
||||
#include "pios_usb_board_data.h" /* PIOS_USB_BOARD_* */
|
||||
@ -163,3 +167,5 @@ int32_t PIOS_USB_DESC_HID_ONLY_Init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_USB */
|
||||
|
@ -28,6 +28,10 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_USB
|
||||
|
||||
#include "pios_usb_util.h"
|
||||
|
||||
uint8_t * PIOS_USB_UTIL_AsciiToUtf8(uint8_t * dst, uint8_t * src, uint16_t srclen)
|
||||
@ -40,3 +44,5 @@ uint8_t * PIOS_USB_UTIL_AsciiToUtf8(uint8_t * dst, uint8_t * src, uint16_t srcle
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_USB */
|
||||
|
@ -30,7 +30,8 @@
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
#if defined(PIOS_INCLUDE_VIDEO)
|
||||
|
||||
#ifdef PIOS_INCLUDE_VIDEO
|
||||
|
||||
extern xSemaphoreHandle osdSemaphore;
|
||||
|
||||
@ -277,7 +278,4 @@ void PIOS_VIDEO_DMA_Handler(void)
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* PIOS_INCLUDE_VIDEO */
|
||||
|
@ -30,7 +30,8 @@
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
#if defined(PIOS_INCLUDE_WAVE)
|
||||
|
||||
#ifdef PIOS_INCLUDE_WAVE
|
||||
|
||||
static const struct pios_dac_cfg * dev_cfg;
|
||||
|
||||
@ -606,7 +607,4 @@ void DAC_DMA_Handler(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* PIOS_INCLUDE_WAVE */
|
||||
|
@ -1,368 +0,0 @@
|
||||
README.TXT (C) Copyright 2006
|
||||
DOSFS Level 1 Version 1.02 Lewin A.R.W. Edwards (sysadm@zws.com)
|
||||
=====================================================================
|
||||
|
||||
Abstract
|
||||
========
|
||||
DOSFS is a FAT-compatible filesystem intended for fairly low-end
|
||||
embedded applications. It is not the leanest possible implementation
|
||||
(the leanest FAT implementations operate in << 512 bytes of RAM, with
|
||||
heavy restrictions). This code strikes a good balance between size
|
||||
and functionality, with an emphasis on RAM footprint.
|
||||
|
||||
Intended target systems would be in the ballpark of 1K RAM, 4K ROM
|
||||
or more.
|
||||
|
||||
Features:
|
||||
* Supports FAT12, FAT16 and FAT32 volumes
|
||||
* Supports storage devices up to 2048Gbytes in size (LBA32)
|
||||
* Supports devices with or without MBRs (hard disks vs. floppy disks
|
||||
or ZIP drives formatted as "big floppies")
|
||||
* Supports multiple partitions on disks with MBRs
|
||||
* Supports subdirectories
|
||||
* Can be operated with a single global 512-byte sector buffer
|
||||
* Fully reentrant code (assuming the underlying physical device driver
|
||||
is reentrant and global sector buffers are not used). There are no
|
||||
global variables in the filesystem
|
||||
* Does not perform any memory allocation
|
||||
* Partial support for random-access files
|
||||
|
||||
Applications:
|
||||
* Firmware upgrades
|
||||
* Failsafe IPL
|
||||
* Media playback
|
||||
* Data logging
|
||||
* Configuration storage
|
||||
|
||||
There is no technical support for this free product; however, if you
|
||||
have questions or suggestions, you are encouraged to email Lewin
|
||||
Edwards at sysadm@zws.com. If you need custom additions to the code,
|
||||
or if you have other projects for which you need engineering
|
||||
assistance, please feel free to email or call (646) 549-3715.
|
||||
|
||||
License
|
||||
=======
|
||||
The license for DOSFS is very simple but verbose to state.
|
||||
|
||||
1. DOSFS is (C) Copyright 2006 by Lewin A.R.W. Edwards ("Author").
|
||||
All rights not explicitly granted herein are reserved. The DOSFS
|
||||
code is the permanent property of the Author and no transfer of
|
||||
ownership is implied by this license.
|
||||
|
||||
2. DOSFS is an educational project, provided as-is. No guarantee of
|
||||
performance or suitability for any application is stated or
|
||||
implied. You use this product entirely at your own risk. Use of
|
||||
this product in any manner automatically waives any right to seek
|
||||
compensation or damages of any sort from the Author. Since the
|
||||
products you might make are entirely out of the Author's control,
|
||||
use of this product also constitutes an agreement by you to take
|
||||
full responsibility for and indemnify the Author against any
|
||||
action for any loss or damage (including economic loss of any
|
||||
type, and specifically including patent litigation) that arises
|
||||
from a product made by you that incorporates any portion of
|
||||
the DOSFS code.
|
||||
|
||||
3. If you live under the jurisdiction of any legislation that would
|
||||
prohibit or limit any condition in this license, you cannot be
|
||||
licensed to use this product.
|
||||
|
||||
4. If you do not fall into the excluded category in point 3, you are
|
||||
hereby licensed to use the DOSFS code in any application that you
|
||||
see fit. You are not required to pay any fee or notify the Author
|
||||
that you are using DOSFS. Any modifications made by you to the
|
||||
DOSFS code are your property and you may distribute the modified
|
||||
version in any manner that you wish. You are not required to
|
||||
disclose sourcecode to such modifications, either to the Author or
|
||||
to any third party. Any such disclosure made to the Author will
|
||||
irrevocably become the property of the Author in the absence of a
|
||||
formal agreement to the contrary, established prior to such
|
||||
disclosure being made.
|
||||
|
||||
To summarize the intent of the above: DOSFS is free. You can do what
|
||||
you want with it. Anything that happens as a result is entirely your
|
||||
responsibility. You can't take ownership of my code and stop me from
|
||||
doing whatever I want with it. If you do something nifty with DOSFS
|
||||
and send me the sourcecode, I may include your changes in the next
|
||||
distribution and it will be released to the world as free software.
|
||||
If someone sues you because your DOSFS-containing product causes
|
||||
any sort of legal, financial or other problem, it's your lawsuit,
|
||||
not mine, and you'll exclude me from the proceedings.
|
||||
|
||||
User-Supplied Functions
|
||||
=======================
|
||||
You must provide functions to read sectors into memory and write
|
||||
them back to the target media. The demo suite includes an emulation
|
||||
module that reads/writes a disk image file (#define HOSTVER pulls
|
||||
in hostemu.h which wraps the prototypes for these functions).
|
||||
There are various tools for UNIX, DOS, Windows et al, to create
|
||||
images from storage media; my preferred utility is dd.
|
||||
|
||||
The functions you must supply in your embedded app are:
|
||||
|
||||
DFS_ReadSector(unit,buffer,sector,count)
|
||||
DFS_WriteSector(unit,buffer,sector,count)
|
||||
|
||||
These two functions read and write, respectively, "count" sectors of
|
||||
size SECTOR_SIZE (512 bytes; see below) from/to physical sector
|
||||
#"sector" of device "unit", to/from the scratch buffer "buffer". They
|
||||
should return 0 for success or nonzero for failure. In the current
|
||||
implementation of DOSFS, count will always be 1.
|
||||
|
||||
The "unit" argument is designed to permit implementation of multiple
|
||||
storage devices, for example multiple media slots on a single device,
|
||||
or to differentiate between master and slave devices on an ATAPI bus.
|
||||
|
||||
This code is designed for 512-byte sectors. Although the sector size
|
||||
is a #define, you should not tinker with it because the vast majority
|
||||
of FAT filesystems use 512-byte sectors, and the DOSFS code doesn't
|
||||
support runtime determination of sector size. This will not affect the
|
||||
vast majority of users.
|
||||
|
||||
Example Code
|
||||
============
|
||||
Refer to the tests in main.c to see how to call DOSFS functions.
|
||||
(These tests are all commented out). Note that the only two files
|
||||
you need to add to your project are dosfs.c and dosfs.h.
|
||||
|
||||
|
||||
Mounting Volumes
|
||||
================
|
||||
--If the device has a partition table (practically all removable flash
|
||||
media are formatted this way), call DFS_GetPtnStart to get the
|
||||
starting sector# of the desired partition. You can optionally also
|
||||
retrieve the active state, partition type byte and partition size
|
||||
in this step. The reason this step is broken out separately is so
|
||||
you can support devices that are formatted like a floppy disk, i.e.
|
||||
the volume starts directly at physical sector 0 of the media.
|
||||
|
||||
--Call DFS_GetVolInfo to read filesystem info into a VOLINFO structure.
|
||||
DFS_GetVolInfo needs to know the unit number and partition starting
|
||||
sector (as returned by DFS_GetPtnStart, or 0 if this is a "floppy-
|
||||
format" volume without an MBR).
|
||||
|
||||
From this point on, the VOLINFO structure is all you'll need - you can
|
||||
forget the unit and partition start sector numbers.
|
||||
|
||||
Enumerating Directory Contents
|
||||
==============================
|
||||
--Call DFS_Opendir and supply a path, populated VOLINFO and a
|
||||
DIRINFO structure to receive the results. Note - you must PREPOPULATE
|
||||
the DIRINFO.scratch field with a pointer to a sector scratch buffer.
|
||||
This buffer must remain unmolested while you have the directory open
|
||||
for searching.
|
||||
--Call DFS_GetNext to receive the DIRENT contents for the next directory
|
||||
item. This function returns DFS_OK for no error, and DFS_EOF if there
|
||||
are no more entries in the directory being searched.
|
||||
Before using the DIRENT, check the first character of the name. If it
|
||||
is NULL, then this is an unusable entry - call DFS_GetNext again to
|
||||
keep searching. LFN directory entries are automatically tagged this way
|
||||
so your application will not be pestered by them.
|
||||
|
||||
Note: A designed side-effect of this code is that when you locate the
|
||||
file of interest, the DIRINFO.currentcluster, DIRINFO.currentsector
|
||||
and DIRINFO.currententry-1 fields will identify the directory entry of
|
||||
interest.
|
||||
|
||||
Reading a File
|
||||
==============
|
||||
--Call DFS_OpenFile with mode = DFS_READ and supply a path and the relevant
|
||||
VOLINFO structure. DFS_OpenFile will populate a FILEINFO that can be used
|
||||
to refer to the file.
|
||||
--Optionally call DFS_Seek to set the file pointer. If you attempt to set
|
||||
the file pointer past the end of file, the file will NOT be extended. Check
|
||||
the FILEINFO.pointer value after DFS_Seek to verify that the pointer is
|
||||
where you expect it to be.
|
||||
--Observe that functionality similar to the "whence" parameter of fseek() can
|
||||
be obtained by using simple arithmetic on the FILEINFO.pointer and
|
||||
FILEINFO.filelen members.
|
||||
--Call DFS_ReadFile with the FILEINFO you obtained from OpenFile, and a
|
||||
pointer to a buffer plus the desired number of bytes to read, and a
|
||||
pointer to a sector-sized scratch buffer. The reason a scratch sector is
|
||||
required is because the underlying sector read function doesn't know
|
||||
about partial reads.
|
||||
--Note that a file opened for reading cannot be written. If you need r/w
|
||||
access, open with mode = DFS_WRITE (see below).
|
||||
|
||||
Writing a file
|
||||
==============
|
||||
--Call DFS_OpenFile with mode = DFS_WRITE and supply a path and the relevant
|
||||
VOLINFO structure. DFS_OpenFile will populate a FILEINFO that can be used to
|
||||
refer to the file.
|
||||
--Optionally call DFS_Seek to set the file pointer. Refer to the notes on
|
||||
this topic in the section on reading files, above.
|
||||
--Call DFS_WriteFile with the FILEINFO you obtained from OpenFile, and a
|
||||
pointer to the source buffer, and a pointer to a sector-sized scratch
|
||||
buffer.
|
||||
--Note that a file open for writing can also be read.
|
||||
--Files are created automatically if they do not exist. Subdirectories are
|
||||
NOT automatically created.
|
||||
--If you open an existing file for writing, the file pointer will start at
|
||||
the beginning of the data; if you want to append, seek to the end before
|
||||
writing new data.
|
||||
--If you perform random-access writes to a file, the length will NOT change
|
||||
unless you exceed the file's original length. There is currently no
|
||||
function to truncate a file at the current pointer position.
|
||||
--On-disk consistency is guaranteed when DFS_WriteFile exits, unless your
|
||||
physical layer has a writeback cache in it.
|
||||
|
||||
Deleting a file
|
||||
===============
|
||||
--Call DFS_UnlinkFile
|
||||
--WARNING: This call will delete a subdirectory (correctly) but will NOT
|
||||
first recurse the directory to delete the contents - so you will end up
|
||||
with lost clusters.
|
||||
|
||||
Notes
|
||||
=====
|
||||
Some platforms may require explicit pragmas or attributes to the structures
|
||||
and unions. For example, arm-gcc will require __attribute__ ((__packed__))
|
||||
otherwise it will try to be "smart" and place the uint8_t members on 4-byte
|
||||
boundaries. There is no truly elegant compiler-independent method to get
|
||||
around this sort of problem.
|
||||
|
||||
The code assumes either a von Neumann architecture, or a compiler that
|
||||
is smart enough to understand where your pointers are aimed and emit
|
||||
the right kind of memory read and write instructions. The implications
|
||||
of this statement depend on your target processor and the compiler you
|
||||
are using. Be very careful not to straddle bank boundaries on bank-
|
||||
switched memory systems.
|
||||
|
||||
Physical 32-bit sector numbers are used throughout. Therefore, the
|
||||
CHS geometry (if any) of the storage media is not known to DOSFS. Your
|
||||
sector r/w functions may need to query the CHS geometry and perform
|
||||
mapping.
|
||||
|
||||
File timestamps set by DOSFS are always 1:01:00am on Jan 1, 2006. If
|
||||
your system has a concept of real time, you can enhance this.
|
||||
|
||||
FILEINFO structures contain a pointer to the corresponding VOLINFO
|
||||
used to open the file, mainly in order to avoid mixups but also to
|
||||
obviate the need for an extra parameter to every file read/write. DOSFS
|
||||
assumes that the VOLINFO won't move around. If you need to move or
|
||||
destroy VOLINFOs pertaining to open files, you'll have to fix up the
|
||||
pointer in the FILEINFO structure yourself.
|
||||
|
||||
The subdirectory delimiter is a forward slash ( '/' ) by default. The
|
||||
reason for this is to avoid the common programming error of forgetting
|
||||
that backslash is an escape character in C strings; i.e. "\MYDIR\FILE"
|
||||
is NOT what you want; "\\MYDIR\\FILE" is what you wanted to type. If you
|
||||
are porting DOS code into an embedded environment, feel free to change
|
||||
this #define.
|
||||
|
||||
DOSFS does not have a concept of "current directory". A current directory
|
||||
is owned by a process, and a process is an operating system concept.
|
||||
DOSFS is a filesystem library, not an operating system. Therefore, any
|
||||
path you provide to a DOSFS call is assumed to be relative to the root of
|
||||
the volume.
|
||||
|
||||
There is no call to close a file or directory that is open for reading or
|
||||
writing. You can simply destroy or reuse the data structures allocated for
|
||||
that operation; there is no internal state in DOSFS so no cleanup is
|
||||
necessary. Similarly, there is no call to close a file that is open for
|
||||
writing. (Observe that dosfs.c has no global variables. All state information
|
||||
is stored in data structures provided by the caller).
|
||||
|
||||
MAX_PATH is defined as 64. MS-type DOS filesystems support 128 characters
|
||||
or more in paths. You can increase this define, but it may GREATLY
|
||||
increase memory requirements.
|
||||
|
||||
VFAT long filenames are not supported. There is a certain amount of
|
||||
patent controversy about them, but more importantly they don't really
|
||||
belong in the scope of a "minimalist embedded filesystem".
|
||||
|
||||
Improving Performance
|
||||
=====================
|
||||
Read performance is fairly good, but can be improved by implementing read
|
||||
caching on the FAT (see below) and, depending on your hardware platform,
|
||||
possibly by implementing multi-sector reads.
|
||||
|
||||
Write performance may benefit ENORMOUSLY from platform-specific
|
||||
optimization, especially if you are working with a flash media type that
|
||||
has a large erase block size. While it is not possible to offer detailed
|
||||
platform-independent advice, my general advice is to implement writeback
|
||||
caching on the FAT area. One method for doing this would be to have a
|
||||
cache system that lives in the DFS_ReadSector/WriteSector functions (on
|
||||
top of the physical sector r/w functions) and is initially switched off.
|
||||
Once you have called DFS_GetVolInfo, you then extract the VOLINFO.fat1
|
||||
and VOLINFO.rootdir parameters and pass them to your caching layer.
|
||||
Sectors >= fat1 and < rootdir should be cached. The cache strategy is
|
||||
determined by the physical storage medium underlying the filesystem.
|
||||
|
||||
CACHING HINT:
|
||||
Observe that there will be numerous read-modify-write operations in the
|
||||
region from VOLINFO.fat1 through VOLINFO.fat1+VOLINFO.secperfat-1, but
|
||||
in the region from VOLINFO.fat1+VOLINFO.secperfat through VOLINFO.rootdir
|
||||
there will ONLY be write operations.
|
||||
|
||||
Platform Compatibility
|
||||
======================
|
||||
DOSFS was derived from code originally written for ARM7TDMI but
|
||||
designed to be portable. It has been tested on AVR (using avrgcc),
|
||||
MSP430 (using Rowley's CrossWorks) and PPC603e (using gcc); the host
|
||||
test suite has also been validated on x86 using gcc under both Cygwin
|
||||
and 32-bit Fedora Core 4 Linux.
|
||||
|
||||
TODO list
|
||||
=========
|
||||
* Add function to create subdirectory
|
||||
* Make DFS_UnlinkFile recognize non-empty subdirectories
|
||||
* Support "fast write" files where the FAT is not updated, for
|
||||
logging applications where latency is important.
|
||||
|
||||
Test cases for V1.02
|
||||
====================
|
||||
Version 1.02 has NOT been through full regression testing. However the
|
||||
bugs fixed in this version are important, and people have been asking
|
||||
about them.
|
||||
|
||||
Test cases for V1.01
|
||||
====================
|
||||
See below.
|
||||
|
||||
Test cases for V1.00
|
||||
====================
|
||||
These are the test cases that were used to validate the correct
|
||||
functionality of the DOSFS suite. Each test was performed on FAT12,
|
||||
FAT16 and FAT32 volumes. P=Pass, F=Fail.
|
||||
|
||||
Case F12 F16 F32
|
||||
---------------------------------------------------------------------
|
||||
Get volume information P P P
|
||||
Open root directory P P P
|
||||
List contents of root directory (fully populated) P P P
|
||||
Open subdirectory P P P
|
||||
List contents of subdirectory (<= 1 cluster) P P P
|
||||
List contents of large subdirectory (> 1 cluster) P P P
|
||||
Open 5-level nested subdirectory P P P
|
||||
Open existing file for reading P P P
|
||||
Open nonexistent file for reading P P P
|
||||
Seek past EOF, file open for reading P P P
|
||||
Seek to cluster boundary P P P
|
||||
Seek past cluster boundary P P P
|
||||
Seek backwards to nonzero offset, pointer > cluster size P P P
|
||||
Block-read entire file >1 cluster in size, odd size P P P
|
||||
Seek to odd location in file P P P
|
||||
Perform <1 sector reads from random file locations P P P
|
||||
Open nonexistent file for writing in root dir P P P
|
||||
Open nonexistent file for writing in subdir P P P
|
||||
Repeat prev. 2 tests on volume with 0 free clusters P P P
|
||||
Seek past EOF, file open for writing P P P
|
||||
Open existing file for writing in root dir P P P
|
||||
Write random-length records to file, 20 clusters total P P P
|
||||
MS-DOS 6.0 SCANDISK cross-check P P P
|
||||
|
||||
Revision History
|
||||
================
|
||||
Jan-06-2005 larwe Initial release (1.0)
|
||||
Jan-29-2006 larwe Bugfix release (1.01)
|
||||
- Fixed error in FAT12 FAT read on boundary of sector
|
||||
- Improved compilability under avrgcc
|
||||
Sep-16-2006 larwe Bugfix release (1.02)
|
||||
- DFS_Seek would not correctly rewind to start of file
|
||||
- DFS_Seek would not correctly seek to a position not on a cluster
|
||||
boundary
|
||||
- DFS_OpenFile fencepost error caused memory access at [start of
|
||||
string-1] with a local variable
|
||||
- DFS_OpenFile could not open a file in the root directory
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
DOSFS has been developed by Lewin Edwards, and is provided as freeware.
|
||||
|
||||
See README.txt for details.
|
||||
|
||||
This package has been downloaded from:
|
||||
http://www.larwe.com/zws/products/dosfs/
|
||||
|
||||
Version 1.03 from 9/30/06 is used.
|
||||
|
||||
|
||||
dfs_sdcard has been added as access layer between DFS functions and PIOS_SDCARD functions
|
||||
|
||||
The original usage examples can be found under unused/main.c
|
||||
|
||||
Addendum:
|
||||
|
||||
TK 2008-12-18:
|
||||
DFS_Seek was running endless, applied a patch which has been posted at
|
||||
http://reza.net/wordpress/?p=110
|
||||
|
||||
TK 2008-12-18:
|
||||
patched the patch: endcluster wasn't calculated correctly
|
||||
|
||||
TK 2008-12-18:
|
||||
added 'DFS_CachingEnabledSet(uint8_t enable)' function to enable a simple
|
||||
caching mechanism. This feature has to be explicitely enabled, as it isn't
|
||||
reentrant and requires to use the same buffer pointer whenever reading a file!
|
||||
|
||||
TK 2008-18-12
|
||||
added missing pendant to DFS_CanonicalToDir;
|
||||
char *DFS_DirToCanonical(char *dest, char *src)
|
||||
expects a 13 byte buffer in *dest
|
||||
|
||||
TK 2009-02-12
|
||||
added dummy "DFS_Close" function
|
||||
It has no effect if writing to SD Card, it's only used by the DosFS wrapper
|
||||
in emulation
|
||||
|
||||
TK 2009-07-04
|
||||
fixed bug in DFS_GetNext() in conjunction with the DFS_GetFreeDirEnt() function
|
||||
New files where not added correctly to subdirectories
|
||||
|
@ -1,143 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org) (tk@midibox.org)
|
||||
* @brief Access layer between DOSFS and PIOS
|
||||
* @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 files */
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
#include "dosfs.h"
|
||||
|
||||
|
||||
/* Local variables */
|
||||
|
||||
/* For caching - this feature has to be explicitly enabled, as it isn't reentrant */
|
||||
/* and requires to use the same buffer pointer whenever reading a file. */
|
||||
static uint32_t last_sector;
|
||||
static uint8_t caching_enabled = 0;
|
||||
|
||||
void DFS_CachingEnabledSet(uint8_t enable)
|
||||
{
|
||||
caching_enabled = enable;
|
||||
last_sector = 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts directory name to canonical name
|
||||
* (missing pendant to DFS_anonicalToDir)
|
||||
* dest must point to a 13-byte buffer
|
||||
*/
|
||||
char *DFS_DirToCanonical(char *dest, char *src)
|
||||
{
|
||||
uint8_t pos = 0;
|
||||
|
||||
while( pos < 8 && src[pos] != ' ' ) {
|
||||
*dest++ = src[pos++];
|
||||
}
|
||||
|
||||
if( src[8] != ' ' ) {
|
||||
*dest++ = '.';
|
||||
|
||||
pos = 8;
|
||||
while( pos < 11 && src[pos] != ' ' ) {
|
||||
*dest++ = src[pos++];
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate string */
|
||||
*dest = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Read sector from SD Card
|
||||
* Returns 0 OK, nonzero for any error
|
||||
*/
|
||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count)
|
||||
{
|
||||
/* Only allow access to single unit */
|
||||
if(unit != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* According to README.txt, count is always 1 - check this! */
|
||||
if(count != 1) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Cache: */
|
||||
if(caching_enabled && sector == last_sector) {
|
||||
/* we assume that sector is already in *buffer */
|
||||
/* since the user has to take care that the same buffer is used for file reads, this */
|
||||
/* feature has to be explicitly enabled with DFS_CachingEnabledSet(uint8_t enable) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
last_sector = sector;
|
||||
|
||||
/* Forward to PIOS */
|
||||
int32_t status;
|
||||
if((status = PIOS_SDCARD_SectorRead(sector, buffer)) < 0) {
|
||||
/* Cannot access SD Card */
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write sector to SD Card
|
||||
* Returns 0 OK, nonzero for any error
|
||||
*/
|
||||
uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count)
|
||||
{
|
||||
/* Only allow access to single unit */
|
||||
if(unit != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* According to README.txt, count is always 1 - check this! */
|
||||
if(count != 1) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Invalidate cache */
|
||||
last_sector = 0xffffffff;
|
||||
|
||||
/* Forward to PIOS */
|
||||
int32_t status;
|
||||
if((status = PIOS_SDCARD_SectorWrite(sector, buffer)) < 0) {
|
||||
/* Cannot access SD Card */
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
@ -1,1336 +0,0 @@
|
||||
/*
|
||||
DOSFS Embedded FAT-Compatible Filesystem
|
||||
(C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com)
|
||||
|
||||
You are permitted to modify and/or use this code in your own projects without
|
||||
payment of royalty, regardless of the license(s) you choose for those projects.
|
||||
|
||||
You cannot re-copyright or restrict use of the code as released by Lewin Edwards.
|
||||
*/
|
||||
|
||||
//#include "common.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
//#include "fat.h"
|
||||
|
||||
#define div(a,b) ldiv(a,b)
|
||||
|
||||
#include "dosfs.h"
|
||||
|
||||
/*
|
||||
Get starting sector# of specified partition on drive #unit
|
||||
NOTE: This code ASSUMES an MBR on the disk.
|
||||
scratchsector should point to a SECTOR_SIZE scratch area
|
||||
Returns 0xffffffff for any error.
|
||||
If pactive is non-NULL, this function also returns the partition active flag.
|
||||
If pptype is non-NULL, this function also returns the partition type.
|
||||
If psize is non-NULL, this function also returns the partition size.
|
||||
*/
|
||||
uint32_t DFS_GetPtnStart(uint8_t unit, uint8_t *scratchsector, uint8_t pnum, uint8_t *pactive, uint8_t *pptype, uint32_t *psize)
|
||||
{
|
||||
uint32_t result=0;
|
||||
PMBR mbr = (PMBR) scratchsector;
|
||||
|
||||
// DOS ptable supports maximum 4 partitions
|
||||
if (pnum > 3)
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// Read MBR from target media
|
||||
if (DFS_ReadSector(unit,scratchsector,0,1)) {
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
|
||||
// check if jump to boot, VBR
|
||||
if(mbr->bootcode[0]==0xEB || mbr->bootcode[0]==0xE9){
|
||||
// MBR is actually VBR
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = (uint32_t) mbr->ptable[pnum].start_0 |
|
||||
(((uint32_t) mbr->ptable[pnum].start_1) << 8) |
|
||||
(((uint32_t) mbr->ptable[pnum].start_2) << 16) |
|
||||
(((uint32_t) mbr->ptable[pnum].start_3) << 24);
|
||||
|
||||
if (pactive)
|
||||
*pactive = mbr->ptable[pnum].active;
|
||||
|
||||
if (pptype)
|
||||
*pptype = mbr->ptable[pnum].type;
|
||||
|
||||
if (psize)
|
||||
*psize = (uint32_t) mbr->ptable[pnum].size_0 |
|
||||
(((uint32_t) mbr->ptable[pnum].size_1) << 8) |
|
||||
(((uint32_t) mbr->ptable[pnum].size_2) << 16) |
|
||||
(((uint32_t) mbr->ptable[pnum].size_3) << 24);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Retrieve volume info from BPB and store it in a VOLINFO structure
|
||||
You must provide the unit and starting sector of the filesystem, and
|
||||
a pointer to a sector buffer for scratch
|
||||
Attempts to read BPB and glean information about the FS from that.
|
||||
Returns 0 OK, nonzero for any error.
|
||||
*/
|
||||
uint32_t DFS_GetVolInfo(uint8_t unit, uint8_t *scratchsector, uint32_t startsector, PVOLINFO volinfo)
|
||||
{
|
||||
PLBR lbr = (PLBR) scratchsector;
|
||||
volinfo->unit = unit;
|
||||
volinfo->startsector = startsector;
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_GetVolInfo\r\n");
|
||||
#endif
|
||||
|
||||
if(DFS_ReadSector(unit,scratchsector,startsector,1))
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// tag: OEMID, refer dosfs.h
|
||||
// strncpy(volinfo->oemid, lbr->oemid, 8);
|
||||
// volinfo->oemid[8] = 0;
|
||||
|
||||
volinfo->secperclus = lbr->bpb.secperclus;
|
||||
volinfo->reservedsecs = (uint16_t) lbr->bpb.reserved_l |
|
||||
(((uint16_t) lbr->bpb.reserved_h) << 8);
|
||||
|
||||
volinfo->numsecs = (uint16_t) lbr->bpb.sectors_s_l |
|
||||
(((uint16_t) lbr->bpb.sectors_s_h) << 8);
|
||||
|
||||
if (!volinfo->numsecs)
|
||||
volinfo->numsecs = (uint32_t) lbr->bpb.sectors_l_0 |
|
||||
(((uint32_t) lbr->bpb.sectors_l_1) << 8) |
|
||||
(((uint32_t) lbr->bpb.sectors_l_2) << 16) |
|
||||
(((uint32_t) lbr->bpb.sectors_l_3) << 24);
|
||||
|
||||
// If secperfat is 0, we must be in a FAT32 volume; get secperfat
|
||||
// from the FAT32 EBPB. The volume label and system ID string are also
|
||||
// in different locations for FAT12/16 vs FAT32.
|
||||
volinfo->secperfat = (uint16_t) lbr->bpb.secperfat_l |
|
||||
(((uint16_t) lbr->bpb.secperfat_h) << 8);
|
||||
if (!volinfo->secperfat) {
|
||||
volinfo->secperfat = (uint32_t) lbr->ebpb.ebpb32.fatsize_0 |
|
||||
(((uint32_t) lbr->ebpb.ebpb32.fatsize_1) << 8) |
|
||||
(((uint32_t) lbr->ebpb.ebpb32.fatsize_2) << 16) |
|
||||
(((uint32_t) lbr->ebpb.ebpb32.fatsize_3) << 24);
|
||||
|
||||
memcpy(volinfo->label, lbr->ebpb.ebpb32.label, 11);
|
||||
volinfo->label[11] = 0;
|
||||
|
||||
// tag: OEMID, refer dosfs.h
|
||||
// memcpy(volinfo->system, lbr->ebpb.ebpb32.system, 8);
|
||||
// volinfo->system[8] = 0;
|
||||
}
|
||||
else {
|
||||
memcpy(volinfo->label, lbr->ebpb.ebpb.label, 11);
|
||||
volinfo->label[11] = 0;
|
||||
|
||||
// tag: OEMID, refer dosfs.h
|
||||
// memcpy(volinfo->system, lbr->ebpb.ebpb.system, 8);
|
||||
// volinfo->system[8] = 0;
|
||||
}
|
||||
|
||||
// note: if rootentries is 0, we must be in a FAT32 volume.
|
||||
volinfo->rootentries = (uint16_t) lbr->bpb.rootentries_l |
|
||||
(((uint16_t) lbr->bpb.rootentries_h) << 8);
|
||||
|
||||
// after extracting raw info we perform some useful precalculations
|
||||
volinfo->fat1 = startsector + volinfo->reservedsecs;
|
||||
|
||||
// The calculation below is designed to round up the root directory size for FAT12/16
|
||||
// and to simply ignore the root directory for FAT32, since it's a normal, expandable
|
||||
// file in that situation.
|
||||
if (volinfo->rootentries) {
|
||||
volinfo->rootdir = volinfo->fat1 + (volinfo->secperfat * 2);
|
||||
volinfo->dataarea = volinfo->rootdir + (((volinfo->rootentries * 32) + (SECTOR_SIZE - 1)) / SECTOR_SIZE);
|
||||
}
|
||||
else {
|
||||
volinfo->dataarea = volinfo->fat1 + (volinfo->secperfat * 2);
|
||||
volinfo->rootdir = (uint32_t) lbr->ebpb.ebpb32.root_0 |
|
||||
(((uint32_t) lbr->ebpb.ebpb32.root_1) << 8) |
|
||||
(((uint32_t) lbr->ebpb.ebpb32.root_2) << 16) |
|
||||
(((uint32_t) lbr->ebpb.ebpb32.root_3) << 24);
|
||||
}
|
||||
|
||||
// Calculate number of clusters in data area and infer FAT type from this information.
|
||||
volinfo->numclusters = (volinfo->numsecs - volinfo->dataarea) / volinfo->secperclus;
|
||||
if (volinfo->numclusters < 4085)
|
||||
volinfo->filesystem = FAT12;
|
||||
else if (volinfo->numclusters < 65525)
|
||||
volinfo->filesystem = FAT16;
|
||||
else
|
||||
volinfo->filesystem = FAT32;
|
||||
|
||||
return DFS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Fetch FAT entry for specified cluster number
|
||||
You must provide a scratch buffer for one sector (SECTOR_SIZE) and a populated VOLINFO
|
||||
Returns a FAT32 BAD_CLUSTER value for any error, otherwise the contents of the desired
|
||||
FAT entry.
|
||||
scratchcache should point to a UINT32. This variable caches the physical sector number
|
||||
last read into the scratch buffer for performance enhancement reasons.
|
||||
*/
|
||||
uint32_t DFS_GetFAT(PVOLINFO volinfo, uint8_t *scratch, uint32_t *scratchcache, uint32_t cluster)
|
||||
{
|
||||
uint32_t offset=0, sector=0, result=0;
|
||||
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_GetFAT\r\n");
|
||||
#endif
|
||||
|
||||
if (volinfo->filesystem == FAT12) {
|
||||
offset = cluster + (cluster / 2);
|
||||
}
|
||||
else if (volinfo->filesystem == FAT16) {
|
||||
offset = cluster * 2;
|
||||
}
|
||||
else if (volinfo->filesystem == FAT32) {
|
||||
offset = cluster * 4;
|
||||
}
|
||||
else
|
||||
return 0x0ffffff7; // FAT32 bad cluster
|
||||
|
||||
// at this point, offset is the BYTE offset of the desired sector from the start
|
||||
// of the FAT. Calculate the physical sector containing this FAT entry.
|
||||
sector = ldiv(offset, SECTOR_SIZE).quot + volinfo->fat1;
|
||||
|
||||
// If this is not the same sector we last read, then read it into RAM
|
||||
if (sector != *scratchcache) {
|
||||
if(DFS_ReadSector(volinfo->unit, scratch, sector, 1)) {
|
||||
// avoid anyone assuming that this cache value is still valid, which
|
||||
// might cause disk corruption
|
||||
*scratchcache = 0;
|
||||
return 0x0ffffff7; // FAT32 bad cluster
|
||||
}
|
||||
*scratchcache = sector;
|
||||
}
|
||||
|
||||
// At this point, we "merely" need to extract the relevant entry.
|
||||
// This is easy for FAT16 and FAT32, but a royal PITA for FAT12 as a single entry
|
||||
// may span a sector boundary. The normal way around this is always to read two
|
||||
// FAT sectors, but that luxury is (by design intent) unavailable to DOSFS.
|
||||
offset = ldiv(offset, SECTOR_SIZE).rem;
|
||||
|
||||
if (volinfo->filesystem == FAT12) {
|
||||
// Special case for sector boundary - Store last byte of current sector.
|
||||
// Then read in the next sector and put the first byte of that sector into
|
||||
// the high byte of result.
|
||||
if (offset == SECTOR_SIZE - 1) {
|
||||
result = (uint32_t) scratch[offset];
|
||||
sector++;
|
||||
if(DFS_ReadSector(volinfo->unit, scratch, sector, 1)) {
|
||||
// avoid anyone assuming that this cache value is still valid, which
|
||||
// might cause disk corruption
|
||||
*scratchcache = 0;
|
||||
return 0x0ffffff7; // FAT32 bad cluster
|
||||
}
|
||||
*scratchcache = sector;
|
||||
// Thanks to Claudio Leonel for pointing out this missing line.
|
||||
result |= ((uint32_t) scratch[0]) << 8;
|
||||
}
|
||||
else {
|
||||
result = (uint32_t) scratch[offset] |
|
||||
((uint32_t) scratch[offset+1]) << 8;
|
||||
}
|
||||
if (cluster & 1)
|
||||
result = result >> 4;
|
||||
else
|
||||
result = result & 0xfff;
|
||||
}
|
||||
else if (volinfo->filesystem == FAT16) {
|
||||
result = (uint32_t) scratch[offset] |
|
||||
((uint32_t) scratch[offset+1]) << 8;
|
||||
}
|
||||
else if (volinfo->filesystem == FAT32) {
|
||||
result = ((uint32_t) scratch[offset] |
|
||||
((uint32_t) scratch[offset+1]) << 8 |
|
||||
((uint32_t) scratch[offset+2]) << 16 |
|
||||
((uint32_t) scratch[offset+3]) << 24) & 0x0fffffff;
|
||||
}
|
||||
else
|
||||
result = 0x0ffffff7; // FAT32 bad cluster
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set FAT entry for specified cluster number
|
||||
You must provide a scratch buffer for one sector (SECTOR_SIZE) and a populated VOLINFO
|
||||
Returns DFS_ERRMISC for any error, otherwise DFS_OK
|
||||
scratchcache should point to a UINT32. This variable caches the physical sector number
|
||||
last read into the scratch buffer for performance enhancement reasons.
|
||||
|
||||
NOTE: This code is HIGHLY WRITE-INEFFICIENT, particularly for flash media. Considerable
|
||||
performance gains can be realized by caching the sector. However this is difficult to
|
||||
achieve on FAT12 without requiring 2 sector buffers of scratch space, and it is a design
|
||||
requirement of this code to operate on a single 512-byte scratch.
|
||||
|
||||
If you are operating DOSFS over flash, you are strongly advised to implement a writeback
|
||||
cache in your physical I/O driver. This will speed up your code significantly and will
|
||||
also conserve power and flash write life.
|
||||
*/
|
||||
uint32_t DFS_SetFAT(PVOLINFO volinfo, uint8_t *scratch, uint32_t *scratchcache, uint32_t cluster, uint32_t new_contents)
|
||||
{
|
||||
uint32_t offset=0, sector=0, result=0;
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_SetFAT (%lu->%lu)\r\n",cluster,new_contents);
|
||||
#endif
|
||||
|
||||
if (volinfo->filesystem == FAT12) {
|
||||
offset = cluster + (cluster / 2);
|
||||
new_contents &=0xfff;
|
||||
}
|
||||
else if (volinfo->filesystem == FAT16) {
|
||||
offset = cluster * 2;
|
||||
new_contents &=0xffff;
|
||||
}
|
||||
else if (volinfo->filesystem == FAT32) {
|
||||
offset = cluster * 4;
|
||||
new_contents &=0x0fffffff; // FAT32 is really "FAT28"
|
||||
}
|
||||
else
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// at this point, offset is the BYTE offset of the desired sector from the start
|
||||
// of the FAT. Calculate the physical sector containing this FAT entry.
|
||||
sector = ldiv(offset, SECTOR_SIZE).quot + volinfo->fat1;
|
||||
|
||||
// If this is not the same sector we last read, then read it into RAM
|
||||
if (sector != *scratchcache) {
|
||||
if(DFS_ReadSector(volinfo->unit, scratch, sector, 1)) {
|
||||
// avoid anyone assuming that this cache value is still valid, which
|
||||
// might cause disk corruption
|
||||
*scratchcache = 0;
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
*scratchcache = sector;
|
||||
}
|
||||
|
||||
// At this point, we "merely" need to extract the relevant entry.
|
||||
// This is easy for FAT16 and FAT32, but a royal PITA for FAT12 as a single entry
|
||||
// may span a sector boundary. The normal way around this is always to read two
|
||||
// FAT sectors, but that luxury is (by design intent) unavailable to DOSFS.
|
||||
offset = ldiv(offset, SECTOR_SIZE).rem;
|
||||
|
||||
if (volinfo->filesystem == FAT12) {
|
||||
|
||||
// If this is an odd cluster, pre-shift the desired new contents 4 bits to
|
||||
// make the calculations below simpler
|
||||
if (cluster & 1)
|
||||
new_contents = new_contents << 4;
|
||||
|
||||
// Special case for sector boundary
|
||||
if (offset == SECTOR_SIZE - 1) {
|
||||
|
||||
// Odd cluster: High 12 bits being set
|
||||
if (cluster & 1) {
|
||||
scratch[offset] = (scratch[offset] & 0x0f) | (new_contents & 0xf0);
|
||||
}
|
||||
// Even cluster: Low 12 bits being set
|
||||
else {
|
||||
scratch[offset] = new_contents & 0xff;
|
||||
}
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, *scratchcache, 1);
|
||||
// mirror the FAT into copy 2
|
||||
if (DFS_OK == result)
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, (*scratchcache)+volinfo->secperfat, 1);
|
||||
|
||||
// If we wrote that sector OK, then read in the subsequent sector
|
||||
// and poke the first byte with the remainder of this FAT entry.
|
||||
if (DFS_OK == result) {
|
||||
// *scratchcache++;
|
||||
++*scratchcache; // TK: to avoid warning "value computed is not used"
|
||||
result = DFS_ReadSector(volinfo->unit, scratch, *scratchcache, 1);
|
||||
if (DFS_OK == result) {
|
||||
// Odd cluster: High 12 bits being set
|
||||
if (cluster & 1) {
|
||||
scratch[0] = new_contents & 0xff00;
|
||||
}
|
||||
// Even cluster: Low 12 bits being set
|
||||
else {
|
||||
scratch[0] = (scratch[0] & 0xf0) | (new_contents & 0x0f);
|
||||
}
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, *scratchcache, 1);
|
||||
// mirror the FAT into copy 2
|
||||
if (DFS_OK == result)
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, (*scratchcache)+volinfo->secperfat, 1);
|
||||
}
|
||||
else {
|
||||
// avoid anyone assuming that this cache value is still valid, which
|
||||
// might cause disk corruption
|
||||
*scratchcache = 0;
|
||||
}
|
||||
}
|
||||
} // if (offset == SECTOR_SIZE - 1)
|
||||
|
||||
// Not a sector boundary. But we still have to worry about if it's an odd
|
||||
// or even cluster number.
|
||||
else {
|
||||
// Odd cluster: High 12 bits being set
|
||||
if (cluster & 1) {
|
||||
scratch[offset] = (scratch[offset] & 0x0f) | (new_contents & 0xf0);
|
||||
scratch[offset+1] = new_contents & 0xff00;
|
||||
}
|
||||
// Even cluster: Low 12 bits being set
|
||||
else {
|
||||
scratch[offset] = new_contents & 0xff;
|
||||
scratch[offset+1] = (scratch[offset+1] & 0xf0) | (new_contents & 0x0f);
|
||||
}
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, *scratchcache, 1);
|
||||
// mirror the FAT into copy 2
|
||||
if (DFS_OK == result)
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, (*scratchcache)+volinfo->secperfat, 1);
|
||||
}
|
||||
}
|
||||
else if (volinfo->filesystem == FAT16) {
|
||||
scratch[offset] = (new_contents & 0xff);
|
||||
scratch[offset+1] = (new_contents & 0xff00) >> 8;
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, *scratchcache, 1);
|
||||
// mirror the FAT into copy 2 - XXX
|
||||
if (DFS_OK == result)
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, (*scratchcache)+volinfo->secperfat, 1);
|
||||
}
|
||||
else if (volinfo->filesystem == FAT32) {
|
||||
scratch[offset] = (new_contents & 0xff);
|
||||
scratch[offset+1] = (new_contents & 0xff00) >> 8;
|
||||
scratch[offset+2] = (new_contents & 0xff0000) >> 16;
|
||||
scratch[offset+3] = (scratch[offset+3] & 0xf0) | ((new_contents & 0x0f000000) >> 24);
|
||||
// Note well from the above: Per Microsoft's guidelines we preserve the upper
|
||||
// 4 bits of the FAT32 cluster value. It's unclear what these bits will be used
|
||||
// for; in every example I've encountered they are always zero.
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, *scratchcache, 1);
|
||||
// mirror the FAT into copy 2
|
||||
if (DFS_OK == result)
|
||||
result = DFS_WriteSector(volinfo->unit, scratch, (*scratchcache)+volinfo->secperfat, 1);
|
||||
}
|
||||
else
|
||||
result = DFS_ERRMISC;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert a filename element from canonical (8.3) to directory entry (11) form
|
||||
src must point to the first non-separator character.
|
||||
dest must point to a 12-byte buffer.
|
||||
*/
|
||||
uint8_t *DFS_CanonicalToDir(uint8_t *dest, uint8_t *src)
|
||||
{
|
||||
uint8_t *destptr = dest;
|
||||
|
||||
memset(dest, ' ', 11);
|
||||
dest[11] = 0;
|
||||
|
||||
while (*src && (*src != DIR_SEPARATOR) && (destptr - dest < 11)) {
|
||||
if (*src >= 'a' && *src <='z') {
|
||||
*destptr++ = (*src - 'a') + 'A';
|
||||
src++;
|
||||
}
|
||||
else if (*src == '.') {
|
||||
src++;
|
||||
destptr = dest + 8;
|
||||
}
|
||||
else {
|
||||
*destptr++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
Find the first unused FAT entry
|
||||
You must provide a scratch buffer for one sector (SECTOR_SIZE) and a populated VOLINFO
|
||||
Returns a FAT32 BAD_CLUSTER value for any error, otherwise the contents of the desired
|
||||
FAT entry.
|
||||
Returns FAT32 bad_sector (0x0ffffff7) if there is no free cluster available
|
||||
*/
|
||||
uint32_t DFS_GetFreeFAT(PVOLINFO volinfo, uint8_t *scratch)
|
||||
{
|
||||
uint32_t i, result = 0xffffffff, scratchcache = 0;
|
||||
|
||||
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_GetFreeFAT\r\n");
|
||||
#endif
|
||||
|
||||
// Search starts at cluster 2, which is the first usable cluster
|
||||
// NOTE: This search can't terminate at a bad cluster, because there might
|
||||
// legitimately be bad clusters on the disk.
|
||||
for (i=2; i < volinfo->numclusters; i++) {
|
||||
result = DFS_GetFAT(volinfo, scratch, &scratchcache, i);
|
||||
if (!result) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0x0ffffff7; // Can't find a free cluster
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Open a directory for enumeration by DFS_GetNextDirEnt
|
||||
You must supply a populated VOLINFO (see DFS_GetVolInfo)
|
||||
** you must also make sure dirinfo->scratch is valid in the dirinfo you pass it** //reza
|
||||
The empty string or a string containing only the directory separator are
|
||||
considered to be the root directory.
|
||||
Returns 0 OK, nonzero for any error.
|
||||
*/
|
||||
uint32_t DFS_OpenDir(PVOLINFO volinfo, uint8_t *dirname, PDIRINFO dirinfo)
|
||||
{
|
||||
// Default behavior is a regular search for existing entries
|
||||
dirinfo->flags = 0;
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_OpenDir\r\n");
|
||||
#endif
|
||||
|
||||
if (!strlen((char *) dirname) || (strlen((char *) dirname) == 1 && dirname[0] == DIR_SEPARATOR)) {
|
||||
if (volinfo->filesystem == FAT32) {
|
||||
dirinfo->currentcluster = volinfo->rootdir;
|
||||
dirinfo->currentsector = 0;
|
||||
dirinfo->currententry = 0;
|
||||
|
||||
// read first sector of directory
|
||||
return DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->dataarea + ((volinfo->rootdir - 2) * volinfo->secperclus), 1);
|
||||
}
|
||||
else {
|
||||
dirinfo->currentcluster = 0;
|
||||
dirinfo->currentsector = 0;
|
||||
dirinfo->currententry = 0;
|
||||
|
||||
// read first sector of directory
|
||||
return DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->rootdir, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// This is not the root directory. We need to find the start of this subdirectory.
|
||||
// We do this by devious means, using our own companion function DFS_GetNext.
|
||||
else {
|
||||
uint8_t tmpfn[12];
|
||||
uint8_t *ptr = dirname;
|
||||
uint32_t result;
|
||||
DIRENT de;
|
||||
|
||||
if (volinfo->filesystem == FAT32) {
|
||||
dirinfo->currentcluster = volinfo->rootdir;
|
||||
dirinfo->currentsector = 0;
|
||||
dirinfo->currententry = 0;
|
||||
|
||||
// read first sector of directory
|
||||
if (DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->dataarea + ((volinfo->rootdir - 2) * volinfo->secperclus), 1))
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
else {
|
||||
dirinfo->currentcluster = 0;
|
||||
dirinfo->currentsector = 0;
|
||||
dirinfo->currententry = 0;
|
||||
|
||||
// read first sector of directory
|
||||
if (DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->rootdir, 1))
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
|
||||
// skip leading path separators
|
||||
while (*ptr == DIR_SEPARATOR && *ptr)
|
||||
ptr++;
|
||||
|
||||
// Scan the path from left to right, finding the start cluster of each entry
|
||||
// Observe that this code is inelegant, but obviates the need for recursion.
|
||||
while (*ptr) {
|
||||
DFS_CanonicalToDir(tmpfn, ptr);
|
||||
|
||||
de.name[0] = 0;
|
||||
|
||||
do {
|
||||
result = DFS_GetNext(volinfo, dirinfo, &de);
|
||||
} while (!result && memcmp(de.name, tmpfn, 11));
|
||||
|
||||
if (!memcmp(de.name, tmpfn, 11) && ((de.attr & ATTR_DIRECTORY) == ATTR_DIRECTORY)) {
|
||||
if (volinfo->filesystem == FAT32) {
|
||||
dirinfo->currentcluster = (uint32_t) de.startclus_l_l |
|
||||
((uint32_t) de.startclus_l_h) << 8 |
|
||||
((uint32_t) de.startclus_h_l) << 16 |
|
||||
((uint32_t) de.startclus_h_h) << 24;
|
||||
}
|
||||
else {
|
||||
dirinfo->currentcluster = (uint32_t) de.startclus_l_l |
|
||||
((uint32_t) de.startclus_l_h) << 8;
|
||||
}
|
||||
dirinfo->currentsector = 0;
|
||||
dirinfo->currententry = 0;
|
||||
|
||||
if (DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->dataarea + ((dirinfo->currentcluster - 2) * volinfo->secperclus), 1))
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
else if (!memcmp(de.name, tmpfn, 11) && !(de.attr & ATTR_DIRECTORY))
|
||||
return DFS_NOTFOUND;
|
||||
|
||||
// seek to next item in list
|
||||
while (*ptr != DIR_SEPARATOR && *ptr)
|
||||
ptr++;
|
||||
if (*ptr == DIR_SEPARATOR)
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (!dirinfo->currentcluster)
|
||||
return DFS_NOTFOUND;
|
||||
}
|
||||
return DFS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Get next entry in opened directory structure. Copies fields into the dirent
|
||||
structure, updates dirinfo. Note that it is the _caller's_ responsibility to
|
||||
handle the '.' and '..' entries.
|
||||
A deleted file will be returned as a NULL entry (first char of filename=0)
|
||||
by this code. Filenames beginning with 0x05 will be translated to 0xE5
|
||||
automatically. Long file name entries will be returned as NULL.
|
||||
returns DFS_EOF if there are no more entries, DFS_OK if this entry is valid,
|
||||
or DFS_ERRMISC for a media error
|
||||
*/
|
||||
uint32_t DFS_GetNext(PVOLINFO volinfo, PDIRINFO dirinfo, PDIRENT dirent)
|
||||
{
|
||||
uint32_t tempint; // required by DFS_GetFAT
|
||||
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_GetNext\r\n");
|
||||
#endif
|
||||
|
||||
// Do we need to read the next sector of the directory?
|
||||
if (dirinfo->currententry >= SECTOR_SIZE / sizeof(DIRENT)) {
|
||||
dirinfo->currententry = 0;
|
||||
dirinfo->currentsector++;
|
||||
|
||||
// Root directory; special case handling
|
||||
// Note that currentcluster will only ever be zero if both:
|
||||
// (a) this is the root directory, and
|
||||
// (b) we are on a FAT12/16 volume, where the root dir can't be expanded
|
||||
if (dirinfo->currentcluster == 0) {
|
||||
// Trying to read past end of root directory?
|
||||
if (dirinfo->currentsector * (SECTOR_SIZE / sizeof(DIRENT)) >= volinfo->rootentries)
|
||||
return DFS_EOF;
|
||||
|
||||
// Otherwise try to read the next sector
|
||||
if (DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->rootdir + dirinfo->currentsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
|
||||
// Normal handling
|
||||
else {
|
||||
if (dirinfo->currentsector >= volinfo->secperclus) {
|
||||
dirinfo->currentsector = 0;
|
||||
if ((dirinfo->currentcluster >= 0xff7 && volinfo->filesystem == FAT12) ||
|
||||
(dirinfo->currentcluster >= 0xfff7 && volinfo->filesystem == FAT16) ||
|
||||
(dirinfo->currentcluster >= 0x0ffffff7 && volinfo->filesystem == FAT32)) {
|
||||
|
||||
// We are at the end of the directory chain. If this is a normal
|
||||
// find operation, we should indicate that there is nothing more
|
||||
// to see.
|
||||
if (!(dirinfo->flags & DFS_DI_BLANKENT))
|
||||
return DFS_EOF;
|
||||
|
||||
// On the other hand, if this is a "find free entry" search,
|
||||
// we need to tell the caller to allocate a new cluster
|
||||
else
|
||||
return DFS_ALLOCNEW;
|
||||
}
|
||||
dirinfo->currentcluster = DFS_GetFAT(volinfo, dirinfo->scratch, &tempint, dirinfo->currentcluster);
|
||||
}
|
||||
if (DFS_ReadSector(volinfo->unit, dirinfo->scratch, volinfo->dataarea + ((dirinfo->currentcluster - 2) * volinfo->secperclus) + dirinfo->currentsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(dirent, &(((PDIRENT) dirinfo->scratch)[dirinfo->currententry]), sizeof(DIRENT));
|
||||
|
||||
if (dirent->name[0] == 0) { // no more files in this directory
|
||||
// If this is a "find blank" then we can reuse this name.
|
||||
#if 0
|
||||
if (dirinfo->flags & DFS_DI_BLANKENT)
|
||||
return DFS_OK;
|
||||
#else
|
||||
|
||||
// TK: DFS_GetFreeDirEnt() expects that currententry has been incremented by 1
|
||||
if (dirinfo->flags & DFS_DI_BLANKENT) {
|
||||
dirinfo->currententry++;
|
||||
return DFS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
else
|
||||
return DFS_EOF;
|
||||
}
|
||||
|
||||
if (dirent->name[0] == 0xe5) // handle deleted file entries
|
||||
dirent->name[0] = 0;
|
||||
#if 1
|
||||
// TK: ensure that DFS_GetFreeDirEnt() doesn't return entries with long name
|
||||
else if( dirinfo->flags & DFS_DI_BLANKENT )
|
||||
{} // do nothing..
|
||||
#endif
|
||||
|
||||
else if ((dirent->attr & ATTR_LONG_NAME) == ATTR_LONG_NAME)
|
||||
dirent->name[0] = 0;
|
||||
else if (dirent->name[0] == 0x05) // handle kanji filenames beginning with 0xE5
|
||||
dirent->name[0] = 0xe5;
|
||||
|
||||
dirinfo->currententry++;
|
||||
|
||||
return DFS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
INTERNAL
|
||||
Find a free directory entry in the directory specified by path
|
||||
This function MAY cause a disk write if it is necessary to extend the directory
|
||||
size.
|
||||
Note - di.scratch must be preinitialized to point to a sector scratch buffer
|
||||
de is a scratch structure
|
||||
Returns DFS_ERRMISC if a new entry could not be located or created
|
||||
de is updated with the same return information you would expect from DFS_GetNext
|
||||
*/
|
||||
uint32_t DFS_GetFreeDirEnt(PVOLINFO volinfo, uint8_t *path, PDIRINFO di, PDIRENT de)
|
||||
{
|
||||
uint32_t tempclus=0,i=0;
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_GetFreeDirEnt\r\n");
|
||||
#endif
|
||||
|
||||
if (DFS_OpenDir(volinfo, path, di))
|
||||
return DFS_NOTFOUND;
|
||||
|
||||
// Set "search for empty" flag so DFS_GetNext knows what we're doing
|
||||
di->flags |= DFS_DI_BLANKENT;
|
||||
|
||||
// We seek through the directory looking for an empty entry
|
||||
// Note we are reusing tempclus as a temporary result holder.
|
||||
tempclus = 0;
|
||||
do {
|
||||
tempclus = DFS_GetNext(volinfo, di, de);
|
||||
|
||||
// Empty entry found
|
||||
if (tempclus == DFS_OK && (!de->name[0])) {
|
||||
return DFS_OK;
|
||||
}
|
||||
|
||||
// End of root directory reached
|
||||
else if (tempclus == DFS_EOF)
|
||||
return DFS_ERRMISC;
|
||||
|
||||
else if (tempclus == DFS_ALLOCNEW) {
|
||||
tempclus = DFS_GetFreeFAT(volinfo, di->scratch);
|
||||
if (tempclus == 0x0ffffff7)
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// write out zeroed sectors to the new cluster
|
||||
memset(di->scratch, 0, SECTOR_SIZE);
|
||||
for (i=0;i<volinfo->secperclus;i++) {
|
||||
if (DFS_WriteSector(volinfo->unit, di->scratch, volinfo->dataarea + ((tempclus - 2) * volinfo->secperclus) + i, 1))
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
// Point old end cluster to newly allocated cluster
|
||||
i = 0;
|
||||
DFS_SetFAT(volinfo, di->scratch, &i, di->currentcluster, tempclus);
|
||||
|
||||
// Update DIRINFO so caller knows where to place the new file
|
||||
di->currentcluster = tempclus;
|
||||
di->currentsector = 0;
|
||||
di->currententry = 1; // since the code coming after this expects to subtract 1
|
||||
|
||||
// Mark newly allocated cluster as end of chain
|
||||
switch(volinfo->filesystem) {
|
||||
case FAT12: tempclus = 0xff8; break;
|
||||
case FAT16: tempclus = 0xfff8; break;
|
||||
case FAT32: tempclus = 0x0ffffff8; break;
|
||||
default: return DFS_ERRMISC;
|
||||
}
|
||||
DFS_SetFAT(volinfo, di->scratch, &i, di->currentcluster, tempclus);
|
||||
}
|
||||
} while (!tempclus);
|
||||
|
||||
// We shouldn't get here
|
||||
return DFS_ERRMISC;
|
||||
}
|
||||
|
||||
/*
|
||||
Open a file for reading or writing. You supply populated VOLINFO, a path to the file,
|
||||
mode (DFS_READ or DFS_WRITE) and an empty fileinfo structure. You also need to
|
||||
provide a pointer to a sector-sized scratch buffer.
|
||||
Returns various DFS_* error states. If the result is DFS_OK, fileinfo can be used
|
||||
to access the file from this point on.
|
||||
*/
|
||||
uint32_t DFS_OpenFile(PVOLINFO volinfo, uint8_t *path, uint8_t mode, uint8_t *scratch, PFILEINFO fileinfo)
|
||||
{
|
||||
uint8_t tmppath[MAX_PATH];
|
||||
uint8_t filename[12];
|
||||
uint8_t *p;
|
||||
DIRINFO di;
|
||||
DIRENT de;
|
||||
uint32_t temp;
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_OpenFile\r\n");
|
||||
#endif
|
||||
|
||||
// larwe 2006-09-16 +1 zero out file structure
|
||||
memset(fileinfo, 0, sizeof(FILEINFO));
|
||||
|
||||
// save access mode
|
||||
fileinfo->mode = mode;
|
||||
|
||||
// Get a local copy of the path. If it's longer than MAX_PATH, abort.
|
||||
strncpy((char *) tmppath, (char *) path, MAX_PATH);
|
||||
tmppath[MAX_PATH - 1] = 0;
|
||||
if (strcmp((char *) path,(char *) tmppath)) {
|
||||
return DFS_PATHLEN;
|
||||
}
|
||||
|
||||
// strip leading path separators
|
||||
while (tmppath[0] == DIR_SEPARATOR)
|
||||
strcpy((char *) tmppath, (char *) tmppath + 1);
|
||||
|
||||
// Parse filename off the end of the supplied path
|
||||
p = tmppath;
|
||||
while (*(p++));
|
||||
|
||||
p--;
|
||||
while (p > tmppath && *p != DIR_SEPARATOR) // larwe 9/16/06 ">=" to ">" bugfix
|
||||
p--;
|
||||
if (*p == DIR_SEPARATOR)
|
||||
p++;
|
||||
|
||||
DFS_CanonicalToDir(filename, p);
|
||||
|
||||
if (p > tmppath)
|
||||
p--;
|
||||
if (*p == DIR_SEPARATOR || p == tmppath) // larwe 9/16/06 +"|| p == tmppath" bugfix
|
||||
*p = 0;
|
||||
|
||||
// At this point, if our path was MYDIR/MYDIR2/FILE.EXT, filename = "FILE EXT" and
|
||||
// tmppath = "MYDIR/MYDIR2".
|
||||
di.scratch = scratch;
|
||||
if (DFS_OpenDir(volinfo, tmppath, &di))
|
||||
return DFS_NOTFOUND;
|
||||
|
||||
while (!DFS_GetNext(volinfo, &di, &de)) {
|
||||
if (!memcmp(de.name, filename, 11)) {
|
||||
// You can't use this function call to open a directory.
|
||||
if (de.attr & ATTR_DIRECTORY)
|
||||
return DFS_NOTFOUND;
|
||||
|
||||
fileinfo->volinfo = volinfo;
|
||||
fileinfo->pointer = 0;
|
||||
// The reason we store this extra info about the file is so that we can
|
||||
// speedily update the file size, modification date, etc. on a file that is
|
||||
// opened for writing.
|
||||
if (di.currentcluster == 0)
|
||||
fileinfo->dirsector = volinfo->rootdir + di.currentsector;
|
||||
else
|
||||
fileinfo->dirsector = volinfo->dataarea + ((di.currentcluster - 2) * volinfo->secperclus) + di.currentsector;
|
||||
fileinfo->diroffset = di.currententry - 1;
|
||||
if (volinfo->filesystem == FAT32) {
|
||||
fileinfo->cluster = (uint32_t) de.startclus_l_l |
|
||||
((uint32_t) de.startclus_l_h) << 8 |
|
||||
((uint32_t) de.startclus_h_l) << 16 |
|
||||
((uint32_t) de.startclus_h_h) << 24;
|
||||
}
|
||||
else {
|
||||
fileinfo->cluster = (uint32_t) de.startclus_l_l |
|
||||
((uint32_t) de.startclus_l_h) << 8;
|
||||
}
|
||||
fileinfo->firstcluster = fileinfo->cluster;
|
||||
fileinfo->filelen = (uint32_t) de.filesize_0 |
|
||||
((uint32_t) de.filesize_1) << 8 |
|
||||
((uint32_t) de.filesize_2) << 16 |
|
||||
((uint32_t) de.filesize_3) << 24;
|
||||
|
||||
return DFS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we KNOW the file does not exist. If the file was opened
|
||||
// with write access, we can create it.
|
||||
if (mode & DFS_WRITE) {
|
||||
uint32_t cluster;
|
||||
|
||||
// Locate or create a directory entry for this file
|
||||
if (DFS_OK != DFS_GetFreeDirEnt(volinfo, tmppath, &di, &de))
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// put sane values in the directory entry
|
||||
memset(&de, 0, sizeof(de));
|
||||
memcpy(de.name, filename, 11);
|
||||
de.crttime_l = 0x20; // 01:01:00am, Jan 1, 2006.
|
||||
de.crttime_h = 0x08;
|
||||
de.crtdate_l = 0x11;
|
||||
de.crtdate_h = 0x34;
|
||||
de.lstaccdate_l = 0x11;
|
||||
de.lstaccdate_h = 0x34;
|
||||
de.wrttime_l = 0x20;
|
||||
de.wrttime_h = 0x08;
|
||||
de.wrtdate_l = 0x11;
|
||||
de.wrtdate_h = 0x34;
|
||||
|
||||
// allocate a starting cluster for the directory entry
|
||||
cluster = DFS_GetFreeFAT(volinfo, scratch);
|
||||
|
||||
de.startclus_l_l = cluster & 0xff;
|
||||
de.startclus_l_h = (cluster & 0xff00) >> 8;
|
||||
de.startclus_h_l = (cluster & 0xff0000) >> 16;
|
||||
de.startclus_h_h = (cluster & 0xff000000) >> 24;
|
||||
|
||||
// update FILEINFO for our caller's sake
|
||||
fileinfo->volinfo = volinfo;
|
||||
fileinfo->pointer = 0;
|
||||
// The reason we store this extra info about the file is so that we can
|
||||
// speedily update the file size, modification date, etc. on a file that is
|
||||
// opened for writing.
|
||||
if (di.currentcluster == 0)
|
||||
fileinfo->dirsector = volinfo->rootdir + di.currentsector;
|
||||
else
|
||||
fileinfo->dirsector = volinfo->dataarea + ((di.currentcluster - 2) * volinfo->secperclus) + di.currentsector;
|
||||
fileinfo->diroffset = di.currententry - 1;
|
||||
fileinfo->cluster = cluster;
|
||||
fileinfo->firstcluster = cluster;
|
||||
fileinfo->filelen = 0;
|
||||
|
||||
// write the directory entry
|
||||
// note that we no longer have the sector containing the directory entry,
|
||||
// tragically, so we have to re-read it
|
||||
if (DFS_ReadSector(volinfo->unit, scratch, fileinfo->dirsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
memcpy(&(((PDIRENT) scratch)[di.currententry-1]), &de, sizeof(DIRENT));
|
||||
if (DFS_WriteSector(volinfo->unit, scratch, fileinfo->dirsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// Mark newly allocated cluster as end of chain
|
||||
switch(volinfo->filesystem) {
|
||||
case FAT12: cluster = 0xff8; break;
|
||||
case FAT16: cluster = 0xfff8; break;
|
||||
case FAT32: cluster = 0x0ffffff8; break;
|
||||
default: return DFS_ERRMISC;
|
||||
}
|
||||
temp = 0;
|
||||
DFS_SetFAT(volinfo, scratch, &temp, fileinfo->cluster, cluster);
|
||||
|
||||
return DFS_OK;
|
||||
}
|
||||
|
||||
return DFS_NOTFOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
Read an open file
|
||||
You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
|
||||
pointer to a SECTOR_SIZE scratch buffer.
|
||||
Note that returning DFS_EOF is not an error condition. This function updates the
|
||||
successcount field with the number of bytes actually read.
|
||||
*/
|
||||
uint32_t DFS_ReadFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len)
|
||||
{
|
||||
uint32_t remain=0;
|
||||
uint32_t result = DFS_OK;
|
||||
uint32_t sector=0;
|
||||
uint32_t bytesread=0;
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_ReadFile\r\n");
|
||||
#endif
|
||||
|
||||
// Don't try to read past EOF
|
||||
if (len > fileinfo->filelen - fileinfo->pointer)
|
||||
len = fileinfo->filelen - fileinfo->pointer;
|
||||
|
||||
remain = len;
|
||||
*successcount = 0;
|
||||
|
||||
while (remain && result == DFS_OK) {
|
||||
// This is a bit complicated. The sector we want to read is addressed at a cluster
|
||||
// granularity by the fileinfo->cluster member. The file pointer tells us how many
|
||||
// extra sectors to add to that number.
|
||||
sector = fileinfo->volinfo->dataarea +
|
||||
((fileinfo->cluster - 2) * fileinfo->volinfo->secperclus) +
|
||||
div(div(fileinfo->pointer,fileinfo->volinfo->secperclus * SECTOR_SIZE).rem, SECTOR_SIZE).quot;
|
||||
|
||||
// Case 1 - File pointer is not on a sector boundary
|
||||
if (div(fileinfo->pointer, SECTOR_SIZE).rem) {
|
||||
uint16_t tempreadsize;
|
||||
|
||||
// We always have to go through scratch in this case
|
||||
result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);
|
||||
|
||||
// This is the number of bytes that we actually care about in the sector
|
||||
// just read.
|
||||
tempreadsize = SECTOR_SIZE - (div(fileinfo->pointer, SECTOR_SIZE).rem);
|
||||
|
||||
// Case 1A - We want the entire remainder of the sector. After this
|
||||
// point, all passes through the read loop will be aligned on a sector
|
||||
// boundary, which allows us to go through the optimal path 2A below.
|
||||
if (remain >= tempreadsize) {
|
||||
memcpy(buffer, scratch + (SECTOR_SIZE - tempreadsize), tempreadsize);
|
||||
bytesread = tempreadsize;
|
||||
buffer += tempreadsize;
|
||||
fileinfo->pointer += tempreadsize;
|
||||
remain -= tempreadsize;
|
||||
}
|
||||
// Case 1B - This read concludes the file read operation
|
||||
else {
|
||||
memcpy(buffer, scratch + (SECTOR_SIZE - tempreadsize), remain);
|
||||
|
||||
buffer += remain;
|
||||
fileinfo->pointer += remain;
|
||||
bytesread = remain;
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
// Case 2 - File pointer is on sector boundary
|
||||
else {
|
||||
// Case 2A - We have at least one more full sector to read and don't have
|
||||
// to go through the scratch buffer. You could insert optimizations here to
|
||||
// read multiple sectors at a time, if you were thus inclined (note that
|
||||
// the maximum multi-read you could perform is a single cluster, so it would
|
||||
// be advantageous to have code similar to case 1A above that would round the
|
||||
// pointer to a cluster boundary the first pass through, so all subsequent
|
||||
// [large] read requests would be able to go a cluster at a time).
|
||||
if (remain >= SECTOR_SIZE) {
|
||||
result = DFS_ReadSector(fileinfo->volinfo->unit, buffer, sector, 1);
|
||||
remain -= SECTOR_SIZE;
|
||||
buffer += SECTOR_SIZE;
|
||||
fileinfo->pointer += SECTOR_SIZE;
|
||||
bytesread = SECTOR_SIZE;
|
||||
}
|
||||
// Case 2B - We are only reading a partial sector
|
||||
else {
|
||||
result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);
|
||||
memcpy(buffer, scratch, remain);
|
||||
buffer += remain;
|
||||
fileinfo->pointer += remain;
|
||||
bytesread = remain;
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*successcount += bytesread;
|
||||
|
||||
// check to see if we stepped over a cluster boundary
|
||||
if (div(fileinfo->pointer - bytesread, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot !=
|
||||
div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot) {
|
||||
// An act of minor evil - we use bytesread as a scratch integer, knowing that
|
||||
// its value is not used after updating *successcount above
|
||||
bytesread = 0;
|
||||
if (((fileinfo->volinfo->filesystem == FAT12) && (fileinfo->cluster >= 0xff8)) ||
|
||||
((fileinfo->volinfo->filesystem == FAT16) && (fileinfo->cluster >= 0xfff8)) ||
|
||||
((fileinfo->volinfo->filesystem == FAT32) && (fileinfo->cluster >= 0x0ffffff8)))
|
||||
result = DFS_EOF;
|
||||
else
|
||||
fileinfo->cluster = DFS_GetFAT(fileinfo->volinfo, scratch, &bytesread, fileinfo->cluster);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
Seek file pointer to a given position
|
||||
This function does not return status - refer to the fileinfo->pointer value
|
||||
to see where the pointer wound up.
|
||||
Requires a SECTOR_SIZE scratch buffer
|
||||
*/
|
||||
void DFS_Seek(PFILEINFO fileinfo, uint32_t offset, uint8_t *scratch)
|
||||
{
|
||||
uint32_t tempint;
|
||||
uint16_t endcluster=0; //canny/reza 5/7 fixed
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_Seek\r\n");
|
||||
#endif
|
||||
|
||||
// larwe 9/16/06 bugfix split case 0a/0b and changed fallthrough handling
|
||||
// Case 0a - Return immediately for degenerate case
|
||||
if (offset == fileinfo->pointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 0b - Don't allow the user to seek past the end of the file
|
||||
if (offset > fileinfo->filelen) {
|
||||
offset = fileinfo->filelen;
|
||||
// NOTE NO RETURN HERE!
|
||||
}
|
||||
|
||||
// Case 1 - Simple rewind to start
|
||||
// Note _intentional_ fallthrough from Case 0b above
|
||||
if (offset == 0) {
|
||||
fileinfo->cluster = fileinfo->firstcluster;
|
||||
fileinfo->pointer = 0;
|
||||
return; // larwe 9/16/06 +1 bugfix
|
||||
}
|
||||
// Case 2 - Seeking backwards. Need to reset and seek forwards
|
||||
else if (offset < fileinfo->pointer) {
|
||||
fileinfo->cluster = fileinfo->firstcluster;
|
||||
fileinfo->pointer = 0;
|
||||
// NOTE NO RETURN HERE!
|
||||
}
|
||||
|
||||
// Case 3 - Seeking forwards
|
||||
// Note _intentional_ fallthrough from Case 2 above
|
||||
// Case 3a - Seek size does not cross cluster boundary -
|
||||
// very simple case
|
||||
// larwe 9/16/06 changed .rem to .quot in both div calls, bugfix
|
||||
if (div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot ==
|
||||
div(fileinfo->pointer + offset, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot) {
|
||||
fileinfo->pointer = offset;
|
||||
}
|
||||
// Case 3b - Seeking across cluster boundary(ies)
|
||||
else {
|
||||
// round file pointer down to cluster boundary
|
||||
fileinfo->pointer = div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot *
|
||||
fileinfo->volinfo->secperclus * SECTOR_SIZE;
|
||||
|
||||
// seek by clusters
|
||||
// larwe 9/30/06 bugfix changed .rem to .quot in both div calls
|
||||
// canny/reza 5/7 added endcluster related code
|
||||
// TK 2008-12-18: fixed endcluster calculation
|
||||
// old: endcluster = div(fileinfo->pointer + offset, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot;
|
||||
endcluster = div(offset, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot;
|
||||
while (div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot !=endcluster) {
|
||||
fileinfo->cluster = DFS_GetFAT(fileinfo->volinfo, scratch, &tempint, fileinfo->cluster);
|
||||
// Abort if there was an error
|
||||
if (fileinfo->cluster == 0x0ffffff7) {
|
||||
fileinfo->pointer = 0;
|
||||
fileinfo->cluster = fileinfo->firstcluster;
|
||||
return;
|
||||
}
|
||||
fileinfo->pointer += SECTOR_SIZE * fileinfo->volinfo->secperclus;
|
||||
}
|
||||
|
||||
// since we know the cluster is right, we have no more work to do
|
||||
fileinfo->pointer = offset;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delete a file
|
||||
scratch must point to a sector-sized buffer
|
||||
*/
|
||||
uint32_t DFS_UnlinkFile(PVOLINFO volinfo, uint8_t *path, uint8_t *scratch)
|
||||
{
|
||||
// PDIRENT de = (PDIRENT) scratch;
|
||||
FILEINFO fi;
|
||||
uint32_t cache = 0;
|
||||
uint32_t tempclus = 0;
|
||||
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_UnlinkFile\r\n");
|
||||
#endif
|
||||
|
||||
// DFS_OpenFile gives us all the information we need to delete it
|
||||
if (DFS_OK != DFS_OpenFile(volinfo, path, DFS_READ, scratch, &fi))
|
||||
return DFS_NOTFOUND;
|
||||
|
||||
// First, read the directory sector and delete that entry
|
||||
if (DFS_ReadSector(volinfo->unit, scratch, fi.dirsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
((PDIRENT) scratch)[fi.diroffset].name[0] = 0xe5;
|
||||
if (DFS_WriteSector(volinfo->unit, scratch, fi.dirsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// Now follow the cluster chain to free the file space
|
||||
while (!((volinfo->filesystem == FAT12 && fi.firstcluster >= 0x0ff7) ||
|
||||
(volinfo->filesystem == FAT16 && fi.firstcluster >= 0xfff7) ||
|
||||
(volinfo->filesystem == FAT32 && fi.firstcluster >= 0x0ffffff7))) {
|
||||
tempclus = fi.firstcluster;
|
||||
|
||||
fi.firstcluster = DFS_GetFAT(volinfo, scratch, &cache, fi.firstcluster);
|
||||
DFS_SetFAT(volinfo, scratch, &cache, tempclus, 0);
|
||||
|
||||
}
|
||||
return DFS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Write an open file
|
||||
You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
|
||||
pointer to a SECTOR_SIZE scratch buffer.
|
||||
This function updates the successcount field with the number of bytes actually written.
|
||||
*/
|
||||
uint32_t DFS_WriteFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len)
|
||||
{
|
||||
uint32_t remain=0;
|
||||
uint32_t result = DFS_OK;
|
||||
uint32_t sector=0;
|
||||
uint32_t byteswritten=0;
|
||||
#ifdef DEBUG_DOSFS
|
||||
printf("DFS_WriteFile\r\n");
|
||||
#endif
|
||||
|
||||
|
||||
// Don't allow writes to a file that's open as readonly
|
||||
if (!(fileinfo->mode & DFS_WRITE))
|
||||
return DFS_ERRMISC;
|
||||
|
||||
remain = len;
|
||||
*successcount = 0;
|
||||
|
||||
while (remain && result == DFS_OK) {
|
||||
// This is a bit complicated. The sector we want to read is addressed at a cluster
|
||||
// granularity by the fileinfo->cluster member. The file pointer tells us how many
|
||||
// extra sectors to add to that number.
|
||||
sector = fileinfo->volinfo->dataarea +
|
||||
((fileinfo->cluster - 2) * fileinfo->volinfo->secperclus) +
|
||||
div(div(fileinfo->pointer,fileinfo->volinfo->secperclus * SECTOR_SIZE).rem, SECTOR_SIZE).quot;
|
||||
|
||||
// Case 1 - File pointer is not on a sector boundary
|
||||
if (div(fileinfo->pointer, SECTOR_SIZE).rem) {
|
||||
uint16_t tempsize;
|
||||
|
||||
// We always have to go through scratch in this case
|
||||
result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);
|
||||
|
||||
// This is the number of bytes that we don't want to molest in the
|
||||
// scratch sector just read.
|
||||
tempsize = div(fileinfo->pointer, SECTOR_SIZE).rem;
|
||||
|
||||
// Case 1A - We are writing the entire remainder of the sector. After
|
||||
// this point, all passes through the read loop will be aligned on a
|
||||
// sector boundary, which allows us to go through the optimal path
|
||||
// 2A below.
|
||||
if (remain >= SECTOR_SIZE - tempsize) {
|
||||
memcpy(scratch + tempsize, buffer, SECTOR_SIZE - tempsize);
|
||||
if (!result)
|
||||
result = DFS_WriteSector(fileinfo->volinfo->unit, scratch, sector, 1);
|
||||
|
||||
byteswritten = SECTOR_SIZE - tempsize;
|
||||
buffer += SECTOR_SIZE - tempsize;
|
||||
fileinfo->pointer += SECTOR_SIZE - tempsize;
|
||||
if (fileinfo->filelen < fileinfo->pointer) {
|
||||
fileinfo->filelen = fileinfo->pointer;
|
||||
}
|
||||
remain -= SECTOR_SIZE - tempsize;
|
||||
}
|
||||
// Case 1B - This concludes the file write operation
|
||||
else {
|
||||
memcpy(scratch + tempsize, buffer, remain);
|
||||
if (!result)
|
||||
result = DFS_WriteSector(fileinfo->volinfo->unit, scratch, sector, 1);
|
||||
|
||||
buffer += remain;
|
||||
fileinfo->pointer += remain;
|
||||
if (fileinfo->filelen < fileinfo->pointer) {
|
||||
fileinfo->filelen = fileinfo->pointer;
|
||||
}
|
||||
byteswritten = remain;
|
||||
remain = 0;
|
||||
}
|
||||
} // case 1
|
||||
// Case 2 - File pointer is on sector boundary
|
||||
else {
|
||||
// Case 2A - We have at least one more full sector to write and don't have
|
||||
// to go through the scratch buffer. You could insert optimizations here to
|
||||
// write multiple sectors at a time, if you were thus inclined. Refer to
|
||||
// similar notes in DFS_ReadFile.
|
||||
if (remain >= SECTOR_SIZE) {
|
||||
result = DFS_WriteSector(fileinfo->volinfo->unit, buffer, sector, 1);
|
||||
remain -= SECTOR_SIZE;
|
||||
buffer += SECTOR_SIZE;
|
||||
fileinfo->pointer += SECTOR_SIZE;
|
||||
if (fileinfo->filelen < fileinfo->pointer) {
|
||||
fileinfo->filelen = fileinfo->pointer;
|
||||
}
|
||||
byteswritten = SECTOR_SIZE;
|
||||
}
|
||||
// Case 2B - We are only writing a partial sector and potentially need to
|
||||
// go through the scratch buffer.
|
||||
else {
|
||||
// If the current file pointer is not yet at or beyond the file
|
||||
// length, we are writing somewhere in the middle of the file and
|
||||
// need to load the original sector to do a read-modify-write.
|
||||
if (fileinfo->pointer < fileinfo->filelen) {
|
||||
result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);
|
||||
if (!result) {
|
||||
memcpy(scratch, buffer, remain);
|
||||
result = DFS_WriteSector(fileinfo->volinfo->unit, scratch, sector, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = DFS_WriteSector(fileinfo->volinfo->unit, buffer, sector, 1);
|
||||
}
|
||||
|
||||
buffer += remain;
|
||||
fileinfo->pointer += remain;
|
||||
if (fileinfo->filelen < fileinfo->pointer) {
|
||||
fileinfo->filelen = fileinfo->pointer;
|
||||
}
|
||||
byteswritten = remain;
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*successcount += byteswritten;
|
||||
|
||||
// check to see if we stepped over a cluster boundary
|
||||
if (div(fileinfo->pointer - byteswritten, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot !=
|
||||
div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot) {
|
||||
uint32_t lastcluster;
|
||||
|
||||
// We've transgressed into another cluster. If we were already at EOF,
|
||||
// we need to allocate a new cluster.
|
||||
// An act of minor evil - we use byteswritten as a scratch integer, knowing
|
||||
// that its value is not used after updating *successcount above
|
||||
byteswritten = 0;
|
||||
|
||||
lastcluster = fileinfo->cluster;
|
||||
fileinfo->cluster = DFS_GetFAT(fileinfo->volinfo, scratch, &byteswritten, fileinfo->cluster);
|
||||
|
||||
// Allocate a new cluster?
|
||||
if (((fileinfo->volinfo->filesystem == FAT12) && (fileinfo->cluster >= 0xff8)) ||
|
||||
((fileinfo->volinfo->filesystem == FAT16) && (fileinfo->cluster >= 0xfff8)) ||
|
||||
((fileinfo->volinfo->filesystem == FAT32) && (fileinfo->cluster >= 0x0ffffff8))) {
|
||||
uint32_t tempclus;
|
||||
|
||||
tempclus = DFS_GetFreeFAT(fileinfo->volinfo, scratch);
|
||||
byteswritten = 0; // invalidate cache
|
||||
if (tempclus == 0x0ffffff7)
|
||||
return DFS_ERRMISC;
|
||||
|
||||
// Link new cluster onto file
|
||||
DFS_SetFAT(fileinfo->volinfo, scratch, &byteswritten, lastcluster, tempclus);
|
||||
fileinfo->cluster = tempclus;
|
||||
|
||||
// Mark newly allocated cluster as end of chain
|
||||
switch(fileinfo->volinfo->filesystem) {
|
||||
case FAT12: tempclus = 0xff8; break;
|
||||
case FAT16: tempclus = 0xfff8; break;
|
||||
case FAT32: tempclus = 0x0ffffff8; break;
|
||||
default: return DFS_ERRMISC;
|
||||
}
|
||||
DFS_SetFAT(fileinfo->volinfo, scratch, &byteswritten, fileinfo->cluster, tempclus);
|
||||
|
||||
result = DFS_OK;
|
||||
}
|
||||
// No else clause is required.
|
||||
}
|
||||
}
|
||||
|
||||
// Update directory entry
|
||||
if (DFS_ReadSector(fileinfo->volinfo->unit, scratch, fileinfo->dirsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
((PDIRENT) scratch)[fileinfo->diroffset].filesize_0 = fileinfo->filelen & 0xff;
|
||||
((PDIRENT) scratch)[fileinfo->diroffset].filesize_1 = (fileinfo->filelen & 0xff00) >> 8;
|
||||
((PDIRENT) scratch)[fileinfo->diroffset].filesize_2 = (fileinfo->filelen & 0xff0000) >> 16;
|
||||
((PDIRENT) scratch)[fileinfo->diroffset].filesize_3 = (fileinfo->filelen & 0xff000000) >> 24;
|
||||
if (DFS_WriteSector(fileinfo->volinfo->unit, scratch, fileinfo->dirsector, 1))
|
||||
return DFS_ERRMISC;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// TK: added 2009-02-12
|
||||
Close a file
|
||||
No original function of DosFS driver
|
||||
It has no effect if writing to SD Card, it's only used by the DosFS wrapper in emulation
|
||||
*/
|
||||
uint32_t DFS_Close(PFILEINFO fileinfo)
|
||||
{
|
||||
return DFS_OK;
|
||||
}
|
||||
|
@ -1,405 +0,0 @@
|
||||
/*
|
||||
DOSFS Embedded FAT-Compatible Filesystem
|
||||
(C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com)
|
||||
*/
|
||||
|
||||
#ifndef _DOSFS_H
|
||||
#define _DOSFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//===================================================================
|
||||
// User-supplied functions
|
||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count);
|
||||
uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count);
|
||||
|
||||
|
||||
//===================================================================
|
||||
// Configurable items
|
||||
#define MAX_PATH 64 // Maximum path length (increasing this will
|
||||
// GREATLY increase stack requirements!)
|
||||
#define DIR_SEPARATOR '/' // character separating directory components
|
||||
|
||||
// End of configurable items
|
||||
//===================================================================
|
||||
|
||||
//===================================================================
|
||||
// 32-bit error codes
|
||||
#define DFS_OK 0 // no error
|
||||
#define DFS_EOF 1 // end of file (not an error)
|
||||
#define DFS_WRITEPROT 2 // volume is write protected
|
||||
#define DFS_NOTFOUND 3 // path or file not found
|
||||
#define DFS_PATHLEN 4 // path too long
|
||||
#define DFS_ALLOCNEW 5 // must allocate new directory cluster
|
||||
#define DFS_ERRMISC 0xffffffff // generic error
|
||||
|
||||
//===================================================================
|
||||
// File access modes
|
||||
#define DFS_READ 1 // read-only
|
||||
#define DFS_WRITE 2 // write-only
|
||||
|
||||
//===================================================================
|
||||
// Miscellaneous constants
|
||||
#define SECTOR_SIZE 512 // sector size in bytes
|
||||
|
||||
//===================================================================
|
||||
// Internal subformat identifiers
|
||||
#define FAT12 0
|
||||
#define FAT16 1
|
||||
#define FAT32 2
|
||||
|
||||
//===================================================================
|
||||
// DOS attribute bits
|
||||
#define ATTR_READ_ONLY 0x01
|
||||
#define ATTR_HIDDEN 0x02
|
||||
#define ATTR_SYSTEM 0x04
|
||||
#define ATTR_VOLUME_ID 0x08
|
||||
#define ATTR_DIRECTORY 0x10
|
||||
#define ATTR_ARCHIVE 0x20
|
||||
#define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID)
|
||||
|
||||
|
||||
/*
|
||||
Directory entry structure
|
||||
note: if name[0] == 0xe5, this is a free dir entry
|
||||
if name[0] == 0x00, this is a free entry and all subsequent entries are free
|
||||
if name[0] == 0x05, the first character of the name is 0xe5 [a kanji nicety]
|
||||
|
||||
Date format: bit 0-4 = day of month (1-31)
|
||||
bit 5-8 = month, 1=Jan..12=Dec
|
||||
bit 9-15 = count of years since 1980 (0-127)
|
||||
Time format: bit 0-4 = 2-second count, (0-29)
|
||||
bit 5-10 = minutes (0-59)
|
||||
bit 11-15= hours (0-23)
|
||||
*/
|
||||
typedef struct _tagDIRENT {
|
||||
uint8_t name[11]; // filename
|
||||
uint8_t attr; // attributes (see ATTR_* constant definitions)
|
||||
uint8_t reserved; // reserved, must be 0
|
||||
uint8_t crttimetenth; // create time, 10ths of a second (0-199 are valid)
|
||||
uint8_t crttime_l; // creation time low byte
|
||||
uint8_t crttime_h; // creation time high byte
|
||||
uint8_t crtdate_l; // creation date low byte
|
||||
uint8_t crtdate_h; // creation date high byte
|
||||
uint8_t lstaccdate_l; // last access date low byte
|
||||
uint8_t lstaccdate_h; // last access date high byte
|
||||
uint8_t startclus_h_l; // high word of first cluster, low byte (FAT32)
|
||||
uint8_t startclus_h_h; // high word of first cluster, high byte (FAT32)
|
||||
uint8_t wrttime_l; // last write time low byte
|
||||
uint8_t wrttime_h; // last write time high byte
|
||||
uint8_t wrtdate_l; // last write date low byte
|
||||
uint8_t wrtdate_h; // last write date high byte
|
||||
uint8_t startclus_l_l; // low word of first cluster, low byte
|
||||
uint8_t startclus_l_h; // low word of first cluster, high byte
|
||||
uint8_t filesize_0; // file size, low byte
|
||||
uint8_t filesize_1; //
|
||||
uint8_t filesize_2; //
|
||||
uint8_t filesize_3; // file size, high byte
|
||||
} DIRENT, *PDIRENT;
|
||||
|
||||
/*
|
||||
Partition table entry structure
|
||||
*/
|
||||
typedef struct _tagPTINFO {
|
||||
uint8_t active; // 0x80 if partition active
|
||||
uint8_t start_h; // starting head
|
||||
uint8_t start_cs_l; // starting cylinder and sector (low byte)
|
||||
uint8_t start_cs_h; // starting cylinder and sector (high byte)
|
||||
uint8_t type; // type ID byte
|
||||
uint8_t end_h; // ending head
|
||||
uint8_t end_cs_l; // ending cylinder and sector (low byte)
|
||||
uint8_t end_cs_h; // ending cylinder and sector (high byte)
|
||||
uint8_t start_0; // starting sector# (low byte)
|
||||
uint8_t start_1; //
|
||||
uint8_t start_2; //
|
||||
uint8_t start_3; // starting sector# (high byte)
|
||||
uint8_t size_0; // size of partition (low byte)
|
||||
uint8_t size_1; //
|
||||
uint8_t size_2; //
|
||||
uint8_t size_3; // size of partition (high byte)
|
||||
} PTINFO, *PPTINFO;
|
||||
|
||||
/*
|
||||
Master Boot Record structure
|
||||
*/
|
||||
typedef struct _tagMBR {
|
||||
uint8_t bootcode[0x1be]; // boot sector
|
||||
PTINFO ptable[4]; // four partition table structures
|
||||
uint8_t sig_55; // 0x55 signature byte
|
||||
uint8_t sig_aa; // 0xaa signature byte
|
||||
} MBR, *PMBR;
|
||||
|
||||
/*
|
||||
BIOS Parameter Block structure (FAT12/16)
|
||||
*/
|
||||
typedef struct _tagBPB {
|
||||
uint8_t bytepersec_l; // bytes per sector low byte (0x00)
|
||||
uint8_t bytepersec_h; // bytes per sector high byte (0x02)
|
||||
uint8_t secperclus; // sectors per cluster (1,2,4,8,16,32,64,128 are valid)
|
||||
uint8_t reserved_l; // reserved sectors low byte
|
||||
uint8_t reserved_h; // reserved sectors high byte
|
||||
uint8_t numfats; // number of FAT copies (2)
|
||||
uint8_t rootentries_l; // number of root dir entries low byte (0x00 normally)
|
||||
uint8_t rootentries_h; // number of root dir entries high byte (0x02 normally)
|
||||
uint8_t sectors_s_l; // small num sectors low byte
|
||||
uint8_t sectors_s_h; // small num sectors high byte
|
||||
uint8_t mediatype; // media descriptor byte
|
||||
uint8_t secperfat_l; // sectors per FAT low byte
|
||||
uint8_t secperfat_h; // sectors per FAT high byte
|
||||
uint8_t secpertrk_l; // sectors per track low byte
|
||||
uint8_t secpertrk_h; // sectors per track high byte
|
||||
uint8_t heads_l; // heads low byte
|
||||
uint8_t heads_h; // heads high byte
|
||||
uint8_t hidden_0; // hidden sectors low byte
|
||||
uint8_t hidden_1; // (note - this is the number of MEDIA sectors before
|
||||
uint8_t hidden_2; // first sector of VOLUME - we rely on the MBR instead)
|
||||
uint8_t hidden_3; // hidden sectors high byte
|
||||
uint8_t sectors_l_0; // large num sectors low byte
|
||||
uint8_t sectors_l_1; //
|
||||
uint8_t sectors_l_2; //
|
||||
uint8_t sectors_l_3; // large num sectors high byte
|
||||
} BPB, *PBPB;
|
||||
|
||||
/*
|
||||
Extended BIOS Parameter Block structure (FAT12/16)
|
||||
*/
|
||||
typedef struct _tagEBPB {
|
||||
uint8_t unit; // int 13h drive#
|
||||
uint8_t head; // archaic, used by Windows NT-class OSes for flags
|
||||
uint8_t signature; // 0x28 or 0x29
|
||||
uint8_t serial_0; // serial#
|
||||
uint8_t serial_1; // serial#
|
||||
uint8_t serial_2; // serial#
|
||||
uint8_t serial_3; // serial#
|
||||
uint8_t label[11]; // volume label
|
||||
uint8_t system[8]; // filesystem ID
|
||||
} EBPB, *PEBPB;
|
||||
|
||||
/*
|
||||
Extended BIOS Parameter Block structure (FAT32)
|
||||
*/
|
||||
typedef struct _tagEBPB32 {
|
||||
uint8_t fatsize_0; // big FAT size in sectors low byte
|
||||
uint8_t fatsize_1; //
|
||||
uint8_t fatsize_2; //
|
||||
uint8_t fatsize_3; // big FAT size in sectors high byte
|
||||
uint8_t extflags_l; // extended flags low byte
|
||||
uint8_t extflags_h; // extended flags high byte
|
||||
uint8_t fsver_l; // filesystem version (0x00) low byte
|
||||
uint8_t fsver_h; // filesystem version (0x00) high byte
|
||||
uint8_t root_0; // cluster of root dir, low byte
|
||||
uint8_t root_1; //
|
||||
uint8_t root_2; //
|
||||
uint8_t root_3; // cluster of root dir, high byte
|
||||
uint8_t fsinfo_l; // sector pointer to FSINFO within reserved area, low byte (2)
|
||||
uint8_t fsinfo_h; // sector pointer to FSINFO within reserved area, high byte (0)
|
||||
uint8_t bkboot_l; // sector pointer to backup boot sector within reserved area, low byte (6)
|
||||
uint8_t bkboot_h; // sector pointer to backup boot sector within reserved area, high byte (0)
|
||||
uint8_t reserved[12]; // reserved, should be 0
|
||||
|
||||
uint8_t unit; // int 13h drive#
|
||||
uint8_t head; // archaic, used by Windows NT-class OSes for flags
|
||||
uint8_t signature; // 0x28 or 0x29
|
||||
uint8_t serial_0; // serial#
|
||||
uint8_t serial_1; // serial#
|
||||
uint8_t serial_2; // serial#
|
||||
uint8_t serial_3; // serial#
|
||||
uint8_t label[11]; // volume label
|
||||
uint8_t system[8]; // filesystem ID
|
||||
} EBPB32, *PEBPB32;
|
||||
|
||||
/*
|
||||
Logical Boot Record structure (volume boot sector)
|
||||
*/
|
||||
typedef struct _tagLBR {
|
||||
uint8_t jump[3]; // JMP instruction
|
||||
uint8_t oemid[8]; // OEM ID, space-padded
|
||||
BPB bpb; // BIOS Parameter Block
|
||||
union {
|
||||
EBPB ebpb; // FAT12/16 Extended BIOS Parameter Block
|
||||
EBPB32 ebpb32; // FAT32 Extended BIOS Parameter Block
|
||||
} ebpb;
|
||||
uint8_t code[420]; // boot sector code
|
||||
uint8_t sig_55; // 0x55 signature byte
|
||||
uint8_t sig_aa; // 0xaa signature byte
|
||||
} LBR, *PLBR;
|
||||
|
||||
/*
|
||||
Volume information structure (Internal to DOSFS)
|
||||
*/
|
||||
typedef struct _tagVOLINFO {
|
||||
uint8_t unit; // unit on which this volume resides
|
||||
uint8_t filesystem; // formatted filesystem
|
||||
|
||||
// These two fields aren't very useful, so support for them has been commented out to
|
||||
// save memory. (Note that the "system" tag is not actually used by DOS to determine
|
||||
// filesystem type - that decision is made entirely on the basis of how many clusters
|
||||
// the drive contains. DOSFS works the same way).
|
||||
// See tag: OEMID in dosfs.c
|
||||
// uint8_t oemid[9]; // OEM ID ASCIIZ
|
||||
// uint8_t system[9]; // system ID ASCIIZ
|
||||
uint8_t label[12]; // volume label ASCIIZ
|
||||
uint32_t startsector; // starting sector of filesystem
|
||||
uint8_t secperclus; // sectors per cluster
|
||||
uint16_t reservedsecs; // reserved sectors
|
||||
uint32_t numsecs; // number of sectors in volume
|
||||
uint32_t secperfat; // sectors per FAT
|
||||
uint16_t rootentries; // number of root dir entries
|
||||
|
||||
uint32_t numclusters; // number of clusters on drive
|
||||
|
||||
// The fields below are PHYSICAL SECTOR NUMBERS.
|
||||
uint32_t fat1; // starting sector# of FAT copy 1
|
||||
uint32_t rootdir; // starting sector# of root directory (FAT12/FAT16) or cluster (FAT32)
|
||||
uint32_t dataarea; // starting sector# of data area (cluster #2)
|
||||
} VOLINFO, *PVOLINFO;
|
||||
|
||||
/*
|
||||
Flags in DIRINFO.flags
|
||||
*/
|
||||
#define DFS_DI_BLANKENT 0x01 // Searching for blank entry
|
||||
|
||||
/*
|
||||
Directory search structure (Internal to DOSFS)
|
||||
*/
|
||||
typedef struct _tagDIRINFO {
|
||||
uint32_t currentcluster; // current cluster in dir
|
||||
uint8_t currentsector; // current sector in cluster
|
||||
uint8_t currententry; // current dir entry in sector
|
||||
uint8_t *scratch; // ptr to user-supplied scratch buffer (one sector)
|
||||
uint8_t flags; // internal DOSFS flags
|
||||
} DIRINFO, *PDIRINFO;
|
||||
|
||||
/*
|
||||
File handle structure (Internal to DOSFS)
|
||||
*/
|
||||
typedef struct _tagFILEINFO {
|
||||
PVOLINFO volinfo; // VOLINFO used to open this file
|
||||
uint32_t dirsector; // physical sector containing dir entry of this file
|
||||
uint8_t diroffset; // # of this entry within the dir sector
|
||||
uint8_t mode; // mode in which this file was opened
|
||||
uint32_t firstcluster; // first cluster of file
|
||||
uint32_t filelen; // byte length of file
|
||||
|
||||
uint32_t cluster; // current cluster
|
||||
uint32_t pointer; // current (BYTE) pointer
|
||||
} FILEINFO, *PFILEINFO;
|
||||
|
||||
/*
|
||||
Get starting sector# of specified partition on drive #unit
|
||||
NOTE: This code ASSUMES an MBR on the disk.
|
||||
scratchsector should point to a SECTOR_SIZE scratch area
|
||||
Returns 0xffffffff for any error.
|
||||
If pactive is non-NULL, this function also returns the partition active flag.
|
||||
If pptype is non-NULL, this function also returns the partition type.
|
||||
If psize is non-NULL, this function also returns the partition size.
|
||||
*/
|
||||
uint32_t DFS_GetPtnStart(uint8_t unit, uint8_t *scratchsector, uint8_t pnum, uint8_t *pactive, uint8_t *pptype, uint32_t *psize);
|
||||
|
||||
/*
|
||||
Retrieve volume info from BPB and store it in a VOLINFO structure
|
||||
You must provide the unit and starting sector of the filesystem, and
|
||||
a pointer to a sector buffer for scratch
|
||||
Attempts to read BPB and glean information about the FS from that.
|
||||
Returns 0 OK, nonzero for any error.
|
||||
*/
|
||||
uint32_t DFS_GetVolInfo(uint8_t unit, uint8_t *scratchsector, uint32_t startsector, PVOLINFO volinfo);
|
||||
|
||||
/*
|
||||
Open a directory for enumeration by DFS_GetNextDirEnt
|
||||
You must supply a populated VOLINFO (see DFS_GetVolInfo)
|
||||
The empty string or a string containing only the directory separator are
|
||||
considered to be the root directory.
|
||||
Returns 0 OK, nonzero for any error.
|
||||
*/
|
||||
uint32_t DFS_OpenDir(PVOLINFO volinfo, uint8_t *dirname, PDIRINFO dirinfo);
|
||||
|
||||
/*
|
||||
Get next entry in opened directory structure. Copies fields into the dirent
|
||||
structure, updates dirinfo. Note that it is the _caller's_ responsibility to
|
||||
handle the '.' and '..' entries.
|
||||
A deleted file will be returned as a NULL entry (first char of filename=0)
|
||||
by this code. Filenames beginning with 0x05 will be translated to 0xE5
|
||||
automatically. Long file name entries will be returned as NULL.
|
||||
returns DFS_EOF if there are no more entries, DFS_OK if this entry is valid,
|
||||
or DFS_ERRMISC for a media error
|
||||
*/
|
||||
uint32_t DFS_GetNext(PVOLINFO volinfo, PDIRINFO dirinfo, PDIRENT dirent);
|
||||
|
||||
/*
|
||||
Open a file for reading or writing. You supply populated VOLINFO, a path to the file,
|
||||
mode (DFS_READ or DFS_WRITE) and an empty fileinfo structure. You also need to
|
||||
provide a pointer to a sector-sized scratch buffer.
|
||||
Returns various DFS_* error states. If the result is DFS_OK, fileinfo can be used
|
||||
to access the file from this point on.
|
||||
*/
|
||||
uint32_t DFS_OpenFile(PVOLINFO volinfo, uint8_t *path, uint8_t mode, uint8_t *scratch, PFILEINFO fileinfo);
|
||||
|
||||
/*
|
||||
Read an open file
|
||||
You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
|
||||
pointer to a SECTOR_SIZE scratch buffer.
|
||||
Note that returning DFS_EOF is not an error condition. This function updates the
|
||||
successcount field with the number of bytes actually read.
|
||||
*/
|
||||
uint32_t DFS_ReadFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len);
|
||||
|
||||
/*
|
||||
Write an open file
|
||||
You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
|
||||
pointer to a SECTOR_SIZE scratch buffer.
|
||||
This function updates the successcount field with the number of bytes actually written.
|
||||
*/
|
||||
uint32_t DFS_WriteFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len);
|
||||
|
||||
/*
|
||||
Seek file pointer to a given position
|
||||
This function does not return status - refer to the fileinfo->pointer value
|
||||
to see where the pointer wound up.
|
||||
Requires a SECTOR_SIZE scratch buffer
|
||||
*/
|
||||
void DFS_Seek(PFILEINFO fileinfo, uint32_t offset, uint8_t *scratch);
|
||||
|
||||
/*
|
||||
Delete a file
|
||||
scratch must point to a sector-sized buffer
|
||||
*/
|
||||
uint32_t DFS_UnlinkFile(PVOLINFO volinfo, uint8_t *path, uint8_t *scratch);
|
||||
|
||||
/*
|
||||
Fetch FAT entry for specified cluster number
|
||||
You must provide a scratch buffer for one sector (SECTOR_SIZE) and a populated VOLINFO
|
||||
Returns a FAT32 BAD_CLUSTER value for any error, otherwise the contents of the desired
|
||||
FAT entry.
|
||||
scratchcache should point to a UINT32. This variable caches the physical sector number
|
||||
last read into the scratch buffer for performance enhancement reasons.
|
||||
*/
|
||||
uint32_t DFS_GetFAT(PVOLINFO volinfo, uint8_t *scratch, uint32_t *scratchcache, uint32_t cluster);
|
||||
|
||||
/*
|
||||
// TK: added 2009-02-12
|
||||
Close a file
|
||||
No original function of DosFS driver
|
||||
It has no effect if writing to SD Card, it's only used by the DosFS wrapper in emulation
|
||||
*/
|
||||
uint32_t DFS_Close(PFILEINFO fileinfo);
|
||||
|
||||
|
||||
|
||||
// TK: added 2008-18-12
|
||||
// for caching - this feature has to be explicitely enabled, as it isn't reentrant
|
||||
// and requires to use the same buffer pointer whenever reading a file
|
||||
void DFS_CachingEnabledSet(uint8_t enable);
|
||||
|
||||
// TK: added 2008-18-12
|
||||
// missing pendant to DFS_CanonicalToDir
|
||||
char *DFS_DirToCanonical(char *dest, char *src);
|
||||
|
||||
|
||||
// If we are building a host-emulation version, include host support
|
||||
#ifdef HOSTVER
|
||||
#include "hostemu.h"
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _DOSFS_H
|
@ -2,12 +2,50 @@
|
||||
# Rules to (help) build the F10x device support.
|
||||
#
|
||||
|
||||
#
|
||||
# Compiler options implied by the F1xx
|
||||
#
|
||||
CDEFS += -DARM_MATH_CM3
|
||||
# Directory containing this makefile
|
||||
PIOS_DEVLIB := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
# Linker scripts path (contains board-specific scripts)
|
||||
LINKER_SCRIPTS_PATH = $(PIOS_DEVLIB)
|
||||
|
||||
# Compiler options implied by the F10x
|
||||
CDEFS += -DSTM32F10X -DSTM32F10X_$(MODEL)
|
||||
CDEFS += -DUSE_STDPERIPH_DRIVER
|
||||
CDEFS += -DARM_MATH_CM3
|
||||
ARCHFLAGS += -mcpu=cortex-m3
|
||||
|
||||
# Board-specific startup files
|
||||
ASRC += $(PIOS_DEVLIB)startup_stm32f10x_$(MODEL)$(MODEL_SUFFIX).S
|
||||
|
||||
# PIOS device library source and includes
|
||||
SRC += $(wildcard $(PIOS_DEVLIB)*.c)
|
||||
|
||||
# CMSIS for the F1
|
||||
include $(PIOS)/Common/Libraries/CMSIS2/library.mk
|
||||
CMSIS_DIR = $(PIOS_DEVLIB)Libraries/CMSIS/Core/CM3
|
||||
SRC += $(CMSIS_DIR)/core_cm3.c
|
||||
SRC += $(CMSIS_DIR)/system_stm32f10x.c
|
||||
EXTRAINCDIRS += $(CMSIS_DIR)
|
||||
|
||||
# ST Peripheral library
|
||||
PERIPHLIB = $(PIOS_DEVLIB)Libraries/STM32F10x_StdPeriph_Driver
|
||||
SRC += $(wildcard $(PERIPHLIB)/src/*.c)
|
||||
EXTRAINCDIRS += $(PERIPHLIB)/inc
|
||||
|
||||
# ST USB Device library
|
||||
USBDEVLIB = $(PIOS_DEVLIB)Libraries/STM32_USB-FS-Device_Driver
|
||||
SRC += $(wildcard $(USBDEVLIB)/src/*.c)
|
||||
EXTRAINCDIRS += $(USBDEVLIB)/inc
|
||||
|
||||
#
|
||||
# CMSIS for the F1
|
||||
# FreeRTOS
|
||||
#
|
||||
include $(PIOSCOMMONLIB)/CMSIS2/library.mk
|
||||
# If the application has included the generic FreeRTOS support, then add in
|
||||
# the device-specific pieces of the code.
|
||||
#
|
||||
ifneq ($(FREERTOS_DIR),)
|
||||
FREERTOS_PORTDIR := $(PIOS_DEVLIB)Libraries/FreeRTOS/Source
|
||||
SRC += $(wildcard $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM3/*.c)
|
||||
SRC += $(wildcard $(FREERTOS_PORTDIR)/portable/MemMang/heap_1.c)
|
||||
EXTRAINCDIRS += $(FREERTOS_PORTDIR)/portable/GCC/ARM_CM3
|
||||
endif
|
||||
|
@ -1,56 +0,0 @@
|
||||
_estack = 0x20004FF0;
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
PROVIDE (pios_isr_vector_table_base = .);
|
||||
KEEP(*(.isr_vector .isr_vector.*))
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.glue_7t) *(.glue_7)
|
||||
*(.rodata .rodata* .gnu.linkonce.r.*)
|
||||
} > BL_FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > BL_FLASH
|
||||
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > BL_FLASH
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
_sidata = .;
|
||||
|
||||
.data : AT (_etext)
|
||||
{
|
||||
_sdata = .;
|
||||
*(.data .data.*)
|
||||
. = ALIGN(4);
|
||||
_edata = . ;
|
||||
} > SRAM
|
||||
|
||||
/* .bss section which is used for uninitialized data */
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
_sbss = . ;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = . ;
|
||||
} > SRAM
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
|
||||
.boardinfo :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.boardinfo))
|
||||
. = ALIGN(4);
|
||||
} > BD_INFO
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
MEMORY
|
||||
{
|
||||
BL_FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x02000 - 0x00080
|
||||
BD_INFO (r) : ORIGIN = 0x08002000 - 0x80, LENGTH = 0x00080
|
||||
FLASH (rx) : ORIGIN = 0x08002000, LENGTH = 0x20000 - 0x02000
|
||||
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x05000
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
PROVIDE(pios_board_info_blob = ORIGIN(BD_INFO));
|
||||
|
||||
_estack = 0x20004FF0;
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
PROVIDE (pios_isr_vector_table_base = .);
|
||||
KEEP(*(.isr_vector .isr_vector.*))
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.glue_7t) *(.glue_7)
|
||||
*(.rodata .rodata* .gnu.linkonce.r.*)
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
_sidata = .;
|
||||
|
||||
.data : AT (_etext)
|
||||
{
|
||||
_sdata = .;
|
||||
*(.data .data.*)
|
||||
. = ALIGN(4);
|
||||
_edata = . ;
|
||||
} > SRAM
|
||||
|
||||
/* .bss section which is used for uninitialized data */
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
_sbss = . ;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = . ;
|
||||
} > SRAM
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
}
|
@ -28,6 +28,9 @@
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_ADC
|
||||
|
||||
#include <pios_adc_priv.h>
|
||||
|
||||
// Private types
|
||||
@ -361,6 +364,8 @@ void PIOS_ADC_DMA_Handler(void)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_ADC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
@ -28,9 +28,10 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
#if defined(PIOS_INCLUDE_BL_HELPER)
|
||||
|
||||
#ifdef PIOS_INCLUDE_BL_HELPER
|
||||
|
||||
#include <pios_board_info.h>
|
||||
#include "stm32f10x_flash.h"
|
||||
|
||||
@ -99,4 +100,5 @@ void PIOS_BL_HELPER_CRC_Ini()
|
||||
{
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PIOS_INCLUDE_BL_HELPER */
|
||||
|
@ -28,7 +28,6 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
// Global variables
|
||||
@ -154,9 +153,9 @@ void PIOS_DEBUG_PinValue4BitL(uint8_t value)
|
||||
*/
|
||||
void PIOS_DEBUG_Panic(const char *msg)
|
||||
{
|
||||
#ifdef PIOS_COM_DEBUG
|
||||
#ifdef PIOS_INCLUDE_DEBUG_CONSOLE
|
||||
register int *lr asm("lr"); // Link-register holds the PC of the caller
|
||||
PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_DEBUG, "\r%s @0x%x\r", msg, lr);
|
||||
DEBUG_PRINTF(0, "\r%s @0x%x\r", msg, lr);
|
||||
#endif
|
||||
|
||||
// Stay put
|
||||
|
@ -30,10 +30,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include <pios.h>
|
||||
|
||||
#if defined(PIOS_INCLUDE_DELAY)
|
||||
#ifdef PIOS_INCLUDE_DELAY
|
||||
|
||||
/* these should be defined by CMSIS, but they aren't */
|
||||
#define DWT_CTRL (*(volatile uint32_t *)0xe0001000)
|
||||
@ -167,7 +166,7 @@ uint32_t PIOS_DELAY_DiffuS(uint32_t raw)
|
||||
return diff / us_ticks;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_DELAY */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,11 +28,12 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_DSM
|
||||
|
||||
#include "pios_dsm_priv.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_DSM)
|
||||
|
||||
/* Forward Declarations */
|
||||
static int32_t PIOS_DSM_Get(uint32_t rcvr_id, uint8_t channel);
|
||||
@ -399,7 +400,7 @@ static void PIOS_DSM_Supervisor(uint32_t dsm_id)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_DSM */
|
||||
#endif /* PIOS_INCLUDE_DSM */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,14 +28,13 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include <pios.h>
|
||||
#include <pios_crc.h>
|
||||
|
||||
#ifdef PIOS_INCLUDE_FLASH_EEPROM
|
||||
|
||||
#include <stm32f10x_flash.h>
|
||||
#include <pios_board_info.h>
|
||||
|
||||
#include <pios_eeprom.h>
|
||||
|
||||
static struct pios_eeprom_cfg config;
|
||||
|
||||
/**
|
||||
@ -153,3 +152,5 @@ int32_t PIOS_EEPROM_Load(uint8_t *data, uint32_t len)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_FLASH_EEPROM */
|
||||
|
@ -29,10 +29,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_EXTI)
|
||||
#ifdef PIOS_INCLUDE_EXTI
|
||||
|
||||
/* Map EXTI line to full config */
|
||||
#define EXTI_MAX_LINES 16
|
||||
|
@ -28,10 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_GPIO)
|
||||
#ifdef PIOS_INCLUDE_GPIO
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
@ -93,7 +92,7 @@ void PIOS_GPIO_Toggle(uint8_t Pin)
|
||||
GPIO_PORT[Pin]->ODR ^= GPIO_PIN[Pin];
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_GPIO */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,10 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_I2C)
|
||||
#ifdef PIOS_INCLUDE_I2C
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
#define USE_FREERTOS
|
||||
@ -1146,7 +1145,7 @@ void PIOS_I2C_ER_IRQ_Handler(uint32_t i2c_id)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_I2C */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -12,6 +12,8 @@
|
||||
****************************************************************************************/
|
||||
#include <pios.h>
|
||||
|
||||
#ifdef PIOS_INCLUDE_IAP
|
||||
|
||||
/****************************************************************************************
|
||||
* Private Definitions/Macros
|
||||
****************************************************************************************/
|
||||
@ -120,3 +122,5 @@ void PIOS_IAP_WriteBootCount (uint16_t boot_count)
|
||||
{
|
||||
BKP_WriteBackupRegister ( IAP_BOOTCOUNT, boot_count );
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_IAP */
|
||||
|
@ -29,10 +29,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_IRQ)
|
||||
#ifdef PIOS_INCLUDE_IRQ
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
@ -90,7 +89,7 @@ int32_t PIOS_IRQ_Enable(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_IRQ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,10 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_LED)
|
||||
#ifdef PIOS_INCLUDE_LED
|
||||
|
||||
#include <pios_led_priv.h>
|
||||
|
||||
@ -148,7 +147,7 @@ void PIOS_LED_Toggle(uint32_t led_id)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_LED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,11 +28,12 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_PPM
|
||||
|
||||
#include "pios_ppm_priv.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_PPM)
|
||||
|
||||
/* Provide a RCVR driver */
|
||||
static int32_t PIOS_PPM_Get(uint32_t rcvr_id, uint8_t channel);
|
||||
@ -349,7 +350,7 @@ static void PIOS_PPM_Supervisor(uint32_t ppm_id) {
|
||||
ppm_dev->Fresh = FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_PPM */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,11 +28,11 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
#include "pios_ppm_out_priv.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_PPM_OUT)
|
||||
#ifdef PIOS_INCLUDE_PPM_OUT
|
||||
|
||||
#include "pios_ppm_out_priv.h"
|
||||
|
||||
#define PIOS_PPM_OUT_MAX_DEVS 1
|
||||
#define PIOS_PPM_OUT_MAX_CHANNELS 8
|
||||
@ -228,4 +228,4 @@ static void PIOS_PPM_OUT_tim_edge_cb (uint32_t tim_id, uint32_t context, uint8_t
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // PIOS_PPM_OUT
|
||||
#endif /* PIOS_INCLUDE_PPM_OUT */
|
||||
|
@ -28,11 +28,12 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_PWM
|
||||
|
||||
#include "pios_pwm_priv.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_PWM)
|
||||
|
||||
/* Provide a RCVR driver */
|
||||
static int32_t PIOS_PWM_Get(uint32_t rcvr_id, uint8_t channel);
|
||||
@ -274,7 +275,7 @@ static void PIOS_PWM_tim_edge_cb (uint32_t tim_id, uint32_t context, uint8_t cha
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_PWM */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,10 +28,10 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_RTC)
|
||||
#ifdef PIOS_INCLUDE_RTC
|
||||
|
||||
#include <pios_rtc_priv.h>
|
||||
|
||||
#ifndef PIOS_RTC_PRESCALER
|
||||
@ -121,7 +121,8 @@ void PIOS_RTC_irq_handler (void)
|
||||
RTC_ClearITPendingBit(RTC_IT_SEC);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PIOS_INCLUDE_RTC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,8 +28,10 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_SERVO
|
||||
|
||||
#include "pios_servo_priv.h"
|
||||
#include "pios_tim_priv.h"
|
||||
|
||||
@ -145,3 +147,5 @@ void PIOS_Servo_Set(uint8_t servo, uint16_t position)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_SERVO */
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
#if defined(PIOS_INCLUDE_SPI)
|
||||
#ifdef PIOS_INCLUDE_SPI
|
||||
|
||||
#include <pios_spi_priv.h>
|
||||
|
||||
@ -577,7 +577,7 @@ void PIOS_SPI_IRQ_Handler(uint32_t spi_id)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_SPI */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -29,10 +29,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_SYS)
|
||||
#ifdef PIOS_INCLUDE_SYS
|
||||
|
||||
/* Private Function Prototypes */
|
||||
void NVIC_Configuration(void);
|
||||
@ -212,7 +211,7 @@ void assert_failed(uint8_t * file, uint32_t line)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_SYS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "pios.h"
|
||||
|
||||
#include "pios_tim.h"
|
||||
#ifdef PIOS_INCLUDE_TIM
|
||||
|
||||
#include "pios_tim_priv.h"
|
||||
|
||||
enum pios_tim_dev_magic {
|
||||
@ -425,3 +426,4 @@ static void PIOS_TIM_8_CC_irq_handler (void)
|
||||
PIOS_TIM_generic_irq_handler (TIM8);
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_TIM */
|
||||
|
@ -28,10 +28,9 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_USART)
|
||||
#ifdef PIOS_INCLUDE_USART
|
||||
|
||||
#include <pios_usart_priv.h>
|
||||
|
||||
@ -324,7 +323,7 @@ static void PIOS_USART_generic_irq_handler(uint32_t usart_id)
|
||||
#endif /* PIOS_INCLUDE_FREERTOS */
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_USART */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -28,16 +28,17 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#ifdef PIOS_INCLUDE_USB
|
||||
|
||||
#include "usb_lib.h"
|
||||
#include "pios_usb_board_data.h"
|
||||
#include "stm32f10x.h"
|
||||
|
||||
#include "pios_usb.h"
|
||||
#include "pios_usb_priv.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_USB_HID)
|
||||
#ifdef PIOS_INCLUDE_USB_HID
|
||||
|
||||
/* Rx/Tx status */
|
||||
static bool transfer_possible = false;
|
||||
@ -66,7 +67,7 @@ static int32_t PIOS_USB_validate(struct pios_usb_dev * usb_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
static struct pios_usb_dev * PIOS_USB_alloc(void)
|
||||
{
|
||||
struct pios_usb_dev * usb_dev;
|
||||
@ -156,14 +157,14 @@ int32_t PIOS_USB_ChangeConnectionState(bool Connected)
|
||||
|
||||
//TODO: Check SetEPRxValid(ENDP1);
|
||||
|
||||
#if defined(USB_LED_ON)
|
||||
#ifdef USB_LED_ON
|
||||
USB_LED_ON; // turn the USB led on
|
||||
#endif
|
||||
} else {
|
||||
// Cable disconnected: disable transfers
|
||||
transfer_possible = false;
|
||||
|
||||
#if defined(USB_LED_OFF)
|
||||
#ifdef USB_LED_OFF
|
||||
USB_LED_OFF; // turn the USB led off
|
||||
#endif
|
||||
}
|
||||
@ -233,7 +234,9 @@ bool PIOS_USB_CheckAvailable(uint32_t id)
|
||||
return PIOS_USB_CableConnected(id) && transfer_possible;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* PIOS_INCLUDE_USB_HID */
|
||||
|
||||
#endif /* PIOS_INCLUDE_USB */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user