diff --git a/F0:F030,F042,F072/usbcan_gpio/gpioproto.c b/F0:F030,F042,F072/usbcan_gpio/gpioproto.c index b76d98f..0485fdd 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpioproto.c +++ b/F0:F030,F042,F072/usbcan_gpio/gpioproto.c @@ -90,9 +90,11 @@ static const char* setCANspeed(char *buf){ return sOKn; } +#include "hashparser.h" static const char *cmd_parser(char *buf){ if(!buf || !*buf) return NULL; if(strlen(buf) > 1){ + chk(buf); // "long" commands char c = *buf++; switch(c){ diff --git a/F0:F030,F042,F072/usbcan_gpio/hashparser.cpp b/F0:F030,F042,F072/usbcan_gpio/hashparser.cpp new file mode 100644 index 0000000..e5a6563 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_gpio/hashparser.cpp @@ -0,0 +1,151 @@ +/* + * This file is part of the usbcangpio project. + * Copyright 2026 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +extern "C"{ +#include +#include "can.h" +#include "flash.h" +#include "hashparser.h" +#include "gpioproto.h" +#define USBIF IGPIO +#include "strfunc.h" +} + +static const char *const sOKn = "OK\n", *const sERRn = "ERR\n"; +extern uint32_t Tms; + +// list of all commands and handlers +#define COMMAND_TABLE \ + COMMAND(canspeed, "CAN bus speed setter/getter (kBaud, 10..1000)") \ + COMMAND(dumpflash, "flash config dump") \ + COMMAND(time, "Current time (ms)") \ + COMMAND(help, "Show this help") + +typedef struct { + const char *name; + const char *desc; +} CmdInfo; + +// prototypes +#define COMMAND(name, desc) static errcodes_t cmd_ ## name(const char*, char*); + COMMAND_TABLE +#undef COMMAND + +static const CmdInfo cmdInfo[] = { // command name, description - for `help` +#define COMMAND(name, desc) { #name, desc }, + COMMAND_TABLE +#undef COMMAND +}; + +static errcodes_t cmd_canspeed(const char *cmd, char _U_ *args){ + SEND(cmd); PUTCHAR('='); SENDn(u2str(CAN_getspeed())); + if(args && *args){SEND("You entered: "); SENDn(args);} + return ERR_AMOUNT; +} + +static errcodes_t cmd_dumpflash(const char _U_ *cmd, char _U_ *args){ + SEND("userconf_sz="); SEND(u2str(the_conf.userconf_sz)); + SEND("\ncurrentconfidx="); SENDn(i2str(currentconfidx)); + for(int i = 0; i < InterfacesAmount; ++i){ + SEND("interface"); PUTCHAR('0' + i); + PUTCHAR('='); + int l = the_conf.iIlengths[i] / 2; + char *ptr = (char*) the_conf.iInterface[i]; + for(int j = 0; j < l; ++j){ + PUTCHAR(*ptr); + ptr += 2; + } + NL(); + } + SEND("canspeed="); SENDn(u2str(the_conf.CANspeed)); + return ERR_AMOUNT; +} + +static errcodes_t cmd_time(const char* cmd, char _U_ *args){ + SEND(cmd); PUTCHAR('='); SENDn(u2str(Tms)); + return ERR_AMOUNT; +} + +static errcodes_t cmd_help(const char _U_ *cmd, char _U_ *args){ + SEND(REPOURL); + for(size_t i = 0; i < sizeof(cmdInfo)/sizeof(cmdInfo[0]); i++){ + SEND(cmdInfo[i].name); + SEND(" - "); + SENDn(cmdInfo[i].desc); + } + return ERR_AMOUNT; +} + +constexpr uint32_t hash(const char* str, uint32_t h = 0){ + return *str ? hash(str + 1, h + ((h << 7) ^ *str)) : h; +} + +static const char* errtxt[ERR_AMOUNT] = { + [ERR_OK] = "OK", + [ERR_BADPAR] = "BADPAR", + [ERR_BADVAL] = "BADVAL", + [ERR_WRONGLEN] = "WRONGLEN", + [ERR_CANTRUN] = "CANTRUN", +}; + + +// TODO: add checking real command length! + +void chk(char *str){ + if(!str || !*str) return; + char command[CMD_MAXLEN+1]; + int i = 0; + while(*str > '@' && i < CMD_MAXLEN){ command[i++] = *str++; } + command[i] = 0; + while(*str && *str <= ' ') ++str; + char *restof = (char*) str; + uint32_t h = hash(command); + errcodes_t ecode = ERR_AMOUNT; + switch(h){ +#define COMMAND(name, desc) case hash(#name): ecode = cmd_ ## name(command, restof); break; + COMMAND_TABLE +#undef COMMAND + default: SEND("Unknown command, try 'help'\n"); break; + } + if(ecode < ERR_AMOUNT) SENDn(errtxt[ecode]); + ; +} + + +/* +if(*args){ + const char *n = getnum(args, &N); + if(n != args){ // get parameter + if(N >= CANMESG_NOPAR){ + USB_sendstr(errtxt[ERR_BADPAR]); newline(); + return RET_GOOD; + } + par = (uint8_t) N; + } + n = strchr(n, '='); + if(n){ + ++n; + const char *nxt = getint(n, &val); + if(nxt != n){ // set setter flag + par |= SETTERFLAG; + } + } +} +*/ diff --git a/F0:F030,F042,F072/usbcan_gpio/hashparser.h b/F0:F030,F042,F072/usbcan_gpio/hashparser.h new file mode 100644 index 0000000..fcad2fd --- /dev/null +++ b/F0:F030,F042,F072/usbcan_gpio/hashparser.h @@ -0,0 +1,34 @@ +/* + * This file is part of the usbcangpio project. + * Copyright 2026 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +// error codes for answer message +typedef enum{ + ERR_OK, // all OK + ERR_BADPAR, // wrong parameter + ERR_BADVAL, // wrong value (for setter) + ERR_WRONGLEN, // wrong message length + ERR_CANTRUN, // can't run given command due to bad parameters or other + ERR_AMOUNT // amount of error codes or "send nothing" +} errcodes_t; + +// maximal length of command (without trailing zero) +#define CMD_MAXLEN (15) + +void chk(char *str); diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin index 1a75ca5..4277f73 100755 Binary files a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin and b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin differ diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user index 01b7cd6..a198073 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user +++ b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files index 5976930..1dbb0d4 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files +++ b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.files @@ -8,6 +8,11 @@ gpioproto.c gpioproto.h hardware.c hardware.h +hashgen/Readme +hashgen/hashgen.c +hashgen/mktestdic +hashparser.cpp +hashparser.h main.c ringbuffer.c ringbuffer.h diff --git a/F0:F030,F042,F072/usbcan_gpio/version.inc b/F0:F030,F042,F072/usbcan_gpio/version.inc index 789476e..f7ff2a9 100644 --- a/F0:F030,F042,F072/usbcan_gpio/version.inc +++ b/F0:F030,F042,F072/usbcan_gpio/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "85" -#define BUILD_DATE "2026-03-07" +#define BUILD_NUMBER "94" +#define BUILD_DATE "2026-03-08" diff --git a/F3:F303/Multistepper/hashgen/hashgen.c b/F3:F303/Multistepper/hashgen/hashgen.c index a3c300f..88350ec 100644 --- a/F3:F303/Multistepper/hashgen/hashgen.c +++ b/F3:F303/Multistepper/hashgen/hashgen.c @@ -31,23 +31,23 @@ typedef struct{ static glob_pars G = {.headerfile = "hash.h", .sourcefile = "hash.c"}; static int help = 0; -static myoption cmdlnopts[] = { +static sl_option_t cmdlnopts[] = { {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), "show this help"}, {"dict", NEED_ARG, NULL, 'd', arg_string, APTR(&G.dict), "dictionary file"}, {"header", NEED_ARG, NULL, 'H', arg_string, APTR(&G.headerfile),"output header filename"}, {"source", NEED_ARG, NULL, 'S', arg_string, APTR(&G.sourcefile),"output source filename"}, - {"genfunc", NO_ARGS, NULL, 'F', arg_int, APTR(&G.genfunc), "generate function bodys"}, + {"genfunc", NO_ARGS, NULL, 'F', arg_int, APTR(&G.genfunc), "generate function bodies"}, end_option }; static void parse_args(int argc, char **argv){ - parseargs(&argc, &argv, cmdlnopts); - if(help) showhelp(-1, cmdlnopts); + sl_parseargs(&argc, &argv, cmdlnopts); + if(help) sl_showhelp(-1, cmdlnopts); if(argc > 0){ red("Unused arguments:\n"); for(int i = 0; i < argc; ++i) printf("%s ", argv[i]); printf("\n"); - showhelp(-1, cmdlnopts); + sl_showhelp(-1, cmdlnopts); } } @@ -189,7 +189,10 @@ static const char *fns = "int fn_%s(uint32_t _U_ hash, char _U_ *args) WAL; // \"%s\" (%u)\n\n" ; static const char *headercontent = -"#ifndef _U_\n\ +"// Generated by HASHGEN (https://github.com/eddyem/eddys_snippets/tree/master/stringHash4MCU_)\n\ +// Licensed by GPLv3\n\ +#pragma once\n\ +#ifndef _U_\n\ #define _U_ __attribute__((__unused__))\n\ #endif\n\n\ #define CMD_MAXLEN (32)\n\n\ @@ -259,12 +262,12 @@ static void build(strhash *H, int hno, int hlen){ } int main(int argc, char **argv){ - initial_setup(); + sl_init(); parse_args(argc, argv); if(!G.dict) ERRX("point dictionary file"); if(!G.headerfile) ERRX("point header source file"); if(!G.sourcefile) ERRX("point c source file"); - mmapbuf *b = My_mmap(G.dict); + sl_mmapbuf_t *b = sl_mmap(G.dict); if(!b) ERRX("Can't open %s", G.dict); char *word = b->data; strhash *H = MALLOC(strhash, ALLOCSZ); @@ -320,6 +323,6 @@ int main(int argc, char **argv){ } if(hno == HASHFNO) WARNX("Can't find proper hash function"); FREE(H); - My_munmap(b); + sl_munmap(b); return 0; } diff --git a/F3:F303/Multistepper/multistepper.bin b/F3:F303/Multistepper/multistepper.bin index 3b536dd..12bd337 100755 Binary files a/F3:F303/Multistepper/multistepper.bin and b/F3:F303/Multistepper/multistepper.bin differ diff --git a/makefile.stm32 b/makefile.stm32 index df54127..ef9a466 100644 --- a/makefile.stm32 +++ b/makefile.stm32 @@ -13,6 +13,7 @@ PREFIX ?= /opt/bin/arm-none-eabi RM := rm -f RMDIR := rmdir CC := $(PREFIX)-gcc +CPP := $(PREFIX)-g++ # don't replace ld with gcc: the binary size would be much greater!! LD := $(PREFIX)-gcc AR := $(PREFIX)-ar @@ -33,7 +34,8 @@ TARGFILE := $(OBJDIR)/TARGET # autoincremental version & build date VERSION_FILE = version.inc SRC := $(wildcard *.c) -OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o)) +SRCPP := $(wildcard *.cpp) +OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o) $(SRCPP:%.cpp=%.o)) STARTUP := $(OBJDIR)/startup.o MAP := $(OBJDIR)/$(BINARY).map OBJS += $(STARTUP) @@ -132,6 +134,10 @@ $(OBJDIR)/%.o: %.c @echo " CC $<" $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) -o $@ -c $< +$(OBJDIR)/%.o: %.cpp + @echo " C++ $<" + $(CPP) -c $(CFLAGS) -fno-exceptions $(DEFS) $(INCLUDE) -o $@ -c $< + $(BIN): $(ELF) @echo " OBJCOPY $(BIN)" $(OBJCOPY) -Obinary $(ELF) $(BIN) @@ -158,7 +164,7 @@ clean: flash: $(BIN) @echo " FLASH $(BIN)" - $(STFLASH) --reset write $(BIN) 0x8000000 + $(STFLASH) write $(BIN) 0x8000000 $(STFLASH) reset boot: $(BIN)