Skip to content

Commit

Permalink
Merge branch 'master' into md-esp20
Browse files Browse the repository at this point in the history
* master: (32 commits)
  BroadcastTime string to rate quarters error handling (#716)
  Adds 9bit reception support to the TI uart drivers. (#713)
  Respond Ack to memcfg write datagrams immediately. (#712)
  Adds time jump information to the broadcast time update callbacks. (#694)
  Refactors fast time state into a separate base class from BroadcastTime. (#692)
  Add missing include guards. (#714)
  Fix bug that convoluted the file mode for the UART hardware mode (#706)
  Refactors the flash writing/erasing code for TI flash into a separate class. (#710)
  Adds STM32 RailcomDriver (#702)
  Adds hex_to_string helper function to format_utils. (#707)
  Deletes stm32f0-f3 SPIFFs driver. (#708)
  Fixes some compile errors: (#709)
  Fixes bug in flash write.
  Fixes compilation warnings.
  Adds support for unaligned reads and writes to the TivaEEPROMFile driver. (#704)
  Removes the driverlib from the path for CC322x.mk Removes a duplicate entry from the clang-format file.
  Stores the last offset in the configuration space when generating the XML. (#693)
  Eliminates b'' from the revision strings. (#701)
  Fork src/freertos_drivers/ti/TivaRailcom.hxx to src/freertos_drivers/st/Stm32Railcom.hxx step 4
  Fork src/freertos_drivers/ti/TivaRailcom.hxx to src/freertos_drivers/st/Stm32Railcom.hxx step 2
  ...
  • Loading branch information
balazsracz committed Jul 8, 2023
2 parents 2514cb0 + 630f590 commit ad6459c
Show file tree
Hide file tree
Showing 53 changed files with 2,521 additions and 1,254 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Standard: Cpp11
IndentWidth: 4
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Allman
# BreakBeforeBraces: Allman
IndentFunctionDeclarationAfterType: false
SpacesInParentheses: false
SpacesInAngles: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
bootloader_client.js
node_modules
# released binary
openmrn-bootloader-client-*
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ release:
pkg -C Brotli .


clean: clean-wasm
clean: clean-wasm clean-bin


clean-wasm:
rm -f $(EXECUTABLE).{wasm,wast}

clean-bin:
rm -f openmrn-bootloader-client-{linux,macos,win.exe}
316 changes: 316 additions & 0 deletions applications/memconfig_utils/main.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
/** \copyright
* Copyright (c) 2013 - 2023, Balazs Racz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \file main.hxx
*
* An application for downloading an entire memory space from a node.
*
* @author Balazs Racz
* @date 7 Sep 2017
*/

#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <unistd.h>

#include <memory>

#include "os/os.h"
#include "utils/constants.hxx"
#include "utils/Hub.hxx"
#include "utils/GridConnectHub.hxx"
#include "utils/GcTcpHub.hxx"
#include "utils/Crc.hxx"
#include "utils/FileUtils.hxx"
#include "utils/format_utils.hxx"
#include "executor/Executor.hxx"
#include "executor/Service.hxx"

#include "openlcb/IfCan.hxx"
#include "openlcb/DatagramCan.hxx"
#include "openlcb/BootloaderClient.hxx"
#include "openlcb/If.hxx"
#include "openlcb/AliasAllocator.hxx"
#include "openlcb/DefaultNode.hxx"
#include "openlcb/NodeInitializeFlow.hxx"
#include "openlcb/MemoryConfig.hxx"
#include "openlcb/MemoryConfigClient.hxx"
#include "utils/socket_listener.hxx"

NO_THREAD nt;
Executor<1> g_executor(nt);
Service g_service(&g_executor);
CanHubFlow can_hub0(&g_service);

OVERRIDE_CONST(gc_generate_newlines, 1);

static const openlcb::NodeID NODE_ID = 0x05010101181FULL;

openlcb::IfCan g_if_can(&g_executor, &can_hub0, 3, 3, 2);
openlcb::InitializeFlow g_init_flow{&g_service};
openlcb::CanDatagramService g_datagram_can(&g_if_can, 10, 2);
static openlcb::AddAliasAllocator g_alias_allocator(NODE_ID, &g_if_can);
openlcb::DefaultNode g_node(&g_if_can, NODE_ID);
openlcb::MemoryConfigHandler g_memcfg(&g_datagram_can, &g_node, 10);
openlcb::MemoryConfigClient g_memcfg_cli(&g_node, &g_memcfg);

namespace openlcb
{
Pool *const g_incoming_datagram_allocator = mainBufferPool;
}

static int port = 12021;
static const char *host = "localhost";
static const char *device_path = nullptr;
static const char *filename = nullptr;
static uint64_t destination_nodeid = 0;
static uint64_t destination_alias = 0;
static int memory_space_id = openlcb::MemoryConfigDefs::SPACE_CONFIG;
static uint32_t offset = 0;
static constexpr uint32_t NLEN = (uint32_t)-1;
static uint32_t len = NLEN;
static bool partial_read = false;
static bool do_read = false;
static bool do_write = false;

void usage(const char *e)
{
fprintf(stderr,
"Usage: %s ([-i destination_host] [-p port] | [-d serial_port]) [-s "
"memory_space_id] [-o offset] [-l len] [-c csum_algo] (-r|-w) "
"(-n nodeid | -a alias) -f filename\n",
e);
fprintf(stderr,
"Connects to an openlcb bus and performs memory configuration protocol "
"operations on openlcb node with id `nodeid` with the contents of a "
"given file or arguments.\n");
fprintf(stderr,
"The bus connection will be through an OpenLCB HUB on "
"destination_host:port with OpenLCB over TCP "
"(in GridConnect format) protocol, or through the CAN-USB device "
"(also in GridConnect protocol) found at serial_port. Device takes "
"precedence over TCP host:port specification.");
fprintf(stderr, "\tThe default target is localhost:12021.\n");
fprintf(stderr, "\tnodeid should be a 12-char hex string with 0x prefix and "
"no separators, like '-n 0x05010101141F'\n");
fprintf(stderr, "\talias should be a 3-char hex string with 0x prefix and no "
"separators, like '-a 0x3F9'\n");
fprintf(stderr,
"\tmemory_space_id defines which memory space to use "
"data into. Default is '-s 0x%02x'.\n",
openlcb::MemoryConfigDefs::SPACE_CONFIG);
fprintf(stderr, "\t-r or -w defines whether to read or write.\n");
fprintf(stderr,
"\tIf offset and len are skipped for a read, then the entire memory "
"space will be downloaded.\n");
#ifdef __EMSCRIPTEN__
fprintf(stderr, "\t-D lists available serial ports.\n");
#endif
exit(1);
}

void parse_args(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "hp:i:d:n:a:s:f:rwo:l:D")) >= 0)
{
switch (opt)
{
case 'h':
usage(argv[0]);
break;
case 'p':
port = atoi(optarg);
break;
case 'i':
host = optarg;
break;
case 'd':
device_path = optarg;
break;
case 'f':
filename = optarg;
break;
case 'n':
destination_nodeid = strtoll(optarg, nullptr, 16);
break;
case 'a':
destination_alias = strtoul(optarg, nullptr, 16);
break;
case 's':
memory_space_id = strtol(optarg, nullptr, 16);
break;
case 'o':
offset = strtol(optarg, nullptr, 10);
break;
case 'l':
len = strtol(optarg, nullptr, 10);
break;
case 'r':
do_read = true;
break;
case 'w':
do_write = true;
break;
#ifdef __EMSCRIPTEN__
case 'D':
JSSerialPort::list_ports();
break;
#endif
default:
fprintf(stderr, "Unknown option %c\n", opt);
usage(argv[0]);
}
}
partial_read = do_read && ((offset != 0) || (len != NLEN));
if ((!filename && !partial_read) ||
(!destination_nodeid && !destination_alias))
{
usage(argv[0]);
}
if ((do_read ? 1 : 0) + (do_write ? 1 : 0) != 1)
{
fprintf(stderr, "Must set exactly one of option -r and option -w.\n\n");
usage(argv[0]);
}
}


class HelperFlow : public StateFlowBase {
public:
HelperFlow() : StateFlowBase(&g_service) {
start_flow(STATE(wait_for_boot));
}

Action wait_for_boot()
{
return sleep_and_call(&timer_, MSEC_TO_NSEC(400), STATE(send_request));
}

/// Application business logic.
Action send_request()
{
openlcb::NodeHandle dst;
dst.alias = destination_alias;
dst.id = destination_nodeid;
HASSERT((!!do_read) + (!!do_write) == 1);
if (do_write)
{
auto payload = read_file_to_string(filename);
printf("Read %" PRIdPTR
" bytes from file %s. Writing to memory space 0x%02x\n",
payload.size(), filename, memory_space_id);
return invoke_subflow_and_wait(&g_memcfg_cli, STATE(write_done),
openlcb::MemoryConfigClientRequest::WRITE, dst, memory_space_id,
0, std::move(payload));
}

if (do_read && partial_read)
{
printf("Loading from space 0x%02x offset %u length %d\n",
(unsigned)memory_space_id, (unsigned)offset, (int)len);
return invoke_subflow_and_wait(&g_memcfg_cli, STATE(part_read_done),
openlcb::MemoryConfigClientRequest::READ_PART, dst,
memory_space_id, offset, len);
}
else if (do_read)
{
auto cb = [](openlcb::MemoryConfigClientRequest *rq) {
static size_t last_len = rq->payload.size();
if ((last_len & ~1023) != (rq->payload.size() & ~1023))
{
printf("Loaded %d bytes\n", (int)rq->payload.size());
last_len = rq->payload.size();
}
};
printf("Loading memory space 0x%02x\n",
(unsigned)memory_space_id);
return invoke_subflow_and_wait(&g_memcfg_cli, STATE(read_done),
openlcb::MemoryConfigClientRequest::READ, dst, memory_space_id,
std::move(cb));
}

printf("Nothing to do.");
return call_immediately(STATE(flow_done));
}

/// Invoked when a write operation is complete. Prints result and
/// terminates.
Action write_done() {
auto b = get_buffer_deleter(full_allocation_result(&g_memcfg_cli));
printf("Result: %04x\n", b->data()->resultCode);
hasError_ = b->data()->resultCode != 0;
return call_immediately(STATE(flow_done));
}

/// Invoked when a partial read operation is complete. Prints result and
/// terminates.
Action part_read_done() {
auto b = get_buffer_deleter(full_allocation_result(&g_memcfg_cli));
printf("Result: %04x\n", b->data()->resultCode);
printf("Data: %s\n", string_to_hex(b->data()->payload).c_str());
hasError_ = b->data()->resultCode != 0;
return call_immediately(STATE(flow_done));
}

/// Invoked when a read operation is complete. Prints result and
/// terminates.
Action read_done() {
auto b = get_buffer_deleter(full_allocation_result(&g_memcfg_cli));
printf("Result: %04x\n", b->data()->resultCode);
write_string_to_file(filename, b->data()->payload);
fprintf(stderr, "Written %" PRIdPTR " bytes to file %s.\n",
b->data()->payload.size(), filename);
hasError_ = b->data()->resultCode != 0;
return call_immediately(STATE(flow_done));
}

/// Terminates the process.
Action flow_done()
{
fflush(stdout);
#ifdef __EMSCRIPTEN__
EM_ASM(process.exit());
#endif
_exit(hasError_ ? 1 : 0);

return exit();
}

StateFlowTimer timer_{this};
bool hasError_ = false;
} helper_flow;


/// Runs the executor. Never returns.
void execute() {
g_if_can.add_addressed_message_support();
// Bootstraps the alias allocation process.
g_if_can.alias_allocator()->send(g_if_can.alias_allocator()->alloc());

g_executor.thread_body();
}
2 changes: 1 addition & 1 deletion applications/memconfig_utils/targets/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SUBDIRS = linux.x86 \
# js.emscripten
js.emscripten


include $(OPENMRNPATH)/etc/recurse.mk
6 changes: 6 additions & 0 deletions applications/memconfig_utils/targets/js.emscripten/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
memconfig_utils.js
node_modules
openmrn-memconfig-utils-linux
openmrn-memconfig-utils-macos
openmrn-memconfig-utils-win.exe

21 changes: 21 additions & 0 deletions applications/memconfig_utils/targets/js.emscripten/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-include ../../config.mk
include $(OPENMRNPATH)/etc/prog.mk
LDFLAGS += --bind -s WASM=0


# How to prepare for releasing this:
# as administrator do
# npm install -g pkg
# then you can call make release
release:
pkg -C Brotli .


clean: clean-wasm clean-bin


clean-wasm:
rm -f $(EXECUTABLE).{wasm,wast}

clean-bin:
rm -f openmrn-memconfig-utils-{linux,macos,win.exe}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(OPENMRNPATH)/etc/app_target_lib.mk
Loading

0 comments on commit ad6459c

Please sign in to comment.