mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-25 16:56:25 +08:00
Fresh import of the PX4 firmware sources.
This commit is contained in:
+211
@@ -0,0 +1,211 @@
|
||||
#
|
||||
# Generic GDB macros for working with NuttX
|
||||
#
|
||||
|
||||
echo Loading NuttX GDB macros. Use 'help nuttx' for more information.\n
|
||||
|
||||
define nuttx
|
||||
echo Use 'help nuttx' for more information.\n
|
||||
end
|
||||
|
||||
document nuttx
|
||||
. Various macros for working with NuttX.
|
||||
.
|
||||
. showheap
|
||||
. Prints the contents of the malloc heap(s).
|
||||
. showtasks
|
||||
. Prints a list of all tasks.
|
||||
. showtask <address>
|
||||
. Prints information about the task at <address>
|
||||
.
|
||||
. Use 'help <macro>' for more specific help.
|
||||
end
|
||||
|
||||
################################################################################
|
||||
# Heap display
|
||||
################################################################################
|
||||
|
||||
define _showheap
|
||||
set $index = $arg0
|
||||
if (sizeof(struct mm_allocnode_s) == 4)
|
||||
set $MM_ALLOC_BIT = 0x8000
|
||||
else
|
||||
set $MM_ALLOC_BIT = 0x80000000
|
||||
end
|
||||
printf "HEAP %d %p - %p\n", $index, g_heapstart[$index], g_heapend[$index]
|
||||
printf "ptr size\n"
|
||||
set $node = (char *)g_heapstart[$index] + sizeof(struct mm_allocnode_s)
|
||||
while $node < g_heapend[$index]
|
||||
printf " %p", $node
|
||||
set $nodestruct = (struct mm_allocnode_s *)$node
|
||||
printf " %u", $nodestruct->size
|
||||
if !($nodestruct->preceding & $MM_ALLOC_BIT)
|
||||
printf " FREE"
|
||||
end
|
||||
if ($nodestruct->size > g_heapsize) || (($node + $nodestruct->size) > g_heapend[$index])
|
||||
printf " (BAD SIZE)"
|
||||
end
|
||||
printf "\n"
|
||||
set $node = $node + $nodestruct->size
|
||||
end
|
||||
end
|
||||
|
||||
define showheap
|
||||
set $nheaps = sizeof(g_heapstart) / sizeof(g_heapstart[0])
|
||||
printf "Printing %d heaps\n", $nheaps
|
||||
set $heapindex = (int)0
|
||||
while $heapindex < $nheaps
|
||||
showheap $heapindex
|
||||
set $heapindex = $heapindex + 1
|
||||
end
|
||||
end
|
||||
|
||||
document showheap
|
||||
. showheap
|
||||
. Prints the contents of the malloc heap(s).
|
||||
end
|
||||
|
||||
################################################################################
|
||||
# Task display
|
||||
################################################################################
|
||||
|
||||
define _showtask_oneline
|
||||
set $task = (struct _TCB *)$arg0
|
||||
printf " %p %.2d %.3d %s\n", $task, $task->pid, $task->sched_priority, $task->name
|
||||
end
|
||||
|
||||
define _showtasklist
|
||||
set $queue = (dq_queue_t *)$arg0
|
||||
set $cursor = (dq_entry_t *)$queue->head
|
||||
|
||||
if $cursor != 0
|
||||
printf " TCB PID PRI\n"
|
||||
else
|
||||
printf " <none>\n"
|
||||
end
|
||||
|
||||
while $cursor != 0
|
||||
|
||||
_showtask_oneline $cursor
|
||||
|
||||
if $cursor == $queue->tail
|
||||
set $cursor = 0
|
||||
else
|
||||
set $next = $cursor->flink
|
||||
|
||||
if $next->blink != $cursor
|
||||
printf "task linkage corrupt\n"
|
||||
set $cursor = 0
|
||||
else
|
||||
set $cursor = $next
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Print task registers for a NuttX v7em target with FPU enabled.
|
||||
#
|
||||
define _showtaskregs_v7em
|
||||
set $task = (struct _TCB *)$arg0
|
||||
set $regs = (uint32_t *)&($task->xcp.regs[0])
|
||||
|
||||
printf " r0: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $regs[27], $regs[28], $regs[29], $regs[30], $regs[2], $regs[3], $regs[4], $regs[5]
|
||||
printf " r8: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $regs[6], $regs[7], $regs[8], $regs[9], $regs[31], $regs[0], $regs[32], $regs[33]
|
||||
printf " XPSR 0x%08x EXC_RETURN 0x%08x PRIMASK 0x%08x\n", $regs[34], $regs[10], $regs[1]
|
||||
end
|
||||
|
||||
#
|
||||
# Print current registers for a NuttX v7em target with FPU enabled.
|
||||
#
|
||||
define _showcurrentregs_v7em
|
||||
printf " r0: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7
|
||||
printf " r8: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", $r8, $r9, $r10, $r11, $r12, $r13, $r14, $r15
|
||||
printf " XPSR 0x%08x\n", $xpsr
|
||||
end
|
||||
|
||||
#
|
||||
# Print details of a semaphore
|
||||
#
|
||||
define _showsemaphore
|
||||
printf "count %d ", $arg0->semcount
|
||||
if $arg0->hlist.holder != 0
|
||||
set $_task = (struct _TCB *)$arg0->hlist.holder
|
||||
printf "held by %s", $_task->name
|
||||
end
|
||||
printf "\n"
|
||||
end
|
||||
|
||||
define showtask
|
||||
set $task = (struct _TCB *)$arg0
|
||||
|
||||
printf "%p %.2d ", $task, $task->pid
|
||||
_showtaskstate $task
|
||||
printf " %s\n", $task->name
|
||||
set $stack_free = 0
|
||||
while ($stack_free < $task->adj_stack_size) && *(uint8_t *)($task->stack_alloc_ptr + $stack_free)
|
||||
set $stack_free = $stack_free + 1
|
||||
end
|
||||
printf" stack 0x%08x-0x%08x (%d) %d free\n", $task->stack_alloc_ptr, $task->adj_stack_ptr, $task->adj_stack_size, $stack_free
|
||||
|
||||
if $task->task_state == TSTATE_WAIT_SEM
|
||||
printf " waiting on %p ", $task->waitsem
|
||||
_showsemaphore $task->waitsem
|
||||
end
|
||||
|
||||
if $task->task_state != TSTATE_TASK_RUNNING
|
||||
_showtaskregs_v7em $task
|
||||
else
|
||||
_showcurrentregs_v7em
|
||||
end
|
||||
|
||||
# XXX print registers here
|
||||
end
|
||||
|
||||
document showtask
|
||||
. showtask <TCB pointer>
|
||||
. Print details of a task.
|
||||
end
|
||||
|
||||
define _showtaskstate
|
||||
if $arg0->task_state == TSTATE_TASK_INVALID
|
||||
printf "INVALID"
|
||||
end
|
||||
if $arg0->task_state == TSTATE_TASK_PENDING
|
||||
printf "PENDING"
|
||||
end
|
||||
if $arg0->task_state == TSTATE_TASK_READYTORUN
|
||||
printf "READYTORUN"
|
||||
end
|
||||
if $arg0->task_state == TSTATE_TASK_RUNNING
|
||||
printf "RUNNING"
|
||||
end
|
||||
if $arg0->task_state == TSTATE_TASK_INACTIVE
|
||||
printf "INACTIVE"
|
||||
end
|
||||
if $arg0->task_state == TSTATE_WAIT_SEM
|
||||
printf "WAIT_SEM"
|
||||
end
|
||||
if $arg0->task_state == TSTATE_WAIT_SIG
|
||||
printf "WAIT_SIG"
|
||||
end
|
||||
if $arg0->task_state > TSTATE_WAIT_SIG
|
||||
printf "%d", $arg0->task_state
|
||||
end
|
||||
end
|
||||
|
||||
define showtasks
|
||||
printf "PENDING\n"
|
||||
_showtasklist &g_pendingtasks
|
||||
printf "RUNNABLE\n"
|
||||
_showtasklist &g_readytorun
|
||||
printf "WAITING\n"
|
||||
_showtasklist &g_waitingforsemaphore
|
||||
printf "INACTIVE\n"
|
||||
_showtasklist &g_inactivetasks
|
||||
end
|
||||
|
||||
document showtasks
|
||||
. showtasks
|
||||
. Print a list of all tasks in the system, separated into their respective queues.
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Setup macros for the BlackMagic debug probe and NuttX.
|
||||
#
|
||||
|
||||
mon swdp_scan
|
||||
attach 1
|
||||
@@ -0,0 +1,11 @@
|
||||
define f4_memdump
|
||||
shell mkdir -p /tmp/dump
|
||||
printf "Dumping CCSRAM to /tmp/dump/ccsram\n"
|
||||
dump memory /tmp/dump/ccsram 0x10000000 0x10010000
|
||||
printf "Dumping SRAM to /tmp/dump/sram\n"
|
||||
dump memory /tmp/dump/sram 0x20000000 0x20020000
|
||||
end
|
||||
|
||||
document f4_memdump
|
||||
Dumps the STM32F4 memory to files in /tmp/dump.
|
||||
end
|
||||
@@ -0,0 +1,64 @@
|
||||
# script for stm32f2xxx
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME stm32f4xxx
|
||||
}
|
||||
|
||||
if { [info exists ENDIAN] } {
|
||||
set _ENDIAN $ENDIAN
|
||||
} else {
|
||||
set _ENDIAN little
|
||||
}
|
||||
|
||||
# Work-area is a space in RAM used for flash programming
|
||||
# By default use 64kB
|
||||
if { [info exists WORKAREASIZE] } {
|
||||
set _WORKAREASIZE $WORKAREASIZE
|
||||
} else {
|
||||
set _WORKAREASIZE 0x10000
|
||||
}
|
||||
|
||||
# JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz
|
||||
#
|
||||
# Since we may be running of an RC oscilator, we crank down the speed a
|
||||
# bit more to be on the safe side. Perhaps superstition, but if are
|
||||
# running off a crystal, we can run closer to the limit. Note
|
||||
# that there can be a pretty wide band where things are more or less stable.
|
||||
jtag_khz 1000
|
||||
|
||||
jtag_nsrst_delay 100
|
||||
jtag_ntrst_delay 100
|
||||
|
||||
#jtag scan chain
|
||||
if { [info exists CPUTAPID ] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
# See STM Document RM0033
|
||||
# Section 32.6.3 - corresponds to Cortex-M3 r2p0
|
||||
set _CPUTAPID 0x4ba00477
|
||||
}
|
||||
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||
|
||||
if { [info exists BSTAPID ] } {
|
||||
set _BSTAPID $BSTAPID
|
||||
} else {
|
||||
# See STM Document RM0033
|
||||
# Section 32.6.2
|
||||
#
|
||||
set _BSTAPID 0x06413041
|
||||
}
|
||||
jtag newtap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME cortex_m3 -endian $_ENDIAN -chain-position $_TARGETNAME -rtos auto
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME
|
||||
|
||||
# if srst is not fitted use SYSRESETREQ to
|
||||
# perform a soft reset
|
||||
cortex_m3 reset_config sysresetreq
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
Linux/Mac OS X
|
||||
==============
|
||||
To install doxygen:
|
||||
$sudo apt-get install doxygen
|
||||
|
||||
If the above does not work go to:
|
||||
http://www.stack.nl/~dimitri/doxygen/download.html for the correct download.
|
||||
|
||||
Then go to the following website for inforamtion on the install:
|
||||
http://www.stack.nl/~dimitri/doxygen/install.html
|
||||
|
||||
Then to generate the html, run the following code while you are in the qgroundcontrol/doc directory:
|
||||
$doxygen Doxyfile
|
||||
|
||||
The html file index.html should be in doc/html unless you changed the output directory.
|
||||
|
||||
The other option for generating the documentation is to use the wizard:
|
||||
$doxywizard &
|
||||
|
||||
doxywizard information:
|
||||
http://www.stack.nl/~dimitri/doxygen/doxywizard_usage.html
|
||||
|
||||
Or go to the Doxygen Manual for information at the website noted below.
|
||||
|
||||
Windows
|
||||
=======
|
||||
Go to the following website for the correct download and follow the wizard to install:
|
||||
http://www.stack.nl/~dimitri/doxygen/download.html
|
||||
|
||||
Run the wizard to generate the documentation.
|
||||
Go to the website below or the Doxygen Manual for information on running doxywizard.
|
||||
http://www.stack.nl/~dimitri/doxygen/doxywizard_usage.html
|
||||
|
||||
Doxygen Manual
|
||||
==============
|
||||
http://www.stack.nl/~dimitri/doxygen/
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
rm -rf html
|
||||
doxygen
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
git log --pretty=format:"Last change: commit %h - %aN, %ar : %s" -1 $1 || echo no git
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"tab_size": 8,
|
||||
"translate_tabs_to_spaces": false
|
||||
},
|
||||
"build_systems":
|
||||
[
|
||||
{
|
||||
"name": "PX4",
|
||||
"working_dir": "${project_path}",
|
||||
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
|
||||
"cmd": ["make"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"board_id": 5,
|
||||
"magic": "PX4FWv1",
|
||||
"description": "Firmware for the PX4FMU board",
|
||||
"image": "",
|
||||
"build_time": 0,
|
||||
"summary": "PX4FMU",
|
||||
"version": "0.1",
|
||||
"image_size": 0,
|
||||
"git_identity": "",
|
||||
"board_revision": 0
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"board_id": 7,
|
||||
"magic": "PX4FWv1",
|
||||
"description": "Firmware for the PX4IO board",
|
||||
"image": "",
|
||||
"build_time": 0,
|
||||
"summary": "PX4IO",
|
||||
"version": "0.1",
|
||||
"image_size": 0,
|
||||
"git_identity": "",
|
||||
"board_revision": 0
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
#
|
||||
# Top-level Makefile for building PX4 firmware images.
|
||||
#
|
||||
#
|
||||
# Note that this is a transitional process; the eventual goal is for this
|
||||
# project to slim down and simply generate PX4 link kits via the NuttX
|
||||
# 'make export' mechanism.
|
||||
#
|
||||
#
|
||||
|
||||
#
|
||||
# Some useful paths.
|
||||
#
|
||||
export PX4BASE = $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
export NUTTX_SRC = $(PX4BASE)/nuttx
|
||||
export NUTTX_APPS = $(PX4BASE)/apps
|
||||
export MAVLINK_SRC = $(PX4BASE)/mavlink
|
||||
export ROMFS_SRC = $(PX4BASE)/ROMFS
|
||||
export IMAGE_DIR = $(PX4BASE)/Images
|
||||
|
||||
#
|
||||
# Tools
|
||||
#
|
||||
MKFW = $(PX4BASE)/Tools/px_mkfw.py
|
||||
UPLOADER = $(PX4BASE)/Tools/px_uploader.py
|
||||
|
||||
#
|
||||
# What are we currently configured for?
|
||||
#
|
||||
CONFIGURED = $(PX4BASE)/.configured
|
||||
ifeq ($(wildcard $(CONFIGURED)),)
|
||||
# the $(CONFIGURED) target will make this a reality before building
|
||||
export TARGET = px4fmu
|
||||
$(shell echo $(TARGET) > $(CONFIGURED))
|
||||
else
|
||||
export TARGET = $(shell cat $(CONFIGURED))
|
||||
endif
|
||||
|
||||
#
|
||||
# What we will build
|
||||
#
|
||||
FIRMWARE_BUNDLE = $(IMAGE_DIR)/$(TARGET).px4
|
||||
FIRMWARE_BINARY = $(IMAGE_DIR)/$(TARGET).bin
|
||||
FIRMWARE_PROTOTYPE = $(IMAGE_DIR)/$(TARGET).prototype
|
||||
|
||||
#
|
||||
# Debugging
|
||||
#
|
||||
MQUIET = --no-print-directory
|
||||
#MQUIET = --print-directory
|
||||
|
||||
all: $(FIRMWARE_BUNDLE)
|
||||
|
||||
#
|
||||
# Generate a wrapped .px4 file from the built binary
|
||||
#
|
||||
$(FIRMWARE_BUNDLE): $(FIRMWARE_BINARY) $(MKFW) $(FIRMWARE_PROTOTYPE)
|
||||
@echo Generating $@
|
||||
@$(MKFW) --prototype $(FIRMWARE_PROTOTYPE) \
|
||||
--git_identity $(PX4BASE) \
|
||||
--image $(FIRMWARE_BINARY) > $@
|
||||
#
|
||||
# Build the firmware binary.
|
||||
#
|
||||
.PHONY: $(FIRMWARE_BINARY)
|
||||
$(FIRMWARE_BINARY): configure_$(TARGET) setup_$(TARGET)
|
||||
@echo Building $@
|
||||
@make -C $(NUTTX_SRC) -r $(MQUIET) all
|
||||
@cp $(NUTTX_SRC)/nuttx.bin $@
|
||||
|
||||
#
|
||||
# The 'configure' targets select one particular firmware configuration
|
||||
# and makes it current.
|
||||
#
|
||||
configure_px4fmu:
|
||||
ifneq ($(TARGET),px4fmu)
|
||||
@make -C $(PX4BASE) distclean
|
||||
endif
|
||||
@cd $(NUTTX_SRC)/tools && /bin/sh configure.sh px4fmu/nsh
|
||||
@echo px4fmu > $(CONFIGURED)
|
||||
|
||||
configure_px4io:
|
||||
ifneq ($(TARGET),px4io)
|
||||
@make -C $(PX4BASE) distclean
|
||||
endif
|
||||
@cd $(NUTTX_SRC)/tools && /bin/sh configure.sh px4io/io
|
||||
@echo px4io > $(CONFIGURED)
|
||||
|
||||
#
|
||||
# Per-configuration additional targets
|
||||
#
|
||||
.PHONY: px4fmu_setup
|
||||
setup_px4fmu:
|
||||
@echo Generating ROMFS
|
||||
@make -C $(ROMFS_SRC) all
|
||||
|
||||
setup_px4io:
|
||||
|
||||
#
|
||||
# Firmware uploading.
|
||||
#
|
||||
|
||||
# serial port defaults by operating system.
|
||||
SYSTYPE = $(shell uname)
|
||||
ifeq ($(SYSTYPE),Darwin)
|
||||
SERIAL_PORTS ?= "/dev/tty.usbmodemPX1,/dev/tty.usbmodemPX2,/dev/tty.usbmodemPX3,/dev/tty.usbmodemPX4"
|
||||
endif
|
||||
ifeq ($(SYSTYPE),Linux)
|
||||
SERIAL_PORTS ?= "/dev/ttyACM5,/dev/ttyACM4,/dev/ttyACM3,/dev/ttyACM2,/dev/ttyACM1,/dev/ttyACM0"
|
||||
endif
|
||||
ifeq ($(SERIAL_PORTS),)
|
||||
SERIAL_PORTS = "\\\\.\\COM18,\\\\.\\COM17,\\\\.\\COM16,\\\\.\\COM15,\\\\.\\COM14,\\\\.\\COM13,\\\\.\\COM12,\\\\.\\COM11,\\\\.\\COM10,\\\\.\\COM9,\\\\.\\COM8,\\\\.\\COM7,\\\\.\\COM6,\\\\.\\COM5,\\\\.\\COM4,\\\\.\\COM3,\\\\.\\COM2,\\\\.\\COM1,\\\\.\\COM0"
|
||||
endif
|
||||
|
||||
upload: $(FIRMWARE_BUNDLE) $(UPLOADER)
|
||||
@python -u $(UPLOADER) --port $(SERIAL_PORTS) $(FIRMWARE_BUNDLE)
|
||||
|
||||
#
|
||||
# Hacks and fixups
|
||||
#
|
||||
|
||||
ifeq ($(SYSTYPE),Darwin)
|
||||
# PATH inherited by Eclipse may not include toolchain install location
|
||||
export PATH := $(PATH):/usr/local/bin
|
||||
endif
|
||||
|
||||
#
|
||||
# Cleanup targets. 'clean' should remove all built products and force
|
||||
# a complete re-compilation, 'distclean' should remove everything
|
||||
# that's generated leaving only files that are in source control.
|
||||
#
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@make -C $(NUTTX_SRC) -r $(MQUIET) clean
|
||||
@make -C $(ROMFS_SRC) -r $(MQUIET) clean
|
||||
|
||||
.PHONY: distclean
|
||||
distclean:
|
||||
@rm -f $(CONFIGURED)
|
||||
@make -C $(NUTTX_SRC) -r $(MQUIET) distclean
|
||||
@make -C $(ROMFS_SRC) -r $(MQUIET) distclean
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/img
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
#
|
||||
# Makefile to generate a PX4FMU ROMFS image.
|
||||
#
|
||||
# In normal use, 'make install' will generate a new ROMFS header and place it
|
||||
# into the px4fmu configuration in the appropriate location.
|
||||
#
|
||||
|
||||
#
|
||||
# Directories of interest
|
||||
#
|
||||
SRCROOT ?= $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
BUILDROOT ?= $(SRCROOT)/img
|
||||
ROMFS_HEADER ?= $(SRCROOT)/../nuttx/configs/px4fmu/include/nsh_romfsimg.h
|
||||
|
||||
#
|
||||
# List of files to install in the ROMFS, specified as <source>~<destination>
|
||||
#
|
||||
ROMFS_FSSPEC := $(SRCROOT)/scripts/rcS~init.d/rcS \
|
||||
$(SRCROOT)/scripts/rc.sensors~init.d/rc.sensors \
|
||||
$(SRCROOT)/scripts/rc.logging~init.d/rc.logging \
|
||||
$(SRCROOT)/scripts/rc.standalone~init.d/rc.standalone \
|
||||
$(SRCROOT)/scripts/rc.PX4IO~init.d/rc.PX4IO \
|
||||
$(SRCROOT)/scripts/rc.PX4IOAR~init.d/rc.PX4IOAR
|
||||
|
||||
#
|
||||
# Add the PX4IO firmware to the spec if someone has dropped it into the
|
||||
# source directory, or otherwise specified its location.
|
||||
#
|
||||
# Normally this is only something you'd do when working on PX4IO; most
|
||||
# users will upgrade with firmware off the microSD card.
|
||||
#
|
||||
PX4IO_FIRMWARE ?= $(SRCROOT)/px4io.bin
|
||||
ifneq ($(wildcard $(PX4IO_FIRMWARE)),)
|
||||
ROMFS_FSSPEC += $(PX4IO_FIRMWARE)~px4io.bin
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# No user-serviceable parts below
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Just the source files from the ROMFS spec, so that we can fail cleanly if they don't
|
||||
# exist
|
||||
#
|
||||
ROMFS_SRCFILES = $(foreach spec,$(ROMFS_FSSPEC),$(firstword $(subst ~, ,$(spec))))
|
||||
|
||||
#
|
||||
# Just the destination directories from the ROMFS spec
|
||||
#
|
||||
ROMFS_DIRS = $(sort $(dir $(foreach spec,$(ROMFS_FSSPEC),$(lastword $(subst ~, ,$(spec))))))
|
||||
|
||||
|
||||
#
|
||||
# Intermediate products
|
||||
#
|
||||
ROMFS_IMG = $(BUILDROOT)/romfs.img
|
||||
ROMFS_WORKDIR = $(BUILDROOT)/romfs
|
||||
|
||||
#
|
||||
# Convenience target for rebuilding the ROMFS header
|
||||
#
|
||||
all: $(ROMFS_HEADER)
|
||||
|
||||
$(ROMFS_HEADER): $(ROMFS_IMG) $(dir $(ROMFS_HEADER))
|
||||
@echo Generating the ROMFS header...
|
||||
@(cd $(dir $(ROMFS_IMG)) && xxd -i $(notdir $(ROMFS_IMG))) > $@
|
||||
|
||||
$(ROMFS_IMG): $(ROMFS_WORKDIR)
|
||||
@echo Generating the ROMFS image...
|
||||
@genromfs -f $@ -d $(ROMFS_WORKDIR) -V "NSHInitVol"
|
||||
|
||||
$(ROMFS_WORKDIR): $(ROMFS_SRCFILES)
|
||||
@echo Rebuilding the ROMFS work area...
|
||||
@rm -rf $(ROMFS_WORKDIR)
|
||||
@mkdir -p $(ROMFS_WORKDIR)
|
||||
@for dir in $(ROMFS_DIRS) ; do mkdir -p $(ROMFS_WORKDIR)/$$dir; done
|
||||
@for spec in $(ROMFS_FSSPEC) ; do \
|
||||
echo $$spec | sed -e 's%^.*~% %' ;\
|
||||
`echo "cp $$spec" | sed -e 's%~% $(ROMFS_WORKDIR)/%'` ;\
|
||||
done
|
||||
|
||||
$(BUILDROOT):
|
||||
@mkdir -p $(BUILDROOT)
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILDROOT)
|
||||
|
||||
distclean: clean
|
||||
@rm -f $(PX4IO_FIRMWARE) $(ROMFS_HEADER)
|
||||
|
||||
.PHONY: all install clean distclean
|
||||
|
||||
#
|
||||
# Hacks and fixups
|
||||
#
|
||||
SYSTYPE = $(shell uname)
|
||||
|
||||
ifeq ($(SYSTYPE),Darwin)
|
||||
# PATH inherited by Eclipse may not include toolchain install location
|
||||
export PATH := $(PATH):/usr/local/bin
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#!nsh
|
||||
#
|
||||
# Flight startup script for PX4FMU with PX4IO carrier board.
|
||||
#
|
||||
|
||||
echo "[init] doing PX4IO startup..."
|
||||
|
||||
#
|
||||
# Start the ORB
|
||||
#
|
||||
uorb start
|
||||
|
||||
#
|
||||
# Start the sensors.
|
||||
#
|
||||
sh /etc/init.d/rc.sensors
|
||||
|
||||
#
|
||||
# Start MAVLink
|
||||
#
|
||||
mavlink -d /dev/ttyS0 -b 57600 &
|
||||
|
||||
#
|
||||
# Start the commander.
|
||||
#
|
||||
# XXX this should be '<command> start'.
|
||||
#
|
||||
commander &
|
||||
|
||||
#
|
||||
# Start the attitude estimator
|
||||
#
|
||||
# XXX this should be '<command> start'.
|
||||
#
|
||||
attitude_estimator_bm &
|
||||
#position_estimator &
|
||||
|
||||
#
|
||||
# Configure PX4FMU for operation with PX4IO
|
||||
#
|
||||
# XXX arguments?
|
||||
#
|
||||
px4fmu start
|
||||
|
||||
#
|
||||
# Start the fixed-wing controller
|
||||
#
|
||||
# XXX this should be '<command> start'.
|
||||
#
|
||||
fixedwing_control &
|
||||
|
||||
#
|
||||
# Fire up the PX4IO interface.
|
||||
#
|
||||
px4io start
|
||||
|
||||
#
|
||||
# Start looking for a GPS.
|
||||
#
|
||||
# XXX this should not need to be backgrounded
|
||||
#
|
||||
gps -d /dev/ttyS3 -m all &
|
||||
|
||||
#
|
||||
# Start logging to microSD if we can
|
||||
#
|
||||
sh /etc/init.d/rc.logging
|
||||
|
||||
#
|
||||
# startup is done; we don't want the shell because we
|
||||
# use the same UART for telemetry (dumb).
|
||||
#
|
||||
echo "[init] startup done, exiting."
|
||||
exit
|
||||
@@ -0,0 +1,69 @@
|
||||
#!nsh
|
||||
#
|
||||
# Flight startup script for PX4FMU on PX4IOAR carrier board.
|
||||
#
|
||||
|
||||
echo "[init] doing PX4IOAR startup..."
|
||||
|
||||
#
|
||||
# Start the ORB
|
||||
#
|
||||
uorb start
|
||||
|
||||
#
|
||||
# Start the sensors.
|
||||
#
|
||||
sh /etc/init.d/rc.sensors
|
||||
|
||||
#
|
||||
# Start MAVLink
|
||||
#
|
||||
mavlink -d /dev/ttyS0 -b 57600 &
|
||||
|
||||
#
|
||||
# Start the commander.
|
||||
#
|
||||
# XXX this should be '<command> start'.
|
||||
#
|
||||
commander &
|
||||
|
||||
#
|
||||
# Start the attitude estimator
|
||||
#
|
||||
# XXX this should be '<command> start'.
|
||||
#
|
||||
attitude_estimator_bm &
|
||||
#position_estimator &
|
||||
|
||||
#
|
||||
# Configure PX4FMU for operation with PX4IOAR
|
||||
#
|
||||
# XXX arguments?
|
||||
#
|
||||
px4fmu start
|
||||
|
||||
#
|
||||
# Fire up the AR.Drone controller.
|
||||
#
|
||||
# XXX this should be '<command> start'.
|
||||
#
|
||||
ardrone_control -d /dev/ttyS1 -m attitude &
|
||||
|
||||
#
|
||||
# Start looking for a GPS.
|
||||
#
|
||||
# XXX this should not need to be backgrounded
|
||||
#
|
||||
gps -d /dev/ttyS3 -m all &
|
||||
|
||||
#
|
||||
# Start logging to microSD if we can
|
||||
#
|
||||
sh /etc/init.d/rc.logging
|
||||
|
||||
#
|
||||
# startup is done; we don't want the shell because we
|
||||
# use the same UART for telemetry (dumb).
|
||||
#
|
||||
echo "[init] startup done, exiting."
|
||||
exit
|
||||
@@ -0,0 +1,10 @@
|
||||
#!nsh
|
||||
#
|
||||
# Test jig startup script
|
||||
#
|
||||
|
||||
echo "[testing] doing production test.."
|
||||
|
||||
tests jig
|
||||
|
||||
echo "[testing] testing done"
|
||||
@@ -0,0 +1,10 @@
|
||||
#!nsh
|
||||
#
|
||||
# Initialise logging services.
|
||||
#
|
||||
|
||||
if [ -d /fs/microsd ]
|
||||
then
|
||||
# XXX this should be '<command> start'.
|
||||
# sdlog &
|
||||
fi
|
||||
@@ -0,0 +1,28 @@
|
||||
#!nsh
|
||||
#
|
||||
# Standard startup script for PX4FMU onboard sensor drivers.
|
||||
#
|
||||
|
||||
#
|
||||
# Start sensor drivers here.
|
||||
#
|
||||
|
||||
#ms5611 start
|
||||
|
||||
#
|
||||
# Start the sensor collection task.
|
||||
#
|
||||
# XXX should be 'sensors start'
|
||||
#
|
||||
sensors &
|
||||
|
||||
#
|
||||
# Test sensor functionality
|
||||
#
|
||||
# XXX integrate with 'sensors start' ?
|
||||
#
|
||||
#if sensors quicktest
|
||||
#then
|
||||
# echo "[init] sensor initialisation FAILED."
|
||||
# reboot
|
||||
#fi
|
||||
@@ -0,0 +1,67 @@
|
||||
#!nsh
|
||||
#
|
||||
# Flight startup script for PX4FMU standalone configuration.
|
||||
#
|
||||
|
||||
echo "[init] doing standalone PX4FMU startup..."
|
||||
|
||||
#
|
||||
# Start the ORB
|
||||
#
|
||||
#uorb start
|
||||
|
||||
#
|
||||
# Start the sensors.
|
||||
#
|
||||
#sh /etc/init.d/rc.sensors
|
||||
|
||||
#
|
||||
# Start MAVLink
|
||||
#
|
||||
# mavlink -d /dev/ttyS0 -b 57600 &
|
||||
|
||||
#
|
||||
# Start the commander.
|
||||
#
|
||||
# XXX this should be 'commander start'.
|
||||
#
|
||||
#commander &
|
||||
|
||||
#
|
||||
# Start the attitude estimator
|
||||
#
|
||||
# XXX this should be '<command> start'.
|
||||
#
|
||||
#attitude_estimator_bm &
|
||||
#position_estimator &
|
||||
|
||||
#
|
||||
# Start the fixed-wing controller.
|
||||
#
|
||||
# XXX should this be looking for configuration to decide
|
||||
# whether the board is configured for fixed-wing use?
|
||||
#
|
||||
# XXX this should be 'fixedwing_control start'.
|
||||
#
|
||||
#fixedwing_control &
|
||||
|
||||
#
|
||||
# Configure FMU for standalone mode
|
||||
#
|
||||
# XXX arguments?
|
||||
#
|
||||
#px4fmu start
|
||||
|
||||
#
|
||||
# Start looking for a GPS.
|
||||
#
|
||||
# XXX this should not need to be backgrounded
|
||||
#
|
||||
#gps -d /dev/ttyS3 -m all &
|
||||
|
||||
#
|
||||
# Start logging to microSD if we can
|
||||
#
|
||||
sh /etc/init.d/rc.logging
|
||||
|
||||
echo "[init] startup done"
|
||||
Executable
+120
@@ -0,0 +1,120 @@
|
||||
#!nsh
|
||||
#
|
||||
# PX4FMU startup script.
|
||||
#
|
||||
# This script is responsible for:
|
||||
#
|
||||
# - mounting the microSD card (if present)
|
||||
# - running the user startup script from the microSD card (if present)
|
||||
# - detecting the configuration of the system and picking a suitable
|
||||
# startup script to continue with
|
||||
#
|
||||
# Note: DO NOT add configuration-specific commands to this script;
|
||||
# add them to the per-configuration scripts instead.
|
||||
#
|
||||
|
||||
#
|
||||
# Default to auto-start mode. An init script on the microSD card
|
||||
# can change this to prevent automatic startup of the flight script.
|
||||
#
|
||||
set MODE autostart
|
||||
set USB_ALLOWED yes
|
||||
set USB no
|
||||
|
||||
#
|
||||
# Try to mount the microSD card.
|
||||
#
|
||||
echo "[init] looking for microSD..."
|
||||
if mount -t vfat /dev/mmcsd0 /fs/microsd
|
||||
then
|
||||
echo "[init] card mounted at /fs/microsd"
|
||||
else
|
||||
echo "[init] no microSD card found"
|
||||
fi
|
||||
|
||||
#
|
||||
# Look for an init script on the microSD card.
|
||||
#
|
||||
# To prevent automatic startup in the current flight mode,
|
||||
# the script should set MODE to some other value.
|
||||
#
|
||||
if [ -f /fs/microsd/etc/rc ]
|
||||
then
|
||||
echo "[init] reading /fs/microsd/etc/rc"
|
||||
sh /fs/microsd/etc/rc
|
||||
fi
|
||||
|
||||
#
|
||||
# Check for USB host
|
||||
#
|
||||
if [ $USB_ALLOWED == yes ]
|
||||
then
|
||||
if sercon
|
||||
then
|
||||
echo "[init] USB interface connected"
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# If we are still in flight mode, work out what airframe
|
||||
# configuration we have and start up accordingly.
|
||||
#
|
||||
if [ $MODE != autostart ]
|
||||
then
|
||||
echo "[init] automatic startup cancelled by user script"
|
||||
else
|
||||
echo "[init] detecting attached hardware..."
|
||||
|
||||
#
|
||||
# Assume that we are PX4FMU in standalone mode
|
||||
#
|
||||
set BOARD PX4FMU
|
||||
|
||||
#
|
||||
# Are we attached to a PX4IOAR (AR.Drone carrier board)?
|
||||
#
|
||||
if boardinfo -t 7
|
||||
then
|
||||
set BOARD PX4IOAR
|
||||
if [ -f /etc/init.d/rc.PX4IOAR ]
|
||||
then
|
||||
echo "[init] reading /etc/init.d/rc.PX4IOAR"
|
||||
sh /etc/init.d/rc.PX4IOAR
|
||||
fi
|
||||
else
|
||||
echo "[init] PX4IOAR not detected"
|
||||
fi
|
||||
|
||||
#
|
||||
# Are we attached to a PX4IO?
|
||||
#
|
||||
if boardinfo -t 6
|
||||
then
|
||||
set BOARD PX4IO
|
||||
if [ -f /etc/init.d/rc.PX4IO ]
|
||||
then
|
||||
echo "[init] reading /etc/init.d/rc.PX4IO"
|
||||
sh /etc/init.d/rc.PX4IO
|
||||
fi
|
||||
else
|
||||
echo "[init] PX4IO not detected"
|
||||
fi
|
||||
|
||||
#
|
||||
# Looks like we are stand-alone
|
||||
#
|
||||
if [ $BOARD == PX4FMU ]
|
||||
then
|
||||
echo "[init] no expansion board detected"
|
||||
if [ -f /etc/init.d/rc.standalone ]
|
||||
then
|
||||
echo "[init] reading /etc/init.d/rc.standalone"
|
||||
sh /etc/init.d/rc.standalone
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# We may not reach here if the airframe-specific script exits the shell.
|
||||
#
|
||||
echo "[init] startup done."
|
||||
fi
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
astyle \
|
||||
--style=linux \
|
||||
--indent=force-tab=8 \
|
||||
--indent-cases \
|
||||
--indent-preprocessor \
|
||||
--break-blocks=all \
|
||||
--pad-oper \
|
||||
--pad-header \
|
||||
--unpad-paren \
|
||||
--keep-one-line-blocks \
|
||||
--keep-one-line-statements \
|
||||
--align-pointer=name \
|
||||
--align-reference=name \
|
||||
--suffix=none \
|
||||
--ignore-exclude-errors-x \
|
||||
--lineend=linux \
|
||||
--exclude=EASTL \
|
||||
$*
|
||||
Executable
+110
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# PX4 firmware image generator
|
||||
#
|
||||
# The PX4 firmware file is a JSON-encoded Python object, containing
|
||||
# metadata fields and a zlib-compressed base64-encoded firmware image.
|
||||
#
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import json
|
||||
import base64
|
||||
import zlib
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
#
|
||||
# Construct a basic firmware description
|
||||
#
|
||||
def mkdesc():
|
||||
proto = {}
|
||||
proto['magic'] = "PX4FWv1"
|
||||
proto['board_id'] = 0
|
||||
proto['board_revision'] = 0
|
||||
proto['version'] = ""
|
||||
proto['summary'] = ""
|
||||
proto['description'] = ""
|
||||
proto['git_identity'] = ""
|
||||
proto['build_time'] = 0
|
||||
proto['image'] = base64.b64encode(bytearray())
|
||||
proto['image_size'] = 0
|
||||
return proto
|
||||
|
||||
# Parse commandline
|
||||
parser = argparse.ArgumentParser(description="Firmware generator for the PX autopilot system.")
|
||||
parser.add_argument("--prototype", action="store", help="read a prototype description from a file")
|
||||
parser.add_argument("--board_id", action="store", help="set the board ID required")
|
||||
parser.add_argument("--board_revision", action="store", help="set the board revision required")
|
||||
parser.add_argument("--version", action="store", help="set a version string")
|
||||
parser.add_argument("--summary", action="store", help="set a brief description")
|
||||
parser.add_argument("--description", action="store", help="set a longer description")
|
||||
parser.add_argument("--git_identity", action="store", help="the working directory to check for git identity")
|
||||
parser.add_argument("--image", action="store", help="the firmware image")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Fetch the firmware descriptor prototype if specified
|
||||
if args.prototype != None:
|
||||
f = open(args.prototype,"r")
|
||||
desc = json.load(f)
|
||||
f.close()
|
||||
else:
|
||||
desc = mkdesc()
|
||||
|
||||
desc['build_time'] = int(time.time())
|
||||
|
||||
if args.board_id != None:
|
||||
desc['board_id'] = int(args.board_id)
|
||||
if args.board_revision != None:
|
||||
desc['board_revision'] = int(args.board_revision)
|
||||
if args.version != None:
|
||||
desc['version'] = str(args.version)
|
||||
if args.summary != None:
|
||||
desc['summary'] = str(args.summary)
|
||||
if args.description != None:
|
||||
desc['description'] = str(args.description)
|
||||
if args.git_identity != None:
|
||||
cmd = " ".join(["git", "--git-dir", args.git_identity + "/.git", "describe", "--always", "--dirty"])
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
|
||||
desc['git_identity'] = p.read().strip()
|
||||
p.close()
|
||||
if args.image != None:
|
||||
f = open(args.image, "rb")
|
||||
bytes = f.read()
|
||||
desc['image_size'] = len(bytes)
|
||||
desc['image'] = base64.b64encode(zlib.compress(bytes,9))
|
||||
|
||||
print json.dumps(desc, indent=4)
|
||||
Executable
+318
@@ -0,0 +1,318 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Serial firmware uploader for the PX4FMU bootloader
|
||||
#
|
||||
# The PX4 firmware file is a JSON-encoded Python object, containing
|
||||
# metadata fields and a zlib-compressed base64-encoded firmware image.
|
||||
#
|
||||
# The uploader uses the following fields from the firmware file:
|
||||
#
|
||||
# image
|
||||
# The firmware that will be uploaded.
|
||||
# image_size
|
||||
# The size of the firmware in bytes.
|
||||
# board_id
|
||||
# The board for which the firmware is intended.
|
||||
# board_revision
|
||||
# Currently only used for informational purposes.
|
||||
#
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import binascii
|
||||
import serial
|
||||
import os
|
||||
import struct
|
||||
import json
|
||||
import zlib
|
||||
import base64
|
||||
import time
|
||||
|
||||
from sys import platform as _platform
|
||||
|
||||
class firmware(object):
|
||||
'''Loads a firmware file'''
|
||||
|
||||
desc = {}
|
||||
image = bytearray()
|
||||
|
||||
def __init__(self, path):
|
||||
|
||||
# read the file
|
||||
f = open(path, "r")
|
||||
self.desc = json.load(f)
|
||||
f.close()
|
||||
|
||||
self.image = zlib.decompress(base64.b64decode(self.desc['image']))
|
||||
|
||||
def property(self, propname):
|
||||
return self.desc[propname]
|
||||
|
||||
|
||||
class uploader(object):
|
||||
'''Uploads a firmware file to the PX FMU bootloader'''
|
||||
|
||||
NOP = chr(0x00)
|
||||
OK = chr(0x10)
|
||||
FAILED = chr(0x11)
|
||||
INSYNC = chr(0x12)
|
||||
EOC = chr(0x20)
|
||||
GET_SYNC = chr(0x21)
|
||||
GET_DEVICE = chr(0x22)
|
||||
CHIP_ERASE = chr(0x23)
|
||||
CHIP_VERIFY = chr(0x24)
|
||||
PROG_MULTI = chr(0x27)
|
||||
READ_MULTI = chr(0x28)
|
||||
REBOOT = chr(0x30)
|
||||
|
||||
INFO_BL_REV = chr(1) # bootloader protocol revision
|
||||
BL_REV = 2 # supported bootloader protocol
|
||||
INFO_BOARD_ID = chr(2) # board type
|
||||
INFO_BOARD_REV = chr(3) # board revision
|
||||
INFO_FLASH_SIZE = chr(4) # max firmware size in bytes
|
||||
|
||||
PROG_MULTI_MAX = 60 # protocol max is 255, must be multiple of 4
|
||||
READ_MULTI_MAX = 60 # protocol max is 255, something overflows with >= 64
|
||||
|
||||
def __init__(self, portname, baudrate):
|
||||
# open the port
|
||||
self.port = serial.Serial(portname, baudrate, timeout=10)
|
||||
|
||||
def close(self):
|
||||
if self.port is not None:
|
||||
self.port.close()
|
||||
|
||||
def __send(self, c):
|
||||
# print("send " + binascii.hexlify(c))
|
||||
self.port.write(str(c))
|
||||
|
||||
def __recv(self, count = 1):
|
||||
c = self.port.read(count)
|
||||
if (len(c) < 1):
|
||||
raise RuntimeError("timeout waiting for data")
|
||||
# print("recv " + binascii.hexlify(c))
|
||||
return c
|
||||
|
||||
def __getSync(self):
|
||||
self.port.flush()
|
||||
c = self.__recv()
|
||||
if (c != self.INSYNC):
|
||||
raise RuntimeError("unexpected 0x%x instead of INSYNC" % ord(c))
|
||||
c = self.__recv()
|
||||
if (c != self.OK):
|
||||
raise RuntimeError("unexpected 0x%x instead of OK" % ord(c))
|
||||
|
||||
# attempt to get back into sync with the bootloader
|
||||
def __sync(self):
|
||||
# send a stream of ignored bytes longer than the longest possible conversation
|
||||
# that we might still have in progress
|
||||
# self.__send(uploader.NOP * (uploader.PROG_MULTI_MAX + 2))
|
||||
self.port.flushInput()
|
||||
self.__send(uploader.GET_SYNC
|
||||
+ uploader.EOC)
|
||||
self.__getSync()
|
||||
|
||||
def __trySync(self):
|
||||
c = self.__recv()
|
||||
if (c != self.INSYNC):
|
||||
#print("unexpected 0x%x instead of INSYNC" % ord(c))
|
||||
return False;
|
||||
c = self.__recv()
|
||||
if (c != self.OK):
|
||||
#print("unexpected 0x%x instead of OK" % ord(c))
|
||||
return False
|
||||
return True
|
||||
|
||||
# send the GET_DEVICE command and wait for an info parameter
|
||||
def __getInfo(self, param):
|
||||
self.__send(uploader.GET_DEVICE + param + uploader.EOC)
|
||||
raw = self.__recv(4)
|
||||
self.__getSync()
|
||||
value = struct.unpack_from('<I', raw)
|
||||
return value[0]
|
||||
|
||||
# send the CHIP_ERASE command and wait for the bootloader to become ready
|
||||
def __erase(self):
|
||||
self.__send(uploader.CHIP_ERASE
|
||||
+ uploader.EOC)
|
||||
self.__getSync()
|
||||
|
||||
# send a PROG_MULTI command to write a collection of bytes
|
||||
def __program_multi(self, data):
|
||||
self.__send(uploader.PROG_MULTI
|
||||
+ chr(len(data)))
|
||||
self.__send(data)
|
||||
self.__send(uploader.EOC)
|
||||
self.__getSync()
|
||||
|
||||
# verify multiple bytes in flash
|
||||
def __verify_multi(self, data):
|
||||
self.__send(uploader.READ_MULTI
|
||||
+ chr(len(data))
|
||||
+ uploader.EOC)
|
||||
programmed = self.__recv(len(data))
|
||||
if (programmed != data):
|
||||
print("got " + binascii.hexlify(programmed))
|
||||
print("expect " + binascii.hexlify(data))
|
||||
return False
|
||||
self.__getSync()
|
||||
return True
|
||||
|
||||
# send the reboot command
|
||||
def __reboot(self):
|
||||
self.__send(uploader.REBOOT)
|
||||
self.port.flush()
|
||||
|
||||
# split a sequence into a list of size-constrained pieces
|
||||
def __split_len(self, seq, length):
|
||||
return [seq[i:i+length] for i in range(0, len(seq), length)]
|
||||
|
||||
# upload code
|
||||
def __program(self, fw):
|
||||
code = fw.image
|
||||
groups = self.__split_len(code, uploader.PROG_MULTI_MAX)
|
||||
for bytes in groups:
|
||||
self.__program_multi(bytes)
|
||||
|
||||
# verify code
|
||||
def __verify(self, fw):
|
||||
self.__send(uploader.CHIP_VERIFY
|
||||
+ uploader.EOC)
|
||||
self.__getSync()
|
||||
code = fw.image
|
||||
groups = self.__split_len(code, uploader.READ_MULTI_MAX)
|
||||
for bytes in groups:
|
||||
if (not self.__verify_multi(bytes)):
|
||||
raise RuntimeError("Verification failed")
|
||||
|
||||
# get basic data about the board
|
||||
def identify(self):
|
||||
# make sure we are in sync before starting
|
||||
self.__sync()
|
||||
|
||||
# get the bootloader protocol ID first
|
||||
bl_rev = self.__getInfo(uploader.INFO_BL_REV)
|
||||
if bl_rev != uploader.BL_REV:
|
||||
raise RuntimeError("Bootloader protocol mismatch")
|
||||
|
||||
self.board_type = self.__getInfo(uploader.INFO_BOARD_ID)
|
||||
self.board_rev = self.__getInfo(uploader.INFO_BOARD_REV)
|
||||
self.fw_maxsize = self.__getInfo(uploader.INFO_FLASH_SIZE)
|
||||
|
||||
# upload the firmware
|
||||
def upload(self, fw):
|
||||
# Make sure we are doing the right thing
|
||||
if self.board_type != fw.property('board_id'):
|
||||
raise RuntimeError("Firmware not suitable for this board")
|
||||
if self.fw_maxsize < fw.property('image_size'):
|
||||
raise RuntimeError("Firmware image is too large for this board")
|
||||
|
||||
print("erase...")
|
||||
self.__erase()
|
||||
|
||||
print("program...")
|
||||
self.__program(fw)
|
||||
|
||||
print("verify...")
|
||||
self.__verify(fw)
|
||||
|
||||
print("done, rebooting.")
|
||||
self.__reboot()
|
||||
self.port.close()
|
||||
|
||||
|
||||
# Parse commandline arguments
|
||||
parser = argparse.ArgumentParser(description="Firmware uploader for the PX autopilot system.")
|
||||
parser.add_argument('--port', action="store", required=True, help="Serial port(s) to which the FMU may be attached")
|
||||
parser.add_argument('--baud', action="store", type=int, default=115200, help="Baud rate of the serial port (default is 115200), only required for true serial ports.")
|
||||
parser.add_argument('firmware', action="store", help="Firmware file to be uploaded")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Load the firmware file
|
||||
fw = firmware(args.firmware)
|
||||
print("Loaded firmware for %x,%x, waiting for the bootloader..." % (fw.property('board_id'), fw.property('board_revision')))
|
||||
|
||||
# Spin waiting for a device to show up
|
||||
while True:
|
||||
for port in args.port.split(","):
|
||||
|
||||
#print("Trying %s" % port)
|
||||
|
||||
# create an uploader attached to the port
|
||||
try:
|
||||
if "linux" in _platform:
|
||||
# Linux, don't open Mac OS and Win ports
|
||||
if not "COM" in port and not "tty.usb" in port:
|
||||
up = uploader(port, args.baud)
|
||||
elif "darwin" in _platform:
|
||||
# OS X, don't open Windows and Linux ports
|
||||
if not "COM" in port and not "ACM" in port:
|
||||
up = uploader(port, args.baud)
|
||||
elif "win" in _platform:
|
||||
# Windows, don't open POSIX ports
|
||||
if not "/" in port:
|
||||
up = uploader(port, args.baud)
|
||||
except:
|
||||
# open failed, rate-limit our attempts
|
||||
time.sleep(0.05)
|
||||
|
||||
# and loop to the next port
|
||||
continue
|
||||
|
||||
# port is open, try talking to it
|
||||
try:
|
||||
# identify the bootloader
|
||||
up.identify()
|
||||
print("Found board %x,%x on %s" % (up.board_type, up.board_rev, port))
|
||||
|
||||
except:
|
||||
# most probably a timeout talking to the port, no bootloader
|
||||
continue
|
||||
|
||||
try:
|
||||
# ok, we have a bootloader, try flashing it
|
||||
up.upload(fw)
|
||||
|
||||
except RuntimeError as ex:
|
||||
|
||||
# print the error
|
||||
print("ERROR: %s" % ex.args)
|
||||
|
||||
finally:
|
||||
# always close the port
|
||||
up.close()
|
||||
|
||||
# we could loop here if we wanted to wait for more boards...
|
||||
sys.exit(0)
|
||||
Executable
+272
@@ -0,0 +1,272 @@
|
||||
5.19 2011-03-12 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* Initial version of the apps/ directory was released as contributed by
|
||||
Uros Platise.
|
||||
|
||||
6.0 2011-03-21 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* README.txt -- README cosmetics
|
||||
* hello/ -- hello world minor changes
|
||||
* Makefile -- Makefile cosmetics (I am slowly adding the Darjeeling JVM)
|
||||
* Make.defs -- New file adds common make definitions for applications.
|
||||
* hello/Makefile -- Now uses new Make.defs definitions. Added README.txt.
|
||||
* apps/poweroff -- New application to turn off board power.
|
||||
* Moved NSH library, netutils, and examples from the nuttx/ directory to
|
||||
the apps/ directory
|
||||
* Moved exec_nuttapp machinery into the nuttapp/ directory.
|
||||
|
||||
6.1 2011-04-10 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* Creation of auto-generated header files now occurs during the context
|
||||
build phase.
|
||||
* Added sdcard insert and eject, nsh command '?' and some code remarks
|
||||
* Renamed nuttapp to namedapp
|
||||
* namedapp/binfs.c -- Create a tiny filesystem that can be used
|
||||
to show the internal named apps under /bin.
|
||||
* Numerous fixes to build system required to support building with native
|
||||
Windows toolchain.
|
||||
|
||||
6.2 2011-05-06 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/nxffs: Add a test a a configuration that will be used to
|
||||
verify NXFFS.
|
||||
|
||||
6.3 2011-05-15 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/interpreter: Add a directory to hold interpreters. The Pascal add-
|
||||
on module now installs and builds under this directory.
|
||||
* apps/interpreter/ficl: Added logic to build Ficl (the "Forth Inspired
|
||||
Command Language"). See http://ficl.sourceforge.net/.
|
||||
* apps/netutils/dhcpc, dhcpcd, and tftp. If these directories are included
|
||||
in the configuration but CONFIG_NET_UDP is disable (which is not very wise),
|
||||
then a make error occurs because tools/mkdep.sh is called with no files.
|
||||
* system/free: Move Uros' custom free command from vsn/free
|
||||
* system/install: Add a new install command submitted by Uros Platise.
|
||||
* examples/rgmp. Add a placeholder for an RGMP build example.
|
||||
RGMP is a project for running GPOS and RTOS simultaneously on
|
||||
multi-processor platforms. See http://rgmp.sourceforge.net/wiki/index.php/Main_Page
|
||||
for further information about RGMP. NOTE: This is an empty example
|
||||
on initial check-in.
|
||||
|
||||
6.4 2011-06-06 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* nshlib/nsh_netcmds.c: If a network device name and IP address are provided
|
||||
with the ifconfig command, then this command will now set the network address.
|
||||
(Contributed by Yu Qiang).
|
||||
* netutils/ftpc: A library to support client-side FTP.
|
||||
* examples/ftpc: A simple add-on to the NSH. From NSH, you can start
|
||||
this simple FTP shell to transfer files to/from a remote FTP server.
|
||||
|
||||
6.5 2011-06-21 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* netutils/ftpc: Simpflication and size reduction.
|
||||
|
||||
6.6 2011-07-11 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* Make.defs, namedapp/namedapp.c: Several structural changes made to get a
|
||||
clean compile under the ez80 ZDS-II toolchain (no design changes).
|
||||
* apps/examples/buttons: Add a test for the new standardized button interfaces
|
||||
* apps/examples/nxtext: Add another NX graphics test. This one focus on
|
||||
placing text on the background while pop-up windows occur. Text should
|
||||
continue to update normally with or without the popup windows present.
|
||||
|
||||
6.7 2011-08-02 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/nx and nxtext: These examples can now be built as NSH
|
||||
"built-in" commands.
|
||||
* apps/examples/nxhello: The simplest graphics example: It just says
|
||||
"Hello, World!" in the center of the display. This example can also be
|
||||
built as an NSH "built-in" command.
|
||||
* apps/examples/nx, ntext, and nxhello: All updated to use the new
|
||||
NuttX font interfaces.
|
||||
* apps/examples/nximage: Another super simple graphics example: It just puts
|
||||
the NuttX logo in the center of the display. This example can also be
|
||||
built as an NSH "built-in" command.
|
||||
* apps/examples/usbstorage: Can now be built as two NSH "built-in" commands:
|
||||
'msconn' will connect the USB mass storage device; 'msdis' will disconnect
|
||||
the USB storage device.
|
||||
* apps/examples/nx*: All NX header files moved from nuttx/include/nuttx to
|
||||
nuttx/include/nuttx/nx.
|
||||
* apps/examples/usbstorage: Added instrumentation to monitor memory usage
|
||||
to check for memory leaks in the USB storage driver.
|
||||
* apps/examples/nxhello/nxhello_bkgd.c: Fix handling of allocated glyph
|
||||
memory.
|
||||
|
||||
6.8 2011-08-11 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/nxlines: Added a test for NX line drawing capabilities.
|
||||
|
||||
6.9 2011-09-11 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/nxlines: Extend the line drawing text to include drawing
|
||||
of circles.
|
||||
* apps/system/i2c: Add an I2C test tool that should help to bring up I2C
|
||||
devices (when it is fully functional).
|
||||
* apps/nshlib/nsh_timcmds.c: Add the date command that can be used to
|
||||
show or set the time (only if CONFIG_RTC is set).
|
||||
|
||||
6.10 2011-10-06 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/system/i2c: Add repitition and address auto-incrementing so that
|
||||
and command can be executed numerous times. Add a new verify command
|
||||
that will write to a register, read from register, and verify that
|
||||
returned value.
|
||||
* apps/graphics/tiff: Add a library that can be used to create TIFF files.
|
||||
* apps/examples/tiff: Add a unit test for the TIFF file creation logic
|
||||
* apps/examples/lcdrw: Add a test to verify if you can or can or read
|
||||
data from an LCD correctly.
|
||||
* apps/examples/usbterm: A USB terminal example.. more of a USB chat or
|
||||
serial bridge: Data received on local console echoed via USB serial;
|
||||
data received on USB serial is echoed on the local console.
|
||||
* apps/examples/touchscreen: Add a simple, generic test for any
|
||||
touschscreen driver.
|
||||
* Makefile: The apps/ Makefile now checks for an apps/external directory
|
||||
or symbolic link. If such a directory/link exists (and has a Makefile),
|
||||
it will be added to the apps/ build. This allows external directories
|
||||
to be included into the apps/ build by simply creating a symbolic link.
|
||||
|
||||
6.11 2011-11-12 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
(No major changes from 6.10)
|
||||
|
||||
6.12 2011-12-06 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/buttons: The button test can now be executed as an NSH
|
||||
built in command.
|
||||
|
||||
6.13 2012-12-26 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/dhcpd: May now be built as an NSH built-in application
|
||||
by setting CONFIG_NSH_BUILTIN_APPS.
|
||||
* apps/netutils/dhcpd/dhcpd.c: Fix several problems using host order address
|
||||
where network addresses expected (and vice versa).
|
||||
* apps/examples/nettest: May now be built as an NSH built-in application
|
||||
by setting CONFIG_NSH_BUILTIN_APPS.
|
||||
* apps/examples/nettest: Correct some build issues with the nettest is
|
||||
built for performance evaluation.
|
||||
* apps/examples/adc: Add a very simple test to drive and test an ADC
|
||||
driver.
|
||||
* apps/examples/pwm: Add an NSH PWM command to drive and test a PWM
|
||||
driver.
|
||||
* apps/examples/can: Add an NSH CAN command to drive and test a CAN
|
||||
driver in loopback mode.
|
||||
|
||||
6.14 2012-01-15 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/buttons/main.c: The test needs to call up_buttoninit() to
|
||||
properly configure the button interrupt GPIOs.
|
||||
* apps/examples/pwm: Add support to test the pulse count option recently
|
||||
added to the PWM interface.
|
||||
|
||||
6.15 2012-02-12 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/nshlib/nsh_serial.c and nsh_usbdev.c: If NuttX is configured to use
|
||||
a USB serial console, then NSH needs to wait until the USB console is
|
||||
connected and available.
|
||||
* apps/examples/composite: Add a test of the USB composite device.
|
||||
* apps/examples/Telnetd: Move the tiny uIP shell example from
|
||||
netutils/Telnetd to examples/Telnetd. Enhanced the Telnetd daemon so that
|
||||
it supports Telnetd via a TTY device driver: A new TTY device driver is
|
||||
created when each new Telnet connection is created. The shell thread
|
||||
is started with stdin, stdout, and stderr mapped to the TTY device.
|
||||
* netutils/Telnetd: The old uIP Telnet demo is gone. In its place is a new
|
||||
Telnet infrastructure. The new Telnet daemon creates sessions that are
|
||||
"wrapped" as character devices and mapped to stdin, stdout, and stderr.
|
||||
Now the Telnet session can be inherited by spawned tasks.
|
||||
* examples/Telnetd: Add a test for the new Telnet daemon.
|
||||
* examples/Telnetd/telnetd_driver.c: Move the internal socket structure from
|
||||
the daemon's socket array into the driver's state data so that it will be
|
||||
independent from the the Telnetd daemon.
|
||||
* apps/system/readline: Moved the old nuttx/lib/stdio/lib_fgets.c here
|
||||
and renamed it as readline(). The old fgets was simplied and the overloaded
|
||||
readline functionality was removed.
|
||||
* apps/netutils/ftpd: Add an FTPD server (does not even compile on initial
|
||||
checkin).
|
||||
* apps/examples/ftpd: Add a test for the FTPD server (untest on initial
|
||||
check-in).
|
||||
* apps/nshlib/nsh_fscmds.c: Add support for a 'dmesg' command that will
|
||||
dump the system log if CONFIG_SYSLOG is selected.
|
||||
|
||||
6.16 2012-03-10 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/qencoder: Add a quadrature driver test.
|
||||
* apps/examples/ostest/fpu.c: Add a test to verify that FPU registers
|
||||
are properly saved and restored on context switches.
|
||||
* apps/system/readline/readline.c: readline() will now treat either a
|
||||
backspace or a DEL character as a backspace (i.e., deleting the character
|
||||
to the left of the cursor). This makes NSH less dependent on particular
|
||||
keyboard mappings of the Backspace key. Submitted by Mike Smith.
|
||||
* apps/examples/cdcacm: An example that illustrates how the CDC/ACM driver
|
||||
may to connected and disconnected through software control.
|
||||
* apps/examples/nsh/nsh_main.c: If available, call up_cxxinitialize() to
|
||||
initialize all statically defined C++ classes.
|
||||
* apps/nshlib: Now supports a USB serial device for NSH console I/O. This
|
||||
allows NSH to be used on boards that have USB but no serial connectors.
|
||||
|
||||
6.17 2012-04-14 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/examples/can: Add conditional compilation so that the test can be
|
||||
configured to only send messages or to only receive messages. This will
|
||||
let the test work in other modes than simple loopback testing.
|
||||
* apps/examples/hello and apps/examples/ostest: Can now be built as NSH
|
||||
built-int functions.
|
||||
* vsn/hello: Removed. The modified apps/examples/hello is enough "Hello,
|
||||
World!"
|
||||
* apps/examples/nxconsole: Add a test of the NX console device.
|
||||
* apps/examples/nxconsole: The NX console example now supports running
|
||||
the NuttShell (NSH) within an NX window.
|
||||
* apps/system/readline: Now uses standard definitions from
|
||||
include/nuttx/ascii.h and vt100.h
|
||||
* Kconfig, */Kconfig: Added skeleton Kconfig files to all directories that
|
||||
may need them.
|
||||
|
||||
6.18 2012-05-19 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* Kconfig: Continued Kconfig file updates (no longer tracking on a per-file
|
||||
basis in the ChangeLog)
|
||||
* apps/examples/watchdog: Add a watchdog timer example.
|
||||
* apps/examples/tiff: Fix wrong path used for temporary file.
|
||||
* apps/examples/touchscreen: Standardize the board-specific, touchscreen
|
||||
initialization interfaces.
|
||||
|
||||
6.19 2012-06-15 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/nshlib/nsh_usbdev.c: Add the capability to use an arbitrary USB
|
||||
device as the console (not necessarily /dev/console). This is a useful
|
||||
option because then you can still use the serial console to debug with.
|
||||
* apps/nshlib/nsh_usbdev.c: User now has to press ENTER 3 times before
|
||||
USB console will start. Otherwise, the USB console starts before there
|
||||
is anyone at the other end to listen.
|
||||
* apps/nshlib/nsh_usbdev.c and nsh_consolemain.c: Add support for the USB
|
||||
capability when a USB console is used.
|
||||
* apps/nshlib/nsh_fscmds.c: Add the 'mv' command
|
||||
|
||||
6.20 2012-07-12 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* namedapp/exec_namedapp.c - Correct an error when round robin scheduling
|
||||
is enabled. The priority of the new, named application was erroneously
|
||||
being set to the priority of the parent thread; losing its configured
|
||||
priority. Reported by Mike Smith.
|
||||
|
||||
6.21 2012-xx-xx Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* apps/include/: Stylistic clean-up of all header files.
|
||||
* apps/modbus and apps/include/modbus: A port of freemodbus-v1.5.0
|
||||
has been added to the NuttX apps/ source tree.
|
||||
* apps/examples/modbus: A port of the freemodbus-v1.5.0 "demo"
|
||||
program that will be used to verify the FreeModBus port
|
||||
* apps/modbus: Don't use strerror(). It is just too big.
|
||||
* apps/modbus: Add CONFIG_MB_TERMIOS. If the driver doesn't support
|
||||
termios ioctls, then don't bother trying to configure the baud, parity
|
||||
etc.
|
||||
* apps/nslib: If waitpid() is supported, then NSH not catches the
|
||||
return value from spawned applications (provided by Mike Smith)
|
||||
* apps/nslib: Lock the schedule while starting built-in applications
|
||||
in order to eliminate race conditions (also from Mike Smith).
|
||||
* apps/examples/adc, pwm, and qencoder: Add support for testing
|
||||
devices with multiple ADC, PWM, and QE devices.
|
||||
* apps/nshlib/nsh_mntcmds.c: Separated mount-related commands out of
|
||||
nsh_fscmds.c. Extended to the mount command so that if no arguments
|
||||
are provided, then the current mountpoints are enumerated.
|
||||
* apps/nshlib/nsh_mntcmds.c: Add an NSH df command to list the
|
||||
properties of mounted file systems.
|
||||
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see misc/tools/kconfig-language.txt.
|
||||
#
|
||||
|
||||
menu "Named Applications"
|
||||
source "$APPSDIR/namedapp/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "Examples"
|
||||
source "$APPSDIR/examples/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "Interpreters"
|
||||
source "$APPSDIR/interpreters/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "Network Utilities"
|
||||
source "$APPSDIR/netutils/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "ModBus"
|
||||
source "$APPSDIR/modbus/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "NSH Library"
|
||||
source "$APPSDIR/nshlib/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "System NSH Add-Ons"
|
||||
source "$APPSDIR/system/Kconfig"
|
||||
endmenu
|
||||
|
||||
menu "VSN board Add-Ons"
|
||||
source "$APPSDIR/vsn/Kconfig"
|
||||
endmenu
|
||||
@@ -0,0 +1,41 @@
|
||||
############################################################################
|
||||
# apps/Make.defs
|
||||
# Common make definitions provided to all applications
|
||||
#
|
||||
# Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
define REGISTER
|
||||
@echo "Register: $1"
|
||||
@echo "{ \"$1\", $2, $3, $4 }," >> "$(APPDIR)/namedapp/namedapp_list.h"
|
||||
@echo "EXTERN int $4(int argc, char *argv[]);" >> "$(APPDIR)/namedapp/namedapp_proto.h"
|
||||
endef
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
############################################################################
|
||||
# apps/Makefile
|
||||
#
|
||||
# Copyright (C) 2011-2012 Uros Platise. All rights reserved.
|
||||
# Authors: Uros Platise <uros.platise@isotel.eu>
|
||||
# Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
-include $(TOPDIR)/Make.defs
|
||||
-include $(TOPDIR)/.config
|
||||
|
||||
APPDIR = ${shell pwd}
|
||||
|
||||
# Application Directories
|
||||
|
||||
# CONFIGURED_APPS is the list of all configured built-in directories/built
|
||||
# action. It is created by the configured appconfig file (a copy of which
|
||||
# appears in this directory as .config)
|
||||
# SUBDIRS is the list of all directories containing Makefiles. It is used
|
||||
# only for cleaning. namedapp must always be the first in the list. This
|
||||
# list can be extended by the .config file as well
|
||||
|
||||
CONFIGURED_APPS =
|
||||
#SUBDIRS = examples graphics interpreters modbus namedapp nshlib netutils system vsn
|
||||
ALL_SUBDIRS = $(dir $(shell /usr/bin/find . -name Makefile))
|
||||
SUBDIRS = namedapp/ $(filter-out ./ ./namedapp/ ./examples/,$(ALL_SUBDIRS))
|
||||
|
||||
|
||||
# There are two different mechanisms for obtaining the list of configured
|
||||
# directories:
|
||||
#
|
||||
# (1) In the legacy method, these paths are all provided in the appconfig
|
||||
# file that is copied to the top-level apps/ directory as .config
|
||||
# (2) With the development of the NuttX configuration tool, however, the
|
||||
# selected applications are now enabled by the configuration tool.
|
||||
# The apps/.config file is no longer used. Instead, the set of
|
||||
# configured build directories can be found by including a Make.defs
|
||||
# file contained in each of the apps/subdirectories.
|
||||
#
|
||||
# When the NuttX configuration tools executes, it will always define the
|
||||
# configure CONFIG_NUTTX_NEWCONFIG to select between these two cases. Then
|
||||
# legacy appconfig files will still work but newly configuration files will
|
||||
# also work. Eventually the CONFIG_NUTTX_NEWCONFIG option will be phased
|
||||
# out.
|
||||
|
||||
ifeq ($(CONFIG_NUTTX_NEWCONFIG),y)
|
||||
|
||||
-include examples/Make.defs
|
||||
-include graphics/Make.defs
|
||||
-include interpreters/Make.defs
|
||||
-include modbus/Make.defs
|
||||
-include namedapp/Make.defs
|
||||
-include netutils/Make.defs
|
||||
-include nshlib/Make.defs
|
||||
-include system/Make.defs
|
||||
-include vsn/Make.defs
|
||||
|
||||
# INSTALLED_APPS is the list of currently available application directories. It
|
||||
# is the same as CONFIGURED_APPS, but filtered to exclude any non-existent
|
||||
# application directory. namedapp is always in the list of applications to be
|
||||
# built.
|
||||
|
||||
INSTALLED_APPS =
|
||||
|
||||
# The legacy case:
|
||||
|
||||
else
|
||||
-include .config
|
||||
|
||||
# INSTALLED_APPS is the list of currently available application directories. It
|
||||
# is the same as CONFIGURED_APPS, but filtered to exclude any non-existent
|
||||
# application directory. namedapp is always in the list of applications to be
|
||||
# built.
|
||||
|
||||
INSTALLED_APPS = namedapp
|
||||
endif
|
||||
|
||||
# Create the list of available applications (INSTALLED_APPS)
|
||||
|
||||
define ADD_BUILTIN
|
||||
INSTALLED_APPS += ${shell if [ -r $1/Makefile ]; then echo "$1"; fi}
|
||||
endef
|
||||
|
||||
$(foreach BUILTIN, $(CONFIGURED_APPS), $(eval $(call ADD_BUILTIN,$(BUILTIN))))
|
||||
|
||||
# The external/ directory may also be added to the INSTALLED_APPS. But there
|
||||
# is no external/ directory in the repository. Rather, this directory may be
|
||||
# provided by the user (possibly as a symbolic link) to add libraries and
|
||||
# applications to the standard build from the repository.
|
||||
|
||||
INSTALLED_APPS += ${shell if [ -r external/Makefile ]; then echo "external"; fi}
|
||||
SUBDIRS += ${shell if [ -r external/Makefile ]; then echo "external"; fi}
|
||||
|
||||
# The final build target
|
||||
|
||||
BIN = libapps$(LIBEXT)
|
||||
|
||||
# Build targets
|
||||
|
||||
all: $(BIN)
|
||||
.PHONY: $(INSTALLED_APPS) context depend clean distclean
|
||||
|
||||
$(INSTALLED_APPS):
|
||||
@$(MAKE) -C $@ TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)";
|
||||
|
||||
$(BIN): $(INSTALLED_APPS)
|
||||
@( for obj in $(OBJS) ; do \
|
||||
$(call ARCHIVE, $@, $${obj}); \
|
||||
done ; )
|
||||
|
||||
.context:
|
||||
@for dir in $(INSTALLED_APPS) ; do \
|
||||
rm -f $$dir/.context ; \
|
||||
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" context ; \
|
||||
done
|
||||
@touch $@
|
||||
|
||||
context: .context
|
||||
|
||||
.depend: context Makefile $(SRCS)
|
||||
@for dir in $(INSTALLED_APPS) ; do \
|
||||
rm -f $$dir/.depend ; \
|
||||
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" depend ; \
|
||||
done
|
||||
@touch $@
|
||||
|
||||
depend: .depend
|
||||
|
||||
clean:
|
||||
@for dir in $(SUBDIRS) ; do \
|
||||
$(MAKE) -C $$dir clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \
|
||||
done
|
||||
@rm -f $(BIN) *~ .*.swp *.o
|
||||
$(call CLEAN)
|
||||
|
||||
distclean: # clean
|
||||
@for dir in $(SUBDIRS) ; do \
|
||||
$(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \
|
||||
done
|
||||
@rm -f .config .context .depend
|
||||
@( if [ -e external ]; then \
|
||||
echo "********************************************************"; \
|
||||
echo "* The external directory/link must be removed manually *"; \
|
||||
echo "********************************************************"; \
|
||||
fi; \
|
||||
)
|
||||
|
||||
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
Application Folder
|
||||
==================
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
General
|
||||
Directory Location
|
||||
Named Applications
|
||||
Named Startup main() function
|
||||
NuttShell (NSH) Built-In Commands
|
||||
Synchronous Built-In Commands
|
||||
Application Configuration File
|
||||
Example Named Application
|
||||
Building NuttX with Board-Specific Pieces Outside the Source Tree
|
||||
|
||||
General
|
||||
-------
|
||||
This folder provides various applications found in sub-directories. These
|
||||
applications are not inherently a part of NuttX but are provided you help
|
||||
you develop your own applications. The apps/ directory is a "break away"
|
||||
part of the configuration that you may chose to use or not.
|
||||
|
||||
Directory Location
|
||||
------------------
|
||||
The default application directory used by the NuttX build should be named
|
||||
apps/ (or apps-x.y/ where x.y is the NuttX version number). This apps/
|
||||
directory should appear in the directory tree at the same level as the
|
||||
NuttX directory. Like:
|
||||
|
||||
.
|
||||
|- nuttx
|
||||
|
|
||||
`- apps
|
||||
|
||||
If all of the above conditions are TRUE, then NuttX will be able to
|
||||
find the application directory. If your application directory has a
|
||||
different name or is location at a different position, then you will
|
||||
have to inform the NuttX build system of that location. There are several
|
||||
ways to do that:
|
||||
|
||||
1) You can define CONFIG_APPS_DIR to be the full path to your application
|
||||
directory in the NuttX configuration file.
|
||||
2) You can provide the path to the application directory on the command line
|
||||
like: make APPDIR=<path> or make CONFIG_APPS_DIR=<path>
|
||||
3) When you configure NuttX using tools/configure.sh, you can provide that
|
||||
path to the application directory on the configuration command line
|
||||
like: ./configure.sh -a <app-dir> <board-name>/<config-name>
|
||||
|
||||
Named Applications
|
||||
------------------
|
||||
NuttX also supports applications that can be started using a name string.
|
||||
In this case, application entry points with their requirements are gathered
|
||||
together in two files:
|
||||
|
||||
- namedapp/namedapp_proto.h Entry points, prototype function
|
||||
- namedapp/namedapp_list.h Application specific information and requirements
|
||||
|
||||
The build occurs in several phases as different build targets are executed:
|
||||
(1) context, (2) depend, and (3) default (all). Application information is
|
||||
collected during the make context build phase.
|
||||
|
||||
To execute an application function:
|
||||
|
||||
exec_namedapp() is defined in the nuttx/include/apps/apps.h
|
||||
|
||||
NuttShell (NSH) Built-In Commands
|
||||
---------------------------------
|
||||
One use of named applications is to provide a way of invoking your custom
|
||||
application through the NuttShell (NSH) command line. NSH will support
|
||||
a seamless method invoking the applications, when the following option is
|
||||
enabled in the NuttX configuration file:
|
||||
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
|
||||
Applications registered in the apps/namedapp/namedapp_list.h file will then
|
||||
be accessible from the NSH command line. If you type 'help' at the NSH
|
||||
prompt, you will see a list of the registered commands.
|
||||
|
||||
Synchronous Built-In Commands
|
||||
-----------------------------
|
||||
By default, built-in commands started from the NSH command line will run
|
||||
asynchronously with NSH. If you want to force NSH to execute commands
|
||||
then wait for the command to execute, you can enable that feature by
|
||||
adding the following to the NuttX configuration file:
|
||||
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
|
||||
The configuration option enables support for the waitpid() RTOS interface.
|
||||
When that interface is enabled, NSH will use it to wait, sleeping until
|
||||
the built-in command executes to completion.
|
||||
|
||||
Of course, even with CONFIG_SCHED_WAITPID=y defined, specific commands
|
||||
can still be forced to run asynchronously by adding the ampersand (&)
|
||||
after the NSH command.
|
||||
|
||||
Application Configuration File
|
||||
------------------------------
|
||||
A special configuration file is used to configure which applications
|
||||
are to be included in the build. The source for this file is
|
||||
configs/<board>/<configuration>/appconfig. The existence of the appconfig
|
||||
file in the board configuration directory is sufficient to enable building
|
||||
of applications.
|
||||
|
||||
The appconfig file is copied into the apps/ directory as .config when
|
||||
NuttX is configured. .config is included in the toplevel apps/Makefile.
|
||||
As a minimum, this configuration file must define files to add to the
|
||||
CONFIGURED_APPS list like:
|
||||
|
||||
CONFIGURED_APPS += examples/hello vsn/poweroff
|
||||
|
||||
Named Start-Up main() function
|
||||
------------------------------
|
||||
A named application can even be used as the main, start-up entry point
|
||||
into your embedded software. When the user defines this option in
|
||||
the NuttX configuration file:
|
||||
|
||||
CONFIG_BUILTIN_APP_START=<application name>
|
||||
|
||||
that application shall be invoked immediately after system starts
|
||||
*instead* of the normal, default "user_start" entry point.
|
||||
Note that <application name> must be provided as: "hello",
|
||||
will call:
|
||||
|
||||
int hello_main(int argc, char *argv[])
|
||||
|
||||
Example Named Application
|
||||
-------------------------
|
||||
An example application skeleton can be found under the examples/hello
|
||||
sub-directory. This example shows how a named application can be added
|
||||
to the project. One must define:
|
||||
|
||||
1. create sub-directory as: appname
|
||||
2. provide entry point: appname_main()
|
||||
3. set the requirements in the file: Makefile, specially the lines:
|
||||
|
||||
APPNAME = appname
|
||||
PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||
STACKSIZE = 768
|
||||
ASRCS = asm source file list as a.asm b.asm ...
|
||||
CSRCS = C source file list as foo1.c foo2.c ..
|
||||
|
||||
4. add application in the apps/.config
|
||||
|
||||
Building NuttX with Board-Specific Pieces Outside the Source Tree
|
||||
-----------------------------------------------------------------
|
||||
|
||||
Q: Has anyone come up with a tidy way to build NuttX with board-
|
||||
specific pieces outside the source tree?
|
||||
A: Here are four:
|
||||
|
||||
1) There is a make target called 'make export'. It will build
|
||||
NuttX, then bundle all of the header files, libaries, startup
|
||||
objects, and other build components into a .zip file. You
|
||||
can can move that .zip file into any build environment you
|
||||
want. You even build NuttX under a DOS CMD window.
|
||||
|
||||
This make target is documented in the top level nuttx/README.txt.
|
||||
|
||||
2) You can replace the entire apps/ directory. If there is
|
||||
nothing in the apps/ directory that you need, you can define
|
||||
CONFIG_APPS_DIR in your .config file so that it points to a
|
||||
different, custom application directory.
|
||||
|
||||
You can copy any pieces that you like from the old apps/directory
|
||||
to your custom apps directory as necessary.
|
||||
|
||||
This is documented in NuttX/configs/README.txt and
|
||||
nuttx/Documentation/NuttxPortingGuide.html (Online at
|
||||
http://nuttx.sourceforge.net/NuttxPortingGuide.html#apndxconfigs
|
||||
under Build options). And in the apps/README.txt file.
|
||||
|
||||
3) If you like the random collection of stuff in the apps/ directory
|
||||
but just want to expand the existing components with your own,
|
||||
external sub-directory then there is an easy way to that too:
|
||||
You just create the sympolic link at apps/external that
|
||||
redirects to your application sub-directory. The apps/Makefile
|
||||
will always automatically check for the existence of an
|
||||
apps/external directory and if it exists, it will automatically
|
||||
incorporate it into the build.
|
||||
|
||||
This feature of the apps/Makefile is documented only here.
|
||||
|
||||
You can, for example, create a script called install.sh that
|
||||
installs a custom application, configuration, and board specific
|
||||
directory:
|
||||
|
||||
a) Copy 'MyBoard' directory to configs/MyBoard.
|
||||
b) Add a symbolic link to MyApplication at apps/external
|
||||
c) Configure NuttX (usually by:
|
||||
|
||||
tools/configure.sh MyBoard/MyConfiguration
|
||||
|
||||
or simply by copying defconfig->nutt/.config,
|
||||
setenv.sh->nuttx/setenv.sh, Make.defs->nuttx/Make.defs,
|
||||
appconfig->apps/.config
|
||||
|
||||
Using the 'external' link makes it especially easy to add a
|
||||
'built-in' application an existing configuration.
|
||||
|
||||
4) Add any link to apps/
|
||||
|
||||
a) Add symbolic links apps/ to as many other directories as you
|
||||
want.
|
||||
b) Then just add the (relative) paths to the links in your
|
||||
appconfig file (that becomes the apps/.config file).
|
||||
|
||||
That is basically the same as my option #3 but doesn't use the
|
||||
magic 'external' link. The toplevel apps/Makefile will always
|
||||
to build whatever in finds in the apps/.config file (plus the
|
||||
external link if present).
|
||||
@@ -0,0 +1,45 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
#
|
||||
# Makefile to build uORB
|
||||
#
|
||||
|
||||
APPNAME = ardrone_control
|
||||
PRIORITY = SCHED_PRIORITY_MAX - 15
|
||||
STACKSIZE = 2048
|
||||
|
||||
# explicit list of sources - not everything is built currently
|
||||
CSRCS = ardrone_control.c ardrone_motor_control.c ardrone_control_helper.c rate_control.c attitude_control.c pid.c
|
||||
|
||||
include $(APPDIR)/mk/app.mk
|
||||
@@ -0,0 +1,272 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* @file Implementation of AR.Drone 1.0 / 2.0 control interface
|
||||
*/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <arch/board/up_hrt.h>
|
||||
#include "ardrone_control.h"
|
||||
#include "attitude_control.h"
|
||||
#include "rate_control.h"
|
||||
#include "ardrone_motor_control.h"
|
||||
#include "position_control.h"
|
||||
#include <uORB/uORB.h>
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/ardrone_control.h>
|
||||
#include <uORB/topics/rc_channels.h>
|
||||
#include <uORB/topics/ardrone_motors_setpoint.h>
|
||||
#include <uORB/topics/sensor_combined.h>
|
||||
|
||||
#include "ardrone_control_helper.h"
|
||||
|
||||
__EXPORT int ardrone_control_main(int argc, char *argv[]);
|
||||
|
||||
/****************************************************************************
|
||||
* Internal Definitions
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
enum {
|
||||
CONTROL_MODE_RATES = 0,
|
||||
CONTROL_MODE_ATTITUDE = 1,
|
||||
} control_mode;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/*File descriptors */
|
||||
int ardrone_write;
|
||||
int gpios;
|
||||
|
||||
bool position_control_thread_started;
|
||||
|
||||
/****************************************************************************
|
||||
* pthread loops
|
||||
****************************************************************************/
|
||||
static void *position_control_loop(void *arg)
|
||||
{
|
||||
struct vehicle_status_s *state = (struct vehicle_status_s *)arg;
|
||||
// Set thread name
|
||||
prctl(PR_SET_NAME, "ardrone pos ctrl", getpid());
|
||||
|
||||
while (1) {
|
||||
if (state->state_machine == SYSTEM_STATE_AUTO) {
|
||||
// control_position(); //FIXME TODO XXX
|
||||
/* temporary 50 Hz execution */
|
||||
usleep(20000);
|
||||
|
||||
} else {
|
||||
position_control_thread_started = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* main
|
||||
****************************************************************************/
|
||||
|
||||
int ardrone_control_main(int argc, char *argv[])
|
||||
{
|
||||
/* welcome user */
|
||||
printf("[ardrone_control] Control started, taking over motors\n");
|
||||
|
||||
/* default values for arguments */
|
||||
char *ardrone_uart_name = "/dev/ttyS1";
|
||||
control_mode = CONTROL_MODE_RATES;
|
||||
|
||||
char *commandline_usage = "\tusage: ardrone_control -d ardrone-devicename -m mode\n\tmodes are:\n\t\trates\n\t\tattitude\n";
|
||||
|
||||
/* read commandline arguments */
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //ardrone set
|
||||
if (argc > i + 1) {
|
||||
ardrone_uart_name = argv[i + 1];
|
||||
|
||||
} else {
|
||||
printf(commandline_usage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--mode") == 0) {
|
||||
if (argc > i + 1) {
|
||||
if (strcmp(argv[i + 1], "rates") == 0) {
|
||||
control_mode = CONTROL_MODE_RATES;
|
||||
|
||||
} else if (strcmp(argv[i + 1], "attitude") == 0) {
|
||||
control_mode = CONTROL_MODE_ATTITUDE;
|
||||
|
||||
} else {
|
||||
printf(commandline_usage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
printf(commandline_usage);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* open uarts */
|
||||
printf("[ardrone_control] AR.Drone UART is %s\n", ardrone_uart_name);
|
||||
ardrone_write = open(ardrone_uart_name, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
/* initialize motors */
|
||||
ar_init_motors(ardrone_write, &gpios);
|
||||
int counter = 0;
|
||||
|
||||
/* pthread for position control */
|
||||
pthread_t position_control_thread;
|
||||
position_control_thread_started = false;
|
||||
|
||||
/* structures */
|
||||
struct vehicle_status_s state;
|
||||
struct vehicle_attitude_s att;
|
||||
struct ardrone_control_s ar_control;
|
||||
struct rc_channels_s rc;
|
||||
struct sensor_combined_s raw;
|
||||
struct ardrone_motors_setpoint_s setpoint;
|
||||
|
||||
/* subscribe to attitude, motor setpoints and system state */
|
||||
int att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
|
||||
int state_sub = orb_subscribe(ORB_ID(vehicle_status));
|
||||
int rc_sub = orb_subscribe(ORB_ID(rc_channels));
|
||||
int sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
|
||||
int setpoint_sub = orb_subscribe(ORB_ID(ardrone_motors_setpoint));
|
||||
|
||||
/* publish AR.Drone motor control state */
|
||||
int ardrone_pub = orb_advertise(ORB_ID(ardrone_control), &ar_control);
|
||||
|
||||
while (1) {
|
||||
/* get a local copy of the vehicle state */
|
||||
orb_copy(ORB_ID(vehicle_status), state_sub, &state);
|
||||
/* get a local copy of rc */
|
||||
orb_copy(ORB_ID(rc_channels), rc_sub, &rc);
|
||||
/* get a local copy of attitude */
|
||||
orb_copy(ORB_ID(vehicle_attitude), att_sub, &att);
|
||||
|
||||
if (state.state_machine == SYSTEM_STATE_AUTO) {
|
||||
if (false == position_control_thread_started) {
|
||||
pthread_attr_t position_control_thread_attr;
|
||||
pthread_attr_init(&position_control_thread_attr);
|
||||
pthread_attr_setstacksize(&position_control_thread_attr, 2048);
|
||||
pthread_create(&position_control_thread, &position_control_thread_attr, position_control_loop, &state);
|
||||
position_control_thread_started = true;
|
||||
}
|
||||
|
||||
control_attitude(&rc, &att, &state, ardrone_pub, &ar_control);
|
||||
|
||||
//No check for remote sticks to disarm in auto mode, land/disarm with ground station
|
||||
|
||||
} else if (state.state_machine == SYSTEM_STATE_MANUAL) {
|
||||
if (control_mode == CONTROL_MODE_RATES) {
|
||||
orb_copy(ORB_ID(sensor_combined), sensor_sub, &raw);
|
||||
orb_copy(ORB_ID(ardrone_motors_setpoint), setpoint_sub, &setpoint);
|
||||
control_rates(&raw, &setpoint);
|
||||
|
||||
} else if (control_mode == CONTROL_MODE_ATTITUDE) {
|
||||
control_attitude(&rc, &att, &state, ardrone_pub, &ar_control);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
//fancy led animation...
|
||||
static int blubb = 0;
|
||||
|
||||
if (counter % 20 == 0) {
|
||||
if (blubb == 0) ar_set_leds(ardrone_write, 0, 1, 0, 0, 0, 0, 0 , 0);
|
||||
|
||||
if (blubb == 1) ar_set_leds(ardrone_write, 1, 1, 0, 0, 0, 0, 0 , 0);
|
||||
|
||||
if (blubb == 2) ar_set_leds(ardrone_write, 1, 0, 0, 0, 0, 0, 0 , 0);
|
||||
|
||||
if (blubb == 3) ar_set_leds(ardrone_write, 0, 0, 0, 1, 0, 0, 0 , 0);
|
||||
|
||||
if (blubb == 4) ar_set_leds(ardrone_write, 0, 0, 1, 1, 0, 0, 0 , 0);
|
||||
|
||||
if (blubb == 5) ar_set_leds(ardrone_write, 0, 0, 1, 0, 0, 0, 0 , 0);
|
||||
|
||||
if (blubb == 6) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 1, 0 , 0);
|
||||
|
||||
if (blubb == 7) ar_set_leds(ardrone_write, 0, 0, 0, 0, 1, 1, 0 , 0);
|
||||
|
||||
if (blubb == 8) ar_set_leds(ardrone_write, 0, 0, 0, 0, 1, 0, 0 , 0);
|
||||
|
||||
if (blubb == 9) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 0 , 1);
|
||||
|
||||
if (blubb == 10) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 1 , 1);
|
||||
|
||||
if (blubb == 11) ar_set_leds(ardrone_write, 0, 0, 0, 0, 0, 0, 1 , 0);
|
||||
|
||||
blubb++;
|
||||
|
||||
if (blubb == 12) blubb = 0;
|
||||
}
|
||||
|
||||
/* run at approximately 200 Hz */
|
||||
usleep(5000);
|
||||
counter++;
|
||||
}
|
||||
|
||||
/* close uarts */
|
||||
close(ardrone_write);
|
||||
ar_multiplexing_deinit(gpios);
|
||||
|
||||
printf("[ardrone_control] ending now...\r\n");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* ardrone_control.h
|
||||
*
|
||||
* Created on: Mar 23, 2012
|
||||
* Author: thomasgubler
|
||||
*/
|
||||
|
||||
#ifndef ARDRONE_CONTROL_H_
|
||||
#define ARDRONE_CONTROL_H_
|
||||
|
||||
|
||||
#endif /* ARDRONE_CONTROL_H_ */
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "ardrone_control_helper.h"
|
||||
#include <unistd.h>
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// int read_sensors_raw(sensors_raw_t *sensors_raw)
|
||||
// {
|
||||
// static int ret;
|
||||
// ret = global_data_wait(&global_data_sensors_raw->access_conf_rate_full);
|
||||
|
||||
// if (ret == 0) {
|
||||
// memcpy(sensors_raw->gyro_raw, global_data_sensors_raw->gyro_raw, sizeof(sensors_raw->gyro_raw));
|
||||
// // printf("Timestamp %d\n", &global_data_sensors_raw->timestamp);
|
||||
|
||||
// } else {
|
||||
// printf("Controller timeout, no new sensor values available\n");
|
||||
// }
|
||||
|
||||
// global_data_unlock(&global_data_sensors_raw->access_conf_rate_full);
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
// int read_attitude(global_data_attitude_t *attitude)
|
||||
// {
|
||||
|
||||
// static int ret;
|
||||
// ret = global_data_wait(&global_data_attitude->access_conf);
|
||||
|
||||
// if (ret == 0) {
|
||||
// memcpy(&attitude->roll, &global_data_attitude->roll, sizeof(global_data_attitude->roll));
|
||||
// memcpy(&attitude->pitch, &global_data_attitude->pitch, sizeof(global_data_attitude->pitch));
|
||||
// memcpy(&attitude->yaw, &global_data_attitude->yaw, sizeof(global_data_attitude->yaw));
|
||||
// memcpy(&attitude->rollspeed, &global_data_attitude->rollspeed, sizeof(global_data_attitude->rollspeed));
|
||||
// memcpy(&attitude->pitchspeed, &global_data_attitude->pitchspeed, sizeof(global_data_attitude->pitchspeed));
|
||||
// memcpy(&attitude->yawspeed, &global_data_attitude->yawspeed, sizeof(global_data_attitude->yawspeed));
|
||||
|
||||
// } else {
|
||||
// printf("Controller timeout, no new attitude values available\n");
|
||||
// }
|
||||
|
||||
// global_data_unlock(&global_data_attitude->access_conf);
|
||||
|
||||
|
||||
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
// void read_quad_motors_setpoint(quad_motors_setpoint_t *rate_setpoint)
|
||||
// {
|
||||
|
||||
// if (0 == global_data_trylock(&global_data_quad_motors_setpoint->access_conf)) { //TODO: check if trylock is the right choice, maybe only lock?
|
||||
// rate_setpoint->motor_front_nw = global_data_quad_motors_setpoint->motor_front_nw;
|
||||
// rate_setpoint->motor_right_ne = global_data_quad_motors_setpoint->motor_right_ne;
|
||||
// rate_setpoint->motor_back_se = global_data_quad_motors_setpoint->motor_back_se;
|
||||
// rate_setpoint->motor_left_sw = global_data_quad_motors_setpoint->motor_left_sw;
|
||||
|
||||
// global_data_unlock(&global_data_quad_motors_setpoint->access_conf);
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* ardrone_control_helper.h
|
||||
*
|
||||
* Created on: May 15, 2012
|
||||
* Author: thomasgubler
|
||||
*/
|
||||
|
||||
#ifndef ARDRONE_CONTROL_HELPER_H_
|
||||
#define ARDRONE_CONTROL_HELPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// typedef struct {
|
||||
// int16_t gyro_raw[3]; // l3gd20
|
||||
// } sensors_raw_t;
|
||||
|
||||
// /* Copy quad_motors_setpoint values from global memory to private variables */ //TODO: change this once the new mavlink message for rates is available
|
||||
// void read_quad_motors_setpoint(quad_motors_setpoint_t *rate_setpoint);
|
||||
|
||||
|
||||
#endif /* ARDRONE_CONTROL_HELPER_H_ */
|
||||
@@ -0,0 +1,277 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008-2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* @file Implementation of AR.Drone 1.0 / 2.0 motor control interface
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "ardrone_motor_control.h"
|
||||
|
||||
static const unsigned long motor_gpios = GPIO_EXT_1 | GPIO_EXT_2 | GPIO_MULTI_1 | GPIO_MULTI_2;
|
||||
static const unsigned long motor_gpio[4] = { GPIO_EXT_1, GPIO_EXT_2, GPIO_MULTI_1, GPIO_MULTI_2 };
|
||||
|
||||
typedef union {
|
||||
uint16_t motor_value;
|
||||
uint8_t bytes[2];
|
||||
} motor_union_t;
|
||||
|
||||
/**
|
||||
* @brief Generate the 8-byte motor set packet
|
||||
*
|
||||
* @return the number of bytes (8)
|
||||
*/
|
||||
void ar_get_motor_packet(uint8_t *motor_buf, uint16_t motor1, uint16_t motor2, uint16_t motor3, uint16_t motor4)
|
||||
{
|
||||
motor_buf[0] = 0x20;
|
||||
motor_buf[1] = 0x00;
|
||||
motor_buf[2] = 0x00;
|
||||
motor_buf[3] = 0x00;
|
||||
motor_buf[4] = 0x00;
|
||||
/*
|
||||
* {0x20, 0x00, 0x00, 0x00, 0x00};
|
||||
* 0x20 is start sign / motor command
|
||||
*/
|
||||
motor_union_t curr_motor;
|
||||
uint16_t nineBitMask = 0x1FF;
|
||||
|
||||
/* Set motor 1 */
|
||||
curr_motor.motor_value = (motor1 & nineBitMask) << 4;
|
||||
motor_buf[0] |= curr_motor.bytes[1];
|
||||
motor_buf[1] |= curr_motor.bytes[0];
|
||||
|
||||
/* Set motor 2 */
|
||||
curr_motor.motor_value = (motor2 & nineBitMask) << 3;
|
||||
motor_buf[1] |= curr_motor.bytes[1];
|
||||
motor_buf[2] |= curr_motor.bytes[0];
|
||||
|
||||
/* Set motor 3 */
|
||||
curr_motor.motor_value = (motor3 & nineBitMask) << 2;
|
||||
motor_buf[2] |= curr_motor.bytes[1];
|
||||
motor_buf[3] |= curr_motor.bytes[0];
|
||||
|
||||
/* Set motor 4 */
|
||||
curr_motor.motor_value = (motor4 & nineBitMask) << 1;
|
||||
motor_buf[3] |= curr_motor.bytes[1];
|
||||
motor_buf[4] |= curr_motor.bytes[0];
|
||||
}
|
||||
|
||||
void ar_enable_broadcast(int fd)
|
||||
{
|
||||
ar_select_motor(fd, 0);
|
||||
}
|
||||
|
||||
int ar_multiplexing_init()
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open("/dev/gpio", O_RDONLY | O_NONBLOCK);
|
||||
|
||||
if (fd < 0) {
|
||||
printf("GPIO: open fail\n");
|
||||
return fd;
|
||||
}
|
||||
|
||||
if (ioctl(fd, GPIO_SET_OUTPUT, motor_gpios) != 0) {
|
||||
printf("GPIO: output set fail\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* deactivate all outputs */
|
||||
int ret = 0;
|
||||
ret += ioctl(fd, GPIO_SET, motor_gpios);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("GPIO: clearing pins fail\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int ar_multiplexing_deinit(int fd)
|
||||
{
|
||||
if (fd < 0) {
|
||||
printf("GPIO: no valid descriptor\n");
|
||||
return fd;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
|
||||
/* deselect motor 1-4 */
|
||||
ret += ioctl(fd, GPIO_SET, motor_gpios);
|
||||
|
||||
if (ret != 0) {
|
||||
printf("GPIO: clear failed %d times\n", ret);
|
||||
}
|
||||
|
||||
if (ioctl(fd, GPIO_SET_INPUT, motor_gpios) != 0) {
|
||||
printf("GPIO: input set fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ar_select_motor(int fd, uint8_t motor)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long gpioset;
|
||||
/*
|
||||
* Four GPIOS:
|
||||
* GPIO_EXT1
|
||||
* GPIO_EXT2
|
||||
* GPIO_UART2_CTS
|
||||
* GPIO_UART2_RTS
|
||||
*/
|
||||
|
||||
/* select motor 0 to enable broadcast */
|
||||
if (motor == 0) {
|
||||
/* select motor 1-4 */
|
||||
ret += ioctl(fd, GPIO_CLEAR, motor_gpios);
|
||||
|
||||
} else {
|
||||
/* select reqested motor */
|
||||
ret += ioctl(fd, GPIO_CLEAR, motor_gpio[motor - 1]);
|
||||
|
||||
/* deselect all others */
|
||||
gpioset = motor_gpios ^ motor_gpio[motor - 1];
|
||||
ret += ioctl(fd, GPIO_SET, gpioset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ar_init_motors(int ardrone_uart, int *gpios_pin)
|
||||
{
|
||||
/* Initialize multiplexing */
|
||||
*gpios_pin = ar_multiplexing_init();
|
||||
|
||||
/* Write ARDrone commands on UART2 */
|
||||
uint8_t initbuf[] = {0xE0, 0x91, 0xA1, 0x00, 0x40};
|
||||
uint8_t multicastbuf[] = {0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0};
|
||||
|
||||
/* initialize all motors
|
||||
* - select one motor at a time
|
||||
* - configure motor
|
||||
*/
|
||||
int i;
|
||||
int errcounter = 0;
|
||||
|
||||
for (i = 1; i < 5; ++i) {
|
||||
/* Initialize motors 1-4 */
|
||||
initbuf[3] = i;
|
||||
errcounter += ar_select_motor(*gpios_pin, i);
|
||||
|
||||
write(ardrone_uart, initbuf + 0, 1);
|
||||
|
||||
/* sleep 400 ms */
|
||||
usleep(200000);
|
||||
usleep(200000);
|
||||
|
||||
write(ardrone_uart, initbuf + 1, 1);
|
||||
/* wait 50 ms */
|
||||
usleep(50000);
|
||||
|
||||
write(ardrone_uart, initbuf + 2, 1);
|
||||
/* wait 50 ms */
|
||||
usleep(50000);
|
||||
|
||||
write(ardrone_uart, initbuf + 3, 1);
|
||||
/* wait 50 ms */
|
||||
usleep(50000);
|
||||
|
||||
write(ardrone_uart, initbuf + 4, 1);
|
||||
/* wait 50 ms */
|
||||
usleep(50000);
|
||||
|
||||
/* enable multicast */
|
||||
write(ardrone_uart, multicastbuf + 0, 1);
|
||||
/* wait 1 ms */
|
||||
usleep(1000);
|
||||
|
||||
write(ardrone_uart, multicastbuf + 1, 1);
|
||||
/* wait 1 ms */
|
||||
usleep(1000);
|
||||
|
||||
write(ardrone_uart, multicastbuf + 2, 1);
|
||||
/* wait 1 ms */
|
||||
usleep(1000);
|
||||
|
||||
write(ardrone_uart, multicastbuf + 3, 1);
|
||||
/* wait 1 ms */
|
||||
usleep(1000);
|
||||
|
||||
write(ardrone_uart, multicastbuf + 4, 1);
|
||||
/* wait 1 ms */
|
||||
usleep(1000);
|
||||
|
||||
write(ardrone_uart, multicastbuf + 5, 1);
|
||||
/* wait 5 ms */
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
/* start the multicast part */
|
||||
errcounter += ar_select_motor(*gpios_pin, 0);
|
||||
|
||||
if (errcounter != 0) {
|
||||
printf("AR: init sequence incomplete, failed %d times", -errcounter);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the leds on the motor controllers, 1 turns led on, 0 off.
|
||||
*/
|
||||
void ar_set_leds(int ardrone_uart, uint8_t led1_red, uint8_t led1_green, uint8_t led2_red, uint8_t led2_green, uint8_t led3_red, uint8_t led3_green, uint8_t led4_red, uint8_t led4_green)
|
||||
{
|
||||
/*
|
||||
* 2 bytes are sent. The first 3 bits describe the command: 011 means led control
|
||||
* the following 4 bits are the red leds for motor 4, 3, 2, 1
|
||||
* then 4 bits with unknown function, then 4 bits for green leds for motor 4, 3, 2, 1
|
||||
* the last bit is unknown.
|
||||
*
|
||||
* The packet is therefore:
|
||||
* 011 rrrr 0000 gggg 0
|
||||
*/
|
||||
uint8_t leds[2];
|
||||
leds[0] = 0x60 | ((led4_red & 0x01) << 4) | ((led3_red & 0x01) << 3) | ((led2_red & 0x01) << 2) | ((led1_red & 0x01) << 1);
|
||||
leds[1] = ((led4_green & 0x01) << 4) | ((led3_green & 0x01) << 3) | ((led2_green & 0x01) << 2) | ((led1_green & 0x01) << 1);
|
||||
write(ardrone_uart, leds, 2);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user