From cb81d5ba73db5a34683718e7f853f0820ea3dcad Mon Sep 17 00:00:00 2001 From: Arne Jansen Date: Tue, 20 Dec 2022 19:38:50 +0100 Subject: [PATCH] hostmot2: collect initial writes into a single packet This initial writes to the interface card happens with a series of small writes that are all sent back-to-back. At least in the case of the gbit- ethernet card litehm2 this can lead to packet loss, leading to a failed startup. This patch collects all packets generated by the force_write code into a single packet. --- docs/man/man9/hm2_eth.9 | 3 ++- docs/man/man9/hostmot2.9 | 2 +- docs/src/config/integrator-concepts.adoc | 18 ++++++++++++++++++ src/hal/drivers/mesa-hostmot2/hm2_eth.c | 14 +++++++++++++- .../drivers/mesa-hostmot2/hostmot2-lowlevel.h | 8 ++++++++ src/hal/drivers/mesa-hostmot2/hostmot2.c | 4 ++++ 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/docs/man/man9/hm2_eth.9 b/docs/man/man9/hm2_eth.9 index 0ad23bd9dce..b8d03494c64 100644 --- a/docs/man/man9/hm2_eth.9 +++ b/docs/man/man9/hm2_eth.9 @@ -40,7 +40,8 @@ As shipped, the board address is 192.168.1.121. .SH DESCRIPTION hm2_eth is a device driver that interfaces Mesa's ethernet based Anything I/O boards (with the HostMot2 firmware) to the LinuxCNC HAL. -The supported boards are: 7I76E, 7I80DB, 7I80HD, 7I92, 7I93, 7I94, 7I95, 7I96, 7I96S, 7I97, 7I98. +The supported boards are: 7I76E, 7I80DB, 7I80HD, 7I92, 7I93, 7I94, 7I95, 7I96, 7I96S, 7I97, 7I98. It also supports boards with the +litehm2 firmware (https://github.com/sensille/litehm2). The board must have its firmware loaded on the board by the mesaflash(1) program. hm2_eth is only available when LinuxCNC is configured with "uspace" realtime. diff --git a/docs/man/man9/hostmot2.9 b/docs/man/man9/hostmot2.9 index 48cb1e59efe..8b9cd74b840 100644 --- a/docs/man/man9/hostmot2.9 +++ b/docs/man/man9/hostmot2.9 @@ -28,7 +28,7 @@ The identifier consists of the last 4 digits of the board serial number, which i This will make configs less portable, but does mean that boards can be re-connected less carefully. .SH DESCRIPTION -hostmot2 is a device driver that interfaces the Mesa HostMot2 firmware to the LinuxCNC HAL. +hostmot2 is a device driver that interfaces the Mesa or litehm2 HostMot2 firmware to the LinuxCNC HAL. This driver by itself does nothing, the boards that actually run the firmware require their own drivers before anything can happen. Currently drivers are available for PCI, Ethernet, SPI and EPP interfaced cards. diff --git a/docs/src/config/integrator-concepts.adoc b/docs/src/config/integrator-concepts.adoc index 981c38d424d..203d6331a86 100644 --- a/docs/src/config/integrator-concepts.adoc +++ b/docs/src/config/integrator-concepts.adoc @@ -278,4 +278,22 @@ button to completely turn off your computer. The RTAI group has been improving this in recent releases, so your LinuxCNC system may shut off by itself after all. +== Computer/Machine Interface Hardware Options + +=== litehm2/rv901t + +Litehm2 is a board-agnostic port of the HostMot2 FPGA firmware. The first +board it supports is the linsn rv901t, which was originally built as a LED +controller board, but due to the available I/O it is well suited to act as +a machine controller. It offers around 80 5V-buffered I/O ports and can +switch between all input and all output. it is also easily modified to split +the ports half/half between input and output. The rv901t interfaces to the +computer via Gigabit or 100Mbit Ethernet. + +Litehm2 is based on the LiteX framework which supports a wide range of +FPGA boards. Currently only the rv901t is supported, but support for more +boards is under development. + +More information can be found at https://github.com/sensille/litehm2. + // vim: set syntax=asciidoc: diff --git a/src/hal/drivers/mesa-hostmot2/hm2_eth.c b/src/hal/drivers/mesa-hostmot2/hm2_eth.c index 6c569efce5c..5466f9ca2da 100644 --- a/src/hal/drivers/mesa-hostmot2/hm2_eth.c +++ b/src/hal/drivers/mesa-hostmot2/hm2_eth.c @@ -992,7 +992,7 @@ static int hm2_eth_enqueue_read(hm2_lowlevel_io_t *this, rtapi_u32 addr, void *b static int hm2_eth_enqueue_write(hm2_lowlevel_io_t *this, rtapi_u32 addr, const void *buffer, int size); static int hm2_eth_write(hm2_lowlevel_io_t *this, rtapi_u32 addr, const void *buffer, int size) { - if(rtapi_task_self() >= 0) + if(rtapi_task_self() >= 0 || this->force_enqueue) return hm2_eth_enqueue_write(this, addr, buffer, size); int send; @@ -1060,6 +1060,16 @@ static int hm2_eth_enqueue_write(hm2_lowlevel_io_t *this, rtapi_u32 addr, const return 1; } +static int hm2_eth_set_force_enqueue(hm2_lowlevel_io_t *this, int do_enqueue) { + if (do_enqueue) { + this->force_enqueue = 1; + return 1; + } else { + this->force_enqueue = 0; + return hm2_eth_send_queued_writes(this); + } +} + static int llio_idx(const char *llio_name) { int *idx = kvlist_lookup(&board_num, llio_name); return (*idx)++; @@ -1372,6 +1382,8 @@ static int hm2_eth_probe(hm2_eth_t *board) { board->llio.receive_queued_reads = hm2_eth_receive_queued_reads; board->llio.queue_write = hm2_eth_enqueue_write; board->llio.send_queued_writes = hm2_eth_send_queued_writes; + if (strncmp(board_name, "litehm2", 7) == 0) + board->llio.set_force_enqueue = hm2_eth_set_force_enqueue; board->llio.reset = hm2_eth_reset; ret = hm2_register(&board->llio, config[boards_count]); diff --git a/src/hal/drivers/mesa-hostmot2/hostmot2-lowlevel.h b/src/hal/drivers/mesa-hostmot2/hostmot2-lowlevel.h index 835f129e670..b1c2376dd7c 100644 --- a/src/hal/drivers/mesa-hostmot2/hostmot2-lowlevel.h +++ b/src/hal/drivers/mesa-hostmot2/hostmot2-lowlevel.h @@ -76,6 +76,9 @@ struct hm2_lowlevel_io_struct { int (*program_fpga)(hm2_lowlevel_io_t *self, const bitfile_t *bitfile); int (*reset)(hm2_lowlevel_io_t *self); + // collect all writes into a single packet while this is set + int64_t force_enqueue; + // for devices with a lot of inherent latency (ethernet and spi are two // examples), it is useful to divide the work of the bulk reads which occur // every servo cycle into up to three groups: @@ -102,6 +105,11 @@ struct hm2_lowlevel_io_struct { // (in which case a dummy implementation of ->queue_write delegates to ->write) int (*queue_write)(hm2_lowlevel_io_t *self, rtapi_u32 addr, const void *buffer, int size); int (*send_queued_writes)(hm2_lowlevel_io_t *self); + + // setting this to one will enqueue all following writes into a single packet. When set + // set back to 0, the packet is set. + int (*set_force_enqueue)(hm2_lowlevel_io_t *self, int do_enqueue); + // // This is a HAL parameter allocated and added to HAL by hostmot2. // diff --git a/src/hal/drivers/mesa-hostmot2/hostmot2.c b/src/hal/drivers/mesa-hostmot2/hostmot2.c index 771f70aeab3..cc986fc4e3a 100644 --- a/src/hal/drivers/mesa-hostmot2/hostmot2.c +++ b/src/hal/drivers/mesa-hostmot2/hostmot2.c @@ -1811,6 +1811,8 @@ void rtapi_app_exit(void) { // this pushes our idea of what things are like into the FPGA's poor little mind void hm2_force_write(hostmot2_t *hm2) { + if (hm2->llio->set_force_enqueue != NULL) + hm2->llio->set_force_enqueue(hm2->llio, 1); hm2_watchdog_force_write(hm2); hm2_ioport_force_write(hm2); hm2_encoder_force_write(hm2); @@ -1830,5 +1832,7 @@ void hm2_force_write(hostmot2_t *hm2) { // the IO Port pin directions is set appropriately. hm2_ssr_force_write(hm2); hm2_outm_force_write(hm2); + if (hm2->llio->set_force_enqueue != NULL) + hm2->llio->set_force_enqueue(hm2->llio, 0); }