a6boot: lots more shrinkifying

trunk
alexis 2022-05-02 21:20:55 -06:00
parent b04b193bc8
commit cb79f9f1b3
11 changed files with 84 additions and 68 deletions

View File

@ -28,29 +28,29 @@ SECTIONS {
KEEP(*(.vectors))
*(.start)
KEEP(*(.start))
. = ALIGN(4);
. = ALIGN(2);
} > blflash =0x4E71
.text : {
*(.text .text.*)
. = ALIGN(4);
. = ALIGN(2);
__text_end = .;
*(.rodata .rodata.*)
. = ALIGN(4);
. = ALIGN(2);
} > ram AT> blflash =0x4E71
.data ALIGN(4) : {
.data ALIGN(2) : {
__data_start = .;
*(.data .data.*);
. = ALIGN(4);
. = ALIGN(2);
} > ram AT> blflash
.bss ADDR(.data) + SIZEOF(.data) : AT (ADDR(.bss)) {
__bss_start = .;
*(.bss .bss.*);
*(COMMON)
. = ALIGN(4);
. = ALIGN(2);
} >ram
.stack ADDR(.bss) + SIZEOF(.bss) : AT (ADDR(.stack)) {

View File

@ -16,11 +16,15 @@ static inline void console_68681_init(void)
// do any resets.
// MR1A and MR2A must remain in this order because this chip is cursed
CONSOLE_M68681->mr1a = GD_68681_MR1x_RX_RTS_EN_bm
| GD_68681_MR1x_PARMODE_NONE_gc
CONSOLE_M68681->mr1a = GD_68681_MR1x_PARMODE_NONE_gc
#if RTSCTS
| GD_68681_MR1x_RX_RTS_EN_bm
#endif
| GD_68681_MR1x_CHSIZE_8_gc;
CONSOLE_M68681->mr2a = GD_68681_MR2x_MODE_NORMAL_gc
#if RTSCTS
| GD_68681_MR2x_TX_CTS_EN_bm
#endif
| GD_68681_MR2x_STOPLEN_1p0_gc;
#if BAUD == 115200
@ -64,7 +68,8 @@ static inline void console_68681_fini(void)
// The M68681 cannot be fully reset in software. We need to issue a
// RESET instruction to generate the hardware reset signal. This will
// be done by the boot code. We'll at least let it finish transmitting.
while (!(CONSOLE_M68681->sra & GD_68681_SRx_TXRDY_bm));
uint8_t const done = GD_68681_SRx_TXRDY_bm | GD_68681_SRx_TXEMT_bm;
while ((CONSOLE_M68681->sra & done) != done);
}
static inline void console_68681_putc(char c)

View File

@ -17,7 +17,7 @@ static uint32_t find_base(uint32_t addr)
if (!e)
return UINT32_MAX;
return region->addr_start;
return region->addr_start & ~0xFFFuL;
}
static void wait_ready(uint32_t base)

View File

@ -17,9 +17,6 @@ bool memory_write16(uint32_t addr, uint16_t data)
bool memory_read16 (uint32_t addr, uint16_t * data)
{
last_exception = 0;
uint16_t out = *(uint16_t const volatile *) addr;
if (last_exception)
return false;
*data = out;
return true;
*data = *(uint16_t const volatile *) addr;
return !last_exception;
}

View File

