Initial Commit - Copy from Altus Metrum AltOS

This commit is contained in:
2024-06-25 19:03:04 +02:00
commit 13fc49c923
2048 changed files with 1206748 additions and 0 deletions

1
ao-tools/ao-stmload/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
ao-stmload

View File

@@ -0,0 +1,16 @@
if LIBSTLINK
bin_PROGRAMS=ao-stmload
AM_CFLAGS=$(WARN_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) $(STLINK_LIBS) $(LIBUSB_LIBS) -lelf
ao_stmload_SOURCES=ao-stmload.c ao-stmload.h
man_MANS = ao-stmload.1
endif

View File

@@ -0,0 +1,61 @@
.\"
.\" 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-stmload" ""
.SH NAME
ao-stmload \- flash a program to an STM32-based AltOS device
.SH SYNOPSIS
.B "ao-stmload"
[\-D \fI/dev/sgX\fP]
[\--device \fI/dev/sgX\fP]
[\--cal \fIradio-calibration\fP]
[\--serial \fserial-number\fP]
\fIfile.elf\fP
.SH DESCRIPTION
.I ao-stmload
loads the specified .elf file into the target device flash memory,
using either existing serial number and radio calibration values or
taking either of those from the command line.
.SH OPTIONS
.TP
\-D /dev/sgX | --device /dev/sgX
This targets an STlinkV1 connection rather than STlinkV2
.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-stmload
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

View File

@@ -0,0 +1,338 @@
/*
* 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; 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 <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 "stlink-common.h"
#include "ao-elf.h"
#include "ccdbg.h"
#include "cc.h"
#include "ao-stmload.h"
#include "ao-selfload.h"
#include "ao-verbose.h"
#include "ao-editaltos.h"
/*
* Read a 16-bit value from the target device with arbitrary
* alignment
*/
static uint16_t
get_uint16_sl(stlink_t *sl, uint32_t addr)
{
const uint8_t *data = sl->q_buf;
uint32_t actual_addr;
int off;
uint16_t result;
sl->q_len = 0;
actual_addr = addr & ~3;
stlink_read_mem32(sl, actual_addr, 8);
if (sl->q_len != 8)
abort();
off = addr & 3;
result = data[off] | (data[off + 1] << 8);
return result;
}
static uint16_t
get_uint16(stlink_t *sl, uint32_t addr)
{
uint16_t result;
result = get_uint16_sl(sl, 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_sl(stlink_t *sl, uint32_t addr)
{
const uint8_t *data = sl->q_buf;
uint32_t actual_addr;
int off;
uint32_t result;
sl->q_len = 0;
printf ("read 0x%x\n", addr);
actual_addr = addr & ~3;
stlink_read_mem32(sl, actual_addr, 8);
if (sl->q_len != 8)
abort();
off = addr & 3;
result = data[off] | (data[off + 1] << 8) | (data[off+2] << 16) | (data[off+3] << 24);
return result;
}
/*
* Read a 32-bit value from the target device with arbitrary
* alignment
*/
static uint32_t
get_uint32(stlink_t *sl, uint32_t addr)
{
uint32_t result;
result = get_uint32_sl(sl, 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(stlink_t *sl)
{
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");
return 0;
}
return 1;
}
static const struct option options[] = {
{ .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 = 1, .val = 'v' },
{ 0, 0, 0, 0},
};
static void usage(char *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, int code)
{
stlink_reset(sl);
stlink_run(sl);
stlink_exit_debug_mode(sl);
stlink_close(sl);
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)
{
int stlink_v1 = 0;
int raw = 0;
char *filename;
Elf *e;
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;
stlink_t *sl = NULL;
int was_flashed = 0;
struct ao_hex_image *load;
int tries;
int success;
int verbose = 0;
struct ao_sym *file_symbols;
int num_file_symbols;
while ((c = getopt_long(argc, argv, "1rc:s:v:", options, NULL)) != -1) {
switch (c) {
case '1':
stlink_v1 = 1;
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]);
}
}
/* Connect to the programming dongle
*/
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, 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);
}
/* 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);
}
/* 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);
if (!raw) {
/* Go fetch existing config values
* if available
*/
was_flashed = check_flashed(sl);
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);
}
}
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 (!ao_editaltos(load, serial, cal))
done(sl, 1);
}
/* And flash the resulting image to the device
*/
success = (stlink_write_flash(sl, load->address, load->data, load->length) >= 0);
if (!success) {
fprintf (stderr, "\"%s\": Write failed\n", filename);
done(sl, 1);
}
done(sl, 0);
}

View File

@@ -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; 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.
*/
#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_ */