From 061bc4bfa1cdbc4a6db18852d58d5fcf5e65430f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 5 Sep 2024 17:50:17 +1000 Subject: [PATCH] added pin_finder firmware this allows for finding the pinout of an unknown ESC --- Makefile | 44 ++++++++++- pin_finder/main.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 pin_finder/main.c diff --git a/Makefile b/Makefile index cb335419..4d6b29ee 100644 --- a/Makefile +++ b/Makefile @@ -111,6 +111,7 @@ endef # list of targets formed using CREATE_BOOTLOADER_TARGET ALL_BUILDS := +#################################################################################### # create a bootloader build target given a build in the form MCU or MCU_nK and a PIN define CREATE_BOOTLOADER_TARGET $(eval BUILD := $(1)) @@ -129,7 +130,7 @@ $(eval xLDSCRIPT := $(if $($(MCU)_LDSCRIPT), $($(MCU)_LDSCRIPT), $(LDSCRIPT_BL)) -include $(DEP_FILE) -$(ELF_FILE): CFLAGS_BL := $$(MCU_$(MCU)) $$(CFLAGS_$(MCU)) $$(CFLAGS_BASE) -DBOOTLOADER -DUSE_$(PIN) $(EXTRA_CFLAGS) +$(ELF_FILE): CFLAGS_BL := $$(MCU_$(MCU)) $$(CFLAGS_$(MCU)) $$(CFLAGS_BASE) -DUSE_$(PIN) $(EXTRA_CFLAGS) $(ELF_FILE): LDFLAGS_BL := $$(LDFLAGS_COMMON) $$(LDFLAGS_$(MCU)) -T$(xLDSCRIPT) $(ELF_FILE): $$(SRC_$(MCU)_BL) $$(SRC_BL) $$(QUIET)echo building bootloader for $(BUILD) with pin $(PIN) @@ -151,8 +152,49 @@ $(TARGET): $(HEX_FILE) ALL_BUILDS := $(ALL_BUILDS) $(TARGET) endef + +############################################# +# create a pinfinder build target given a MCU +define CREATE_PINFINDER_TARGET +$(eval MCU := $$(1)) +$(eval ELF_FILE := $(BIN_DIR)/PINFINDER_$(MCU).elf) +$(eval HEX_FILE := $(ELF_FILE:.elf=.hex)) +$(eval DEP_FILE := $(ELF_FILE:.elf=.d)) +$(eval TARGET := PINFINDER_$(MCU)) + +# get MCU specific compiler, objcopy and link script or use the ARM SDK one +$(eval xCC := $(if $($(MCU)_CC), $($(MCU)_CC), $(CC))) +$(eval xOBJCOPY := $(if $($(MCU)_OBJCOPY), $($(MCU)_OBJCOPY), $(OBJCOPY))) +$(eval xLDSCRIPT := $(if $($(MCU)_LDSCRIPT), $($(MCU)_LDSCRIPT), $(LDSCRIPT_BL))) + +-include $(DEP_FILE) + +$(ELF_FILE): CFLAGS_BL := $$(MCU_$(MCU)) $$(CFLAGS_$(MCU)) $$(CFLAGS_BASE) $(EXTRA_CFLAGS) +$(ELF_FILE): LDFLAGS_BL := $$(LDFLAGS_COMMON) $$(LDFLAGS_$(MCU)) -T$(xLDSCRIPT) +$(ELF_FILE): $$(SRC_$(MCU)_BL) pin_finder/main.c + $$(QUIET)echo building pinfinder for $(MCU) + $$(QUIET)$$(MKDIR) -p $(OBJ) + $$(QUIET)echo Compiling $(notdir $$@) + $$(QUIET)$(xCC) $$(CFLAGS_BL) $$(LDFLAGS_BL) -MMD -MP -MF $(DEP_FILE) -o $$(@) $$(SRC_$(MCU)_BL) pin_finder/main.c + $$(QUIET)$$(CP) -f $$@ $$(OBJ)$$(DSEP)debug.elf + $$(QUIET)$$(CP) -f Mcu$(DSEP)$(call lc,$(MCU))$(DSEP)openocd.cfg $$(OBJ)$$(DSEP)openocd.cfg > $$(NUL) + +# Generate bin and hex files +$(HEX_FILE): $(ELF_FILE) + $$(QUIET)echo Generating $(notdir $$@) + $$(QUIET)$(xOBJCOPY) -O binary $$(<) $$(@:.hex=.bin) + $$(QUIET)$(xOBJCOPY) $$(<) -O ihex $$(@:.bin=.hex) + +$(TARGET): $(HEX_FILE) + +# add to list +ALL_BUILDS := $(ALL_BUILDS) $(TARGET) +endef + $(foreach BUILD,$(MCU_BUILDS),$(foreach PIN,$(BOOTLOADER_PINS),$(eval $(call CREATE_BOOTLOADER_TARGET,$(BUILD),$(PIN))))) +$(foreach BUILD,$(MCU_TYPES),$(eval $(call CREATE_PINFINDER_TARGET,$(BUILD)))) + bootloaders: $(ALL_BUILDS) # include the targets for installing tools diff --git a/pin_finder/main.c b/pin_finder/main.c new file mode 100644 index 00000000..556244a8 --- /dev/null +++ b/pin_finder/main.c @@ -0,0 +1,184 @@ +/* + bootloader for AM32 ESC firmware + + based on https://github.com/AlkaMotors/AT32F421_AM32_Bootloader + */ +#include +#include + +#include + +/* Includes ------------------------------------------------------------------*/ +#include +#include + +#pragma GCC optimize("O0") + +#include + +#define GPIO_PORT_TYPE typeof(GPIOA) + +static GPIO_PORT_TYPE input_port; +static uint32_t input_pin; + +#define MCU_FLASH_START 0x08000000 +#define FIRMWARE_RELATIVE_START 0x1000 + +#define BAUDRATE 2400 +#define BITTIME (1000000/BAUDRATE) +#define HALFBITTIME (500000/BAUDRATE) + +#include + +static void setTransmit() +{ + gpio_set(input_pin); + gpio_mode_set_output(input_pin, GPIO_OUTPUT_PUSH_PULL); +} + +static void delayMicroseconds(uint32_t micros) +{ + while (micros > 0) { + uint32_t us = micros>10000?10000:micros; + bl_timer_reset(); + while (bl_timer_us() < us) ; + micros -= us; + } +} + +static void serialwriteChar(uint8_t data) +{ + // start bit is low + gpio_clear(input_pin); + delayMicroseconds(BITTIME); + + // send data bits + uint8_t bits_written = 0; + while (bits_written < 8) { + if (data & 0x01) { + gpio_set(input_pin); + } else { + // GPIO_BC(input_port) = input_pin; + gpio_clear(input_pin); + } + bits_written++; + data = data >> 1; + delayMicroseconds(BITTIME); + } + + // send stop bit + gpio_set(input_pin); + delayMicroseconds(BITTIME); +} + +static void sendString(const uint8_t *data, int len) +{ + for(int i = 0; i < len; i++){ + serialwriteChar(data[i]); + } +} + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +static bool is_debug(uint8_t portnum, uint32_t pin) { + return portnum == 0 && (pin == 13 || pin == 14); +} + +static struct { + const char *pname; + GPIO_PORT_TYPE port; +} ports[] = { + { "PA", GPIOA }, + { "PB", GPIOB }, +}; + +static void pin_scanner(void) +{ + for (uint8_t i=0; i< ARRAY_SIZE(ports); i++) { + for (uint8_t p=0; p< 16; p++) { + if (is_debug(i, p)) { + continue; + } + + for (uint8_t i2=0; i2< ARRAY_SIZE(ports); i2++) { + for (uint8_t p2=0; p2< 16; p2++) { + if (is_debug(i2, p2)) { + continue; + } + if (i == i2 && p == p2) { + continue; + } + input_port = ports[i].port; + input_pin = GPIO_PIN(p); + + /* + write the pin combination to the proposed signal pin + */ + char str[12]; + str[0] = '['; + strncpy(&str[1], ports[i].pname, sizeof(str)-1); + str[3] = '0' + (p / 10); + str[4] = '0' + (p % 10); + str[5] = ':'; + strncpy(&str[6], ports[i2].pname, sizeof(str)-6); + str[8] = '0' + (p2 / 10); + str[9] = '0' + (p2 % 10); + str[10] = ']'; + str[11] = 0; + + setTransmit(); + gpio_set(input_pin); + delayMicroseconds(1000); + + sendString((const uint8_t *)str, strlen(str)); + + gpio_mode_set_input(input_pin, GPIO_PULL_NONE); + + delayMicroseconds(200); + + /* + oscillate the 2nd pin 10 times, 500us high, 1000us low + */ + input_port = ports[i2].port; + input_pin = GPIO_PIN(p2); + setTransmit(); + delayMicroseconds(200); + for (uint16_t c=0;c<5;c++) { + gpio_set(input_pin); + delayMicroseconds(500); + gpio_clear(input_pin); + delayMicroseconds(1000); + } + gpio_mode_set_input(input_pin, GPIO_PULL_NONE); + } + } + } + } +} + +int main(void) +{ + bl_clock_config(); + bl_timer_init(); + + // give time for debugger to attach + delayMicroseconds(3000000); + + // setup all as float input + for (uint8_t i=0; i< ARRAY_SIZE(ports); i++) { + for (uint8_t p=0; p< 16; p++) { + if (is_debug(i, p)) { + continue; + } + input_port = ports[i].port; + input_pin = GPIO_PIN(p); + bl_gpio_init(); + gpio_mode_set_input(input_pin, GPIO_PULL_NONE); + } + } + + while (true) { + pin_scanner(); + } + return 0; +}