@ -17,7 +17,7 @@
#define CMDBUF_LEN 256
#if HAS_DEVICES
static size_t _device;
static uint8_t _device;
#else
# define _device 0
#endif
@ -31,10 +31,10 @@ extern void start(void);
typedef struct {
// If the buffer starts with this, call command
char const * match;
char match[7];
// Usage text
char const * usage;
char usage[7];
// Command function. Will be passed a pointer to the argument
// (everything after the matcher). If whitespace is true, whitespace
@ -54,7 +54,7 @@ enum bootloc {
#define M_INTRO "\na6boot"
#define M_PROMPT "> "
#define M_BACKSPACE "\b \b"
#define M_HELP "Command or srec:\n"
#define M_HELP "a6boot g" BUILD_HASH "\n"
#define M_OK "OK\n"
#define M_NLOK "\nOK\n"
#define M_EQUALS " = "
@ -82,12 +82,12 @@ static void _cmd_peekw(char const *arg);
static void _cmd_pokeb(char const *arg);
static void _cmd_pokew(char const *arg);
static void _cmd_help(char const *arg);
static void _cmd_srec(char const *arg);
static void _cmd_read(char const *arg);
static void _cmd_cksum(char const *arg);
static void _cmd_reboot(char const * arg);
static void _cmd_boot(char const * arg);
static void _cmd_erase(char const * arg);
static void _do_srec(void);
static void _prompt(void);
static void _do_cmd(void);
@ -107,15 +107,15 @@ static const blcmd_t _cmds[] = {
#if HAS_DEVICES
{"device", "[DEV|list]", &_cmd_device},
#endif
{"peekb", "ADDR", &_cmd_peekb},
{"peekw", "ADDR", &_cmd_peekw},
{"pokeb", "ADDR VAL", &_cmd_pokeb},
{"pokew", "ADDR VAL", &_cmd_pokew},
{"read", "START END", &_cmd_read},
{"cksum", "START END", &_cmd_cksum},
{"erase", "ADDR", &_cmd_erase},
{"reboot", "", &_cmd_reboot},
{"boot", "SSP PC", &_cmd_boot},
{"peekb", "AD", &_cmd_peekb},
{"peekw", "AD", &_cmd_peekw},
{"pokeb", "AD VAL", &_cmd_pokeb},
{"pokew", "AD VAL", &_cmd_pokew},
{"read", "ST END", &_cmd_read},
{"cksum", "ST END", &_cmd_cksum},
{"erase", "ST END", &_cmd_erase},
{"reboot", "", &_cmd_reboot},
{"boot", "SSP PC", &_cmd_boot},
};
#define N_CMDS (sizeof(_cmds) / sizeof(blcmd_t))
@ -144,9 +144,6 @@ int main(void)
vectab[BUS_ERROR] = mem_error;
vectab[ILL_ERROR] = &unexp_vec;
vectab[ZDIV_ERROR] = &unexp_vec;
vectab[CHK_ERROR] = &unexp_vec;
vectab[TRAPV_ERROR] = &unexp_vec;
vectab[PRIV_ERROR] = &unexp_vec;
if (!_entry_prompt())
_boot(BOOT_APPLICATION, 0, 0);
@ -174,6 +171,7 @@ static void _boot(enum bootloc where, uintptr_t ssp, uintptr_t pc)
console_putc(':');
print_hex(pc, 6);
console_putc('\n');
console_fini();
(cpu_type == GD_M68K_M68000 ? &boot : &boot68010)
(APP_OFFSET, ssp, pc);
@ -208,7 +206,7 @@ static bool _entry_prompt(void)
static void _prompt(void)
{
size_t i = 0;
uint16_t i = 0;
print_string(M_PROMPT);
for (;;)
@ -255,7 +253,7 @@ static void _do_cmd(void)
if (cmd[0] == 'S')
{
_cmd_srec(cmd);
_do_srec();
return;
}
@ -284,9 +282,8 @@ static void _do_cmd(void)
static void _cmd_help(char const *arg)
{
print_string(M_HELP);
for (size_t i = 0; i < N_CMDS; i++)
for (uint8_t i = 0; i < N_CMDS; i++)
{
console_putc(' ');
print_string(_cmds[i].match);
console_putc(' ');
print_string(_cmds[i].usage);
@ -301,9 +298,9 @@ static void _cmd_pokew(char const *arg) { _cmd_poke_width(arg, 2); }
static void _cmd_peek_width(char const *arg, uint8_t width)
{
uint32_t addr;
uint32_t addr, discard;
if (_parse_two(arg, &addr, &addr) != 1)
if (_parse_two(arg, &addr, &discard) != 1)
{
_fail(M_FAIL_ARG);
return;
@ -363,7 +360,7 @@ static void _cmd_device(char const * arg)
}
else if (!strcmp(arg, "list"))
{
for (size_t i = 0; i < board_devices_n; i++)
for (uint8_t i = 0; i < board_devices_n; i++)
{
print_hex(i + 1, 0);
print_string(M_EQUALS);
@ -374,7 +371,7 @@ static void _cmd_device(char const * arg)
}
else
{
for (size_t i = 0; i < board_devices_n; i++)
for (uint8_t i = 0; i < board_devices_n; i++)
{
if (!strcmp(arg, board_devices[i]))
{
@ -388,7 +385,7 @@ static void _cmd_device(char const * arg)
}
#endif
static void _cmd_srec(char const *arg)
static void _do_srec(void)
{
uint32_t addr;
uint8_t offs, len;
@ -413,9 +410,9 @@ static void _cmd_srec(char const *arg)
if (_fail_memreg(e)) return;
if ((addr & (region->sec_align - 1)) == 0 || !region->sec_align)
if ((addr & (region->sec_align - 1)) == 0 && region->sec_align)
{
if (region->erase && !region->erase(addr))
if (!region->erase(addr))
{
_fail(M_FAIL_MEMDEV);
return;
@ -435,6 +432,8 @@ static void _cmd_srec(char const *arg)
}
}
region->flush();
print_string(M_OK);
}
@ -450,17 +449,18 @@ static void _cmd_cksum(char const * arg)
static void _cmd_read_or_cksum(char const * arg, bool cksum)
{
uint32_t addr, len;
uint32_t addr, end;
uint32_t checksum = 0;
if (_parse_two(arg, &addr, &len) != 2 || !len)
if (_parse_two(arg, &addr, &end) != 2 || end <= addr)
{
_fail(M_FAIL_ARG);
return;
}
addr &= 0xFFFFFFFE;
len &= 0xFFFFFFFE;
end &= 0xFFFFFFFE;
uint32_t len = end - addr;
// Read back in chunks
while (len) {
@ -487,7 +487,7 @@ static void _cmd_read_or_cksum(char const * arg, bool cksum)
if (cksum)
{
for (size_t i = 0; i < chunk_len; i++)
for (uint16_t i = 0; i < chunk_len; i++)
flet32(&checksum, cmdbuf[i]);
}
else
@ -521,19 +521,22 @@ static void _cmd_erase(char const * arg)
return;
}
else if (n == 1)
addr_end = addr_st;
addr_end = addr_st + 2;
a6boot_memreg_t const * region;
enum memreg_error e = find_region(
_device, addr_st, addr_end - addr_st, true, &region
);
if (_fail_memreg(e) || !region->erase) return;
if (_fail_memreg(e)) return;
while (addr_st <= addr_end)
{
if (!region->erase(addr_st))
{
_fail(M_FAIL_MEMDEV);
return;
}
addr_st += region->sec_align;
}

View File

@ -14,7 +14,7 @@ enum memreg_error find_region(
{
a6boot_memreg_t const * candidate = NULL;
for (size_t i = 0; i < board_memmap_n; i++)
for (uint8_t i = 0; i < board_memmap_n; i++)
{
uint32_t rstart = board_memmap[i].addr_start;
uint32_t rlen = board_memmap[i].length;
@ -37,9 +37,11 @@ enum memreg_error find_region(
if (!candidate)
return MEMREG_NOMEM;
if (wr ? !candidate->write : !candidate->read)
return MEMREG_ACCESS;
*region = candidate;
return MEMREG_OK;
}
bool memmap_no_write(uint32_t addr, uint16_t data) { return false; }
bool memmap_no_read(uint32_t addr, uint16_t * data) { return false; }
bool memmap_no_erase(uint32_t addr) { return false; }
void memmap_no_flush(void) {}

View File

@ -32,25 +32,24 @@ typedef struct {
// Sector alignment. When writing to an address that is a multiple of
// the sector alignment, the sector will be erased first. Should be a
// power of 2, may be 0 (always erase).
// power of 2, may be 0 (never erase).
uint32_t sec_align;
// How to write a word. Return false for invalid accesses. Make sure
// to handle bus/address exceptions. NULL for read-only.
// to handle bus/address exceptions. memmap_no for read-only.
bool (*write)(uint32_t addr, uint16_t data);
// How to read a word. Return false for invalid accesses. Make sure
// to handle bus/address exceptions
// to handle bus/address exceptions. memmap_no for write-only.
bool (*read)(uint32_t addr, uint16_t * data);
// Erase. Details are implementation-defined but this should erase the
// region containing the address. May be null if this is nonsense for
// the given device.
// region containing the address. memmap_yes if not eraseable
bool (*erase)(uint32_t addr);
// Flush. After a series of write operations are performed, this
// should be called. If the device requires writes to be combined into
// a larger block, this will flush out the last block. May be null if
// a larger block, this will flush out the last block. memmap_yes if
// not required.
void (*flush)(void);
} a6boot_memreg_t;
@ -76,4 +75,10 @@ enum memreg_error find_region(
a6boot_memreg_t const ** region
);
// Placeholder no-ops
bool memmap_no_write(uint32_t addr, uint16_t data);
bool memmap_no_read(uint32_t addr, uint16_t * data);
bool memmap_no_erase(uint32_t addr);
void memmap_no_flush(void);
#endif // !defined(MEMMAP_H)

View File

@ -38,6 +38,7 @@ bootloader_elf = custom_target(
'-ggdb',
'-o', '@OUTPUT@',
'-nostdlib',
'-DBUILD_HASH="' + build_hash + '"',
'-I', meson.current_source_dir(),
'-I', meson.current_source_dir() / '../gendrv/include',
'-I', meson.build_root() / 'subprojects/picolibc',

View File

@ -17,12 +17,12 @@ void ** board_init_vectab(void)
}
a6boot_memreg_t board_memmap[] = {
{0x000000, 0x080000, 0, NULL, &memory_read16, NULL, NULL },
{0x100000, 0x100000, 0, &memory_write16, &memory_read16, NULL, NULL },
{0x200000, 0xE00000, 0, &memory_write16, &memory_read16, NULL, NULL },
{0x000000, 0x080000, 0, &memmap_no_write, &memory_read16, &memmap_no_erase, &memmap_no_flush },
{0x100000, 0x100000, 0, &memory_write16, &memory_read16, &memmap_no_erase, &memmap_no_flush },
{0x200000, 0xE00000, 0, &memory_write16, &memory_read16, &memmap_no_erase, &memmap_no_flush },
};
size_t board_memmap_n = sizeof(board_memmap)/sizeof(a6boot_memreg_t);
uint8_t board_memmap_n = sizeof(board_memmap)/sizeof(a6boot_memreg_t);
// Kept as an example, but not needed
/*
@ -30,7 +30,7 @@ char const * board_devices[] = {
"MEMORY",
};
size_t board_devices_n = sizeof(board_devices)/sizeof(char const *);
uint8_t board_devices_n = sizeof(board_devices)/sizeof(char const *);
*/
void console_init(void)

View File

@ -10,8 +10,9 @@
#include "memmap.h"
#include "console_dbgcon.h"
#define BASE_68681 0x0E0000
#define BAUD 9600
#define BASE_68681 0x0E0001
#define BAUD 38400
#define RTSCTS 0
void console_init(void);
void console_fini(void);
@ -34,7 +35,7 @@ void ** board_init_vectab(void);
extern a6boot_memreg_t board_memmap[];
// Number of memory map entries
extern size_t board_memmap_n;
extern uint8_t board_memmap_n;
// Where the application lives
#define APP_OFFSET 0x2000
@ -45,7 +46,7 @@ extern size_t board_memmap_n;
extern char const * board_devices[];
// Number of devices
extern size_t board_devices_n;
extern uint8_t board_devices_n;
*/
#endif // !defined(BOARD_H)

View File

@ -32,6 +32,8 @@ prog_python = python.find_installation('python3')
#----------------------------------------------------------------------------
# Configure the project
build_hash = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip()
link_with = []
link_whole = []
link_args = []