From 154df68cb2a74a3b22456e8ec5af3af54352a41f Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 17 May 2022 22:37:09 +0200 Subject: fix buffer overflow in error handling module - fixed ring buffer overflow in errcatch module - fixed naming of commands in sercomm module - added comments to macro's in consts.h - properly handle `W2_E_WARN_UNCAUGHT_ERROR` and `W2_E_WARN_ERR_BUFFER_FULL` (these used to cause infinite loops) - added buffer full warning code - added options to hide some simulation messages - more boilerplate sercomm module code --- robot/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'robot/makefile') diff --git a/robot/makefile b/robot/makefile index 6f50519..ce57090 100644 --- a/robot/makefile +++ b/robot/makefile @@ -34,7 +34,7 @@ CFLAGS += -DW2_BUILD_STR="$(BUILD_STR)" all: $(if $(SIM), a.out, out.hex) clean: - rm -f *.o out.hex a.out compile_commands.json + rm -f *.o out.hex a.out a.out: $(OBJECTS) $(CC) $(OBJECTS) $(CFLAGS) $(LDFLAGS) -- cgit v1.2.3 From 3f4b1c7284304d8c4ae2e4dd17359a2b4c1c573c Mon Sep 17 00:00:00 2001 From: lonkaars Date: Wed, 18 May 2022 11:18:04 +0200 Subject: [WIP] serial communication (broken w/ segfault) --- robot/bin.c | 34 ++++++++++++++++++++++++++++++++++ robot/bin.h | 39 +++++++++++++++++++++++++++++++++------ robot/errcatch.c | 3 +-- robot/errcatch.h | 4 +++- robot/hypervisor.c | 4 ++-- robot/makefile | 2 +- robot/sercomm.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- robot/sercomm.h | 23 ++++++++++++++++++----- robot/setup.c | 27 +++++++++++++++++++++++++++ robot/sim.h | 3 ++- 10 files changed, 168 insertions(+), 19 deletions(-) (limited to 'robot/makefile') diff --git a/robot/bin.c b/robot/bin.c index 4242edc..a2c91a4 100644 --- a/robot/bin.c +++ b/robot/bin.c @@ -1,3 +1,5 @@ +#include + #include "bin.h" #define W2_ENDIAN_LITTLE (1) @@ -12,8 +14,40 @@ #define _BYTE_2 ((uint32_t)(0xff << (_SHIFT_2B))) #define _BYTE_3 ((uint32_t)(0xff << (_SHIFT_3B))) +const uint8_t W2_STRUCT_T_SIZES[] = {sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t)}; + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshift-count-overflow" +w2_s_bin *w2_bin_from_uint8_t(uint8_t data) { + size_t size = 1; + w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); + ret->bytes = size; + ret->data[0] = data; + return ret; +} + +w2_s_bin *w2_bin_from_uint16_t(uint16_t data) { + size_t size = 2; + w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); + data = w2_bin_hton16(data); + ret->bytes = size; + ret->data[0] = (data & _BYTE_1) >> _SHIFT_1B; + ret->data[1] = (data & _BYTE_0) >> _SHIFT_0B; + return ret; +} + +w2_s_bin *w2_bin_from_uint32_t(uint32_t data) { + size_t size = 4; + w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); + data = w2_bin_hton32(data); + ret->bytes = size; + ret->data[0] = (data & _BYTE_3) >> _SHIFT_3B; + ret->data[1] = (data & _BYTE_2) >> _SHIFT_2B; + ret->data[2] = (data & _BYTE_1) >> _SHIFT_1B; + ret->data[3] = (data & _BYTE_0) >> _SHIFT_0B; + return ret; +} + uint32_t w2_bin_hton32(uint32_t h32) { if (g_w2_endianness == W2_ENDIAN_BIG) return h32; return ((h32 & _BYTE_0) << _SHIFT_3B) | ((h32 & _BYTE_1) << _SHIFT_1B) | diff --git a/robot/bin.h b/robot/bin.h index ccde132..1c9b951 100644 --- a/robot/bin.h +++ b/robot/bin.h @@ -1,19 +1,46 @@ #pragma once +/** + * helper file for binary data + * + * - fix endianness with functions inspired by UNIX arpa/inet.h + * - convert uint16_t and uint32_t to w2_s_bin + */ #include +extern uint8_t g_w2_endianness; + +#define W2_T_UINT8_T (0) +#define W2_T_UINT16_T (1) +#define W2_T_UINT32_T (2) + +enum w2_e_struct_types { + W2_ST_UINT8_T, + W2_ST_UINT16_T, + W2_ST_UINT32_T, +}; + +extern const uint8_t W2_STRUCT_T_SIZES[]; + typedef struct { uint16_t bytes; uint8_t data[]; } w2_s_bin; -extern uint8_t g_w2_endianness; +typedef struct { + enum w2_e_struct_types type; + uint16_t length; + const uint8_t *data; +} w2_s_struct_property; -/** - * helper file for binary data - * - * - fix endianness with functions inspired by UNIX arpa/inet.h - */ +typedef struct { + uint16_t length; + w2_s_struct_property *properties[]; +} w2_s_property_list; + +w2_s_bin *w2_bin_from_uint8_t(uint8_t data); +w2_s_bin *w2_bin_from_uint16_t(uint16_t data); +w2_s_bin *w2_bin_from_uint32_t(uint32_t data); /** convert 32-bit value from host endian to network (big-endian) */ uint32_t w2_bin_hton32(uint32_t h32); diff --git a/robot/errcatch.c b/robot/errcatch.c index f66b2a1..82da820 100644 --- a/robot/errcatch.c +++ b/robot/errcatch.c @@ -1,4 +1,3 @@ -#include #include #include @@ -31,7 +30,7 @@ void w2_errcatch_main() { } w2_s_error *w2_alloc_error(enum w2_e_errorcodes code, uint16_t length, const char *message) { - w2_s_error *error = calloc(sizeof(w2_s_error) + length, 1); + w2_s_error *error = malloc(sizeof(w2_s_error) + length); memcpy(error, &(w2_s_error const){.code = code, .message_length = length}, sizeof(w2_s_error)); strncpy(error->message, message, length); diff --git a/robot/errcatch.h b/robot/errcatch.h index c6edcfb..f0e25d9 100644 --- a/robot/errcatch.h +++ b/robot/errcatch.h @@ -39,6 +39,8 @@ enum w2_e_errorcodes { W2_E_WARN_ERR_BUFFER_FULL = 0x04 | W2_E_TYPE_WARN, /** line lost, trying to calibrate */ W2_E_WARN_LINE_LOST = 0x05 | W2_E_TYPE_WARN, + /** serial buffer full, gets thrown on next cycle */ + W2_E_WARN_SERCOMM_BUFFER_FULL = 0x06 | W2_E_TYPE_WARN, }; /** @@ -75,6 +77,6 @@ void w2_errcatch_throw_msg(enum w2_e_errorcodes code, uint16_t length, const cha /** * allocate and initialize error struct * - * TODO: doesn't handle null pointers from calloc + * TODO: doesn't handle null pointers from malloc */ w2_s_error *w2_alloc_error(enum w2_e_errorcodes code, uint16_t length, const char *message); diff --git a/robot/hypervisor.c b/robot/hypervisor.c index c558de8..c08a24c 100644 --- a/robot/hypervisor.c +++ b/robot/hypervisor.c @@ -7,7 +7,7 @@ void w2_hypervisor_main() { #ifdef W2_SIM - siminfo("cycle start\n"); + if (DBG_ENABLE_CYCLEINFO) siminfo("cycle start\n"); #endif time_reset(); @@ -24,7 +24,7 @@ void w2_hypervisor_main() { if (mode_time > W2_MAX_MODULE_CYCLE_MS) w2_errcatch_throw(W2_E_WARN_CYCLE_EXPIRED); #ifdef W2_SIM - siminfo("cycle end\n"); + if (DBG_ENABLE_CYCLEINFO) siminfo("cycle end\n"); usleep(100e3); #endif } diff --git a/robot/makefile b/robot/makefile index ce57090..53010dd 100644 --- a/robot/makefile +++ b/robot/makefile @@ -14,7 +14,7 @@ SOURCES := $(filter-out sim.c, $(wildcard *.c)) HEADERS := $(filter-out sim.h, $(wildcard *.h)) # simulation -# SIM = true +SIM = true CFLAGS += $(if $(SIM), -DW2_SIM, -mcall-prologues -mmcu=$(MCU)) LDFLAGS += $(if $(SIM), , -lpololu_$(DEVICE)) PREFIX := $(if $(SIM), , avr-) diff --git a/robot/sercomm.c b/robot/sercomm.c index a0eed3a..e845b1a 100644 --- a/robot/sercomm.c +++ b/robot/sercomm.c @@ -1,3 +1,49 @@ +#include +#include + +#include "bin.h" +#include "orangutan_shim.h" #include "sercomm.h" -void w2_sercomm_main() {} +w2_s_bin *g_w2_sercomm_buffer[W2_SERCOMM_BUFFER_SIZE] = {}; +uint8_t g_w2_sercomm_index = 0; +uint8_t g_w2_sercomm_offset = 0; +uint8_t g_w2_sercomm_buffer_full = 0; + +void w2_sercomm_main() { +#ifdef W2_SIM + simprintfunc("w2_sercomm_main", ""); +#endif + // send data + while (g_w2_sercomm_index != g_w2_sercomm_offset) { +#ifdef W2_SIM + simprint("line 0"); + w2_s_bin *data = g_w2_sercomm_buffer[g_w2_sercomm_index]; + simprint("line 1"); + + simprintf("bytes: %i\n", data->bytes); + char* data_cast = malloc(data->bytes); + simprint("line 2"); + memcpy(data_cast, data->data, data->bytes); + simprint("line 3"); + serial_send(data_cast, data->bytes); + simprint("line 4"); + g_w2_sercomm_offset = (g_w2_sercomm_offset + 1) % W2_SERCOMM_BUFFER_SIZE; + simprint("line 5"); +#endif + } +} + +void w2_sercomm_append_msg(w2_s_bin *data) { +#ifdef W2_SIM + simprintfunc("w2_sercomm_append_msg", ""); +#endif + uint8_t next_index = (g_w2_sercomm_index + 1) % W2_SERCOMM_BUFFER_SIZE; + g_w2_sercomm_buffer_full = next_index == g_w2_sercomm_offset; + free(g_w2_sercomm_buffer[g_w2_sercomm_index]); + w2_s_bin *data_copy = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * data->bytes); + memcpy(&data_copy->bytes, data->data, data->bytes); + g_w2_sercomm_buffer[g_w2_sercomm_index] = data_copy; + if (g_w2_sercomm_buffer_full) return; + g_w2_sercomm_index = next_index; +} diff --git a/robot/sercomm.h b/robot/sercomm.h index d960d0d..dd17af8 100644 --- a/robot/sercomm.h +++ b/robot/sercomm.h @@ -7,28 +7,42 @@ #define W2_CMDDIR_TX (1) enum w2_e_serial_commands { + /** ping command */ W2_CMD_PING = 0x00, + /** exception command */ W2_CMD_EXPT = 0x02, + /** mode command */ W2_CMD_MODE = 0x04, + /** speed command */ W2_CMD_SPED = 0x06, + /** direct control command */ W2_CMD_DIRC = 0x08, + /** coordinate command */ W2_CMD_CORD = 0x0a, + /** backorder modify command */ W2_CMD_BOMD = 0x0c, + /** soft reset command */ W2_CMD_SRES = 0x0e, + /** map config command */ W2_CMD_MCFG = 0x10, + /** sensor data command */ W2_CMD_SENS = 0x12, + /** info command */ W2_CMD_INFO = 0x14, + /** display control command */ W2_CMD_DISP = 0x16, + /** play midi command */ W2_CMD_PLAY = 0x18, + /** control leds command */ W2_CMD_CLED = 0x1a, }; /** sercomm ring buffer */ extern w2_s_bin *g_w2_sercomm_buffer[W2_SERCOMM_BUFFER_SIZE]; /** stores head of ring buffer */ -extern uint8_t g_w2_error_index; +extern uint8_t g_w2_sercomm_index; /** stores start of ring buffer */ -extern uint8_t g_w2_error_offset; +extern uint8_t g_w2_sercomm_offset; /** * serial pc-robot communication module @@ -38,10 +52,9 @@ extern uint8_t g_w2_error_offset; */ void w2_sercomm_main(); -void w2_sercomm_append_msg(w2_s_bin data); +void w2_sercomm_append_msg(w2_s_bin *data); -w2_s_bin w2_sercomm_rx_generic(); -w2_s_bin w2_sercomm_tx_generic(); +w2_s_bin w2_sercomm_struct_pack(w2_s_property_list generic_struct); w2_s_bin w2_sercomm_rx_ping(); w2_s_bin w2_sercomm_tx_ping(); diff --git a/robot/setup.c b/robot/setup.c index d040286..59a6404 100644 --- a/robot/setup.c +++ b/robot/setup.c @@ -27,4 +27,31 @@ void w2_setup_main() { // indicate startup done play("L50 c>c"); + +#ifdef W2_SIM + #include "sercomm.h" + w2_s_bin *data = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * 20); + data->bytes = 20; + data->data[0] = 0x00; + data->data[1] = 0x01; + data->data[2] = 0x00; + data->data[3] = 0x01; + data->data[4] = 0x00; + data->data[5] = 0x01; + data->data[6] = 0x00; + data->data[7] = 0x01; + data->data[8] = 0xde; + data->data[9] = 0xad; + data->data[10] = 0xbe; + data->data[11] = 0xef; + data->data[12] = 0xff; + data->data[13] = 0xff; + data->data[14] = 0x00; + data->data[15] = 0x00; + data->data[16] = 0xff; + data->data[17] = 0xff; + data->data[18] = 0x00; + data->data[19] = 0x69; + w2_sercomm_append_msg(data); +#endif } diff --git a/robot/sim.h b/robot/sim.h index 9c80ecf..c872dda 100644 --- a/robot/sim.h +++ b/robot/sim.h @@ -5,9 +5,10 @@ #include // debug fine-tuning -#define DBG_ENABLE_PRINTFUNC (0) +#define DBG_ENABLE_PRINTFUNC (1) #define DBG_ENABLE_SIMWARN (1) #define DBG_ENABLE_SIMINFO (1) +#define DBG_ENABLE_CYCLEINFO (0) // debug print options #define DBG_BYTES_PER_LINE 16 -- cgit v1.2.3 From 937a3a736aaf2c468c8c8e8dbc7963a87eae890f Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 24 May 2022 21:56:59 +0200 Subject: move some code to a shared folder --- client/makefile | 1 + robot/bin.c | 64 -------------------------------------------------------- robot/bin.h | 52 --------------------------------------------- robot/consts.h | 17 --------------- robot/errcatch.c | 1 - robot/errcatch.h | 2 +- robot/makefile | 1 + robot/sercomm.c | 2 +- robot/sercomm.h | 4 ++-- robot/setup.c | 4 ++-- robot/sim.c | 2 +- shared/bin.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ shared/bin.h | 52 +++++++++++++++++++++++++++++++++++++++++++++ shared/consts.h | 17 +++++++++++++++ shared/makefile | 2 ++ shared/readme.md | 8 +++++++ 16 files changed, 152 insertions(+), 141 deletions(-) delete mode 100644 robot/bin.c delete mode 100644 robot/bin.h delete mode 100644 robot/consts.h create mode 100644 shared/bin.c create mode 100644 shared/bin.h create mode 100644 shared/consts.h create mode 100644 shared/makefile create mode 100644 shared/readme.md (limited to 'robot/makefile') diff --git a/client/makefile b/client/makefile index 23d5ce6..2209c95 100644 --- a/client/makefile +++ b/client/makefile @@ -6,6 +6,7 @@ EXECNAME = main SOURCES := $(wildcard *.c) HEADERS := $(wildcard *.h) +include ../shared/makefile OBJECTS := $(patsubst %.c,%.o, $(SOURCES)) all: main diff --git a/robot/bin.c b/robot/bin.c deleted file mode 100644 index a2c91a4..0000000 --- a/robot/bin.c +++ /dev/null @@ -1,64 +0,0 @@ -#include - -#include "bin.h" - -#define W2_ENDIAN_LITTLE (1) -#define W2_ENDIAN_BIG (0) - -#define _SHIFT_0B (8 * 0) -#define _SHIFT_1B (8 * 1) -#define _SHIFT_2B (8 * 2) -#define _SHIFT_3B (8 * 3) -#define _BYTE_0 ((uint32_t)(0xff << (_SHIFT_0B))) -#define _BYTE_1 ((uint32_t)(0xff << (_SHIFT_1B))) -#define _BYTE_2 ((uint32_t)(0xff << (_SHIFT_2B))) -#define _BYTE_3 ((uint32_t)(0xff << (_SHIFT_3B))) - -const uint8_t W2_STRUCT_T_SIZES[] = {sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t)}; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshift-count-overflow" -w2_s_bin *w2_bin_from_uint8_t(uint8_t data) { - size_t size = 1; - w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); - ret->bytes = size; - ret->data[0] = data; - return ret; -} - -w2_s_bin *w2_bin_from_uint16_t(uint16_t data) { - size_t size = 2; - w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); - data = w2_bin_hton16(data); - ret->bytes = size; - ret->data[0] = (data & _BYTE_1) >> _SHIFT_1B; - ret->data[1] = (data & _BYTE_0) >> _SHIFT_0B; - return ret; -} - -w2_s_bin *w2_bin_from_uint32_t(uint32_t data) { - size_t size = 4; - w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); - data = w2_bin_hton32(data); - ret->bytes = size; - ret->data[0] = (data & _BYTE_3) >> _SHIFT_3B; - ret->data[1] = (data & _BYTE_2) >> _SHIFT_2B; - ret->data[2] = (data & _BYTE_1) >> _SHIFT_1B; - ret->data[3] = (data & _BYTE_0) >> _SHIFT_0B; - return ret; -} - -uint32_t w2_bin_hton32(uint32_t h32) { - if (g_w2_endianness == W2_ENDIAN_BIG) return h32; - return ((h32 & _BYTE_0) << _SHIFT_3B) | ((h32 & _BYTE_1) << _SHIFT_1B) | - ((h32 & _BYTE_2) >> _SHIFT_1B) | ((h32 & _BYTE_3) >> _SHIFT_3B); -} -#pragma GCC diagnostic pop - -uint16_t w2_bin_hton16(uint16_t h16) { - if (g_w2_endianness == W2_ENDIAN_BIG) return h16; - return ((h16 & _BYTE_0) << _SHIFT_1B) | ((h16 & _BYTE_1) >> _SHIFT_1B); -} - -uint32_t w2_bin_ntoh32(uint32_t n32) { return w2_bin_hton32(n32); } -uint16_t w2_bin_ntoh16(uint16_t n16) { return w2_bin_hton16(n16); } diff --git a/robot/bin.h b/robot/bin.h deleted file mode 100644 index 1c9b951..0000000 --- a/robot/bin.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -/** - * helper file for binary data - * - * - fix endianness with functions inspired by UNIX arpa/inet.h - * - convert uint16_t and uint32_t to w2_s_bin - */ - -#include - -extern uint8_t g_w2_endianness; - -#define W2_T_UINT8_T (0) -#define W2_T_UINT16_T (1) -#define W2_T_UINT32_T (2) - -enum w2_e_struct_types { - W2_ST_UINT8_T, - W2_ST_UINT16_T, - W2_ST_UINT32_T, -}; - -extern const uint8_t W2_STRUCT_T_SIZES[]; - -typedef struct { - uint16_t bytes; - uint8_t data[]; -} w2_s_bin; - -typedef struct { - enum w2_e_struct_types type; - uint16_t length; - const uint8_t *data; -} w2_s_struct_property; - -typedef struct { - uint16_t length; - w2_s_struct_property *properties[]; -} w2_s_property_list; - -w2_s_bin *w2_bin_from_uint8_t(uint8_t data); -w2_s_bin *w2_bin_from_uint16_t(uint16_t data); -w2_s_bin *w2_bin_from_uint32_t(uint32_t data); - -/** convert 32-bit value from host endian to network (big-endian) */ -uint32_t w2_bin_hton32(uint32_t h32); -/** convert 16-bit value from host endian to network (big-endian) */ -uint16_t w2_bin_hton16(uint16_t h16); -/** convert 32-bit value from network (big-endian) to host endian */ -uint32_t w2_bin_ntoh32(uint32_t n32); -/** convert 16-bit value from network (big-endian) to host endian */ -uint16_t w2_bin_ntoh16(uint16_t n16); diff --git a/robot/consts.h b/robot/consts.h deleted file mode 100644 index 70efcac..0000000 --- a/robot/consts.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#ifndef W2_BUILD_STR -// is defined by CFLAGS += -DW2_BUILD_STR in makefile -#define W2_BUILD_STR ("????????") -#endif - -/** max logic module execution time in milliseconds */ -#define W2_MAX_MODULE_CYCLE_MS (20) -/** serial baud rate (bit/s) */ -#define W2_SERIAL_BAUD (9600) -/** size of the error handling buffer (in errors, not bytes) */ -#define W2_ERROR_BUFFER_SIZE (16) -/** size of the serial communication buffer (in messages, not bytes) */ -#define W2_SERCOMM_BUFFER_SIZE (16) -/** size of input (receive) buffer (in bytes) */ -#define W2_SERIAL_READ_BUFFER_SIZE (255) diff --git a/robot/errcatch.c b/robot/errcatch.c index 2a59d3d..4bdbaef 100644 --- a/robot/errcatch.c +++ b/robot/errcatch.c @@ -1,7 +1,6 @@ #include #include -#include "consts.h" #include "errcatch.h" #include "halt.h" #include "modes.h" diff --git a/robot/errcatch.h b/robot/errcatch.h index f0e25d9..1e273bd 100644 --- a/robot/errcatch.h +++ b/robot/errcatch.h @@ -2,7 +2,7 @@ #include -#include "consts.h" +#include "../shared/consts.h" #define W2_E_TYPE_MASK (0b11 << 6) diff --git a/robot/makefile b/robot/makefile index 53010dd..cd5c032 100644 --- a/robot/makefile +++ b/robot/makefile @@ -12,6 +12,7 @@ LDFLAGS=-Wl,-gc-sections -Wl,-relax SOURCES := $(filter-out sim.c, $(wildcard *.c)) HEADERS := $(filter-out sim.h, $(wildcard *.h)) +include ../shared/makefile # simulation SIM = true diff --git a/robot/sercomm.c b/robot/sercomm.c index d1bb3b3..7072f9e 100644 --- a/robot/sercomm.c +++ b/robot/sercomm.c @@ -1,7 +1,7 @@ #include #include -#include "bin.h" +#include "../shared/bin.h" #include "orangutan_shim.h" #include "sercomm.h" diff --git a/robot/sercomm.h b/robot/sercomm.h index bc9fc1e..44fdf08 100644 --- a/robot/sercomm.h +++ b/robot/sercomm.h @@ -1,7 +1,7 @@ #pragma once -#include "bin.h" -#include "consts.h" +#include "../shared/bin.h" +#include "../shared/consts.h" #define W2_CMDDIR_RX (0) #define W2_CMDDIR_TX (1) diff --git a/robot/setup.c b/robot/setup.c index 36c5da1..6af1a05 100644 --- a/robot/setup.c +++ b/robot/setup.c @@ -1,7 +1,7 @@ #include -#include "bin.h" -#include "consts.h" +#include "../shared/bin.h" +#include "../shared/consts.h" #include "halt.h" #include "modes.h" #include "orangutan_shim.h" diff --git a/robot/sim.c b/robot/sim.c index 47c0c78..b061c9a 100644 --- a/robot/sim.c +++ b/robot/sim.c @@ -6,7 +6,7 @@ #include #include "sim.h" -#include "consts.h" +#include "../shared/consts.h" #include "sercomm.h" struct timespec reference_time; // NOLINT diff --git a/shared/bin.c b/shared/bin.c new file mode 100644 index 0000000..a2c91a4 --- /dev/null +++ b/shared/bin.c @@ -0,0 +1,64 @@ +#include + +#include "bin.h" + +#define W2_ENDIAN_LITTLE (1) +#define W2_ENDIAN_BIG (0) + +#define _SHIFT_0B (8 * 0) +#define _SHIFT_1B (8 * 1) +#define _SHIFT_2B (8 * 2) +#define _SHIFT_3B (8 * 3) +#define _BYTE_0 ((uint32_t)(0xff << (_SHIFT_0B))) +#define _BYTE_1 ((uint32_t)(0xff << (_SHIFT_1B))) +#define _BYTE_2 ((uint32_t)(0xff << (_SHIFT_2B))) +#define _BYTE_3 ((uint32_t)(0xff << (_SHIFT_3B))) + +const uint8_t W2_STRUCT_T_SIZES[] = {sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t)}; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshift-count-overflow" +w2_s_bin *w2_bin_from_uint8_t(uint8_t data) { + size_t size = 1; + w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); + ret->bytes = size; + ret->data[0] = data; + return ret; +} + +w2_s_bin *w2_bin_from_uint16_t(uint16_t data) { + size_t size = 2; + w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); + data = w2_bin_hton16(data); + ret->bytes = size; + ret->data[0] = (data & _BYTE_1) >> _SHIFT_1B; + ret->data[1] = (data & _BYTE_0) >> _SHIFT_0B; + return ret; +} + +w2_s_bin *w2_bin_from_uint32_t(uint32_t data) { + size_t size = 4; + w2_s_bin *ret = malloc(sizeof(w2_s_bin) + sizeof(uint8_t) * size); + data = w2_bin_hton32(data); + ret->bytes = size; + ret->data[0] = (data & _BYTE_3) >> _SHIFT_3B; + ret->data[1] = (data & _BYTE_2) >> _SHIFT_2B; + ret->data[2] = (data & _BYTE_1) >> _SHIFT_1B; + ret->data[3] = (data & _BYTE_0) >> _SHIFT_0B; + return ret; +} + +uint32_t w2_bin_hton32(uint32_t h32) { + if (g_w2_endianness == W2_ENDIAN_BIG) return h32; + return ((h32 & _BYTE_0) << _SHIFT_3B) | ((h32 & _BYTE_1) << _SHIFT_1B) | + ((h32 & _BYTE_2) >> _SHIFT_1B) | ((h32 & _BYTE_3) >> _SHIFT_3B); +} +#pragma GCC diagnostic pop + +uint16_t w2_bin_hton16(uint16_t h16) { + if (g_w2_endianness == W2_ENDIAN_BIG) return h16; + return ((h16 & _BYTE_0) << _SHIFT_1B) | ((h16 & _BYTE_1) >> _SHIFT_1B); +} + +uint32_t w2_bin_ntoh32(uint32_t n32) { return w2_bin_hton32(n32); } +uint16_t w2_bin_ntoh16(uint16_t n16) { return w2_bin_hton16(n16); } diff --git a/shared/bin.h b/shared/bin.h new file mode 100644 index 0000000..1c9b951 --- /dev/null +++ b/shared/bin.h @@ -0,0 +1,52 @@ +#pragma once +/** + * helper file for binary data + * + * - fix endianness with functions inspired by UNIX arpa/inet.h + * - convert uint16_t and uint32_t to w2_s_bin + */ + +#include + +extern uint8_t g_w2_endianness; + +#define W2_T_UINT8_T (0) +#define W2_T_UINT16_T (1) +#define W2_T_UINT32_T (2) + +enum w2_e_struct_types { + W2_ST_UINT8_T, + W2_ST_UINT16_T, + W2_ST_UINT32_T, +}; + +extern const uint8_t W2_STRUCT_T_SIZES[]; + +typedef struct { + uint16_t bytes; + uint8_t data[]; +} w2_s_bin; + +typedef struct { + enum w2_e_struct_types type; + uint16_t length; + const uint8_t *data; +} w2_s_struct_property; + +typedef struct { + uint16_t length; + w2_s_struct_property *properties[]; +} w2_s_property_list; + +w2_s_bin *w2_bin_from_uint8_t(uint8_t data); +w2_s_bin *w2_bin_from_uint16_t(uint16_t data); +w2_s_bin *w2_bin_from_uint32_t(uint32_t data); + +/** convert 32-bit value from host endian to network (big-endian) */ +uint32_t w2_bin_hton32(uint32_t h32); +/** convert 16-bit value from host endian to network (big-endian) */ +uint16_t w2_bin_hton16(uint16_t h16); +/** convert 32-bit value from network (big-endian) to host endian */ +uint32_t w2_bin_ntoh32(uint32_t n32); +/** convert 16-bit value from network (big-endian) to host endian */ +uint16_t w2_bin_ntoh16(uint16_t n16); diff --git a/shared/consts.h b/shared/consts.h new file mode 100644 index 0000000..70efcac --- /dev/null +++ b/shared/consts.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef W2_BUILD_STR +// is defined by CFLAGS += -DW2_BUILD_STR in makefile +#define W2_BUILD_STR ("????????") +#endif + +/** max logic module execution time in milliseconds */ +#define W2_MAX_MODULE_CYCLE_MS (20) +/** serial baud rate (bit/s) */ +#define W2_SERIAL_BAUD (9600) +/** size of the error handling buffer (in errors, not bytes) */ +#define W2_ERROR_BUFFER_SIZE (16) +/** size of the serial communication buffer (in messages, not bytes) */ +#define W2_SERCOMM_BUFFER_SIZE (16) +/** size of input (receive) buffer (in bytes) */ +#define W2_SERIAL_READ_BUFFER_SIZE (255) diff --git a/shared/makefile b/shared/makefile new file mode 100644 index 0000000..815d33c --- /dev/null +++ b/shared/makefile @@ -0,0 +1,2 @@ +SOURCES += $(wildcard ../shared/*.c) +HEADERS += $(wildcard ../shared/*.h) diff --git a/shared/readme.md b/shared/readme.md new file mode 100644 index 0000000..870f015 --- /dev/null +++ b/shared/readme.md @@ -0,0 +1,8 @@ +# shared code + +this is the subdirectory for all code that is shared between the robot code and +the client code. to use these, include the .h files with a relative path (e.g. +`#include "../shared/consts.h"`). makefiles should add `include +../shared/makefile` to add the .c and .h files to `$SOURCES` and `$HEADERS` in +the makefile targets (this is already done for the robot and client +subdirectories). -- cgit v1.2.3 From b0a905b14ff90f2240e5aa2928d5329d8494cb46 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 24 May 2022 22:06:09 +0200 Subject: fix `make clean` --- client/makefile | 6 +++--- robot/makefile | 6 +++--- shared/makefile | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'robot/makefile') diff --git a/client/makefile b/client/makefile index 2209c95..8bc8ac7 100644 --- a/client/makefile +++ b/client/makefile @@ -4,20 +4,20 @@ RM = rm -f CFLAGS = EXECNAME = main +all: $(EXECNAME) + SOURCES := $(wildcard *.c) HEADERS := $(wildcard *.h) include ../shared/makefile OBJECTS := $(patsubst %.c,%.o, $(SOURCES)) -all: main - .o: $(CC) -c $(CFLAGS) $< $(EXECNAME): $(OBJECTS) $(CC) $(OBJECTS) -o $(EXECNAME) -clean: +clean:: $(RM) $(EXECNAME) *.o format: diff --git a/robot/makefile b/robot/makefile index cd5c032..6de886c 100644 --- a/robot/makefile +++ b/robot/makefile @@ -10,6 +10,8 @@ PORT ?= /dev/ttyACM0 CFLAGS=-g -Wall $(DEVICE_SPECIFIC_CFLAGS) -Os LDFLAGS=-Wl,-gc-sections -Wl,-relax +all: $(if $(SIM), a.out, out.hex) + SOURCES := $(filter-out sim.c, $(wildcard *.c)) HEADERS := $(filter-out sim.h, $(wildcard *.h)) include ../shared/makefile @@ -32,9 +34,7 @@ OBJ2HEX=$(PREFIX)objcopy BUILD_STR=$(shell git update-index -q --refresh; git describe --tags --dirty='*' --broken='x' | cut -c1-20) CFLAGS += -DW2_BUILD_STR="$(BUILD_STR)" -all: $(if $(SIM), a.out, out.hex) - -clean: +clean:: rm -f *.o out.hex a.out a.out: $(OBJECTS) diff --git a/shared/makefile b/shared/makefile index 815d33c..cfdf8ac 100644 --- a/shared/makefile +++ b/shared/makefile @@ -1,2 +1,5 @@ SOURCES += $(wildcard ../shared/*.c) HEADERS += $(wildcard ../shared/*.h) + +clean:: + rm -f ../shared/*.o -- cgit v1.2.3 From f353e78916a57fe21084fe34fd80c13ae4844d32 Mon Sep 17 00:00:00 2001 From: lonkaars Date: Thu, 26 May 2022 12:42:34 +0200 Subject: implement info command --- robot/hypervisor.c | 17 ++++++++++++++++- robot/hypervisor.h | 6 ++++++ robot/makefile | 2 +- robot/sercomm.c | 26 ++++++++++++++++++++++++-- robot/setup.c | 3 +++ shared/consts.h | 2 ++ shared/util.c | 6 ++++++ shared/util.h | 3 +++ 8 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 shared/util.c create mode 100644 shared/util.h (limited to 'robot/makefile') diff --git a/robot/hypervisor.c b/robot/hypervisor.c index c4e7aba..0baa406 100644 --- a/robot/hypervisor.c +++ b/robot/hypervisor.c @@ -1,11 +1,17 @@ #include "hypervisor.h" +#include "../shared/util.h" #include "errcatch.h" #include "io.h" #include "modes.h" #include "orangutan_shim.h" #include "sercomm.h" -uint64_t g_w2_hypervisor_cycles = 0; +uint64_t g_w2_hypervisor_cycles = 0; +uint64_t g_w2_hypervisor_uptime_ms = 0; +unsigned long g_w2_hypervisor_ema_sercomm_ms = 0; +unsigned long g_w2_hypervisor_ema_errcatch_ms = 0; +unsigned long g_w2_hypervisor_ema_io_ms = 0; +unsigned long g_w2_hypervisor_ema_mode_ms = 0; void w2_hypervisor_main() { #ifdef W2_SIM @@ -13,6 +19,7 @@ void w2_hypervisor_main() { if (DBG_ENABLE_CYCLEINFO) siminfo("cycle start\n"); #endif + g_w2_hypervisor_uptime_ms += get_ms(); time_reset(); w2_sercomm_main(); @@ -24,6 +31,14 @@ void w2_hypervisor_main() { w2_modes_main(); unsigned long mode_time = get_ms() - io_time; + // calculate exponential moving averages + g_w2_hypervisor_ema_sercomm_ms = + w2_util_exp_mov_avg(g_w2_hypervisor_ema_sercomm_ms, sercomm_time); + g_w2_hypervisor_ema_errcatch_ms = + w2_util_exp_mov_avg(g_w2_hypervisor_ema_errcatch_ms, errcatch_time); + g_w2_hypervisor_ema_io_ms = w2_util_exp_mov_avg(g_w2_hypervisor_ema_io_ms, io_time); + g_w2_hypervisor_ema_mode_ms = w2_util_exp_mov_avg(g_w2_hypervisor_ema_mode_ms, mode_time); + if (mode_time > W2_MAX_MODULE_CYCLE_MS) w2_errcatch_throw(W2_E_WARN_CYCLE_EXPIRED); #ifdef W2_SIM diff --git a/robot/hypervisor.h b/robot/hypervisor.h index 35fa64c..5008c8f 100644 --- a/robot/hypervisor.h +++ b/robot/hypervisor.h @@ -3,6 +3,12 @@ #include extern uint64_t g_w2_hypervisor_cycles; +extern uint64_t g_w2_hypervisor_uptime_ms; + +extern unsigned long g_w2_hypervisor_ema_sercomm_ms; +extern unsigned long g_w2_hypervisor_ema_errcatch_ms; +extern unsigned long g_w2_hypervisor_ema_io_ms; +extern unsigned long g_w2_hypervisor_ema_mode_ms; /** * backbone of all other modules diff --git a/robot/makefile b/robot/makefile index 6de886c..a6e96ee 100644 --- a/robot/makefile +++ b/robot/makefile @@ -32,7 +32,7 @@ OBJ2HEX=$(PREFIX)objcopy # debug build info string BUILD_STR=$(shell git update-index -q --refresh; git describe --tags --dirty='*' --broken='x' | cut -c1-20) -CFLAGS += -DW2_BUILD_STR="$(BUILD_STR)" +CFLAGS += -DW2_BUILD_STR=\"$(BUILD_STR)\" clean:: rm -f *.o out.hex a.out diff --git a/robot/sercomm.c b/robot/sercomm.c index 293e3c6..a3ccdb0 100644 --- a/robot/sercomm.c +++ b/robot/sercomm.c @@ -3,6 +3,7 @@ #include "../shared/bin.h" #include "../shared/serial_parse.h" +#include "hypervisor.h" #include "orangutan_shim.h" #include "sercomm.h" @@ -53,7 +54,7 @@ void w2_cmd_ping_rx(w2_s_bin *data) { size_t return_size = sizeof(w2_s_cmd_ping_tx); w2_s_cmd_ping_tx *return_message = malloc(return_size); - return_message->opcode = (message->opcode & W2_CMD_DIRECTION_MASK) | W2_CMDDIR_TX; + return_message->opcode = W2_CMD_PING | W2_CMDDIR_TX; return_message->id = message->id; w2_s_bin *return_message_bin = w2_bin_s_alloc(return_size, (uint8_t *)return_message); @@ -81,7 +82,28 @@ void w2_cmd_mcfg_rx(w2_s_bin *data) { return; } void w2_cmd_sens_rx(w2_s_bin *data) { return; } -void w2_cmd_info_rx(w2_s_bin *data) { return; } +void w2_cmd_info_rx(w2_s_bin *data) { + w2_s_cmd_info_rx *message = malloc(w2_cmd_sizeof(data->data, data->bytes)); + memcpy(message, data->data, data->bytes); + + size_t return_size = sizeof(w2_s_cmd_info_tx); + w2_s_cmd_info_tx *return_message = malloc(return_size); + return_message->opcode = W2_CMD_INFO | W2_CMDDIR_TX; + strncpy((char *)return_message->build_str, W2_BUILD_STR, sizeof(return_message->build_str)); + return_message->errcatch_ms = (uint8_t)g_w2_hypervisor_ema_errcatch_ms; + return_message->io_ms = (uint8_t)g_w2_hypervisor_ema_io_ms; + return_message->sercomm_ms = (uint8_t)g_w2_hypervisor_ema_sercomm_ms; + return_message->mode_ms = (uint8_t)g_w2_hypervisor_ema_mode_ms; + return_message->uptime_s = w2_bin_hton32((uint32_t)(g_w2_hypervisor_uptime_ms / 1e3)); + + w2_s_bin *return_message_bin = w2_bin_s_alloc(return_size, (uint8_t *)return_message); + + w2_sercomm_append_msg(return_message_bin); + + free(message); + free(return_message); + free(return_message_bin); +} void w2_cmd_disp_rx(w2_s_bin *data) { return; } diff --git a/robot/setup.c b/robot/setup.c index f8468bf..d075c41 100644 --- a/robot/setup.c +++ b/robot/setup.c @@ -29,6 +29,9 @@ void w2_setup_main() { serial_set_baud_rate(W2_SERIAL_BAUD); serial_receive_ring(g_w2_serial_buffer, W2_SERIAL_READ_BUFFER_SIZE); + // reset timer + time_reset(); + // indicate startup done play("L50 c>c"); } diff --git a/shared/consts.h b/shared/consts.h index 70efcac..f9d4c11 100644 --- a/shared/consts.h +++ b/shared/consts.h @@ -15,3 +15,5 @@ #define W2_SERCOMM_BUFFER_SIZE (16) /** size of input (receive) buffer (in bytes) */ #define W2_SERIAL_READ_BUFFER_SIZE (255) +/** exponential moving average new measurement weight (double 0-1) */ +#define W2_EMA_WEIGHT (0.10) diff --git a/shared/util.c b/shared/util.c new file mode 100644 index 0000000..55f3491 --- /dev/null +++ b/shared/util.c @@ -0,0 +1,6 @@ +#include "consts.h" + +unsigned long w2_util_exp_mov_avg(unsigned long current_avg, unsigned long new_meas) { + return (unsigned long)((((double)(current_avg)) * ((double)(1.f - W2_EMA_WEIGHT))) + + (((double)(new_meas)) * ((double)(W2_EMA_WEIGHT)))); +} diff --git a/shared/util.h b/shared/util.h new file mode 100644 index 0000000..95f4c68 --- /dev/null +++ b/shared/util.h @@ -0,0 +1,3 @@ +#pragma once + +unsigned long w2_util_exp_mov_avg(unsigned long current_avg, unsigned long new_meas); -- cgit v1.2.3