summaryrefslogtreecommitdiff
path: root/ao-tools
diff options
context:
space:
mode:
authorBdale Garbee <bdale@gag.com>2013-12-19 01:38:40 -0700
committerBdale Garbee <bdale@gag.com>2013-12-19 01:38:40 -0700
commit575bbaf976c5840fd0e308549c45a466fdec1352 (patch)
tree11bfb498348bf7687bffc24699c4b1a998988ee4 /ao-tools
parentb825116df173b77e2cab217a7b76112c742f9279 (diff)
parentbc3610d8cecbfed40c62d4dcb93fc9a4d2a7c9e3 (diff)
Merge branch 'branch-1.3' into debian
Conflicts: ChangeLog altoslib/AltosRecordMM.java altosui/Makefile.am altosui/altos-windows.nsi.in configure.ac debian/changelog debian/control doc/Makefile doc/altusmetrum.xsl doc/release-notes-1.2.1.xsl doc/release-notes-1.2.xsl
Diffstat (limited to 'ao-tools')
-rw-r--r--ao-tools/Makefile.am8
-rw-r--r--ao-tools/ao-dbg/Makefile.am2
-rw-r--r--ao-tools/ao-dbg/ao-dbg-command.c24
-rw-r--r--ao-tools/ao-dbg/ao-dbg-main.c11
-rw-r--r--ao-tools/ao-dbg/ao-dbg-parse.c2
-rw-r--r--ao-tools/ao-elftohex/Makefile.am12
-rw-r--r--ao-tools/ao-elftohex/ao-elftohex.138
-rw-r--r--ao-tools/ao-elftohex/ao-elftohex.c102
-rw-r--r--ao-tools/ao-flash/Makefile.am3
-rw-r--r--ao-tools/ao-flash/ao-flash-lpc21
-rw-r--r--ao-tools/ao-flash/ao-flash-lpc.136
-rw-r--r--ao-tools/ao-flash/ao-flash-stm33
-rw-r--r--ao-tools/ao-flash/ao-flash-stm.138
-rw-r--r--ao-tools/ao-load/ao-load.c14
-rw-r--r--ao-tools/ao-mega/.gitignore1
-rw-r--r--ao-tools/ao-mega/Makefile.am12
-rw-r--r--ao-tools/ao-mega/ao-mega.130
-rw-r--r--ao-tools/ao-mega/ao-mega.c143
-rw-r--r--ao-tools/ao-rawload/ao-rawload.c12
-rw-r--r--ao-tools/ao-stmload/Makefile.am8
-rw-r--r--ao-tools/ao-stmload/ao-stmload.c400
-rw-r--r--ao-tools/ao-stmload/ao-stmload.h17
-rw-r--r--ao-tools/ao-telem/ao-telem.c33
-rw-r--r--ao-tools/ao-usbload/Makefile.am12
-rw-r--r--ao-tools/ao-usbload/ao-usbload.181
-rw-r--r--ao-tools/ao-usbload/ao-usbload.c305
-rw-r--r--ao-tools/ao-usbload/ao-usbload.h36
-rw-r--r--ao-tools/lib/Makefile.am14
-rw-r--r--ao-tools/lib/ao-editaltos.c153
-rw-r--r--ao-tools/lib/ao-editaltos.h50
-rw-r--r--ao-tools/lib/ao-elf.c (renamed from ao-tools/ao-stmload/ao-elf.c)160
-rw-r--r--ao-tools/lib/ao-elf.h (renamed from ao-tools/ao-stmload/ao-elf.h)10
-rw-r--r--ao-tools/lib/ao-hex.c626
-rw-r--r--ao-tools/lib/ao-hex.h82
-rw-r--r--ao-tools/lib/ao-selfload.c (renamed from ao-tools/ao-stmload/ao-selfload.c)59
-rw-r--r--ao-tools/lib/ao-selfload.h37
-rw-r--r--ao-tools/lib/ao-verbose.c36
-rw-r--r--ao-tools/lib/ao-verbose.h32
-rw-r--r--ao-tools/lib/cc-mega.c160
-rw-r--r--ao-tools/lib/cc-telemetry.h69
-rw-r--r--ao-tools/lib/cc.h3
-rw-r--r--ao-tools/lib/ccdbg-command.c2
-rw-r--r--ao-tools/lib/ccdbg-flash.c2
-rw-r--r--ao-tools/lib/ccdbg-hex.c381
-rw-r--r--ao-tools/lib/ccdbg-memory.c8
-rw-r--r--ao-tools/lib/ccdbg-rom.c8
-rw-r--r--ao-tools/lib/ccdbg.h56
47 files changed, 2498 insertions, 884 deletions
diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am
index 4600f1d6..a42988d6 100644
--- a/ao-tools/Makefile.am
+++ b/ao-tools/Makefile.am
@@ -1,3 +1,7 @@
SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \
- ao-load ao-telem ao-stmload ao-send-telem ao-sky-flash \
- ao-dumpflash ao-edit-telem ao-dump-up
+ ao-load ao-telem ao-send-telem ao-sky-flash \
+ ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
+ ao-flash ao-usbload
+if LIBSTLINK
+SUBDIRS += ao-stmload
+endif
diff --git a/ao-tools/ao-dbg/Makefile.am b/ao-tools/ao-dbg/Makefile.am
index ad2cb280..2c33cf06 100644
--- a/ao-tools/ao-dbg/Makefile.am
+++ b/ao-tools/ao-dbg/Makefile.am
@@ -7,6 +7,6 @@ man_MANS = ao-dbg.1
ao_dbg_DEPENDENCIES = $(AO_DBG_LIBS)
-ao_dbg_LDADD=$(AO_DBG_LIBS) $(LIBUSB_LIBS) -lreadline
+ao_dbg_LDADD=$(AO_DBG_LIBS) $(LIBUSB_LIBS) $(LIBREADLINE)
ao_dbg_SOURCES = ao-dbg-parse.c ao-dbg-command.c ao-dbg-main.c
diff --git a/ao-tools/ao-dbg/ao-dbg-command.c b/ao-tools/ao-dbg/ao-dbg-command.c
index eab7bc68..11c521e8 100644
--- a/ao-tools/ao-dbg/ao-dbg-command.c
+++ b/ao-tools/ao-dbg/ao-dbg-command.c
@@ -202,8 +202,8 @@ command_dump (int argc, char **argv)
enum command_result
command_file (int argc, char **argv)
{
- struct hex_file *hex;
- struct hex_image *image;
+ struct ao_hex_file *hex;
+ struct ao_hex_image *image;
FILE *file;
if (argc != 2)
@@ -211,16 +211,16 @@ command_file (int argc, char **argv)
file = fopen (argv[1], "r");
if (!file)
return command_error;
- hex = ccdbg_hex_file_read(file, argv[1]);
+ hex = ao_hex_file_read(file, argv[1]);
fclose(file);
if (!hex)
return command_error;
if (hex->nrecord == 0) {
- ccdbg_hex_file_free(hex);
+ ao_hex_file_free(hex);
return command_error;
}
- image = ccdbg_hex_image_create(hex);
- ccdbg_hex_file_free(hex);
+ image = ao_hex_image_create(hex);
+ ao_hex_file_free(hex);
start_address = image->address;
ccdbg_set_rom(s51_dbg, image);
return command_success;
@@ -495,8 +495,8 @@ command_load (int argc, char **argv)
{
char *filename = argv[1];
FILE *file;
- struct hex_file *hex;
- struct hex_image *image;
+ struct ao_hex_file *hex;
+ struct ao_hex_image *image;
if (!filename)
return command_error;
@@ -505,13 +505,13 @@ command_load (int argc, char **argv)
perror(filename);
return command_error;
}
- hex = ccdbg_hex_file_read(file, filename);
+ hex = ao_hex_file_read(file, filename);
fclose(file);
if (!hex) {
return command_error;
}
- image = ccdbg_hex_image_create(hex);
- ccdbg_hex_file_free(hex);
+ image = ao_hex_image_create(hex);
+ ao_hex_file_free(hex);
if (!image) {
fprintf(stderr, "image create failed\n");
return command_error;
@@ -523,7 +523,7 @@ command_load (int argc, char **argv)
} else {
fprintf(stderr, "Can only load to RAM\n");
}
- ccdbg_hex_image_free(image);
+ ao_hex_image_free(image);
return command_success;
}
diff --git a/ao-tools/ao-dbg/ao-dbg-main.c b/ao-tools/ao-dbg/ao-dbg-main.c
index 21b83a3d..25eca54b 100644
--- a/ao-tools/ao-dbg/ao-dbg-main.c
+++ b/ao-tools/ao-dbg/ao-dbg-main.c
@@ -16,6 +16,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "ao-dbg.h"
#include <unistd.h>
#include <sys/types.h>
@@ -204,13 +208,16 @@ s51_putc(int c)
putc(c, s51_output);
}
+#if HAVE_LIBREADLINE
#include <readline/readline.h>
#include <readline/history.h>
+#endif
int
s51_read_line(char *line, int len)
{
int ret;
+#if HAVE_LIBREADLINE
if (s51_output == stdout && s51_input == stdin && s51_prompt) {
char *r;
@@ -221,7 +228,9 @@ s51_read_line(char *line, int len)
line[len-1] = '\0';
add_history(r);
return 1;
- } else {
+ } else
+#endif
+ {
if (s51_prompt)
s51_printf("%s", s51_prompt);
else
diff --git a/ao-tools/ao-dbg/ao-dbg-parse.c b/ao-tools/ao-dbg/ao-dbg-parse.c
index dcb9099d..ba691834 100644
--- a/ao-tools/ao-dbg/ao-dbg-parse.c
+++ b/ao-tools/ao-dbg/ao-dbg-parse.c
@@ -198,7 +198,7 @@ command_read (void)
if (!s51_tty) {
if (!s51_device)
s51_device = getenv("AO_DBG_DEVICE");
- s51_tty = cc_usbdevs_find_by_arg(s51_device, "TIDongle");
+ s51_tty = cc_usbdevs_find_by_arg(s51_device, "TeleDongle");
}
s51_dbg = ccdbg_open (s51_tty);
if (!s51_dbg)
diff --git a/ao-tools/ao-elftohex/Makefile.am b/ao-tools/ao-elftohex/Makefile.am
new file mode 100644
index 00000000..dd0046d7
--- /dev/null
+++ b/ao-tools/ao-elftohex/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS=ao-elftohex
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_ELFTOHEX_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_elftohex_DEPENDENCIES = $(AO_ELFTOHEX_LIBS)
+
+ao_elftohex_LDADD=$(AO_ELFTOHEX_LIBS) -lelf
+
+ao_elftohex_SOURCES=ao-elftohex.c
+
+man_MANS = ao-elftohex.1
diff --git a/ao-tools/ao-elftohex/ao-elftohex.1 b/ao-tools/ao-elftohex/ao-elftohex.1
new file mode 100644
index 00000000..e52e6f5a
--- /dev/null
+++ b/ao-tools/ao-elftohex/ao-elftohex.1
@@ -0,0 +1,38 @@
+.\"
+.\" Copyright © 2013 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-elftohex" ""
+.SH NAME
+ao-elftohex \- convert a program to IHX format
+.SH SYNOPSIS
+.B "ao-elftohex"
+[\--output-\fIoutput.ihx\fP]
+[\--verbose]
+\fIinput.elf\fP
+.SH DESCRIPTION
+.I ao-elftohex
+reads the specified .elf file and writes out a .ihx version.
+.SH OPTIONS
+.TP
+\--output=\fIoutput.ihx\fP
+This specifies the output file (default is stdout)
+.TP
+\--verbose
+Dumps some debug information.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-elftohex/ao-elftohex.c b/ao-tools/ao-elftohex/ao-elftohex.c
new file mode 100644
index 00000000..db8f86f1
--- /dev/null
+++ b/ao-tools/ao-elftohex/ao-elftohex.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ao-hex.h"
+#include "ao-elf.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { .name = "output", .has_arg = 1, .val = 'o' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<level>] [--output=<output.ihx>] <input.elf>\n", program);
+ exit(1);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *input = NULL;
+ char *output = NULL;
+ struct ao_hex_image *image;
+ struct ao_sym *file_symbols;
+ int num_file_symbols;
+ FILE *file;
+ int c;
+
+ while ((c = getopt_long(argc, argv, "v:o:", options, NULL)) != -1) {
+ switch (c) {
+ case 'o':
+ output = optarg;
+ break;
+ case 'v':
+ ao_verbose = (int) strtol(optarg, NULL, 0);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ input = argv[optind];
+ if (input == NULL)
+ usage(argv[0]);
+
+ if (ends_with (input, ".ihx"))
+ image = ao_hex_load(input, &file_symbols, &num_file_symbols);
+ else
+ image = ao_load_elf(input, &file_symbols, &num_file_symbols);
+
+ if (!image)
+ usage(argv[0]);
+
+ if (!output)
+ file = stdout;
+ else {
+ file = fopen(output, "w");
+ if (!file) {
+ perror(output);
+ exit(1);
+ }
+ }
+
+ if (!ao_hex_save(file, image, file_symbols, num_file_symbols)) {
+ fprintf(stderr, "%s: failed to write hex file\n", output ? output : "<stdout>");
+ if (output)
+ unlink(output);
+ exit(1);
+ }
+ exit(0);
+}
diff --git a/ao-tools/ao-flash/Makefile.am b/ao-tools/ao-flash/Makefile.am
new file mode 100644
index 00000000..6b7ea6bb
--- /dev/null
+++ b/ao-tools/ao-flash/Makefile.am
@@ -0,0 +1,3 @@
+bin_SCRIPTS=ao-flash-stm ao-flash-lpc
+
+man_MANS = ao-flash-stm.1 ao-flash-lpc.1 \ No newline at end of file
diff --git a/ao-tools/ao-flash/ao-flash-lpc b/ao-tools/ao-flash/ao-flash-lpc
new file mode 100644
index 00000000..57f632b4
--- /dev/null
+++ b/ao-tools/ao-flash/ao-flash-lpc
@@ -0,0 +1,21 @@
+#!/bin/sh
+case "$#" in
+0)
+ echo "usage: $0 <filename> ..."
+ exit 1
+ ;;
+esac
+cmds=/tmp/flash$$
+trap "rm $cmds" 0 1 15
+for file in "$@"; do
+ echo "flash write_image $file"
+done > $cmds
+openocd \
+ -f interface/stlink-v2.cfg \
+ -f target/lpc11u14.cfg \
+ -c init \
+ -c 'reset halt' \
+ -f $cmds \
+ -c 'reset init' \
+ -c 'reset run' \
+ -c shutdown
diff --git a/ao-tools/ao-flash/ao-flash-lpc.1 b/ao-tools/ao-flash/ao-flash-lpc.1
new file mode 100644
index 00000000..46312030
--- /dev/null
+++ b/ao-tools/ao-flash/ao-flash-lpc.1
@@ -0,0 +1,36 @@
+.\"
+.\" Copyright © 2013 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-FLASH-LPC 1 "ao-flash-lpc" ""
+.SH NAME
+ao-flash-lpc \- flash a program to an LPC11U14-based AltOS device using openocd
+.SH SYNOPSIS
+.B "ao-flash-lpc"
+\fIfile.elf\fP
+.SH DESCRIPTION
+.I ao-flash-lpc
+loads the specified .elf file into the target device flash memory.
+.SH USAGE
+.I ao-flash-lpc
+is a simple script that passes the correct arguments to openocd to
+load a file into the target device via a connected STlink
+debugging dongle.
+.SH "SEE ALSO"
+openocd(1)
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-flash/ao-flash-stm b/ao-tools/ao-flash/ao-flash-stm
new file mode 100644
index 00000000..9eebf5d2
--- /dev/null
+++ b/ao-tools/ao-flash/ao-flash-stm
@@ -0,0 +1,33 @@
+#!/bin/sh
+case "$#" in
+0)
+ echo "usage: $0 <filename> ..."
+ exit 1
+ ;;
+esac
+
+ST_FLASH=st-flash
+
+if which $ST_FLASH > /dev/null; then
+ :
+else
+ echo "$0: $ST_FLASH not found. Check to see if the stlink package is installed"
+ exit 1
+fi
+
+file=$1
+
+bin=/tmp/flash$$.bin
+trap "rm $bin" 0 1 15
+
+base=`arm-none-eabi-nm $file | awk '/interrupt_vector/ { print $1 }'`
+case x"$base" in
+x)
+ echo "$file: No interrupt vector address found"
+ exit 1
+ ;;
+esac
+
+arm-none-eabi-objcopy -O binary $file $bin
+
+$ST_FLASH --reset write $bin $base
diff --git a/ao-tools/ao-flash/ao-flash-stm.1 b/ao-tools/ao-flash/ao-flash-stm.1
new file mode 100644
index 00000000..81aa5927
--- /dev/null
+++ b/ao-tools/ao-flash/ao-flash-stm.1
@@ -0,0 +1,38 @@
+.\"
+.\" Copyright © 2013 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-FLASH-STM 1 "ao-flash-stm" ""
+.SH NAME
+ao-flash-stm \- flash a program to an STM32-based AltOS device using st-flash
+.SH SYNOPSIS
+.B "ao-flash-stm"
+\fIfile.elf\fP
+.SH DESCRIPTION
+.I ao-flash-stm
+loads the specified .elf file into the target device flash memory.
+.SH USAGE
+.I ao-flash-stm
+converts the specified .elf file into a raw binary file and then uses
+st-flash to load it into the target device via a connected STlink
+debugging dongle. If st-flash is not available,
+.I ao-flash-stm
+will emit an error message and terminate.
+.SH "SEE ALSO"
+st-flash(1)
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c
index e3cef4a5..c1f55149 100644
--- a/ao-tools/ao-load/ao-load.c
+++ b/ao-tools/ao-load/ao-load.c
@@ -80,7 +80,7 @@ find_symbols(FILE *map)
}
static int
-rewrite(struct hex_image *image, unsigned addr, char *data, int len)
+rewrite(struct ao_hex_image *image, unsigned addr, char *data, int len)
{
int i;
if (addr < image->address || image->address + image->length < addr + len)
@@ -114,8 +114,8 @@ main (int argc, char **argv)
struct ccdbg *dbg;
uint8_t status;
uint16_t pc;
- struct hex_file *hex;
- struct hex_image *image;
+ struct ao_hex_file *hex;
+ struct ao_hex_image *image;
char *filename;
FILE *file;
FILE *map;
@@ -182,18 +182,18 @@ main (int argc, char **argv)
}
fclose(map);
- hex = ccdbg_hex_file_read(file, filename);
+ hex = ao_hex_file_read(file, filename);
fclose(file);
if (!hex) {
perror(filename);
exit (1);
}
- image = ccdbg_hex_image_create(hex);
+ image = ao_hex_image_create(hex);
if (!image) {
fprintf(stderr, "image create failed\n");
exit (1);
}
- ccdbg_hex_file_free(hex);
+ ao_hex_file_free(hex);
serial = strtoul(serial_string, NULL, 0);
if (!serial)
@@ -276,7 +276,7 @@ main (int argc, char **argv)
} else {
printf("Cannot load code to 0x%04x\n",
image->address);
- ccdbg_hex_image_free(image);
+ ao_hex_image_free(image);
ccdbg_close(dbg);
exit(1);
}
diff --git a/ao-tools/ao-mega/.gitignore b/ao-tools/ao-mega/.gitignore
new file mode 100644
index 00000000..7bb37391
--- /dev/null
+++ b/ao-tools/ao-mega/.gitignore
@@ -0,0 +1 @@
+ao-mega
diff --git a/ao-tools/ao-mega/Makefile.am b/ao-tools/ao-mega/Makefile.am
new file mode 100644
index 00000000..22b62608
--- /dev/null
+++ b/ao-tools/ao-mega/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS=ao-mega
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_mega_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS)
+
+ao_mega_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS)
+
+ao_mega_SOURCES = ao-mega.c
+
+man_MANS = ao-mega.1
diff --git a/ao-tools/ao-mega/ao-mega.1 b/ao-tools/ao-mega/ao-mega.1
new file mode 100644
index 00000000..0f96bdc8
--- /dev/null
+++ b/ao-tools/ao-mega/ao-mega.1
@@ -0,0 +1,30 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-TELEM 1 "ao-mega" ""
+.SH NAME
+ao-mega \- Dump a mega flight log (eeprom only)
+.SH SYNOPSIS
+.B "ao-mega"
+{flight.mega}
+.SH DESCRIPTION
+.I ao-mega
+reads the specified flight log and dumps it in human readable format.
+output.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-mega/ao-mega.c b/ao-tools/ao-mega/ao-mega.c
new file mode 100644
index 00000000..523229e6
--- /dev/null
+++ b/ao-tools/ao-mega/ao-mega.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "cc.h"
+
+static const struct option options[] = {
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s\n"
+ "\t{flight.mega} ...\n", program);
+ exit(1);
+}
+
+#define bool(b) ((b) ? "true" : "false")
+
+static const char *state_names[] = {
+ "startup",
+ "idle",
+ "pad",
+ "boost",
+ "fast",
+ "coast",
+ "drogue",
+ "main",
+ "landed",
+ "invalid"
+};
+
+
+#define NUM_STATE (sizeof state_names/sizeof state_names[0])
+
+int
+main (int argc, char **argv)
+{
+ char line[256];
+ int c, i, ret, j;
+ char *s;
+ FILE *file;
+ int serial;
+ const char *state;
+ while ((c = getopt_long(argc, argv, "", options, NULL)) != -1) {
+ switch (c) {
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ for (i = optind; i < argc; i++) {
+ file = fopen(argv[i], "r");
+ if (!file) {
+ perror(argv[i]);
+ ret++;
+ continue;
+ }
+ s = strstr(argv[i], "-serial-");
+ if (s)
+ serial = atoi(s + 8);
+ else
+ serial = 0;
+ while (fgets(line, sizeof (line), file)) {
+ struct ao_log_mega log;
+
+ if (cc_mega_parse(line, &log)) {
+ if (log.is_config) {
+ printf ("kind %d\n", log.u.config_int.kind);
+ } else {
+ printf ("tick %5d ", log.tick);
+ switch (log.type) {
+ case AO_LOG_FLIGHT:
+ printf ("flight %5u ground_accel %d ground_pres %u\n",
+ log.u.flight.flight,
+ log.u.flight.ground_accel,
+ log.u.flight.ground_pres);
+ break;
+ case AO_LOG_STATE:
+ if (log.u.state.state < NUM_STATE)
+ state = state_names[log.u.state.state];
+ else
+ state = "invalid";
+ printf ("state %d (%s)\n", log.u.state.state, state);
+ break;
+ case AO_LOG_SENSOR:
+ printf ("p %9u t %9u ax %6d ay %6d az %6d gx %6d gy %6d gz %6d mx %6d my %6d mz %6d a %6d\n",
+ log.u.sensor.pres,
+ log.u.sensor.temp,
+ log.u.sensor.accel_x,
+ log.u.sensor.accel_y,
+ log.u.sensor.accel_z,
+ log.u.sensor.gyro_x,
+ log.u.sensor.gyro_y,
+ log.u.sensor.gyro_z,
+ log.u.sensor.mag_x,
+ log.u.sensor.mag_y,
+ log.u.sensor.mag_z,
+ log.u.sensor.accel);
+ break;
+ case AO_LOG_TEMP_VOLT:
+ printf ("batt %6d pbatt %6d n_sense %d",
+ log.u.volt.v_batt,
+ log.u.volt.v_pbatt,
+ log.u.volt.n_sense);
+ for (j = 0; j < log.u.volt.n_sense; j++) {
+ printf (" s%d %6d",
+ j, log.u.volt.sense[j]);
+ }
+ printf ("pyro %04x\n", log.u.volt.pyro);
+ printf ("\n");
+ break;
+ default:
+ printf ("type %c\n", log.type, log.tick);
+ break;
+ }
+ }
+ }
+ }
+ fclose (file);
+
+ }
+ return ret;
+}
diff --git a/ao-tools/ao-rawload/ao-rawload.c b/ao-tools/ao-rawload/ao-rawload.c
index a4746b19..17ed73ca 100644
--- a/ao-tools/ao-rawload/ao-rawload.c
+++ b/ao-tools/ao-rawload/ao-rawload.c
@@ -40,8 +40,8 @@ main (int argc, char **argv)
struct ccdbg *dbg;
uint8_t status;
uint16_t pc;
- struct hex_file *hex;
- struct hex_image *image;
+ struct ao_hex_file *hex;
+ struct ao_hex_image *image;
char *filename;
FILE *file;
char *tty = NULL;
@@ -75,17 +75,17 @@ main (int argc, char **argv)
perror(filename);
exit(1);
}
- hex = ccdbg_hex_file_read(file, filename);
+ hex = ao_hex_file_read(file, filename);
fclose(file);
if (!hex)
exit (1);
- image = ccdbg_hex_image_create(hex);
+ image = ao_hex_image_create(hex);
if (!image) {
fprintf(stderr, "image create failed\n");
exit (1);
}
- ccdbg_hex_file_free(hex);
+ ao_hex_file_free(hex);
if (!tty)
tty = cc_usbdevs_find_by_arg(device, "TIDongle");
dbg = ccdbg_open(tty);
@@ -107,7 +107,7 @@ main (int argc, char **argv)
} else {
printf("Cannot load code to 0x%04x\n",
image->address);
- ccdbg_hex_image_free(image);
+ ao_hex_image_free(image);
ccdbg_close(dbg);
exit(1);
}
diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am
index 4eaf699c..45eb6216 100644
--- a/ao-tools/ao-stmload/Makefile.am
+++ b/ao-tools/ao-stmload/Makefile.am
@@ -2,16 +2,14 @@ if LIBSTLINK
bin_PROGRAMS=ao-stmload
-LIBSTLINKDIR=/local/src/stlink
-
-AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBSTLINK_CFLAGS) $(LIBUSB_CFLAGS)
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(STLINK_CFLAGS) $(LIBUSB_CFLAGS)
AO_STMLOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS)
-ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf
+ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(STLINK_LIBS) $(LIBUSB_LIBS) -lelf
-ao_stmload_SOURCES=ao-stmload.c ao-elf.c ao-stmload.h ao-selfload.c
+ao_stmload_SOURCES=ao-stmload.c ao-stmload.h
man_MANS = ao-stmload.1
diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c
index dd25f07f..4210a111 100644
--- a/ao-tools/ao-stmload/ao-stmload.c
+++ b/ao-tools/ao-stmload/ao-stmload.c
@@ -25,93 +25,16 @@
#include <unistd.h>
#include <getopt.h>
#include <string.h>
+#include <stdbool.h>
#include "stlink-common.h"
#include "ao-elf.h"
#include "ccdbg.h"
-#include "cc-usb.h"
#include "cc.h"
#include "ao-stmload.h"
+#include "ao-selfload.h"
+#include "ao-verbose.h"
+#include "ao-editaltos.h"
-#define AO_USB_DESC_STRING 3
-
-struct sym ao_symbols[] = {
-
- { 0, AO_BOOT_APPLICATION_BASE + 0x100, "ao_romconfig_version", 1 },
-#define AO_ROMCONFIG_VERSION (ao_symbols[0].addr)
-
- { 0, AO_BOOT_APPLICATION_BASE + 0x102, "ao_romconfig_check", 1 },
-#define AO_ROMCONFIG_CHECK (ao_symbols[1].addr)
-
- { 0, AO_BOOT_APPLICATION_BASE + 0x104, "ao_serial_number", 1 },
-#define AO_SERIAL_NUMBER (ao_symbols[2].addr)
-
- { 0, AO_BOOT_APPLICATION_BASE + 0x108, "ao_radio_cal", 0 },
-#define AO_RADIO_CAL (ao_symbols[3].addr)
-
- { 0, AO_BOOT_APPLICATION_BASE + 0x10c, "ao_usb_descriptors", 0 },
-#define AO_USB_DESCRIPTORS (ao_symbols[4].addr)
-};
-
-#define NUM_SYMBOLS 5
-#define NUM_REQUIRED_SYMBOLS 3
-
-int ao_num_symbols = NUM_SYMBOLS;
-int ao_num_required_symbols = NUM_REQUIRED_SYMBOLS;
-
-/*
- * Edit the to-be-written memory block
- */
-static int
-rewrite(struct hex_image *load, unsigned address, uint8_t *data, int length)
-{
- int i;
-
- if (address < load->address || load->address + load->length < address + length)
- return 0;
-
- printf("rewrite %04x:", address);
- for (i = 0; i < length; i++)
- printf (" %02x", load->data[address - load->address + i]);
- printf(" ->");
- for (i = 0; i < length; i++)
- printf (" %02x", data[i]);
- printf("\n");
- memcpy(load->data + address - load->address, data, length);
-}
-
-/*
- * Read a 16-bit value from the USB target
- */
-
-static uint16_t
-get_uint16_cc(struct cc_usb *cc, uint32_t addr)
-{
- struct hex_image *hex = ao_self_read(cc, addr, 2);
- uint16_t v;
- uint8_t *data;
-
- if (!hex)
- return 0;
- data = hex->data + addr - hex->address;
- v = data[0] | (data[1] << 8);
- free(hex);
- return v;
-}
-
-static uint32_t
-get_uint32_cc(struct cc_usb *cc, uint32_t addr)
-{
- struct hex_image *hex = ao_self_read(cc, addr, 4);
- uint32_t v;
- uint8_t *data;
-
- if (!hex)
- return 0;
- data = hex->data + addr - hex->address;
- v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
- free(hex);
- return v;
-}
/*
* Read a 16-bit value from the target device with arbitrary
@@ -141,13 +64,10 @@ get_uint16_sl(stlink_t *sl, uint32_t addr)
}
static uint16_t
-get_uint16(stlink_t *sl, struct cc_usb *cc, uint32_t addr)
+get_uint16(stlink_t *sl, uint32_t addr)
{
uint16_t result;
- if (cc)
- result = get_uint16_cc(cc, addr);
- else
- result = get_uint16_sl(sl, addr);
+ result = get_uint16_sl(sl, addr);
printf ("read 0x%08x = 0x%04x\n", addr, result);
return result;
}
@@ -185,14 +105,11 @@ get_uint32_sl(stlink_t *sl, uint32_t addr)
* alignment
*/
static uint32_t
-get_uint32(stlink_t *sl, struct cc_usb *cc, uint32_t addr)
+get_uint32(stlink_t *sl, uint32_t addr)
{
uint32_t result;
- if (cc)
- result = get_uint32_cc(cc, addr);
- else
- result = get_uint32_sl(sl, addr);
+ result = get_uint32_sl(sl, addr);
printf ("read 0x%08x = 0x%08x\n", addr, result);
return result;
}
@@ -206,10 +123,10 @@ get_uint32(stlink_t *sl, struct cc_usb *cc, uint32_t addr)
* places this at 0x100 from the start of the rom section
*/
static int
-check_flashed(stlink_t *sl, struct cc_usb *cc)
+check_flashed(stlink_t *sl)
{
- uint16_t romconfig_version = get_uint16(sl, cc, AO_ROMCONFIG_VERSION);
- uint16_t romconfig_check = get_uint16(sl, cc, AO_ROMCONFIG_CHECK);
+ uint16_t romconfig_version = get_uint16(sl, AO_ROMCONFIG_VERSION);
+ uint16_t romconfig_check = get_uint16(sl, AO_ROMCONFIG_CHECK);
if (romconfig_version != (uint16_t) ~romconfig_check) {
fprintf (stderr, "Device has not been flashed before\n");
@@ -219,34 +136,27 @@ check_flashed(stlink_t *sl, struct cc_usb *cc)
}
static const struct option options[] = {
- { .name = "stlink", .has_arg = 0, .val = 'S' },
- { .name = "tty", .has_arg = 1, .val = 'T' },
- { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "v1", .has_arg = 0, .val = '1' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
{ .name = "cal", .has_arg = 1, .val = 'c' },
{ .name = "serial", .has_arg = 1, .val = 's' },
- { .name = "verbose", .has_arg = 0, .val = 'v' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
{ 0, 0, 0, 0},
};
static void usage(char *program)
{
- fprintf(stderr, "usage: %s [--stlink] [--verbose] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] file.{elf,ihx}\n", program);
+ fprintf(stderr, "usage: %s [--v1] [--raw] [--verbose=<verbose>] [--cal=<radio-cal>] [--serial=<serial>] file.{elf,ihx}\n", program);
exit(1);
}
void
-done(stlink_t *sl, struct cc_usb *cc, int code)
+done(stlink_t *sl, int code)
{
- if (cc) {
-/* cc_usb_printf(cc, "a\n"); */
- cc_usb_close(cc);
- }
- if (sl) {
- stlink_reset(sl);
- stlink_run(sl);
- stlink_exit_debug_mode(sl);
- stlink_close(sl);
- }
+ stlink_reset(sl);
+ stlink_run(sl);
+ stlink_exit_debug_mode(sl);
+ stlink_close(sl);
exit (code);
}
@@ -264,7 +174,8 @@ ends_with(char *whole, char *suffix)
int
main (int argc, char **argv)
{
- char *device = NULL;
+ int stlink_v1 = 0;
+ int raw = 0;
char *filename;
Elf *e;
char *serial_end;
@@ -281,21 +192,20 @@ main (int argc, char **argv)
int c;
stlink_t *sl = NULL;
int was_flashed = 0;
- struct hex_image *load;
+ struct ao_hex_image *load;
int tries;
- struct cc_usb *cc = NULL;
- int use_stlink = 0;
- char *tty = NULL;
int success;
int verbose = 0;
+ struct ao_sym *file_symbols;
+ int num_file_symbols;
- while ((c = getopt_long(argc, argv, "T:D:c:s:Sv", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "1rc:s:v:", options, NULL)) != -1) {
switch (c) {
- case 'T':
- tty = optarg;
+ case '1':
+ stlink_v1 = 1;
break;
- case 'D':
- device = optarg;
+ case 'r':
+ raw = 1;
break;
case 'c':
cal = strtoul(optarg, &cal_end, 10);
@@ -307,9 +217,6 @@ main (int argc, char **argv)
if (serial_end == optarg || *serial_end != '\0')
usage(argv[0]);
break;
- case 'S':
- use_stlink = 1;
- break;
case 'v':
verbose++;
break;
@@ -319,7 +226,7 @@ main (int argc, char **argv)
}
}
- ao_self_verbose = verbose;
+ ao_verbose = verbose;
if (verbose > 1)
ccdbg_add_debug(CC_DEBUG_BITBANG);
@@ -329,219 +236,102 @@ main (int argc, char **argv)
usage(argv[0]);
if (ends_with (filename, ".elf")) {
- load = ao_load_elf(filename);
+ load = ao_load_elf(filename, &file_symbols, &num_file_symbols);
} else if (ends_with (filename, ".ihx")) {
- int i;
- load = ccdbg_hex_load(filename);
- for (i = 0; i < ao_num_symbols; i++)
- ao_symbols[i].addr = ao_symbols[i].default_addr;
+ load = ao_hex_load(filename, &file_symbols, &num_file_symbols);
} else
usage(argv[0]);
- if (use_stlink) {
- /* Connect to the programming dongle
- */
+ if (!raw) {
+ if (!ao_editaltos_find_symbols(file_symbols, num_file_symbols, ao_symbols, ao_num_symbols)) {
+ fprintf(stderr, "Cannot find required symbols\n");
+ usage(argv[0]);
+ }
+ }
+
+ /* Connect to the programming dongle
+ */
- for (tries = 0; tries < 3; tries++) {
- if (device) {
- sl = stlink_v1_open(50);
- } else {
- sl = stlink_open_usb(50);
+ for (tries = 0; tries < 3; tries++) {
+ if (stlink_v1) {
+ sl = stlink_v1_open(50);
+ } else {
+ sl = stlink_open_usb(50);
- }
- if (!sl) {
- fprintf (stderr, "No STLink devices present\n");
- done (sl, NULL, 1);
- }
-
- if (sl->chip_id != 0)
- break;
- stlink_reset(sl);
- stlink_close(sl);
- sl = NULL;
}
if (!sl) {
- fprintf (stderr, "Debugger connection failed\n");
- exit(1);
+ fprintf (stderr, "No STLink devices present\n");
+ done (sl, 1);
}
- /* Verify that the loaded image fits entirely within device flash
- */
- if (load->address < sl->flash_base ||
- sl->flash_base + sl->flash_size < load->address + load->length) {
- fprintf (stderr, "\%s\": Invalid memory range 0x%08x - 0x%08x\n", filename,
- load->address, load->address + load->length);
- done(sl, NULL, 1);
- }
-
- /* Enter debugging mode
- */
- if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE)
- stlink_exit_dfu_mode(sl);
-
- if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
- stlink_enter_swd_mode(sl);
- } else {
- int is_loader;
- int tries;
-
- for (tries = 0; tries < 3; tries++) {
- char *this_tty = tty;
- if (!this_tty)
- this_tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
- if (!this_tty)
- this_tty = cc_usbdevs_find_by_arg(device, "MegaMetrum");
- if (!this_tty)
- this_tty = getenv("ALTOS_TTY");
- if (!this_tty)
- this_tty="/dev/ttyACM0";
-
- cc = cc_usb_open(this_tty);
-
- if (!cc)
- exit(1);
- cc_usb_printf(cc, "v\n");
- is_loader = 0;
- for (;;) {
- char line[256];
- cc_usb_getline(cc, line, sizeof(line));
- if (!strncmp(line, "altos-loader", 12))
- is_loader = 1;
- if (!strncmp(line, "software-version", 16))
- break;
- }
- if (is_loader)
- break;
- printf ("rebooting to loader\n");
- cc_usb_printf(cc, "X\n");
- cc_usb_close(cc);
- sleep(1);
- cc = NULL;
- }
- if (!is_loader) {
- fprintf(stderr, "Cannot switch to boot loader\n");
- exit(1);
- }
-#if 0
- {
- uint8_t check[256];
- int i = 0;
-
- ao_self_block_read(cc, AO_BOOT_APPLICATION_BASE, check);
- for (;;) {
- uint8_t block[256];
- putchar ('.');
- if (++i == 40) {
- putchar('\n');
- i = 0;
- }
- fflush(stdout);
- ao_self_block_write(cc, AO_BOOT_APPLICATION_BASE, block);
- ao_self_block_read(cc, AO_BOOT_APPLICATION_BASE, block);
- if (memcmp(block, check, 256) != 0) {
- fprintf (stderr, "read differed\n");
- exit(1);
- }
- }
- }
-#endif
+ if (sl->chip_id != 0)
+ break;
+ stlink_reset(sl);
+ stlink_close(sl);
+ sl = NULL;
}
-
- /* Go fetch existing config values
- * if available
- */
- was_flashed = check_flashed(sl, cc);
-
- if (!serial) {
- if (!was_flashed) {
- fprintf (stderr, "Must provide serial number\n");
- done(sl, cc, 1);
- }
- serial = get_uint16(sl, cc, AO_SERIAL_NUMBER);
- if (!serial || serial == 0xffff) {
- fprintf (stderr, "Invalid existing serial %d\n", serial);
- done(sl, cc, 1);
- }
+ if (!sl) {
+ fprintf (stderr, "Debugger connection failed\n");
+ exit(1);
}
- if (!cal && AO_RADIO_CAL && was_flashed) {
- cal = get_uint32(sl, cc, AO_RADIO_CAL);
- if (!cal || cal == 0xffffffff) {
- fprintf (stderr, "Invalid existing rf cal %d\n", cal);
- done(sl, cc, 1);
- }
+ /* Verify that the loaded image fits entirely within device flash
+ */
+ if (load->address < sl->flash_base ||
+ sl->flash_base + sl->flash_size < load->address + load->length) {
+ fprintf (stderr, "\%s\": Invalid memory range 0x%08x - 0x%08x\n", filename,
+ load->address, load->address + load->length);
+ done(sl, 1);
}
- /* Write the config values into the flash image
+ /* Enter debugging mode
*/
+ if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE)
+ stlink_exit_dfu_mode(sl);
- serial_int[0] = serial & 0xff;
- serial_int[1] = (serial >> 8) & 0xff;
+ if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
+ stlink_enter_swd_mode(sl);
- if (!rewrite(load, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) {
- fprintf(stderr, "Cannot rewrite serial integer at %08x\n",
- AO_SERIAL_NUMBER);
- done(sl, cc, 1);
- }
- if (AO_USB_DESCRIPTORS) {
- uint32_t usb_descriptors = AO_USB_DESCRIPTORS - load->address;
- string_num = 0;
+ if (!raw) {
+ /* Go fetch existing config values
+ * if available
+ */
+ was_flashed = check_flashed(sl);
- while (load->data[usb_descriptors] != 0 && usb_descriptors < load->length) {
- if (load->data[usb_descriptors+1] == AO_USB_DESC_STRING) {
- ++string_num;
- if (string_num == 4)
- break;
+ if (!serial) {
+ if (!was_flashed) {
+ fprintf (stderr, "Must provide serial number\n");
+ done(sl, 1);
+ }
+ serial = get_uint16(sl, AO_SERIAL_NUMBER);
+ if (!serial || serial == 0xffff) {
+ fprintf (stderr, "Invalid existing serial %d\n", serial);
+ done(sl, 1);
}
- usb_descriptors += load->data[usb_descriptors];
- }
- if (usb_descriptors >= load->length || load->data[usb_descriptors] == 0 ) {
- fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS);
- done(sl, cc, 1);
}
- serial_ucs2_len = load->data[usb_descriptors] - 2;
- serial_ucs2 = malloc(serial_ucs2_len);
- if (!serial_ucs2) {
- fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len);
- done(sl, cc, 1);
- }
- s = serial;
- for (i = serial_ucs2_len / 2; i; i--) {
- serial_ucs2[i * 2 - 1] = 0;
- serial_ucs2[i * 2 - 2] = (s % 10) + '0';
- s /= 10;
- }
- if (!rewrite(load, usb_descriptors + 2 + load->address, serial_ucs2, serial_ucs2_len)) {
- fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS);
- done(sl, cc, 1);
+ if (!cal && AO_RADIO_CAL && was_flashed) {
+ cal = get_uint32(sl, AO_RADIO_CAL);
+ if (!cal || cal == 0xffffffff) {
+ fprintf (stderr, "Invalid existing rf cal %d\n", cal);
+ done(sl, 1);
+ }
}
- }
-
- if (cal && AO_RADIO_CAL) {
- cal_int[0] = cal & 0xff;
- cal_int[1] = (cal >> 8) & 0xff;
- cal_int[2] = (cal >> 16) & 0xff;
- cal_int[3] = (cal >> 24) & 0xff;
- if (!rewrite(load, AO_RADIO_CAL, cal_int, sizeof (cal_int))) {
- fprintf(stderr, "Cannot rewrite radio calibration at %08x\n", AO_RADIO_CAL);
- exit(1);
- }
+ if (!ao_editaltos(load, serial, cal))
+ done(sl, 1);
}
/* And flash the resulting image to the device
*/
- if (cc)
- success = ao_self_write(cc, load);
- else
- success = (stlink_write_flash(sl, load->address, load->data, load->length) >= 0);
+
+ success = (stlink_write_flash(sl, load->address, load->data, load->length) >= 0);
if (!success) {
fprintf (stderr, "\"%s\": Write failed\n", filename);
- done(sl, cc, 1);
+ done(sl, 1);
}
- done(sl, cc, 0);
+ done(sl, 0);
}
diff --git a/ao-tools/ao-stmload/ao-stmload.h b/ao-tools/ao-stmload/ao-stmload.h
index 98884535..1ba9a977 100644
--- a/ao-tools/ao-stmload/ao-stmload.h
+++ b/ao-tools/ao-stmload/ao-stmload.h
@@ -18,16 +18,11 @@
#ifndef _AO_STMLOAD_H_
#define _AO_STMLOAD_H_
-struct sym {
- unsigned addr;
- unsigned default_addr;
- char *name;
- int required;
-};
+#include "ao-elf.h"
#define AO_BOOT_APPLICATION_BASE 0x08001000
-extern struct sym ao_symbols[];
+extern struct ao_sym ao_symbols[];
extern int ao_num_symbols;
extern int ao_num_required_symbols;
@@ -38,12 +33,4 @@ ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]);
void
ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]);
-struct hex_image *
-ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length);
-
-int
-ao_self_write(struct cc_usb *cc, struct hex_image *image);
-
-extern int ao_self_verbose;
-
#endif /* _AO_STMLOAD_H_ */
diff --git a/ao-tools/ao-telem/ao-telem.c b/ao-tools/ao-telem/ao-telem.c
index d2dae5a7..f1755b82 100644
--- a/ao-tools/ao-telem/ao-telem.c
+++ b/ao-tools/ao-telem/ao-telem.c
@@ -194,6 +194,39 @@ main (int argc, char **argv)
telem.mega_data.height);
break;
+ case AO_TELEMETRY_METRUM_SENSOR:
+ printf ("state %1d accel %5d pres %9d temp %6.2f acceleration %6.2f speed %6.2f height %5d v_batt %5d sense_a %5d sense_m %5d\n",
+ telem.metrum_sensor.state,
+ telem.metrum_sensor.accel,
+ telem.metrum_sensor.pres,
+ telem.metrum_sensor.temp / 100.0,
+ telem.metrum_sensor.acceleration / 16.0,
+ telem.metrum_sensor.speed / 16.0,
+ telem.metrum_sensor.height,
+ telem.metrum_sensor.v_batt,
+ telem.metrum_sensor.sense_a,
+ telem.metrum_sensor.sense_m);
+ break;
+ case AO_TELEMETRY_METRUM_DATA:
+ printf ("ground_pres %9d ground_accel %5d accel_plus %5d accel_minus %5d\n",
+ telem.metrum_data.ground_pres,
+ telem.metrum_data.ground_accel,
+ telem.metrum_data.accel_plus_g,
+ telem.metrum_data.accel_minus_g);
+ break;
+ case AO_TELEMETRY_MINI:
+ printf ("state %1d v_batt %5d sense_a %5d sense_m %5d pres %9d temp %6.2f acceleration %6.2f speed %6.2f height %5d ground_pres %9d\n",
+ telem.mini.state,
+ telem.mini.v_batt,
+ telem.mini.sense_a,
+ telem.mini.sense_m,
+ telem.mini.pres,
+ telem.mini.temp / 100.0,
+ telem.mini.acceleration / 16.0,
+ telem.mini.speed / 16.0,
+ telem.mini.height,
+ telem.mini.ground_pres);
+ break;
default:
printf("\n");
}
diff --git a/ao-tools/ao-usbload/Makefile.am b/ao-tools/ao-usbload/Makefile.am
new file mode 100644
index 00000000..e3b63a85
--- /dev/null
+++ b/ao-tools/ao-usbload/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS=ao-usbload
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_STMLOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_usbload_DEPENDENCIES = $(AO_STMLOAD_LIBS)
+
+ao_usbload_LDADD=$(AO_STMLOAD_LIBS) $(LIBUSB_LIBS) -lelf
+
+ao_usbload_SOURCES=ao-usbload.c ao-usbload.h
+
+man_MANS = ao-usbload.1
diff --git a/ao-tools/ao-usbload/ao-usbload.1 b/ao-tools/ao-usbload/ao-usbload.1
new file mode 100644
index 00000000..48165921
--- /dev/null
+++ b/ao-tools/ao-usbload/ao-usbload.1
@@ -0,0 +1,81 @@
+.\"
+.\" Copyright © 2009 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-usbload" ""
+.SH NAME
+ao-usbload \- flash a program to an ARM-based AltOS device
+.SH SYNOPSIS
+.B "ao-usbload"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+[\--cal \fIradio-calibration\fP]
+[\--serial \fserial-number\fP]
+\fIfile.elf\fP or \fIfile.ihx\fP
+.SH DESCRIPTION
+.I ao-usbload
+loads the specified .elf or .ihx file into the target device flash
+memory via the AltOS boot loader, using either existing serial number
+and radio calibration values or taking either of those from the
+command line.
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.TP
+\-s serial-number | --serial serial-number
+This programs the device serial number into the image. If no serial
+number is specified, then the existing serial number, if any, will be
+read from the device.
+.TP
+\-c radio-calibration | --cal radio-calibration This programs the
+radio calibration value into the image for hardware which doesn't have
+any eeprom storage for this value. If no calibration value is
+specified, an existing calibration value will be used. The value here
+can be computed given the current radio calibration value, the
+measured frequency and the desired frequency:
+.IP
+ cal' = cal * (desired/measured)
+.IP
+The default calibration value is 7119667.
+.SH USAGE
+.I ao-usbload
+reads the specified .elf file into memory, edits the image to
+customize it using the specified serial number and radio calibration
+values. It then connects to the debug dongle and writes the program to
+the target device flash memory.
+.SH AUTHOR
+Keith Packard
diff --git a/ao-tools/ao-usbload/ao-usbload.c b/ao-tools/ao-usbload/ao-usbload.c
new file mode 100644
index 00000000..0c8a23df
--- /dev/null
+++ b/ao-tools/ao-usbload/ao-usbload.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-usbload.h"
+#include "ao-selfload.h"
+#include "ao-verbose.h"
+#include "ao-editaltos.h"
+
+static uint16_t
+get_uint16(struct cc_usb *cc, uint32_t addr)
+{
+ uint16_t result;
+ result = ao_self_get_uint16(cc, addr);
+ printf ("read 0x%08x = 0x%04x\n", addr, result);
+ return result;
+}
+
+/*
+ * Read a 32-bit value from the target device with arbitrary
+ * alignment
+ */
+static uint32_t
+get_uint32(struct cc_usb *cc, uint32_t addr)
+{
+ uint32_t result;
+
+ result = ao_self_get_uint32(cc, addr);
+ printf ("read 0x%08x = 0x%08x\n", addr, result);
+ return result;
+}
+
+/*
+ * Check to see if the target device has been
+ * flashed with a similar firmware image before
+ *
+ * This is done by looking for the same romconfig version,
+ * which should be at the same location as the linker script
+ * places this at 0x100 from the start of the rom section
+ */
+static int
+check_flashed(struct cc_usb *cc)
+{
+ uint16_t romconfig_version = get_uint16(cc, AO_ROMCONFIG_VERSION);
+ uint16_t romconfig_check = get_uint16(cc, AO_ROMCONFIG_CHECK);
+
+ if (romconfig_version != (uint16_t) ~romconfig_check) {
+ fprintf (stderr, "Device has not been flashed before\n");
+ return 0;
+ }
+ return 1;
+}
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
+ { .name = "cal", .has_arg = 1, .val = 'c' },
+ { .name = "serial", .has_arg = 1, .val = 's' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--raw] [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] file.{elf,ihx}\n", program);
+ exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+/* cc_usb_printf(cc, "a\n"); */
+ cc_usb_close(cc);
+ exit (code);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device = NULL;
+ char *filename;
+ Elf *e;
+ int raw = 0;
+ char *serial_end;
+ unsigned int serial = 0;
+ char *serial_ucs2;
+ int serial_ucs2_len;
+ char serial_int[2];
+ unsigned int s;
+ int i;
+ int string_num;
+ uint32_t cal = 0;
+ char cal_int[4];
+ char *cal_end;
+ int c;
+ int was_flashed = 0;
+ struct ao_hex_image *load;
+ int tries;
+ struct cc_usb *cc = NULL;
+ char *tty = NULL;
+ int success;
+ int verbose = 0;
+ struct ao_sym *file_symbols;
+ int num_file_symbols;
+
+ while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'r':
+ raw = 1;
+ break;
+ case 'c':
+ cal = strtoul(optarg, &cal_end, 10);
+ if (cal_end == optarg || *cal_end != '\0')
+ usage(argv[0]);
+ break;
+ case 's':
+ serial = strtoul(optarg, &serial_end, 10);
+ if (serial_end == optarg || *serial_end != '\0')
+ usage(argv[0]);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ao_verbose = verbose;
+
+ if (verbose > 1)
+ ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+ filename = argv[optind];
+ if (filename == NULL)
+ usage(argv[0]);
+
+ if (ends_with (filename, ".elf")) {
+ load = ao_load_elf(filename, &file_symbols, &num_file_symbols);
+ } else if (ends_with (filename, ".ihx")) {
+ load = ao_hex_load(filename, &file_symbols, &num_file_symbols);
+ } else
+ usage(argv[0]);
+
+ if (!raw) {
+ if (!ao_editaltos_find_symbols(file_symbols, num_file_symbols, ao_symbols, ao_num_symbols)) {
+ fprintf(stderr, "Cannot find required symbols\n");
+ usage(argv[0]);
+ }
+ }
+
+ {
+ int is_loader;
+ int tries;
+
+ for (tries = 0; tries < 3; tries++) {
+ char *this_tty = tty;
+ if (!this_tty)
+ this_tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
+ if (!this_tty)
+ this_tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+ if (!this_tty)
+ this_tty = getenv("ALTOS_TTY");
+ if (!this_tty)
+ this_tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(this_tty);
+
+ if (!cc)
+ exit(1);
+ cc_usb_printf(cc, "v\n");
+ is_loader = 0;
+ for (;;) {
+ char line[256];
+ cc_usb_getline(cc, line, sizeof(line));
+ if (!strncmp(line, "altos-loader", 12))
+ is_loader = 1;
+ if (!strncmp(line, "software-version", 16))
+ break;
+ }
+ if (is_loader)
+ break;
+ printf ("rebooting to loader\n");
+ cc_usb_printf(cc, "X\n");
+ cc_usb_close(cc);
+ sleep(1);
+ cc = NULL;
+ }
+ if (!is_loader) {
+ fprintf(stderr, "Cannot switch to boot loader\n");
+ exit(1);
+ }
+#if 0
+ {
+ uint8_t check[256];
+ int i = 0;
+
+ ao_self_block_read(cc, AO_BOOT_APPLICATION_BASE, check);
+ for (;;) {
+ uint8_t block[256];
+ putchar ('.');
+ if (++i == 40) {
+ putchar('\n');
+ i = 0;
+ }
+ fflush(stdout);
+ ao_self_block_write(cc, AO_BOOT_APPLICATION_BASE, block);
+ ao_self_block_read(cc, AO_BOOT_APPLICATION_BASE, block);
+ if (memcmp(block, check, 256) != 0) {
+ fprintf (stderr, "read differed\n");
+ exit(1);
+ }
+ }
+ }
+#endif
+ }
+
+ if (!raw) {
+ /* Go fetch existing config values
+ * if available
+ */
+ was_flashed = check_flashed(cc);
+
+ if (!serial) {
+ if (!was_flashed) {
+ fprintf (stderr, "Must provide serial number\n");
+ done(cc, 1);
+ }
+ serial = get_uint16(cc, AO_SERIAL_NUMBER);
+ if (!serial || serial == 0xffff) {
+ fprintf (stderr, "Invalid existing serial %d\n", serial);
+ done(cc, 1);
+ }
+ }
+
+ if (!cal && AO_RADIO_CAL && was_flashed) {
+ cal = get_uint32(cc, AO_RADIO_CAL);
+ if (!cal || cal == 0xffffffff) {
+ fprintf (stderr, "Invalid existing rf cal %d\n", cal);
+ done(cc, 1);
+ }
+ }
+
+ if (!ao_editaltos(load, serial, cal))
+ done(cc, 1);
+ }
+
+ /* And flash the resulting image to the device
+ */
+ success = ao_self_write(cc, load);
+
+ if (!success) {
+ fprintf (stderr, "\"%s\": Write failed\n", filename);
+ done(cc, 1);
+ }
+
+ done(cc, 0);
+}
diff --git a/ao-tools/ao-usbload/ao-usbload.h b/ao-tools/ao-usbload/ao-usbload.h
new file mode 100644
index 00000000..1ba9a977
--- /dev/null
+++ b/ao-tools/ao-usbload/ao-usbload.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_STMLOAD_H_
+#define _AO_STMLOAD_H_
+
+#include "ao-elf.h"
+
+#define AO_BOOT_APPLICATION_BASE 0x08001000
+
+extern struct ao_sym ao_symbols[];
+
+extern int ao_num_symbols;
+extern int ao_num_required_symbols;
+
+void
+ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]);
+
+void
+ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]);
+
+#endif /* _AO_STMLOAD_H_ */
diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am
index 1f8f2e42..a03a976c 100644
--- a/ao-tools/lib/Makefile.am
+++ b/ao-tools/lib/Makefile.am
@@ -11,7 +11,6 @@ libao_tools_a_SOURCES = \
ccdbg-debug.h \
ccdbg-flash.c \
ccdbg.h \
- ccdbg-hex.c \
ccdbg-io.c \
ccdbg-manual.c \
ccdbg-memory.c \
@@ -21,6 +20,7 @@ libao_tools_a_SOURCES = \
cc-convert.c \
cc-dsp.c \
cc-integrate.c \
+ cc-mega.c \
cc-period.c \
cc-process.c \
cc-usb.c \
@@ -39,4 +39,14 @@ libao_tools_a_SOURCES = \
i0.c \
chbevl.c \
mconf.h \
- cephes.h
+ cephes.h \
+ ao-hex.c \
+ ao-hex.h \
+ ao-editaltos.c \
+ ao-editaltos.h \
+ ao-elf.c \
+ ao-elf.h \
+ ao-selfload.c \
+ ao-selfload.h \
+ ao-verbose.c \
+ ao-verbose.h
diff --git a/ao-tools/lib/ao-editaltos.c b/ao-tools/lib/ao-editaltos.c
new file mode 100644
index 00000000..a8b64098
--- /dev/null
+++ b/ao-tools/lib/ao-editaltos.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "ao-editaltos.h"
+
+struct ao_sym ao_symbols[] = {
+
+ { 0, 0, "ao_romconfig_version", 1 },
+ { 0, 0, "ao_romconfig_check", 1 },
+ { 0, 0, "ao_serial_number", 1 },
+ { 0, 0, "ao_radio_cal", 0 },
+ { 0, 0, "ao_usb_descriptors", 0 },
+};
+
+#define NUM_SYMBOLS 5
+
+int ao_num_symbols = NUM_SYMBOLS;
+
+/*
+ * Edit the to-be-written memory block
+ */
+static bool
+rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length)
+{
+ int i;
+
+ if (address < load->address || load->address + load->length < address + length)
+ return false;
+
+ printf("rewrite %04x:", address);
+ for (i = 0; i < length; i++)
+ printf (" %02x", load->data[address - load->address + i]);
+ printf(" ->");
+ for (i = 0; i < length; i++)
+ printf (" %02x", data[i]);
+ printf("\n");
+ memcpy(load->data + address - load->address, data, length);
+ return true;
+}
+
+/*
+ * Find the symbols needed to correctly load the program
+ */
+
+bool
+ao_editaltos_find_symbols(struct ao_sym *file_symbols, int num_file_symbols,
+ struct ao_sym *symbols, int num_symbols)
+{
+ int f, s;
+
+ for (f = 0; f < num_file_symbols; f++) {
+ for (s = 0; s < num_symbols; s++) {
+ if (strcmp(symbols[s].name, file_symbols[f].name) == 0) {
+ symbols[s].addr = file_symbols[f].addr;
+ symbols[s].found = true;
+ }
+ }
+ }
+ for (s = 0; s < num_symbols; s++)
+ if (!symbols[s].found && symbols[s].required)
+ return false;
+ return true;
+}
+
+bool
+ao_editaltos(struct ao_hex_image *image,
+ uint16_t serial,
+ uint32_t cal)
+{
+ uint8_t *serial_ucs2;
+ int serial_ucs2_len;
+ uint8_t serial_int[2];
+ unsigned int s;
+ int i;
+ int string_num;
+ uint8_t cal_int[4];
+
+ /* Write the config values into the flash image
+ */
+
+ serial_int[0] = serial & 0xff;
+ serial_int[1] = (serial >> 8) & 0xff;
+
+ if (!rewrite(image, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) {
+ fprintf(stderr, "Cannot rewrite serial integer at %08x\n",
+ AO_SERIAL_NUMBER);
+ return false;
+ }
+
+ if (AO_USB_DESCRIPTORS) {
+ uint32_t usb_descriptors = AO_USB_DESCRIPTORS - image->address;
+ string_num = 0;
+
+ while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) {
+ if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) {
+ ++string_num;
+ if (string_num == 4)
+ break;
+ }
+ usb_descriptors += image->data[usb_descriptors];
+ }
+ if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) {
+ fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS);
+ return false;
+ }
+
+ serial_ucs2_len = image->data[usb_descriptors] - 2;
+ serial_ucs2 = malloc(serial_ucs2_len);
+ if (!serial_ucs2) {
+ fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len);
+ return false;
+ }
+ s = serial;
+ for (i = serial_ucs2_len / 2; i; i--) {
+ serial_ucs2[i * 2 - 1] = 0;
+ serial_ucs2[i * 2 - 2] = (s % 10) + '0';
+ s /= 10;
+ }
+ if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) {
+ fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS);
+ return false;
+ }
+ }
+
+ if (cal && AO_RADIO_CAL) {
+ cal_int[0] = cal & 0xff;
+ cal_int[1] = (cal >> 8) & 0xff;
+ cal_int[2] = (cal >> 16) & 0xff;
+ cal_int[3] = (cal >> 24) & 0xff;
+
+ if (!rewrite(image, AO_RADIO_CAL, cal_int, sizeof (cal_int))) {
+ fprintf(stderr, "Cannot rewrite radio calibration at %08x\n", AO_RADIO_CAL);
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/ao-tools/lib/ao-editaltos.h b/ao-tools/lib/ao-editaltos.h
new file mode 100644
index 00000000..74530435
--- /dev/null
+++ b/ao-tools/lib/ao-editaltos.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_EDITALTOS_H_
+#define _AO_EDITALTOS_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "ao-hex.h"
+
+extern struct ao_sym ao_symbols[];
+extern int ao_num_symbols;
+
+#define AO_USB_DESC_STRING 3
+
+#define AO_ROMCONFIG_VERSION (ao_symbols[0].addr)
+#define AO_ROMCONFIG_CHECK (ao_symbols[1].addr)
+#define AO_SERIAL_NUMBER (ao_symbols[2].addr)
+#define AO_RADIO_CAL (ao_symbols[3].addr)
+#define AO_USB_DESCRIPTORS (ao_symbols[4].addr)
+
+struct ao_editaltos_funcs {
+ uint16_t (*get_uint16)(void *closure, uint32_t addr);
+ uint32_t (*get_uint32)(void *closure, uint32_t addr);
+};
+
+bool
+ao_editaltos_find_symbols(struct ao_sym *file_symbols, int num_file_symbols,
+ struct ao_sym *symbols, int num_symbols);
+
+bool
+ao_editaltos(struct ao_hex_image *image,
+ uint16_t serial,
+ uint32_t radio_cal);
+
+#endif /* _AO_EDITALTOS_H_ */
diff --git a/ao-tools/ao-stmload/ao-elf.c b/ao-tools/lib/ao-elf.c
index dad8fb80..99b37210 100644
--- a/ao-tools/ao-stmload/ao-elf.c
+++ b/ao-tools/lib/ao-elf.c
@@ -15,37 +15,41 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#include "ao-elf.h"
#include <err.h>
-#include <gelf.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <unistd.h>
#include <string.h>
-#include "ccdbg.h"
-#include "ao-stmload.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "ao-elf.h"
+#include "ao-hex.h"
+#include "ao-verbose.h"
/*
- * Look through the Elf file for the AltOS symbols
- * that can be adjusted before the image is written
- * to the device
+ * Look through the Elf file for symbols that can be adjusted before
+ * the image is written to the device
*/
-static int
-find_symbols (Elf *e)
+static struct ao_sym *
+load_symbols (Elf *e, int *num_symbolsp)
{
Elf_Scn *scn;
Elf_Data *symbol_data = NULL;
GElf_Shdr shdr;
GElf_Sym sym;
- int i, symbol_count, s;
- int required = 0;
+ int i, symbol_count;
char *symbol_name;
- char *section_name;
size_t shstrndx;
+ struct ao_sym *symbols = NULL;
+ struct ao_sym *symbol;
+ int num_symbols = 0;
+ int size_symbols = 0;
if (elf_getshdrstrndx(e, &shstrndx) < 0)
- return 0;
+ return false;
/*
* Find the symbols
@@ -55,7 +59,7 @@ find_symbols (Elf *e)
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) != &shdr)
- return 0;
+ return false;
if (shdr.sh_type == SHT_SYMTAB) {
symbol_data = elf_getdata(scn, NULL);
@@ -65,36 +69,60 @@ find_symbols (Elf *e)
}
if (!symbol_data)
- return 0;
+ return NULL;
for (i = 0; i < symbol_count; i++) {
gelf_getsym(symbol_data, i, &sym);
symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name);
+ if (!symbol_name[0])
+ continue;
- for (s = 0; s < ao_num_symbols; s++)
- if (!strcmp (ao_symbols[s].name, symbol_name)) {
- int t;
- ao_symbols[s].addr = sym.st_value;
- if (ao_symbols[s].required)
- ++required;
- }
- }
+ if (num_symbols == size_symbols) {
+ struct ao_sym *new_symbols;
+ int new_size;
+
+ if (!size_symbols)
+ new_size = 16;
+ else
+ new_size = size_symbols * 2;
+ new_symbols = realloc(symbols, new_size * sizeof (struct ao_sym));
+ if (!new_symbols)
+ goto bail;
- return required >= ao_num_required_symbols;
+ symbols = new_symbols;
+ size_symbols = new_size;
+ }
+ symbol = &symbols[num_symbols];
+ memset(symbol, 0, sizeof (struct ao_sym));
+ symbol->name = strdup(symbol_name);
+ if (!symbol->name)
+ goto bail;
+ symbol->addr = sym.st_value;
+ ao_printf(AO_VERBOSE_EXE, "Add symbol %s: %08x\n", symbol->name, symbol->addr);
+ num_symbols++;
+ }
+ *num_symbolsp = num_symbols;
+ return symbols;
+bail:
+ for (i = 0; i < num_symbols; i++)
+ free(symbols[i].name);
+ free(symbols);
+ return NULL;
}
-uint32_t round4(uint32_t a) {
+static uint32_t
+round4(uint32_t a) {
return (a + 3) & ~3;
}
-struct hex_image *
+static struct ao_hex_image *
new_load (uint32_t addr, uint32_t len)
{
- struct hex_image *new;
+ struct ao_hex_image *new;
len = round4(len);
- new = calloc (1, sizeof (struct hex_image) + len);
+ new = calloc (1, sizeof (struct ao_hex_image) + len);
if (!new)
abort();
@@ -103,8 +131,8 @@ new_load (uint32_t addr, uint32_t len)
return new;
}
-void
-load_paste(struct hex_image *into, struct hex_image *from)
+static void
+load_paste(struct ao_hex_image *into, struct ao_hex_image *from)
{
if (from->address < into->address || into->address + into->length < from->address + from->length)
abort();
@@ -116,10 +144,10 @@ load_paste(struct hex_image *into, struct hex_image *from)
* Make a new load structure large enough to hold the old one and
* the new data
*/
-struct hex_image *
-expand_load(struct hex_image *from, uint32_t address, uint32_t length)
+static struct ao_hex_image *
+expand_load(struct ao_hex_image *from, uint32_t address, uint32_t length)
{
- struct hex_image *new;
+ struct ao_hex_image *new;
if (from) {
uint32_t from_last = from->address + from->length;
@@ -147,10 +175,10 @@ expand_load(struct hex_image *from, uint32_t address, uint32_t length)
* Create a new load structure with data from the existing one
* and the new data
*/
-struct hex_image *
-load_write(struct hex_image *from, uint32_t address, uint32_t length, void *data)
+static struct ao_hex_image *
+load_write(struct ao_hex_image *from, uint32_t address, uint32_t length, void *data)
{
- struct hex_image *new;
+ struct ao_hex_image *new;
new = expand_load(from, address, length);
memcpy(new->data + address - new->address, data, length);
@@ -161,22 +189,21 @@ load_write(struct hex_image *from, uint32_t address, uint32_t length, void *data
* Construct a large in-memory block for all
* of the loaded sections of the program
*/
-static struct hex_image *
+static struct ao_hex_image *
get_load(Elf *e)
{
Elf_Scn *scn;
size_t shstrndx;
GElf_Shdr shdr;
Elf_Data *data;
- char *got_name;
size_t nphdr;
size_t p;
GElf_Phdr phdr;
- GElf_Addr p_paddr;
- GElf_Off p_offset;
GElf_Addr sh_paddr;
- struct hex_image *load = NULL;
+ struct ao_hex_image *load = NULL;
+#if 0
char *section_name;
+#endif
size_t nshdr;
size_t s;
@@ -201,31 +228,32 @@ get_load(Elf *e)
if (phdr.p_type != PT_LOAD)
continue;
- p_offset = phdr.p_offset;
/* Get the associated file section */
#if 0
- printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n",
- (uint32_t) phdr.p_offset,
- (uint32_t) phdr.p_vaddr,
- (uint32_t) phdr.p_paddr,
- (uint32_t) phdr.p_filesz,
- (uint32_t) phdr.p_memsz);
+ fprintf (stderr, "offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n",
+ (uint32_t) phdr.p_offset,
+ (uint32_t) phdr.p_vaddr,
+ (uint32_t) phdr.p_paddr,
+ (uint32_t) phdr.p_filesz,
+ (uint32_t) phdr.p_memsz);
#endif
for (s = 0; s < nshdr; s++) {
scn = elf_getscn(e, s);
if (!scn) {
- printf ("getscn failed\n");
+ fprintf (stderr, "getscn failed\n");
abort();
}
if (gelf_getshdr(scn, &shdr) != &shdr) {
- printf ("gelf_getshdr failed\n");
+ fprintf (stderr, "gelf_getshdr failed\n");
abort();
}
+#if 0
section_name = elf_strptr(e, shstrndx, shdr.sh_name);
+#endif
if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) {
@@ -234,11 +262,13 @@ get_load(Elf *e)
sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset;
- printf ("\tsize %08x rom %08x exec %08x %s\n",
- (uint32_t) shdr.sh_size,
- (uint32_t) sh_paddr,
- (uint32_t) shdr.sh_addr,
- section_name);
+#if 0
+ fprintf (stderr, "\tsize %08x rom %08x exec %08x %s\n",
+ (uint32_t) shdr.sh_size,
+ (uint32_t) sh_paddr,
+ (uint32_t) shdr.sh_addr,
+ section_name);
+#endif
data = elf_getdata(scn, NULL);
@@ -255,19 +285,13 @@ get_load(Elf *e)
* check for the symbols we need
*/
-struct hex_image *
-ao_load_elf(char *name)
+struct ao_hex_image *
+ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols)
{
int fd;
Elf *e;
- Elf_Scn *scn;
- Elf_Data *symbol_data = NULL;
- GElf_Shdr shdr;
- GElf_Sym sym;
- size_t n, shstrndx, sz;
- int i, symbol_count, s;
- int required = 0;
- struct hex_image *image;
+ size_t shstrndx;
+ struct ao_hex_image *image;
if (elf_version(EV_CURRENT) == EV_NONE)
return NULL;
@@ -288,10 +312,8 @@ ao_load_elf(char *name)
if (elf_getshdrstrndx(e, &shstrndx) != 0)
return NULL;
- if (!find_symbols(e)) {
- fprintf (stderr, "Cannot find required symbols\n");
- return NULL;
- }
+ if (symbols)
+ *symbols = load_symbols(e, num_symbols);
image = get_load(e);
if (!image) {
diff --git a/ao-tools/ao-stmload/ao-elf.h b/ao-tools/lib/ao-elf.h
index 4303d5ca..0f79d142 100644
--- a/ao-tools/ao-stmload/ao-elf.h
+++ b/ao-tools/lib/ao-elf.h
@@ -18,7 +18,11 @@
#ifndef _AO_ELF_H_
#define _AO_ELF_H_
-struct hex_image *
-ao_load_elf(char *name);
+#include <stdbool.h>
+#include <gelf.h>
+#include "ao-hex.h"
-#endif
+struct ao_hex_image *
+ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols);
+
+#endif /* _AO_ELF_H_ */
diff --git a/ao-tools/lib/ao-hex.c b/ao-tools/lib/ao-hex.c
new file mode 100644
index 00000000..5cfc63c1
--- /dev/null
+++ b/ao-tools/lib/ao-hex.c
@@ -0,0 +1,626 @@
+/*
+ * Copyright © 2008 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "ao-hex.h"
+#include "ao-verbose.h"
+
+struct ao_hex_input {
+ FILE *file;
+ int line;
+ char *name;
+};
+
+enum ao_hex_read_state {
+ read_marker,
+ read_length,
+ read_address,
+ read_type,
+ read_data,
+ read_checksum,
+ read_newline,
+ read_white,
+ read_done,
+};
+
+
+static void
+ao_hex_error(struct ao_hex_input *input, char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "Hex error %s:%d: ", input->name, input->line);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+static void
+ao_hex_free(struct ao_hex_record *record)
+{
+ if (!record) return;
+ free(record);
+}
+
+static struct ao_hex_record *
+ao_hex_alloc(uint8_t length)
+{
+ struct ao_hex_record *record;
+
+ record = calloc(1, sizeof(struct ao_hex_record) + length);
+ record->length = length;
+ return record;
+}
+
+static int
+ishex(char c)
+{
+ return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
+}
+
+static int
+fromhex(char c)
+{
+ if (isdigit(c))
+ return c - '0';
+ if ('a' <= c && c <= 'f')
+ return c - 'a' + 10;
+ if ('A' <= c && c <= 'F')
+ return c - 'A' + 10;
+ abort();
+ return 0;
+}
+
+static uint8_t
+ao_hex_checksum(struct ao_hex_record *record)
+{
+ uint8_t checksum = 0;
+ int i;
+
+ checksum += record->length;
+ checksum += record->address >> 8;
+ checksum += record->address & 0xff;
+ checksum += record->type;
+ for (i = 0; i < record->length; i++)
+ checksum += record->data[i];
+ return -checksum;
+}
+
+static struct ao_hex_record *
+ao_hex_read_record(struct ao_hex_input *input)
+{
+ struct ao_hex_record *record = NULL;
+ enum ao_hex_read_state state = read_marker;
+ char c;
+ int nhexbytes;
+ uint32_t hex;
+ uint32_t ndata;
+ uint8_t checksum;
+
+ while (state != read_done) {
+ c = getc(input->file);
+ if (c == EOF && state != read_white && state != read_marker) {
+ ao_hex_error(input, "Unexpected EOF");
+ goto bail;
+ }
+ if (c == ' ')
+ continue;
+ if (c == '\n')
+ input->line++;
+ switch (state) {
+ case read_marker:
+ if (c == EOF)
+ return NULL;
+ if (c != ':') {
+ ao_hex_error(input, "Missing ':'");
+ goto bail;
+ }
+ state = read_length;
+ nhexbytes = 2;
+ hex = 0;
+ break;
+ case read_length:
+ case read_address:
+ case read_type:
+ case read_data:
+ case read_checksum:
+ if (!ishex(c)) {
+ ao_hex_error(input, "Non-hex char '%c'",
+ c);
+ goto bail;
+ }
+ hex = hex << 4 | fromhex(c);
+ --nhexbytes;
+ if (nhexbytes != 0)
+ break;
+
+ switch (state) {
+ case read_length:
+ record = ao_hex_alloc(hex);
+ if (!record) {
+ ao_hex_error(input, "Out of memory");
+ goto bail;
+ }
+ state = read_address;
+ nhexbytes = 4;
+ break;
+ case read_address:
+ record->address = hex;
+ state = read_type;
+ nhexbytes = 2;
+ break;
+ case read_type:
+ record->type = hex;
+ state = read_data;
+ nhexbytes = 2;
+ ndata = 0;
+ break;
+ case read_data:
+ record->data[ndata] = hex;
+ ndata++;
+ nhexbytes = 2;
+ break;
+ case read_checksum:
+ record->checksum = hex;
+ state = read_newline;
+ break;
+ default:
+ break;
+ }
+ if (state == read_data)
+ if (ndata == record->length) {
+ nhexbytes = 2;
+ state = read_checksum;
+ }
+ hex = 0;
+ break;
+ case read_newline:
+ if (c != '\n' && c != '\r') {
+ ao_hex_error(input, "Missing newline");
+ goto bail;
+ }
+ state = read_white;
+ break;
+ case read_white:
+ if (!isspace(c)) {
+ if (c == '\n')
+ input->line--;
+ if (c != EOF)
+ ungetc(c, input->file);
+ state = read_done;
+ }
+ break;
+ case read_done:
+ break;
+ }
+ }
+ checksum = ao_hex_checksum(record);
+ if (checksum != record->checksum) {
+ ao_hex_error(input, "Invalid checksum (read 0x%02x computed 0x%02x)\n",
+ record->checksum, checksum);
+ goto bail;
+ }
+ return record;
+
+bail:
+ ao_hex_free(record);
+ return NULL;
+}
+
+void
+ao_hex_file_free(struct ao_hex_file *hex)
+{
+ int i;
+
+ if (!hex)
+ return;
+ for (i = 0; i < hex->nrecord; i++)
+ ao_hex_free(hex->records[i]);
+ free(hex);
+}
+
+struct ao_hex_file *
+ao_hex_file_read(FILE *file, char *name)
+{
+ struct ao_hex_input input;
+ struct ao_hex_file *hex = NULL, *newhex;
+ struct ao_hex_record *record;
+ int srecord = 1;
+ int done = 0;
+
+ hex = calloc(sizeof (struct ao_hex_file) + sizeof (struct ao_hex_record *), 1);
+ if (!hex)
+ return NULL;
+ input.name = name;
+ input.line = 1;
+ input.file = file;
+ while (!done) {
+ record = ao_hex_read_record(&input);
+ if (!record) {
+ if (feof(input.file)) {
+ done = 1;
+ break;
+ } else
+ goto bail;
+ }
+ if (hex->nrecord == srecord) {
+ srecord *= 2;
+ newhex = realloc(hex,
+ sizeof (struct ao_hex_file) +
+ srecord * sizeof (struct ao_hex_record *));
+ if (!newhex)
+ goto bail;
+ hex = newhex;
+ }
+ hex->records[hex->nrecord++] = record;
+ }
+ return hex;
+
+bail:
+ ao_hex_file_free(hex);
+ return NULL;
+}
+
+static struct ao_sym *
+load_symbols(struct ao_hex_file *hex,
+ int *num_symbolsp)
+{
+ uint32_t extended_addr;
+ uint32_t addr;
+ int i;
+ struct ao_hex_record *record;
+ struct ao_sym *symbols = NULL;
+ struct ao_sym *symbol;
+ int num_symbols = 0;
+ int size_symbols = 0;
+
+ extended_addr = 0;
+ for (i = 0; i < hex->nrecord; i++) {
+ record = hex->records[i];
+ switch (record->type) {
+ case AO_HEX_RECORD_NORMAL:
+ addr = extended_addr + record->address;
+ break;
+ case AO_HEX_RECORD_EOF:
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_4:
+ if (record->length != 2)
+ goto bail;
+ extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_8:
+ if (record->length != 2)
+ goto bail;
+ extended_addr = (record->data[0] << 24) | (record->data[1] << 16);
+ break;
+ case AO_HEX_RECORD_SYMBOL:
+ addr = extended_addr + record->address;
+ if (num_symbols == size_symbols) {
+ struct ao_sym *new_symbols;
+ int new_size;
+
+ if (!size_symbols)
+ new_size = 16;
+ else
+ new_size = size_symbols * 2;
+ new_symbols = realloc(symbols, new_size * sizeof (struct ao_sym));
+ if (!new_symbols)
+ goto bail;
+
+ symbols = new_symbols;
+ size_symbols = new_size;
+ }
+ symbol = &symbols[num_symbols];
+ memset(symbol, 0, sizeof (struct ao_sym));
+ symbol->name = calloc(record->length + 1, 1);
+ if (!symbol->name)
+ goto bail;
+ memcpy(symbol->name, record->data, record->length);
+ symbol->addr = addr;
+ ao_printf(AO_VERBOSE_EXE, "Add symbol %s: %08x\n", symbol->name, symbol->addr);
+ num_symbols++;
+ break;
+ }
+ }
+ *num_symbolsp = num_symbols;
+ return symbols;
+bail:
+ for (i = 0; i < num_symbols; i++)
+ free(symbols[i].name);
+ free(symbols);
+ return NULL;
+}
+
+static void
+ao_hex_record_set_checksum(struct ao_hex_record *record)
+{
+ uint8_t cksum = 0;
+ int i;
+
+ cksum += record->length;
+ cksum += record->address >> 8;
+ cksum += record->address;
+ cksum += record->type;
+ for (i = 0; i < record->length; i++)
+ cksum += record->data[i];
+
+ record->checksum = -cksum;
+}
+
+struct ao_hex_image *
+ao_hex_image_create(struct ao_hex_file *hex)
+{
+ struct ao_hex_image *image;
+ struct ao_hex_record *record;
+ int i;
+ uint32_t addr;
+ uint32_t base, bound;
+ uint32_t offset;
+ uint32_t extended_addr;
+
+ int length;
+
+ /* Find the address bounds of the file
+ */
+ base = 0xffffffff;
+ bound = 0x0;
+ extended_addr = 0;
+ for (i = 0; i < hex->nrecord; i++) {
+ uint32_t r_bound;
+ record = hex->records[i];
+ switch (record->type) {
+ case AO_HEX_RECORD_NORMAL:
+ addr = extended_addr + record->address;
+ r_bound = addr + record->length;
+ if (addr < base)
+ base = addr;
+ if (r_bound > bound)
+ bound = r_bound;
+ break;
+ case AO_HEX_RECORD_EOF:
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_4:
+ if (record->length != 2)
+ return NULL;
+ extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_8:
+ if (record->length != 2)
+ return NULL;
+ extended_addr = (record->data[0] << 24) | (record->data[1] << 16);
+ break;
+ case AO_HEX_RECORD_SYMBOL:
+ break;
+ }
+ }
+ length = bound - base;
+ image = calloc(sizeof(struct ao_hex_image) + length, 1);
+ if (!image)
+ return NULL;
+ image->address = base;
+ image->length = length;
+ memset(image->data, 0xff, length);
+ extended_addr = 0;
+ for (i = 0; i < hex->nrecord; i++) {
+ record = hex->records[i];
+ switch (record->type) {
+ case AO_HEX_RECORD_NORMAL:
+ addr = extended_addr + record->address;
+ offset = addr - base;
+ memcpy(image->data + offset, record->data, record->length);
+ break;
+ case AO_HEX_RECORD_EOF:
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_4:
+ extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_8:
+ extended_addr = (record->data[0] << 24) | (record->data[1] << 16);
+ break;
+ case AO_HEX_RECORD_SYMBOL:
+ break;
+ }
+ }
+ return image;
+}
+
+void
+ao_hex_image_free(struct ao_hex_image *image)
+{
+ free(image);
+}
+
+int
+ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b)
+{
+ if (a->length != b->length)
+ return 0;
+ if (memcmp(a->data, b->data, a->length) != 0)
+ return 0;
+ return 1;
+}
+
+struct ao_hex_image *
+ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbolsp)
+{
+ FILE *file;
+ struct ao_hex_file *hex_file;
+ struct ao_hex_image *hex_image;
+
+ file = fopen (filename, "r");
+ if (!file)
+ return NULL;
+
+ hex_file = ao_hex_file_read(file, filename);
+ fclose(file);
+ if (!hex_file)
+ return NULL;
+ hex_image = ao_hex_image_create(hex_file);
+ if (!hex_image)
+ return NULL;
+
+ if (symbols)
+ *symbols = load_symbols(hex_file, num_symbolsp);
+
+ ao_hex_file_free(hex_file);
+ return hex_image;
+}
+
+#define BYTES_PER_RECORD 32
+
+static struct ao_hex_file *
+ao_hex_file_create(struct ao_hex_image *image, struct ao_sym *symbols, int num_symbols)
+{
+ /* split data into n-byte-sized chunks */
+ uint32_t data_records = (image->length + BYTES_PER_RECORD-1) / BYTES_PER_RECORD;
+ /* extended address and data for each block, EOF, address and data for each symbol */
+ uint32_t total_records = data_records * 2 + 1 + num_symbols * 2;
+ uint32_t offset;
+ uint32_t address;
+ uint32_t length;
+ char *name;
+ struct ao_hex_file *hex_file;
+ int nrecord = 0;
+ int s;
+ struct ao_hex_record *record;
+
+ hex_file = calloc(sizeof (struct ao_hex_file) + sizeof (struct ao_hex_record *) * total_records, 1);
+ if (!hex_file)
+ return NULL;
+
+ /* Add the data
+ */
+ for (offset = 0; offset < image->length; offset += BYTES_PER_RECORD) {
+ uint32_t address = image->address + offset;
+ uint32_t length = image->length - offset;
+
+ if (length > BYTES_PER_RECORD)
+ length = BYTES_PER_RECORD;
+
+ record = calloc(sizeof (struct ao_hex_record) + 2, 1);
+ record->type = AO_HEX_RECORD_EXTENDED_ADDRESS_8;
+ record->address = 0;
+ record->length = 2;
+ record->data[0] = address >> 24;
+ record->data[1] = address >> 16;
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+
+ record = calloc(sizeof (struct ao_hex_record) + length, 1);
+ record->type = AO_HEX_RECORD_NORMAL;
+ record->address = address;
+ record->length = length;
+ memcpy(record->data, image->data + offset, length);
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+ }
+
+ /* Stick an EOF after the data
+ */
+ record = calloc(sizeof (struct ao_hex_record), 1);
+ record->type = AO_HEX_RECORD_EOF;
+ record->address = 0;
+ record->length = 0;
+ record->data[0] = 0;
+ record->data[1] = 0;
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+
+ /* Add the symbols
+ */
+
+ for (s = 0; s < num_symbols; s++) {
+
+ name = symbols[s].name;
+ address = symbols[s].addr;
+ length = strlen (name);
+
+ record = calloc(sizeof (struct ao_hex_record) + 2, 1);
+ record->type = AO_HEX_RECORD_EXTENDED_ADDRESS_8;
+ record->address = 0;
+ record->length = 2;
+ record->data[0] = address >> 24;
+ record->data[1] = address >> 16;
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+
+ record = calloc(sizeof (struct ao_hex_record) + length, 1);
+ record->type = AO_HEX_RECORD_SYMBOL;
+ record->address = address;
+ record->length = length;
+ memcpy(record->data, name, length);
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+ }
+
+ hex_file->nrecord = nrecord;
+ return hex_file;
+}
+
+static bool
+ao_hex_write_record(FILE *file, struct ao_hex_record *record)
+{
+ int i;
+
+ fputc(':', file);
+ fprintf(file, "%02x", record->length);
+ fprintf(file, "%04x", record->address);
+ fprintf(file, "%02x", record->type);
+ for (i = 0; i < record->length; i++)
+ fprintf(file, "%02x", record->data[i]);
+ fprintf(file, "%02x", record->checksum);
+ fputc('\n', file);
+ return true;
+}
+
+bool
+ao_hex_save(FILE *file, struct ao_hex_image *image,
+ struct ao_sym *symbols, int num_symbols)
+{
+ struct ao_hex_file *hex_file;
+ int i;
+ bool ret = false;
+
+ hex_file = ao_hex_file_create(image, symbols, num_symbols);
+ if (!hex_file)
+ goto create_failed;
+
+ for (i = 0; i < hex_file->nrecord; i++) {
+ if (!ao_hex_write_record(file, hex_file->records[i]))
+ goto write_failed;
+ }
+ ret = true;
+
+ if (fflush(file) != 0)
+ ret = false;
+write_failed:
+ ao_hex_file_free(hex_file);
+create_failed:
+ return ret;
+}
diff --git a/ao-tools/lib/ao-hex.h b/ao-tools/lib/ao-hex.h
new file mode 100644
index 00000000..98497460
--- /dev/null
+++ b/ao-tools/lib/ao-hex.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_HEX_H_
+#define _AO_HEX_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#define AO_HEX_RECORD_NORMAL 0x00
+#define AO_HEX_RECORD_EOF 0x01
+#define AO_HEX_RECORD_EXTENDED_ADDRESS_4 0x02
+#define AO_HEX_RECORD_EXTENDED_ADDRESS_8 0x04
+#define AO_HEX_RECORD_SYMBOL 0xfe
+
+/* Intel hex file format data
+ */
+struct ao_hex_record {
+ uint8_t length;
+ uint16_t address;
+ uint8_t type;
+ uint8_t checksum;
+ uint8_t data[0];
+};
+
+struct ao_hex_file {
+ int nrecord;
+ struct ao_hex_record *records[0];
+};
+
+struct ao_hex_image {
+ uint32_t address;
+ uint32_t length;
+ uint8_t data[0];
+};
+
+struct ao_sym {
+ unsigned addr;
+ unsigned default_addr;
+ char *name;
+ bool required;
+ bool found;
+};
+
+struct ao_hex_file *
+ao_hex_file_read(FILE *file, char *name);
+
+void
+ao_hex_file_free(struct ao_hex_file *hex);
+
+struct ao_hex_image *
+ao_hex_image_create(struct ao_hex_file *hex);
+
+void
+ao_hex_image_free(struct ao_hex_image *image);
+
+struct ao_hex_image *
+ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols);
+
+int
+ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b);
+
+bool
+ao_hex_save(FILE *file, struct ao_hex_image *image,
+ struct ao_sym *symbols, int num_symbols);
+
+#endif /* _AO_HEX_H_ */
diff --git a/ao-tools/ao-stmload/ao-selfload.c b/ao-tools/lib/ao-selfload.c
index 95667dca..41e45adc 100644
--- a/ao-tools/ao-stmload/ao-selfload.c
+++ b/ao-tools/lib/ao-selfload.c
@@ -21,16 +21,13 @@
#include <sysexits.h>
#include <unistd.h>
#include <string.h>
-#include "cc.h"
-#include "cc-usb.h"
-#include "ccdbg.h"
-#include "ao-stmload.h"
+#include "ao-hex.h"
+#include "ao-selfload.h"
+#include "ao-verbose.h"
-int ao_self_verbose;
+#define TRACE(...) ao_printf(AO_VERBOSE_SELF, __VA_ARGS__)
-#define TRACE(...) if (ao_self_verbose) printf (__VA_ARGS__)
-
-void
+static void
ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256])
{
int byte;
@@ -47,7 +44,7 @@ ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256])
}
}
-void
+static void
ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256])
{
int byte;
@@ -64,16 +61,16 @@ ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256])
}
}
-struct hex_image *
+struct ao_hex_image *
ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length)
{
- struct hex_image *image;
+ struct ao_hex_image *image;
int pages;
int page;
uint32_t base = address & ~0xff;
uint32_t bound = (address + length + 0xff) & ~0xff;
- image = calloc(sizeof (struct hex_image) + (bound - base), 1);
+ image = calloc(sizeof (struct ao_hex_image) + (bound - base), 1);
image->address = base;
image->length = bound - base;
pages = image->length / 0x100;
@@ -82,8 +79,8 @@ ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length)
return image;
}
-int
-ao_self_write(struct cc_usb *cc, struct hex_image *image)
+bool
+ao_self_write(struct cc_usb *cc, struct ao_hex_image *image)
{
uint8_t block[256];
uint8_t check[256];
@@ -125,3 +122,37 @@ ao_self_write(struct cc_usb *cc, struct hex_image *image)
cc_usb_printf(cc,"a\n");
return 1;
}
+
+/*
+ * Read a 16-bit value from the USB target
+ */
+
+uint16_t
+ao_self_get_uint16(struct cc_usb *cc, uint32_t addr)
+{
+ struct ao_hex_image *hex = ao_self_read(cc, addr, 2);
+ uint16_t v;
+ uint8_t *data;
+
+ if (!hex)
+ return 0;
+ data = hex->data + addr - hex->address;
+ v = data[0] | (data[1] << 8);
+ free(hex);
+ return v;
+}
+
+uint32_t
+ao_self_get_uint32(struct cc_usb *cc, uint32_t addr)
+{
+ struct ao_hex_image *hex = ao_self_read(cc, addr, 4);
+ uint32_t v;
+ uint8_t *data;
+
+ if (!hex)
+ return 0;
+ data = hex->data + addr - hex->address;
+ v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+ free(hex);
+ return v;
+}
diff --git a/ao-tools/lib/ao-selfload.h b/ao-tools/lib/ao-selfload.h
new file mode 100644
index 00000000..a001a404
--- /dev/null
+++ b/ao-tools/lib/ao-selfload.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_SELFLOAD_H_
+#define _AO_SELFLOAD_H_
+
+#include <stdbool.h>
+#include "ao-hex.h"
+#include "cc-usb.h"
+
+struct ao_hex_image *
+ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length);
+
+bool
+ao_self_write(struct cc_usb *cc, struct ao_hex_image *image);
+
+uint16_t
+ao_self_get_uint16(struct cc_usb *cc, uint32_t addr);
+
+uint32_t
+ao_self_get_uint32(struct cc_usb *cc, uint32_t addr);
+
+#endif /* _AO_SELFLOAD_H_ */
diff --git a/ao-tools/lib/ao-verbose.c b/ao-tools/lib/ao-verbose.c
new file mode 100644
index 00000000..a1678ed1
--- /dev/null
+++ b/ao-tools/lib/ao-verbose.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao-verbose.h"
+#include <stdio.h>
+
+uint32_t ao_verbose;
+
+void
+ao_printf(uint32_t verbose, const char *format, ...)
+{
+ va_list args;
+
+ if (!(ao_verbose & verbose))
+ return;
+
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+}
+
+
diff --git a/ao-tools/lib/ao-verbose.h b/ao-tools/lib/ao-verbose.h
new file mode 100644
index 00000000..26c2fe41
--- /dev/null
+++ b/ao-tools/lib/ao-verbose.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_VERBOSE_H_
+#define _AO_VERBOSE_H_
+
+#include <stdint.h>
+#include <stdarg.h>
+
+uint32_t ao_verbose;
+
+#define AO_VERBOSE_EXE 1
+#define AO_VERBOSE_SELF 2
+
+void
+ao_printf(uint32_t verbose, const char *format, ...);
+
+#endif /* _AO_VERBOSE_H_ */
diff --git a/ao-tools/lib/cc-mega.c b/ao-tools/lib/cc-mega.c
new file mode 100644
index 00000000..3aa24a6d
--- /dev/null
+++ b/ao-tools/lib/cc-mega.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "cc.h"
+#include <string.h>
+#include <ctype.h>
+
+static const char *
+parse_hex(const char *data, int *result)
+{
+ char d[12];
+ int x;
+ int i;
+
+ while (isspace (*data))
+ data++;
+ for (i = 0; i < sizeof (d) - 1 && isxdigit(*data); i++)
+ d[i] = *data++;
+ d[i] = '\0';
+ if (sscanf(d, "%x", &x) != 1)
+ return NULL;
+ *result = x;
+ return data;
+}
+
+static const char *
+parse_uint16(const char *data, uint16_t *result)
+{
+ int x;
+ data = parse_hex(data, &x);
+ *result =x;
+ return data;
+}
+
+static const char *
+parse_uint8(const char *data, uint8_t *result)
+{
+ int x;
+ data = parse_hex(data, &x);
+ *result =x;
+ return data;
+}
+
+static int
+parse_eeprom(const char *input_line, struct ao_log_mega *l) {
+ const char *line;
+ int b;
+
+ if (input_line[1] != ' ')
+ return 0;
+ if (!isupper(input_line[0]))
+ return 0;
+
+ l->type = input_line[0];
+ l->is_config = 0;
+ line = input_line + 2;
+
+ line = parse_uint16(line, &l->tick);
+ for (b = 0; b < 28; b++) {
+ if (!line)
+ return 0;
+ line = parse_uint8(line, &l->u.bytes[b]);
+ }
+ return 1;
+}
+
+#define YUP(t) do { \
+ l->u.config_int.kind = (t); \
+ l->is_config = 1; \
+ return 1; \
+ } while (0);
+
+static int
+parse_config(const char *input_line, struct ao_log_mega *l) {
+ if (sscanf (input_line, "Config version: %d.%d",
+ &l->u.config_int.data[0],
+ &l->u.config_int.data[1]))
+ YUP(AO_CONFIG_CONFIG);
+ if (sscanf (input_line, "Main deploy: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MAIN);
+ if (sscanf (input_line, "Apogee delay: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_APOGEE);
+ if (sscanf (input_line, "Apogee lockout: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_LOCKOUT);
+ if (sscanf (input_line, "Frequency: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_FREQUENCY);
+ if (sscanf (input_line, "Radio enable: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_RADIO_ENABLE);
+ if (sscanf (input_line, "Accel cal +1g: %d -1g: %d",
+ &l->u.config_int.data[0],
+ &l->u.config_int.data[1]))
+ YUP(AO_CONFIG_ACCEL_CAL);
+ if (sscanf (input_line, "Radio cal: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_RADIO_CAL);
+ if (sscanf (input_line, "Max flight log: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MAX_LOG);
+ if (sscanf (input_line, "Ignite mode: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_IGNITE_MODE);
+ if (sscanf (input_line, "Pad orientation: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_PAD_ORIENTATION);
+ if (sscanf (input_line, "serial-number %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_SERIAL_NUMBER);
+ if (sscanf (input_line, "log-format %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_LOG_FORMAT);
+ if (sscanf (input_line, "ms5607 reserved: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_RESERVED);
+ if (sscanf (input_line, "ms5607 sens: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_SENS);
+ if (sscanf (input_line, "ms5607 off: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_OFF);
+ if (sscanf (input_line, "ms5607 tcs: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_TCS);
+ if (sscanf (input_line, "ms5607 tco: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_TCO);
+ if (sscanf (input_line, "ms5607 tref: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_TREF);
+ if (sscanf (input_line, "ms5607 tempsens: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_TEMPSENS);
+ if (sscanf (input_line, "ms5607 crc: %d",
+ &l->u.config_int.data[0]))
+ YUP(AO_CONFIG_MS5607_CRC);
+ return 0;
+}
+
+int
+cc_mega_parse(const char *input_line, struct ao_log_mega *l) {
+ return parse_eeprom(input_line, l) || parse_config(input_line, l);
+}
diff --git a/ao-tools/lib/cc-telemetry.h b/ao-tools/lib/cc-telemetry.h
index 9a5be49f..c28aceb8 100644
--- a/ao-tools/lib/cc-telemetry.h
+++ b/ao-tools/lib/cc-telemetry.h
@@ -201,6 +201,72 @@ struct ao_telemetry_mega_data {
/* 32 */
};
+#define AO_TELEMETRY_METRUM_SENSOR 0x0A
+
+struct ao_telemetry_metrum_sensor {
+ uint16_t serial; /* 0 */
+ uint16_t tick; /* 2 */
+ uint8_t type; /* 4 */
+
+ uint8_t state; /* 5 flight state */
+ int16_t accel; /* 6 Z axis */
+
+ int32_t pres; /* 8 Pa * 10 */
+ int16_t temp; /* 12 °C * 100 */
+
+ int16_t acceleration; /* 14 m/s² * 16 */
+ int16_t speed; /* 16 m/s * 16 */
+ int16_t height; /* 18 m */
+
+ int16_t v_batt; /* 20 battery voltage */
+ int16_t sense_a; /* 22 apogee continuity sense */
+ int16_t sense_m; /* 24 main continuity sense */
+
+ uint8_t pad[6]; /* 26 */
+ /* 32 */
+};
+
+#define AO_TELEMETRY_METRUM_DATA 0x0B
+
+struct ao_telemetry_metrum_data {
+ uint16_t serial; /* 0 */
+ uint16_t tick; /* 2 */
+ uint8_t type; /* 4 */
+
+ int32_t ground_pres; /* 8 average pres on pad */
+ int16_t ground_accel; /* 12 average accel on pad */
+ int16_t accel_plus_g; /* 14 accel calibration at +1g */
+ int16_t accel_minus_g; /* 16 accel calibration at -1g */
+
+ uint8_t pad[14]; /* 18 */
+ /* 32 */
+};
+
+#define AO_TELEMETRY_MINI 0x10
+
+struct ao_telemetry_mini {
+ uint16_t serial; /* 0 */
+ uint16_t tick; /* 2 */
+ uint8_t type; /* 4 */
+
+ uint8_t state; /* 5 flight state */
+ int16_t v_batt; /* 6 battery voltage */
+ int16_t sense_a; /* 8 apogee continuity */
+ int16_t sense_m; /* 10 main continuity */
+
+ int32_t pres; /* 12 Pa * 10 */
+ int16_t temp; /* 16 °C * 100 */
+
+ int16_t acceleration; /* 18 m/s² * 16 */
+ int16_t speed; /* 20 m/s * 16 */
+ int16_t height; /* 22 m */
+
+ int32_t ground_pres; /* 24 average pres on pad */
+
+ int32_t pad28; /* 28 */
+ /* 32 */
+};
+
/* #define AO_SEND_ALL_BARO */
#define AO_TELEMETRY_BARO 0x80
@@ -234,6 +300,9 @@ union ao_telemetry_all {
struct ao_telemetry_companion companion;
struct ao_telemetry_mega_sensor mega_sensor;
struct ao_telemetry_mega_data mega_data;
+ struct ao_telemetry_metrum_sensor metrum_sensor;
+ struct ao_telemetry_metrum_data metrum_data;
+ struct ao_telemetry_mini mini;
struct ao_telemetry_baro baro;
};
diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h
index 625540bb..c07f8cd0 100644
--- a/ao-tools/lib/cc.h
+++ b/ao-tools/lib/cc.h
@@ -306,7 +306,8 @@ struct ao_log_mega {
int16_t v_pbatt; /* 6 */
int16_t n_sense; /* 8 */
int16_t sense[10]; /* 10 */
- } volt; /* 30 */
+ uint16_t pyro; /* 30 */
+ } volt; /* 32 */
/* AO_LOG_GPS_TIME */
struct {
int32_t latitude; /* 4 */
diff --git a/ao-tools/lib/ccdbg-command.c b/ao-tools/lib/ccdbg-command.c
index a1002879..55c912b2 100644
--- a/ao-tools/lib/ccdbg-command.c
+++ b/ao-tools/lib/ccdbg-command.c
@@ -157,7 +157,7 @@ ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc)
}
uint8_t
-ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image)
+ccdbg_execute_hex_image(struct ccdbg *dbg, struct ao_hex_image *image)
{
uint16_t pc;
uint8_t status;
diff --git a/ao-tools/lib/ccdbg-flash.c b/ao-tools/lib/ccdbg-flash.c
index 1b46870b..44eb952b 100644
--- a/ao-tools/lib/ccdbg-flash.c
+++ b/ao-tools/lib/ccdbg-flash.c
@@ -238,7 +238,7 @@ ccdbg_flash_lock(struct ccdbg *dbg, uint8_t lock)
#endif
uint8_t
-ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
+ccdbg_flash_hex_image(struct ccdbg *dbg, struct ao_hex_image *image)
{
uint16_t flash_prog;
uint16_t flash_len;
diff --git a/ao-tools/lib/ccdbg-hex.c b/ao-tools/lib/ccdbg-hex.c
deleted file mode 100644
index 184b4e3b..00000000
--- a/ao-tools/lib/ccdbg-hex.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright © 2008 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ccdbg.h"
-#include <stdarg.h>
-#include <ctype.h>
-
-struct hex_input {
- FILE *file;
- int line;
- char *name;
-};
-
-enum hex_read_state {
- read_marker,
- read_length,
- read_address,
- read_type,
- read_data,
- read_checksum,
- read_newline,
- read_white,
- read_done,
-};
-
-
-static void
-ccdbg_hex_error(struct hex_input *input, char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- fprintf(stderr, "Hex error %s:%d: ", input->name, input->line);
- vfprintf(stderr, format, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-static void
-ccdbg_hex_free(struct hex_record *record)
-{
- if (!record) return;
- free(record);
-}
-
-static struct hex_record *
-ccdbg_hex_alloc(uint8_t length)
-{
- struct hex_record *record;
-
- record = calloc(1, sizeof(struct hex_record) + length);
- record->length = length;
- return record;
-}
-
-static int
-ishex(char c)
-{
- return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
-}
-
-static int
-fromhex(char c)
-{
- if (isdigit(c))
- return c - '0';
- if ('a' <= c && c <= 'f')
- return c - 'a' + 10;
- if ('A' <= c && c <= 'F')
- return c - 'A' + 10;
- abort();
- return 0;
-}
-
-static uint8_t
-ccdbg_hex_checksum(struct hex_record *record)
-{
- uint8_t checksum = 0;
- int i;
-
- checksum += record->length;
- checksum += record->address >> 8;
- checksum += record->address & 0xff;
- checksum += record->type;
- for (i = 0; i < record->length; i++)
- checksum += record->data[i];
- return -checksum;
-}
-
-static struct hex_record *
-ccdbg_hex_read_record(struct hex_input *input)
-{
- struct hex_record *record = NULL;
- enum hex_read_state state = read_marker;
- char c;
- int nhexbytes;
- uint32_t hex;
- uint32_t ndata;
- uint8_t checksum;
-
- while (state != read_done) {
- c = getc(input->file);
- if (c == EOF && state != read_white) {
- ccdbg_hex_error(input, "Unexpected EOF");
- goto bail;
- }
- if (c == ' ')
- continue;
- if (c == '\n')
- input->line++;
- switch (state) {
- case read_marker:
- if (c != ':') {
- ccdbg_hex_error(input, "Missing ':'");
- goto bail;
- }
- state = read_length;
- nhexbytes = 2;
- hex = 0;
- break;
- case read_length:
- case read_address:
- case read_type:
- case read_data:
- case read_checksum:
- if (!ishex(c)) {
- ccdbg_hex_error(input, "Non-hex char '%c'",
- c);
- goto bail;
- }
- hex = hex << 4 | fromhex(c);
- --nhexbytes;
- if (nhexbytes != 0)
- break;
-
- switch (state) {
- case read_length:
- record = ccdbg_hex_alloc(hex);
- if (!record) {
- ccdbg_hex_error(input, "Out of memory");
- goto bail;
- }
- state = read_address;
- nhexbytes = 4;
- break;
- case read_address:
- record->address = hex;
- state = read_type;
- nhexbytes = 2;
- break;
- case read_type:
- record->type = hex;
- state = read_data;
- nhexbytes = 2;
- ndata = 0;
- break;
- case read_data:
- record->data[ndata] = hex;
- ndata++;
- nhexbytes = 2;
- break;
- case read_checksum:
- record->checksum = hex;
- state = read_newline;
- break;
- default:
- break;
- }
- if (state == read_data)
- if (ndata == record->length) {
- nhexbytes = 2;
- state = read_checksum;
- }
- hex = 0;
- break;
- case read_newline:
- if (c != '\n' && c != '\r') {
- ccdbg_hex_error(input, "Missing newline");
- goto bail;
- }
- state = read_white;
- break;
- case read_white:
- if (!isspace(c)) {
- if (c == '\n')
- input->line--;
- if (c != EOF)
- ungetc(c, input->file);
- state = read_done;
- }
- break;
- case read_done:
- break;
- }
- }
- checksum = ccdbg_hex_checksum(record);
- if (checksum != record->checksum) {
- ccdbg_hex_error(input, "Invalid checksum (read 0x%02x computed 0x%02x)\n",
- record->checksum, checksum);
- goto bail;
- }
- return record;
-
-bail:
- ccdbg_hex_free(record);
- return NULL;
-}
-
-void
-ccdbg_hex_file_free(struct hex_file *hex)
-{
- int i;
-
- if (!hex)
- return;
- for (i = 0; i < hex->nrecord; i++)
- ccdbg_hex_free(hex->records[i]);
- free(hex);
-}
-
-struct hex_file *
-ccdbg_hex_file_read(FILE *file, char *name)
-{
- struct hex_input input;
- struct hex_file *hex = NULL, *newhex;
- struct hex_record *record;
- int srecord = 1;
- int done = 0;
-
- hex = calloc(sizeof (struct hex_file) + sizeof (struct hex_record *), 1);
- input.name = name;
- input.line = 1;
- input.file = file;
- while (!done) {
- record = ccdbg_hex_read_record(&input);
- if (!record)
- goto bail;
- if (hex->nrecord == srecord) {
- srecord *= 2;
- newhex = realloc(hex,
- sizeof (struct hex_file) +
- srecord * sizeof (struct hex_record *));
- if (!newhex)
- goto bail;
- hex = newhex;
- }
- hex->records[hex->nrecord++] = record;
- if (record->type == HEX_RECORD_EOF)
- done = 1;
- }
- return hex;
-
-bail:
- ccdbg_hex_file_free(hex);
- return NULL;
-}
-
-struct hex_image *
-ccdbg_hex_image_create(struct hex_file *hex)
-{
- struct hex_image *image;
- struct hex_record *record;
- int i;
- uint32_t addr;
- uint32_t base, bound;
- uint32_t offset;
- uint32_t extended_addr;
-
- int length;
-
- base = 0xffffffff;
- bound = 0x0;
- extended_addr = 0;
- for (i = 0; i < hex->nrecord; i++) {
- uint32_t r_bound;
- record = hex->records[i];
- switch (record->type) {
- case 0:
- addr = extended_addr + record->address;
- r_bound = addr + record->length;
- if (addr < base)
- base = addr;
- if (r_bound > bound)
- bound = r_bound;
- break;
- case 1:
- break;
- case 2:
- if (record->length != 2)
- return NULL;
- extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
- break;
- case 4:
- if (record->length != 2)
- return NULL;
- extended_addr = ((record->data[0] << 8) | record->data[1]) << 16;
- break;
- }
-
- }
- length = bound - base;
- image = calloc(sizeof(struct hex_image) + length, 1);
- if (!image)
- return NULL;
- image->address = base;
- image->length = length;
- memset(image->data, 0xff, length);
- extended_addr = 0;
- for (i = 0; i < hex->nrecord; i++) {
- record = hex->records[i];
- switch (record->type) {
- case 0:
- addr = extended_addr + record->address;
- offset = addr - base;
- memcpy(image->data + offset, record->data, record->length);
- break;
- case 1:
- break;
- case 2:
- extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
- break;
- case 4:
- extended_addr = ((record->data[0] << 8) | record->data[1]) << 16;
- break;
- }
- }
- return image;
-}
-
-void
-ccdbg_hex_image_free(struct hex_image *image)
-{
- free(image);
-}
-
-int
-ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b)
-{
- if (a->length != b->length)
- return 0;
- if (memcmp(a->data, b->data, a->length) != 0)
- return 0;
- return 1;
-}
-
-struct hex_image *
-ccdbg_hex_load(char *filename)
-{
- FILE *file;
- struct hex_file *hex_file;
- struct hex_image *hex_image;
-
- file = fopen (filename, "r");
- if (!file)
- return 0;
-
- hex_file = ccdbg_hex_file_read(file, filename);
- fclose(file);
- if (!hex_file)
- return 0;
- hex_image = ccdbg_hex_image_create(hex_file);
- if (!hex_image)
- return 0;
- ccdbg_hex_file_free(hex_file);
- return hex_image;
-}
diff --git a/ao-tools/lib/ccdbg-memory.c b/ao-tools/lib/ccdbg-memory.c
index 554ac637..04059e2e 100644
--- a/ao-tools/lib/ccdbg-memory.c
+++ b/ao-tools/lib/ccdbg-memory.c
@@ -117,18 +117,18 @@ ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte)
}
uint8_t
-ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset)
+ccdbg_write_hex_image(struct ccdbg *dbg, struct ao_hex_image *image, uint16_t offset)
{
ccdbg_write_memory(dbg, image->address + offset, image->data, image->length);
return 0;
}
-struct hex_image *
+struct ao_hex_image *
ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length)
{
- struct hex_image *image;
+ struct ao_hex_image *image;
- image = calloc(sizeof(struct hex_image) + length, 1);
+ image = calloc(sizeof(struct ao_hex_image) + length, 1);
image->address = address;
image->length = length;
memset(image->data, 0xff, length);
diff --git a/ao-tools/lib/ccdbg-rom.c b/ao-tools/lib/ccdbg-rom.c
index 71bed220..6e8e7378 100644
--- a/ao-tools/lib/ccdbg-rom.c
+++ b/ao-tools/lib/ccdbg-rom.c
@@ -19,10 +19,10 @@
#include "ccdbg.h"
uint8_t
-ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom)
+ccdbg_set_rom(struct ccdbg *dbg, struct ao_hex_image *rom)
{
if (dbg->rom)
- ccdbg_hex_image_free(dbg->rom);
+ ao_hex_image_free(dbg->rom);
dbg->rom = rom;
return 0;
}
@@ -30,7 +30,7 @@ ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom)
uint8_t
ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes)
{
- struct hex_image *rom = dbg->rom;
+ struct ao_hex_image *rom = dbg->rom;
if (!rom)
return 0;
if (addr < rom->address || rom->address + rom->length < addr + nbytes)
@@ -42,7 +42,7 @@ uint8_t
ccdbg_rom_replace_xmem(struct ccdbg *dbg,
uint16_t addr, uint8_t *bytes, int nbytes)
{
- struct hex_image *rom = dbg->rom;
+ struct ao_hex_image *rom = dbg->rom;
if (!rom)
return 0;
diff --git a/ao-tools/lib/ccdbg.h b/ao-tools/lib/ccdbg.h
index a27ff5d1..b17f289d 100644
--- a/ao-tools/lib/ccdbg.h
+++ b/ao-tools/lib/ccdbg.h
@@ -33,6 +33,7 @@
#include "ccdbg-debug.h"
#include "cc-bitbang.h"
#include "cc-usb.h"
+#include "ao-hex.h"
/* 8051 instructions
*/
@@ -103,29 +104,9 @@
struct ccdbg {
struct cc_bitbang *bb;
struct cc_usb *usb;
- struct hex_image *rom;
+ struct ao_hex_image *rom;
};
-/* Intel hex file format data
- */
-struct hex_record {
- uint8_t length;
- uint16_t address;
- uint8_t type;
- uint8_t checksum;
- uint8_t data[0];
-};
-
-struct hex_file {
- int nrecord;
- struct hex_record *records[0];
-};
-
-struct hex_image {
- uint32_t address;
- uint32_t length;
- uint8_t data[0];
-};
#define CC_STATE_ACC 0x1
#define CC_STATE_PSW 0x2
@@ -139,10 +120,6 @@ struct ccstate {
uint8_t sfr[CC_STATE_NSFR];
};
-#define HEX_RECORD_NORMAL 0x00
-#define HEX_RECORD_EOF 0x01
-#define HEX_RECORD_EXTENDED_ADDRESS 0x02
-
/* CC1111 debug port commands
*/
#define CC_CHIP_ERASE 0x14
@@ -234,30 +211,11 @@ uint8_t
ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc);
uint8_t
-ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image);
+ccdbg_execute_hex_image(struct ccdbg *dbg, struct ao_hex_image *image);
/* ccdbg-flash.c */
uint8_t
-ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image);
-
-/* ccdbg-hex.c */
-struct hex_file *
-ccdbg_hex_file_read(FILE *file, char *name);
-
-void
-ccdbg_hex_file_free(struct hex_file *hex);
-
-struct hex_image *
-ccdbg_hex_image_create(struct hex_file *hex);
-
-void
-ccdbg_hex_image_free(struct hex_image *image);
-
-struct hex_image *
-ccdbg_hex_load(char *filename);
-
-int
-ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b);
+ccdbg_flash_hex_image(struct ccdbg *dbg, struct ao_hex_image *image);
/* ccdbg-io.c */
struct ccdbg *
@@ -304,9 +262,9 @@ uint8_t
ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte);
uint8_t
-ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset);
+ccdbg_write_hex_image(struct ccdbg *dbg, struct ao_hex_image *image, uint16_t offset);
-struct hex_image *
+struct ao_hex_image *
ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length);
uint8_t
@@ -317,7 +275,7 @@ ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes);
/* ccdbg-rom.c */
uint8_t
-ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom);
+ccdbg_set_rom(struct ccdbg *dbg, struct ao_hex_image *rom);
uint8_t
ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes);