Skip to content

Commit

Permalink
hostsmash
Browse files Browse the repository at this point in the history
- Fixed several static C analysis complaints, including memory leaks on failure
- Added "-c [set|show]" to set and show the KickSmash clock from the host
- Millisecond delay changed to use nanosleep() for current Linux OS
- Fixed bad message debug output to not show more bytes than were received
- Enhanced message handler to show KickSmash ouput which doesn't form message

smashftp
- Fixed ^C abort of command to not cause future commands to abort
- Fixed bug where remote file get didn't cause a failing program status

smash
- Corrected -c -k (get KickSmash clock if set) to work; did respond to -c -L
- Fixed bug where "-t 4" didn't execute the remote message test.

KickSmash fw
- Fixed timeout (buffer-too-small) when slow Amiga is fetching files from PC host
- Console UART Rx pin is now pulled up to prevent false input
  • Loading branch information
Chris Hooper committed Nov 21, 2024
1 parent 9ead083 commit 0d606d3
Show file tree
Hide file tree
Showing 15 changed files with 354 additions and 89 deletions.
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ generated.*.ld
cscope.out
.cscope_cmd.*
objs/
objs.x86_64/
objs.mac/
objs.rom/
objs.rom_d/
objs.win32/
objs.win64/
objs.*/
rev1/
rev2/
rev3/
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
KickSmash32 is a Kickstart ROM replacement module for the Amiga 3000
and Amiga 4000 computer systems. Features include:
* In-system programming via an Amiga command line utility
* Out-of-system programming (USB-C) via a Linux command line utility
* In-system programming via an Amiga command line utility (smash)
* Out-of-system programming (USB-C) via a Linux command line utility (hostsmash)
* Up to 8 independent flash banks
* Configurable ROM bank switching on long reboot or cold power-on
* Optional host file service to the Amiga over the USB-C link
* Optional host file service to the Amiga over the USB-C link (smashfs and smashftp)

![KickSmash32 photo](photos/2024_11_07_kicksmash32_rev5_profile_view_2.jpg?raw=true "Kicksmash32")

Expand Down
13 changes: 7 additions & 6 deletions amiga/smash.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* THE AUTHOR ASSUMES NO LIABILITY FOR ANY DAMAGE ARISING OUT OF THE USE
* OR MISUSE OF THIS UTILITY OR INFORMATION REPORTED BY THIS UTILITY.
*/
const char *version = "\0$VER: smash 1.0 ("__DATE__") © Chris Hooper";
const char *version = "\0$VER: smash 1.1 ("__DATE__") © Chris Hooper";

#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -3233,12 +3233,12 @@ cmd_clock(int argc, char *argv[])
switch (*ptr) {
case 'h': // load
goto usage;
case 'k': // load if set
flag_load_if_set++;
break;
case 'l': // load
flag_load++;
break;
case 'L': // load if set
flag_load_if_set++;
break;
case 'n': // save if not set
flag_save_if_not_set++;
break;
Expand All @@ -3262,7 +3262,8 @@ cmd_clock(int argc, char *argv[])
return (rc);
}
}
if ((flag_load == 0) && (flag_save == 0) && (flag_save_if_not_set == 0))
if ((flag_load == 0) && (flag_load_if_set == 0) &&
(flag_save == 0) && (flag_save_if_not_set == 0))
flag_show++;

if (flag_load || flag_load_if_set) {
Expand Down Expand Up @@ -3412,7 +3413,7 @@ main(int argc, char *argv[])
exit(1);
}
}
} else if ((*ptr >= '0') && (*ptr < '4') && (ptr[1] == '\0')) {
} else if ((*ptr >= '0') && (*ptr <= '4') && (ptr[1] == '\0')) {
flag_test_mask |= BIT(*ptr - '0');
flag_test++;
} else {
Expand Down
16 changes: 15 additions & 1 deletion amiga/smashftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* THE AUTHOR ASSUMES NO LIABILITY FOR ANY DAMAGE ARISING OUT OF THE USE
* OR MISUSE OF THIS UTILITY OR INFORMATION REPORTED BY THIS UTILITY.
*/
const char *version = "\0$VER: smashftp 1.0 ("__DATE__") © Chris Hooper";
const char *version = "\0$VER: smashftp 1.1 ("__DATE__") © Chris Hooper";

#include <stdio.h>
#include <stdint.h>
Expand Down Expand Up @@ -109,6 +109,17 @@ is_user_abort(void)
return (0);
}

/*
* clear_user_abort
* ----------------
* Clear any pending user abort signal.
*/
void
clear_user_abort(void)
{
SetSignal(0, SIGBREAKF_CTRL_C);
}

static uint64_t
smash_time(void)
{
Expand Down Expand Up @@ -920,6 +931,7 @@ get_file(const char *src, const char *dst)
}
rc = sm_fread(handle, buflen, (void **) &data, &rlen, 0);
if (rlen == 0) {
failed_to_read:
printf("Failed to read %s at pos %x: %s\n",
src, (uint) pos, smash_err(rc));
break;
Expand All @@ -934,6 +946,8 @@ get_file(const char *src, const char *dst)
break;
}
pos += rlen;
if (rc != RC_SUCCESS)
goto failed_to_read;
}
time_end = smash_time();
diff = (uint) (time_end - time_start);
Expand Down
1 change: 1 addition & 0 deletions amiga/smashftp.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ rc_t cmd_time(int argc, char * const *argv);
rc_t cmd_version(int argc, char * const *argv);
rc_t parse_value(const char *arg, uint8_t *value, uint width);
rc_t parse_addr(char * const **arg, int *argc, uint64_t *space, uint64_t *addr);
void clear_user_abort(void);

extern const char cmd_time_help[];
extern const char cmd_version_help[];
Expand Down
2 changes: 2 additions & 0 deletions amiga/smashftp_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,8 @@ cmdline(void)
HIST_ENTRY *hist_cur;
char *sline;

clear_user_abort(); // Clear Control-C abort

line = readline("\rsmashftp> ");
if (line == NULL)
continue;
Expand Down
26 changes: 26 additions & 0 deletions doc/sw_hostsmash.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ The hostsmash utility has three main functions:
* Program Kickstart ROM firmware stored in KickSmash flash
* Serve local file storage to the Amiga

Other documentation sections:
* Provide current time to the Amiga
* Hostsmash command arguments
* Hostsmash on Windows
* Hostsmash future development

===========================================================================

Connecting to the KickSmash firmware CLI
----------------------------------------
Expand Down Expand Up @@ -363,6 +370,19 @@ you can return to the volume directory using "cd ::"
9.OS322:>


Provide current time to the Amiga
---------------------------------
The hostsmash command can be used to set the current time for KickSmash,
which can then provide that clock to the Amiga via the smash command.
Since KickSmash does not have a battery-backed RTC, it will need the time
set at each power cycle, unless it's also connected to your USB host.
Use the following command to set the KickSmash clock:
hostsmash -c set

From your Amiga, you can retrieve the current time from Kicksmash using
smash -c load


Hostsmash command arguments
---------------------------
This section documents all hostsmash command arguments, including
Expand All @@ -372,6 +392,7 @@ All hostsmash command options:
-A --all show all verify miscompares
-a --addr <addr> starting EEPROM address
-b --bank <num> starting EEPROM address as multiple of file size
-c --clock [show|set] show or set Kicksmash time of day clock
-D --delay <msec> pacing delay between sent characters (ms)
-d --device <filename> serial device to use (e.g. /dev/ttyACM0)
-e --erase erase EEPROM (use -a <addr> for sector erase)
Expand Down Expand Up @@ -519,6 +540,11 @@ Debug options
This is useful if you are debugging binary data (such as
service messages) from the Amiga through KickSmash.

Other options
-c --clock [show|set] show or set Kicksmash time of day clock
Hostsmash can provide the current local time to KickSmash, which
can then be read from the Amiga using the "smash -c load" command.


Hostsmash on Windows
--------------------
Expand Down
26 changes: 19 additions & 7 deletions doc/sw_smash.txt
Original file line number Diff line number Diff line change
Expand Up @@ -532,11 +532,11 @@ Length 0x8000 is 32 KB.
Clock
-----
The smash clock command may also be used to save and restore the Amiga
system clock from KickSmash. This is not currently terribly useful because
KickSmash does not have battery backup. It will lose the current time
at a power cycle, unless it is also being powered by USB-C. In the
future, the hostsmash utility will be able to set the KickSmash clock
from your host PC's own system clock.
system clock from KickSmash. This is not terribly useful unless your Amiga
is connected to a USB host, as KickSmash does not have battery backup. It
will lose the current time at a power cycle, unless it is also being powered
by USB-C. The hostsmash utility is able to set the KickSmash clock from your
host PC's own system clock with the "hostsmash -c set" command.

The smash clock command has several options:
9.OS322:> smash clock help
Expand All @@ -558,6 +558,18 @@ around +/- 20 ppm (pulses per million). At 20 ppm, the worst case drift
should be about 1.72 seconds per day.

The smash clock load command will set the Amiga's time based on the
KickSmash board's current time. The loadifset command is similar, but
KickSmash board's current time. The loadifset command is similar, but
will not generate an error message (and of course not perform the load)
if the KickSmash clock has not been set.
if the KickSmash clock has not been set. If your Amiga's RTC is not
functioning, you can put the following in your Startup-Sequence to
acquire the time from KickSmash if it has been set there:
smash -c loadifset

If your Amiga's RTC is functioning, and assuming hostsmash has provided
the current time to KickSmash, you can use "smash -c load" followed by
"SetClock save" to accurately set your Amiga RTC. Example:
8.OS322:> smash -c load
15-Nov-24 12:14:22.536350
8.OS322:> SetClock save
8.OS322:> date
Friday 15-Nov-24 12:14:30
11 changes: 9 additions & 2 deletions fw/m29f160xt.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,9 +657,16 @@ ee_wait_for_done_status(uint32_t timeout_usec, int verbose, int mode)
return (0);
}
} else {
if (same_count)
if (same_count) {
/*
* Read a different status value after flash status stopped
* updating. This should not happen unless a flash data line
* is floating or the flash is somehow responding to OE from
* phantom sources.
*/
printf("S");
same_count = 0;
same_count = 0;
}
lstatus = status;
}

