diff options
Diffstat (limited to 'ao-tools/lib')
-rw-r--r-- | ao-tools/lib/Makefile.am | 14 | ||||
-rw-r--r-- | ao-tools/lib/ao-editaltos.c | 153 | ||||
-rw-r--r-- | ao-tools/lib/ao-editaltos.h | 50 | ||||
-rw-r--r-- | ao-tools/lib/ao-elf.c | 325 | ||||
-rw-r--r-- | ao-tools/lib/ao-elf.h | 28 | ||||
-rw-r--r-- | ao-tools/lib/ao-hex.c | 626 | ||||
-rw-r--r-- | ao-tools/lib/ao-hex.h | 82 | ||||
-rw-r--r-- | ao-tools/lib/ao-selfload.c | 158 | ||||
-rw-r--r-- | ao-tools/lib/ao-selfload.h | 37 | ||||
-rw-r--r-- | ao-tools/lib/ao-verbose.c | 36 | ||||
-rw-r--r-- | ao-tools/lib/ao-verbose.h | 32 | ||||
-rw-r--r-- | ao-tools/lib/cc-mega.c | 160 | ||||
-rw-r--r-- | ao-tools/lib/cc-telemetry.h | 69 | ||||
-rw-r--r-- | ao-tools/lib/cc.h | 3 | ||||
-rw-r--r-- | ao-tools/lib/ccdbg-command.c | 2 | ||||
-rw-r--r-- | ao-tools/lib/ccdbg-flash.c | 2 | ||||
-rw-r--r-- | ao-tools/lib/ccdbg-hex.c | 381 | ||||
-rw-r--r-- | ao-tools/lib/ccdbg-memory.c | 8 | ||||
-rw-r--r-- | ao-tools/lib/ccdbg-rom.c | 8 | ||||
-rw-r--r-- | ao-tools/lib/ccdbg.h | 56 |
20 files changed, 1787 insertions, 443 deletions
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/lib/ao-elf.c b/ao-tools/lib/ao-elf.c new file mode 100644 index 00000000..99b37210 --- /dev/null +++ b/ao-tools/lib/ao-elf.c @@ -0,0 +1,325 @@ +/* + * 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 <err.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdbool.h> +#include <unistd.h> +#include <string.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 symbols that can be adjusted before + * the image is written to the device + */ +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; + char *symbol_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 false; + + /* + * Find the symbols + */ + + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + + if (gelf_getshdr(scn, &shdr) != &shdr) + return false; + + if (shdr.sh_type == SHT_SYMTAB) { + symbol_data = elf_getdata(scn, NULL); + symbol_count = shdr.sh_size / shdr.sh_entsize; + break; + } + } + + if (!symbol_data) + 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; + + 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 = 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; +} + +static uint32_t +round4(uint32_t a) { + return (a + 3) & ~3; +} + +static struct ao_hex_image * +new_load (uint32_t addr, uint32_t len) +{ + struct ao_hex_image *new; + + len = round4(len); + new = calloc (1, sizeof (struct ao_hex_image) + len); + if (!new) + abort(); + + new->address = addr; + new->length = len; + return new; +} + +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(); + + memcpy(into->data + from->address - into->address, from->data, from->length); +} + +/* + * Make a new load structure large enough to hold the old one and + * the new data + */ +static struct ao_hex_image * +expand_load(struct ao_hex_image *from, uint32_t address, uint32_t length) +{ + struct ao_hex_image *new; + + if (from) { + uint32_t from_last = from->address + from->length; + uint32_t last = address + length; + + if (address > from->address) + address = from->address; + if (last < from_last) + last = from_last; + + length = last - address; + + if (address == from->address && length == from->length) + return from; + } + new = new_load(address, length); + if (from) { + load_paste(new, from); + free (from); + } + return new; +} + +/* + * Create a new load structure with data from the existing one + * and the new data + */ +static struct ao_hex_image * +load_write(struct ao_hex_image *from, uint32_t address, uint32_t length, void *data) +{ + struct ao_hex_image *new; + + new = expand_load(from, address, length); + memcpy(new->data + address - new->address, data, length); + return new; +} + +/* + * Construct a large in-memory block for all + * of the loaded sections of the program + */ +static struct ao_hex_image * +get_load(Elf *e) +{ + Elf_Scn *scn; + size_t shstrndx; + GElf_Shdr shdr; + Elf_Data *data; + size_t nphdr; + size_t p; + GElf_Phdr phdr; + GElf_Addr sh_paddr; + struct ao_hex_image *load = NULL; +#if 0 + char *section_name; +#endif + size_t nshdr; + size_t s; + + if (elf_getshdrstrndx(e, &shstrndx) < 0) + return 0; + + if (elf_getphdrnum(e, &nphdr) < 0) + return 0; + + if (elf_getshdrnum(e, &nshdr) < 0) + return 0; + + /* + * As far as I can tell, all of the phdr sections should + * be flashed to memory + */ + for (p = 0; p < nphdr; p++) { + + /* Find this phdr */ + gelf_getphdr(e, p, &phdr); + + if (phdr.p_type != PT_LOAD) + continue; + + /* Get the associated file section */ + +#if 0 + 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) { + fprintf (stderr, "getscn failed\n"); + abort(); + } + if (gelf_getshdr(scn, &shdr) != &shdr) { + 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) { + + if (shdr.sh_size == 0) + continue; + + sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset; + +#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); + + /* Write the section data into the memory block */ + load = load_write(load, sh_paddr, shdr.sh_size, data->d_buf); + } + } + } + return load; +} + +/* + * Open the specified ELF file and + * check for the symbols we need + */ + +struct ao_hex_image * +ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols) +{ + int fd; + Elf *e; + size_t shstrndx; + struct ao_hex_image *image; + + if (elf_version(EV_CURRENT) == EV_NONE) + return NULL; + + fd = open(name, O_RDONLY, 0); + + if (fd < 0) + return NULL; + + e = elf_begin(fd, ELF_C_READ, NULL); + + if (!e) + return NULL; + + if (elf_kind(e) != ELF_K_ELF) + return NULL; + + if (elf_getshdrstrndx(e, &shstrndx) != 0) + return NULL; + + if (symbols) + *symbols = load_symbols(e, num_symbols); + + image = get_load(e); + if (!image) { + fprintf (stderr, "Cannot create memory image from file\n"); + return NULL; + } + + return image; +} diff --git a/ao-tools/lib/ao-elf.h b/ao-tools/lib/ao-elf.h new file mode 100644 index 00000000..0f79d142 --- /dev/null +++ b/ao-tools/lib/ao-elf.h @@ -0,0 +1,28 @@ +/* + * 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_ELF_H_ +#define _AO_ELF_H_ + +#include <stdbool.h> +#include <gelf.h> +#include "ao-hex.h" + +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/lib/ao-selfload.c b/ao-tools/lib/ao-selfload.c new file mode 100644 index 00000000..41e45adc --- /dev/null +++ b/ao-tools/lib/ao-selfload.c @@ -0,0 +1,158 @@ +/* + * 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 <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <sysexits.h> +#include <unistd.h> +#include <string.h> +#include "ao-hex.h" +#include "ao-selfload.h" +#include "ao-verbose.h" + +#define TRACE(...) ao_printf(AO_VERBOSE_SELF, __VA_ARGS__) + +static void +ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]) +{ + int byte; + cc_usb_sync(cc); + cc_usb_printf(cc, "R %x\n", address); + for (byte = 0; byte < 0x100; byte++) { + block[byte] = cc_usb_getchar(cc); + } + TRACE ("\nread %08x\n", address); + for (byte = 0; byte < 0x100; byte++) { + TRACE (" %02x", block[byte]); + if ((byte & 0xf) == 0xf) + TRACE ("\n"); + } +} + +static void +ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]) +{ + int byte; + cc_usb_sync(cc); + cc_usb_printf(cc, "W %x\n", address); + TRACE ("write %08x\n", address); + for (byte = 0; byte < 0x100; byte++) { + TRACE (" %02x", block[byte]); + if ((byte & 0xf) == 0xf) + TRACE ("\n"); + } + for (byte = 0; byte < 0x100; byte++) { + cc_usb_printf(cc, "%c", block[byte]); + } +} + +struct ao_hex_image * +ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length) +{ + 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 ao_hex_image) + (bound - base), 1); + image->address = base; + image->length = bound - base; + pages = image->length / 0x100; + for (page = 0; page < pages; page++) + ao_self_block_read(cc, image->address + page * 0x100, image->data + page * 0x100); + return image; +} + +bool +ao_self_write(struct cc_usb *cc, struct ao_hex_image *image) +{ + uint8_t block[256]; + uint8_t check[256]; + uint32_t base, bound, length, address; + uint32_t pages; + uint32_t page; + + base = image->address & ~0xff; + bound = (image->address + image->length + 0xff) & ~0xff; + + address = base; + length = bound - base; + + pages = length / 0x100; + printf ("Write %08x %d pages: ", address, length/0x100); fflush(stdout); + for (page = 0; page < pages; page++) { + uint32_t start, stop; + address = base + page * 0x100; + + if (address < image->address || address + 0x100 > image->address + image->length) { + ao_self_block_read(cc, address, block); + } + start = address; + stop = address + 0x100; + if (start < image->address) + start = image->address; + if (stop > image->address + image->length) + stop = image->address + image->length; + memcpy(block + start - address, image->data + start - image->address, stop - start); + ao_self_block_write(cc, address, block); + ao_self_block_read(cc, address, check); + if (memcmp(block, check, 0x100) != 0) { + fprintf(stderr, "Block at 0x%08x doesn't match\n", address); + return 0; + } + putchar('.'); fflush(stdout); + } + printf("done\n"); + 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); |