a6boot: lots more shrinkifying
parent
b04b193bc8
commit
cb79f9f1b3
|
@ -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)) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, ®ion
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = []
|
||||
|
|
Loading…
Reference in New Issue