Expand Down
39 changes: 37 additions & 2 deletions fw/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ execute_cmd(uint16_t cmd, uint16_t cmd_len)
ks_reply(0, KS_STATUS_OK, 0, NULL, 0, NULL);
break; // End processing
case KS_CMD_ID: {
/* Send Kickflash identification and configuration */
/* Send KickSmash identification and configuration */
smash_id_t reply;
uint temp[3];
uint pos = 0;
Expand Down Expand Up @@ -2080,7 +2080,7 @@ execute_usb_cmd(uint16_t cmd, uint16_t cmd_len, uint8_t *rawbuf)
usb_msg_reply(0, KS_STATUS_OK, 0, NULL, 0, NULL);
break; // End processing
case KS_CMD_ID: {
/* Send Kickflash identification and configuration */
/* Send KickSmash identification and configuration */
smash_id_t reply;
uint temp[3];
int pos = 0;
Expand Down Expand Up @@ -2320,6 +2320,41 @@ execute_usb_cmd(uint16_t cmd, uint16_t cmd_len, uint8_t *rawbuf)
cons_utoa = prod_utoa;
usb_msg_reply(0, KS_STATUS_OK, 0, NULL, 0, NULL);
break;
case KS_CMD_CLOCK: {
uint64_t now = timer_tick_get();
uint64_t usec = timer_tick_to_usec(now);
uint32_t am_time[2];

if (cmd & (KS_CLOCK_SET | KS_CLOCK_SET_IFNOT)) {
uint32_t t_usec;
uint32_t t_sec;

if (cmd_len != 8) {
usb_msg_reply(0, KS_STATUS_BADLEN, 0, NULL, 0, NULL);
break;
}
memcpy(am_time, buf, sizeof (am_time));
t_sec = am_time[0];
t_usec = am_time[1];
if (((cmd & KS_CLOCK_SET_IFNOT) == 0) || (amiga_time == 0))
amiga_time = t_sec * 1000000ULL + t_usec - usec;
usb_msg_reply(0, KS_STATUS_OK, 0, NULL, 0, NULL);
} else {
if (amiga_time == 0) {
am_time[0] = 0;
am_time[1] = 0;
} else {
uint64_t both = usec + amiga_time;
uint32_t t_usec = both % 1000000;
uint32_t t_sec = both / 1000000;
am_time[0] = t_sec;
am_time[1] = t_usec;
}
usb_msg_reply(0, KS_STATUS_OK, sizeof (am_time), &am_time,
0, NULL);
}
break;
}
default:
fail_cmd_u++;
break;
Expand Down
27 changes: 20 additions & 7 deletions fw/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "timer.h"
#include "irq.h"
#include "usb.h"
#include "gpio.h"

#if defined(STM32F1)
#include <libopencm3/stm32/f1/nvic.h>
Expand All @@ -30,21 +31,20 @@ typedef uint32_t USART_TypeDef_P;


#if defined(STM32F1)
/* STM32F1XX on Rev2+ uses PA9 for CONS_TX and PA10 for CONS_RX */
/* STM32F1XX on Rev4+ uses PB6 for CONS_TX and PB7 for CONS_RX */
/* STM32F1XX uses PB6 for CONS_TX and PB7 for CONS_RX */
#define CONSOLE_USART USART1
#define CONSOLE_IRQn NVIC_USART1_IRQ
#define CONSOLE_IRQHandler usart1_isr
#elif defined(STM32F4)
/* STM32F407 Discovery on Rev1 uses PA10 for CONS_TX and PA11 for CONS_RX */
/* STM32F407 Discovery uses PA10 for CONS_TX and PA11 for CONS_RX */
#define CONSOLE_USART USART3
#define CONSOLE_IRQn NVIC_USART3_IRQ
#define CONSOLE_IRQHandler usart3_isr
#endif

static volatile uint cons_in_rb_producer; // Console input current writer pos
static uint cons_in_rb_consumer; // Console input current reader pos
static uint8_t cons_in_rb[1024]; // Console input ring buffer (FIFO)
static uint8_t cons_in_rb[4096]; // Console input ring buffer (FIFO)
static uint8_t usb_out_buf[4096]; // USB output buffer
static uint16_t usb_out_bufpos = 0; // USB output buffer position
static bool uart_console_active = false;
Expand Down Expand Up @@ -72,11 +72,17 @@ static void uart_send_blocking(USART_TypeDef_P usart, uint16_t data)
uart_send(usart, data);
}

int
void
uart_putchar(int ch)
{
uart_send_blocking(CONSOLE_USART, (uint16_t) ch);
return (0);
}

void
uart_puts(const char *str)
{
while (*str != '\0')
uart_putchar(*str);
}

static uint16_t
Expand Down Expand Up @@ -295,7 +301,8 @@ putchar(int ch)
usb_putchar_wait(ch);
if (usb_console_active && !uart_console_active)
return (0);
return (uart_putchar(ch));
uart_putchar(ch);
return (0);
}

int
Expand Down Expand Up @@ -366,8 +373,14 @@ uart_init(void)

gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO6); // CONS_TX

#undef FLOATING_CONS_RX
#ifdef FLOATING_CONS_RX
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, GPIO7); // CONS_RX
#else
gpio_setmode(GPIOB, GPIO7, GPIO_SETMODE_INPUT_PULLUPDOWN); // CONS_RX
#endif

#endif

Expand Down
3 changes: 2 additions & 1 deletion fw/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ void usb_rb_put(uint ch);
*/
int input_break_pending(void);

int uart_putchar(int ch);
void uart_putchar(int ch);
void uart_puts(const char *str);
void uart_flush(void);
int puts_binary(const void *buf, uint32_t len);

Expand Down
2 changes: 1 addition & 1 deletion fw/version.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
#include "version.h"

const char * const version_str =
"Version 1.1 built "BUILD_DATE" "BUILD_TIME;
"Version 1.3 built "BUILD_DATE" "BUILD_TIME;
Loading

0 comments on commit 0d606d3

Please sign in to comment.