From ca76106df3772012f6f851937c21489bc6ef4def Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Thu, 3 Nov 2022 21:12:50 +0300 Subject: [PATCH 1/7] [nix] Add build instructions for nix This auto-fetches STM32 CUBE HAL libraries from github v1.8.4, builds firmware and generate helper scripts: * flasher - to flash the firmware * debug - to run debugger in background and connect gdb to it Simple process to use: $ nix-build $ ./result/flasher $ ./result/debug ... (gdb) Change-Id: Ibd68ce0ef40f1feb5ef731dca99088f2ff8013ea --- default.nix | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 default.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..6884e8b --- /dev/null +++ b/default.nix @@ -0,0 +1,71 @@ +let pkgs = import {}; + stdenv = pkgs.stdenv; + stflash = "${pkgs.stlink}/bin/st-flash"; + stutil = "${pkgs.stlink}/bin/st-util"; + simplescript = body: let + name = "__binscript"; + script = pkgs.writeShellScriptBin name body; + in "${script}/bin/${name}"; + + getoneof = simplescript '' + files="$(eval echo "$*")" + nfiles="$(echo "$files" | wc -w)" + if [ x"$nfiles" == x"1" ] && [ -f "$files" ]; then + echo "$files" + exit 0 + fi + exit 1 + ''; + flasher = simplescript '' + set -e + ${stflash} --reset write "$(${getoneof} "$1/*.bin")" 0x8000000 || true + ''; + rungdb = let + runner = simplescript '' + set -e + port="$(( $RANDOM % 10000 + 42424 ))" + stpid= + elf="$1" + function cleanup { + if [ -n "$stpid" ]; then + echo "Stopping stutil on $stpid" + kill $stpid + wait $stpid + fi + } + trap cleanup EXIT + ${stutil} -p $port >/dev/null 2>/dev/null & + stpid="$!" + ${pkgs.gdb}/bin/gdb "$elf" -ex 'target extended-remote localhost:'"$port" + ''; + in simplescript '' + set -e + exec ${runner} "$(${getoneof} "$1/*.elf")" + ''; +in +stdenv.mkDerivation { + name = "bluepill-serial-monster"; + buildInputs = with pkgs; [ + pkgs.libusb1 + gcc-arm-embedded + ]; + src = ./.; + STM32CUBE_PATH = pkgs.fetchFromGitHub { + owner = "STMicroelectronics"; + repo = "STM32CubeF1"; + rev = "v1.8.4"; + sha256 = "ICGgQCkY5E5Lcd7+U+hX5+MJcTF7J51NFDx6iy/SfgA="; + }; + installPhase = '' + mkdir -p "$out" + cp *.bin "$out" + cp *.elf "$out" + echo '#!/bin/bash' > $out/flasher + echo "exec ${flasher} \"$out\"" >> "$out/flasher" + chmod +x "$out/flasher" + echo '#!/bin/bash' > $out/debug + echo "exec ${rungdb} \"$out\"" >> "$out/debug" + chmod +x "$out/debug" + ''; + postInstall = "true"; +} From 0c13f7e3352b663f6303f24bf316f06c6fff59f5 Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Fri, 28 Oct 2022 21:27:39 +0300 Subject: [PATCH 2/7] Auto remove all trailing wihitespaces Before introducing any improvements fix trivial formating issue --- Makefile | 2 +- cdc_config.h | 4 ++-- cdc_shell.c | 10 +++++----- cdc_shell.h | 4 ++-- circ_buf.h | 4 ++-- device_config.c | 12 ++++++------ device_config.h | 4 ++-- gpio.c | 6 +++--- gpio.h | 4 ++-- main.c | 4 ++-- status_led.c | 4 ++-- status_led.h | 4 ++-- system_clock.c | 4 ++-- system_clock.h | 4 ++-- usb.h | 4 ++-- usb_cdc.c | 14 +++++++------- usb_cdc.h | 4 ++-- usb_core.c | 10 +++++----- usb_core.h | 6 +++--- usb_descriptors.c | 16 ++++++++-------- usb_descriptors.h | 4 ++-- usb_io.c | 6 +++--- usb_io.h | 4 ++-- usb_panic.c | 4 ++-- usb_panic.h | 4 ++-- usb_std.h | 6 +++--- usb_uid.c | 4 ++-- usb_uid.h | 4 ++-- version.h | 4 ++-- 29 files changed, 82 insertions(+), 82 deletions(-) diff --git a/Makefile b/Makefile index 3a3f7b4..545a24f 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ WARNINGS = -Wall OPTIMIZATION = -O3 DEBUG = -ggdb -CFLAGS = $(DEFINES) $(STM32_INCLUDES) $(CPUFLAGS) $(WARNINGS) $(OPTIMIZATION) $(DEBUG) +CFLAGS = $(DEFINES) $(STM32_INCLUDES) $(CPUFLAGS) $(WARNINGS) $(OPTIMIZATION) $(DEBUG) LDFLAGS = $(CPUFLAGS) -T$(STM32_LDSCRIPT) --specs=nosys.specs --specs=nano.specs DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)/$*.d diff --git a/cdc_config.h b/cdc_config.h index 045c843..5a43dcd 100644 --- a/cdc_config.h +++ b/cdc_config.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/cdc_shell.c b/cdc_shell.c index 72d50e7..c78117f 100644 --- a/cdc_shell.c +++ b/cdc_shell.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -323,7 +323,7 @@ static void cdc_shell_cmd_uart(int argc, char *argv[]) { } } else { cdc_shell_write_string(cdc_shell_err_uart_missing_arguments); - } + } } @@ -360,7 +360,7 @@ static void cdc_shell_cmd_version(int argc, char *argv[]) { static void cdc_shell_cmd_help(int argc, char *argv[]); static const cdc_shell_cmd_t cdc_shell_commands[] = { - { + { .cmd = "help", .handler = cdc_shell_cmd_help, .description = "shows this help message, use \"help command-name\" to get command-specific help", @@ -374,7 +374,7 @@ static const cdc_shell_cmd_t cdc_shell_commands[] = { "Use: \"config save\" to permanently save device configuration.\r\n" "Use: \"config reset\" to reset device configuration to default.", }, - { + { .cmd = "uart", .handler = cdc_shell_cmd_uart, .description = "set and view UART parameters", diff --git a/cdc_shell.h b/cdc_shell.h index 4e16db7..45bb0b2 100644 --- a/cdc_shell.h +++ b/cdc_shell.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/circ_buf.h b/circ_buf.h index 1cfb48e..a43fb30 100644 --- a/circ_buf.h +++ b/circ_buf.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/device_config.c b/device_config.c index a510ce2..6587249 100644 --- a/device_config.c +++ b/device_config.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -23,7 +23,7 @@ static const device_config_t default_device_config = { .port_config = { /* Port 0 */ { - .pins = + .pins = { /* rx */ { .port = GPIOA, .pin = 10, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, /* tx */ { .port = GPIOA, .pin = 9, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high }, @@ -38,7 +38,7 @@ static const device_config_t default_device_config = { }, /* Port 1 */ { - .pins = + .pins = { /* rx */ { .port = GPIOA, .pin = 3, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, /* tx */ { .port = GPIOA, .pin = 2, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high }, @@ -53,7 +53,7 @@ static const device_config_t default_device_config = { }, /* Port 2 */ { - .pins = + .pins = { /* rx */ { .port = GPIOB, .pin = 11, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, /* tx */ { .port = GPIOB, .pin = 10, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high }, @@ -176,4 +176,4 @@ void device_config_save() { void device_config_reset() { memcpy(¤t_device_config, &default_device_config, sizeof(default_device_config)); device_config_save(); -} \ No newline at end of file +} diff --git a/device_config.h b/device_config.h index 0269bf0..1fd2f26 100644 --- a/device_config.h +++ b/device_config.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/gpio.c b/gpio.c index d2d265a..86c90bf 100644 --- a/gpio.c +++ b/gpio.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -51,7 +51,7 @@ void gpio_pin_init(const gpio_pin_t *pin) { void gpio_pin_set(const gpio_pin_t *pin, int is_active) { if (pin->port) { - pin->port->BSRR = (GPIO_BSRR_BS0 << pin->pin) + pin->port->BSRR = (GPIO_BSRR_BS0 << pin->pin) << (!!is_active != (pin->polarity == gpio_polarity_low) ? 0 : GPIO_BSRR_BR0_Pos); } } diff --git a/gpio.h b/gpio.h index 32085a8..160f921 100644 --- a/gpio.h +++ b/gpio.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/main.c b/main.c index 1befa66..dc37acd 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/status_led.c b/status_led.c index defc35e..cd5e95e 100644 --- a/status_led.c +++ b/status_led.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/status_led.h b/status_led.h index f2177d6..fc02bfa 100644 --- a/status_led.h +++ b/status_led.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/system_clock.c b/system_clock.c index 084910a..3b70f31 100644 --- a/system_clock.c +++ b/system_clock.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/system_clock.h b/system_clock.h index e84c91e..f7a7afb 100644 --- a/system_clock.h +++ b/system_clock.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb.h b/usb.h index 1f21ab5..bda9ffe 100644 --- a/usb.h +++ b/usb.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb_cdc.c b/usb_cdc.c index b48f4b5..9ac8bea 100644 --- a/usb_cdc.c +++ b/usb_cdc.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -26,7 +26,7 @@ static uint8_t usb_cdc_config_mode = 0; static const usb_cdc_line_coding_t usb_cdc_default_line_coding = { .dwDTERate = 9600, - .bCharFormat = usb_cdc_char_format_1_stop_bit, + .bCharFormat = usb_cdc_char_format_1_stop_bit, .bParityType = usb_cdc_parity_type_none, .bDataBits = 8, }; @@ -77,11 +77,11 @@ static DMA_Channel_TypeDef* usb_cdc_get_port_dma_channel(int port, usb_cdc_port_ { DMA1_Channel6, DMA1_Channel7 }, { DMA1_Channel3, DMA1_Channel2 }, }; - if (port < (sizeof(port_dma_channels) / sizeof(*port_dma_channels)) && + if (port < (sizeof(port_dma_channels) / sizeof(*port_dma_channels)) && port_dir < usb_cdc_port_direction_last) { return port_dma_channels[port][port_dir]; } - return (DMA_Channel_TypeDef*)0; + return (DMA_Channel_TypeDef*)0; } static uint8_t const usb_cdc_port_data_endpoints[] = { @@ -579,7 +579,7 @@ void usb_cdc_reset() { NVIC_EnableIRQ(DMA1_Channel4_IRQn); NVIC_SetPriority(DMA1_Channel7_IRQn, SYSTEM_INTERRUTPS_PRIORITY_HIGH); NVIC_EnableIRQ(DMA1_Channel7_IRQn); - /* + /* * Disable JTAG interface (SWD is still enabled), * this frees PA15, PB3, PB4 (needed for DSR/RI inputs). */ @@ -720,7 +720,7 @@ usb_status_t usb_cdc_ctrl_process_request(usb_setup_t *setup, void **payload, if (setup->wLength == sizeof(usb_cdc_line_coding_t)) { int dry_run = 0; circ_buf_t *tx_buf = &usb_cdc_states[port].tx_buf; - /* + /* * If the TX buffer is not empty, defer setting * line coding until all data are sent over the serial port. */ diff --git a/usb_cdc.h b/usb_cdc.h index c37bc7c..f98fa2d 100644 --- a/usb_cdc.h +++ b/usb_cdc.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb_core.c b/usb_core.c index eb089b7..c5d7589 100644 --- a/usb_core.c +++ b/usb_core.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -26,7 +26,7 @@ static struct { void usb_device_handle_reset() { usb_device.state = usb_device_state_reset; - usb_device.address = 0; + usb_device.address = 0; usb_device.configuration = 0; usb_cdc_reset(); usb_io_reset(); @@ -262,7 +262,7 @@ static void usb_control_endpoint_process_rx(uint8_t ep_num) { usb_control_ep_struct.setup = (usb_setup_t *)&usb_control_ep_struct.setup_buf; usb_control_ep_struct.payload = usb_control_ep_struct.setup->payload; usb_control_ep_struct.payload_size = usb_control_ep_struct.setup->wLength; - if ((usb_control_ep_struct.setup->direction == usb_setup_direction_host_to_device) && + if ((usb_control_ep_struct.setup->direction == usb_setup_direction_host_to_device) && (usb_control_ep_struct.setup->wLength != 0)) { if (usb_control_ep_struct.payload_size > USB_SETUP_MAX_PAYLOAD_SIZE) { usb_control_endpoint_stall(ep_num); @@ -295,7 +295,7 @@ static void usb_control_endpoint_process_rx(uint8_t ep_num) { switch (usb_control_endpoint_process_request(usb_control_ep_struct.setup, &usb_control_ep_struct.payload, &usb_control_ep_struct.payload_size, - &usb_control_ep_struct.tx_complete_callback)) { + &usb_control_ep_struct.tx_complete_callback)) { case usb_status_ack: if (usb_control_ep_struct.setup->direction == usb_setup_direction_device_to_host) { if (usb_control_ep_struct.payload_size < usb_control_ep_struct.setup->wLength) { diff --git a/usb_core.h b/usb_core.h index 3db5da9..b0e5080 100644 --- a/usb_core.h +++ b/usb_core.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -37,7 +37,7 @@ void usb_control_endpoint_event_handler(uint8_t ep_num, usb_endpoint_event_t ep_ typedef enum { usb_device_state_reset = 0x00, usb_device_state_address_set = 0x01, - usb_device_state_configured = 0x02, + usb_device_state_configured = 0x02, } usb_device_state_t; /* Device Level Events */ diff --git a/usb_descriptors.c b/usb_descriptors.c index 59b8348..76f7fcc 100644 --- a/usb_descriptors.c +++ b/usb_descriptors.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -29,42 +29,42 @@ const usb_endpoint_t usb_endpoints[usb_endpoint_address_last] = { .event_handler = usb_control_endpoint_event_handler, }, /* CDC 0 Interrupt Endpoint */ - { + { .type = usb_endpoint_type_interrupt, .rx_size = 0, .tx_size = USB_CDC_INTERRUPT_ENDPOINT_SIZE, .event_handler = 0, }, /* CDC 0 Data Endpoint */ - { + { .type = usb_endpoint_type_bulk, .rx_size = USB_CDC_DATA_0_ENDPOINT_SIZE, .tx_size = USB_CDC_DATA_0_ENDPOINT_SIZE, .event_handler = usb_cdc_data_endpoint_event_handler, }, /* CDC 1 Interrupt Endpoint */ - { + { .type = usb_endpoint_type_interrupt, .rx_size = 0, .tx_size = USB_CDC_INTERRUPT_ENDPOINT_SIZE, .event_handler = 0, }, /* CDC 1 Data Endpoint */ - { + { .type = usb_endpoint_type_bulk, .rx_size = USB_CDC_DATA_1_ENDPOINT_SIZE, .tx_size = USB_CDC_DATA_1_ENDPOINT_SIZE, .event_handler = usb_cdc_data_endpoint_event_handler, }, /* CDC 2 Interrupt Endpoint */ - { + { .type = usb_endpoint_type_interrupt, .rx_size = 0, .tx_size = USB_CDC_INTERRUPT_ENDPOINT_SIZE, .event_handler = 0, }, /* CDC 2 Data Endpoint */ - { + { .type = usb_endpoint_type_bulk, .rx_size = USB_CDC_DATA_2_ENDPOINT_SIZE, .tx_size = USB_CDC_DATA_2_ENDPOINT_SIZE, diff --git a/usb_descriptors.h b/usb_descriptors.h index 4cbbd65..f9f9c55 100644 --- a/usb_descriptors.h +++ b/usb_descriptors.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb_io.c b/usb_io.c index 6c257f4..10652d3 100644 --- a/usb_io.c +++ b/usb_io.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -245,7 +245,7 @@ void usb_poll() { status_led_set(1); } else if (istr & USB_ISTR_RESET) { USB->ISTR = (uint16_t)(~USB_ISTR_RESET); - usb_device_handle_reset(); + usb_device_handle_reset(); } else if (istr & USB_ISTR_SUSP) { USB->ISTR = (uint16_t)(~USB_ISTR_SUSP); USB->CNTR |= USB_CNTR_FSUSP; diff --git a/usb_io.h b/usb_io.h index 71e4ad8..2fd88e4 100644 --- a/usb_io.h +++ b/usb_io.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb_panic.c b/usb_panic.c index 81f589b..fd0373d 100644 --- a/usb_panic.c +++ b/usb_panic.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb_panic.h b/usb_panic.h index 14838b9..f63ddb3 100644 --- a/usb_panic.h +++ b/usb_panic.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb_std.h b/usb_std.h index d4a5843..d538b1d 100644 --- a/usb_std.h +++ b/usb_std.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ @@ -119,7 +119,7 @@ typedef struct { /* USB Interface Descriptor */ typedef struct { - uint8_t bLength; + uint8_t bLength; uint8_t bDescriptorType; uint8_t bInterfaceNumber; uint8_t bAlternateSetting; diff --git a/usb_uid.c b/usb_uid.c index 5c48a98..216f1b2 100644 --- a/usb_uid.c +++ b/usb_uid.c @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/usb_uid.h b/usb_uid.h index 749c34f..5b3ca67 100644 --- a/usb_uid.h +++ b/usb_uid.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2020 Kirill Kotyagin */ diff --git a/version.h b/version.h index ad543bf..e006b27 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ /* - * MIT License - * + * MIT License + * * Copyright (c) 2022 Kirill Kotyagin */ From 031914bc65aee83f5d8c15212b7c87fea50d7893 Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Fri, 28 Oct 2022 21:40:18 +0300 Subject: [PATCH 3/7] Invert configuration shell pin For now shell is enabled by default. Connect **PB5** pin to ground to disable it. --- README.md | 5 +++-- device_config.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1eecd96..30ab1af 100644 --- a/README.md +++ b/README.md @@ -198,8 +198,9 @@ _bluepill-serial-monster_ provides a configuration shell that allows controlling various parameters of the UART signal lines. To access the configuration shell, open the first USB serial port (UART1) -with any terminal emulator application (such as _screen_, _Tera Term_, etc.) -and connect **PB5** to ground. Serial port settings do not matter. +with any terminal emulator application (such as _screen_, _Tera Term_, etc.). It +is enabled by default. To disable configuration shell - connect **PB5** to +ground. Serial port settings do not matter. You should see the configuration shell prompt: diff --git a/device_config.c b/device_config.c index 6587249..0ee27ac 100644 --- a/device_config.c +++ b/device_config.c @@ -18,7 +18,7 @@ static const device_config_t default_device_config = { .status_led_pin = { .port = GPIOC, .pin = 13, .dir = gpio_dir_output, .speed = gpio_speed_low, .func = gpio_func_general, .output = gpio_output_od, .polarity = gpio_polarity_low }, - .config_pin = { .port = GPIOB, .pin = 5, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, + .config_pin = { .port = GPIOB, .pin = 5, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, .cdc_config = { .port_config = { /* Port 0 */ From 782715953c575c68c090ea519547f9ddd660f7e4 Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Tue, 1 Nov 2022 23:18:07 +0300 Subject: [PATCH 4/7] Add aux.h file Implements several macros for shorten aliases for some __attribute__, ARRAY_SIZE and BUILD_BUG --- aux.h | 43 +++++++++++++++++++++++++++++++++++++++++++ cdc_shell.c | 13 ++++++------- device_config.h | 2 +- gpio.h | 16 +++++++++------- usb_cdc.c | 16 ++++++++-------- usb_cdc.h | 34 ++++++++++++++++++---------------- usb_descriptors.h | 5 +++-- usb_io.h | 6 ++++-- usb_std.h | 38 ++++++++++++++++++++------------------ 9 files changed, 112 insertions(+), 61 deletions(-) create mode 100644 aux.h diff --git a/aux.h b/aux.h new file mode 100644 index 0000000..2821007 --- /dev/null +++ b/aux.h @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (c) 2022 Yury Shvedov + */ + +#ifndef AUX_H +#define AUX_H + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) // From linux kernel +#define BUILD_BUG_ON_RET(condition, ret) ({ BUILD_BUG_ON(condition); (ret); }) + +#ifndef __packed +#define __packed __attribute__ ((packed)) +#endif + +#ifndef __packed_aligned +#define __packed_aligned(n) __attribute__ ((packed, aligned(n))) +#endif + +#ifndef __wpacked +#define __wpacked __packed_aligned(4) +#endif + +#ifndef __spacked +#define __spacked __packed_aligned(2) +#endif + +#ifndef __aligned +#define __aligned(n) __attribute__ ((aligned(n))) +#endif + +#ifndef __noinline +#define __noinline __attribute__ ((noinline)) +#endif + +#ifndef __always_inline +#define __always_inline __attribute__ ((always_inline)) +#endif + + +#endif /* AUX_H */ diff --git a/cdc_shell.c b/cdc_shell.c index c78117f..d5a5683 100644 --- a/cdc_shell.c +++ b/cdc_shell.c @@ -38,8 +38,7 @@ typedef struct { /* Shell Helper Functions */ -__attribute__ ((noinline)) -static void cdc_shell_write_string(const char *buf) { +__noinline static void cdc_shell_write_string(const char *buf) { cdc_shell_write(buf, strlen(buf)); } @@ -78,7 +77,7 @@ static const char *_cdc_uart_signal_names[cdc_pin_last] = { }; static cdc_pin_t _cdc_uart_signal_by_name(char *name) { - for (int i = 0; i < sizeof(_cdc_uart_signal_names)/sizeof(*_cdc_uart_signal_names); i++) { + for (int i = 0; i < ARRAY_SIZE(_cdc_uart_signal_names); i++) { if (strcmp(name, _cdc_uart_signal_names[i]) == 0) { return (cdc_pin_t)i; } @@ -91,7 +90,7 @@ static const char *_cdc_uart_output_types[gpio_output_last] = { }; static gpio_output_t _cdc_uart_output_type_by_name(char *name) { - for (int i = 0; i< sizeof(_cdc_uart_output_types)/sizeof(*_cdc_uart_output_types); i++) { + for (int i = 0; i < ARRAY_SIZE(_cdc_uart_output_types); i++) { if (strcmp(name, _cdc_uart_output_types[i]) == 0) { return (gpio_output_t)i; } @@ -104,7 +103,7 @@ static const char *_cdc_uart_polarities[gpio_polarity_last] = { }; static gpio_polarity_t _cdc_uart_polarity_by_name(char *name) { - for (int i = 0; i< sizeof(_cdc_uart_polarities)/sizeof(*_cdc_uart_polarities); i++) { + for (int i = 0; i < ARRAY_SIZE(_cdc_uart_polarities); i++) { if (strcmp(name, _cdc_uart_polarities[i]) == 0) { return (gpio_polarity_t)i; } @@ -117,7 +116,7 @@ static const char *_cdc_uart_pull_types[gpio_pull_last] = { }; static gpio_pull_t _cdc_uart_pull_type_by_name(char *name) { - for (int i = 0; i< sizeof(_cdc_uart_pull_types)/sizeof(*_cdc_uart_pull_types); i++) { + for (int i = 0; i < ARRAY_SIZE(_cdc_uart_pull_types); i++) { if (strcmp(name, _cdc_uart_pull_types[i]) == 0) { return (gpio_pull_t)i; } @@ -591,7 +590,7 @@ void cdc_shell_process_input(const void *buf, size_t count) { cdc_shell_handle_backspace(); } else if (isprint(*(unsigned char *)(buf_p))) { cdc_shell_insert_symbol(*buf_p); - if ((cmd_line_cursor - cmd_line_buf) >= sizeof(cmd_line_buf)/sizeof(*cmd_line_buf)) { + if ((cmd_line_cursor - cmd_line_buf) >= ARRAY_SIZE(cmd_line_buf)) { cdc_shell_clear_cmd_buf(); cdc_shell_write_string(cdc_shell_new_line); cdc_shell_write_string(cdc_shell_err_too_long); diff --git a/device_config.h b/device_config.h index 1fd2f26..5395eae 100644 --- a/device_config.h +++ b/device_config.h @@ -17,7 +17,7 @@ typedef struct { gpio_pin_t config_pin; cdc_config_t cdc_config; uint32_t crc; /* should be the last member of the struct */ -} __attribute__ ((packed, aligned(4))) device_config_t; +} __wpacked device_config_t; void device_config_init(); device_config_t *device_config_get(); diff --git a/gpio.h b/gpio.h index 160f921..66ea8f5 100644 --- a/gpio.h +++ b/gpio.h @@ -10,26 +10,28 @@ #include #include +#include "aux.h" + typedef enum { gpio_dir_input, gpio_dir_output, gpio_dir_unknown, gpio_dir_last = gpio_dir_unknown -} __attribute__ ((packed)) gpio_dir_t; +} __packed gpio_dir_t; typedef enum { gpio_func_general, gpio_func_alternate, gpio_func_unknown, gpio_func_last = gpio_func_unknown -} __attribute__ ((packed)) gpio_func_t; +} __packed gpio_func_t; typedef enum { gpio_output_pp, gpio_output_od, gpio_output_unknown, gpio_output_last = gpio_output_unknown -} __attribute__ ((packed)) gpio_output_t; +} __packed gpio_output_t; typedef enum { gpio_pull_floating, @@ -37,14 +39,14 @@ typedef enum { gpio_pull_down, gpio_pull_unknown, gpio_pull_last = gpio_pull_unknown -} __attribute__ ((packed)) gpio_pull_t; +} __packed gpio_pull_t; typedef enum { gpio_polarity_high, gpio_polarity_low, gpio_polarity_unknown, gpio_polarity_last = gpio_polarity_unknown, -} __attribute__ ((packed)) gpio_polarity_t; +} __packed gpio_polarity_t; typedef enum { gpio_speed_low, @@ -52,7 +54,7 @@ typedef enum { gpio_speed_high, gpio_speed_unknown, gpio_speed_last = gpio_speed_unknown -} __attribute__ ((packed)) gpio_speed_t; +} __packed gpio_speed_t; typedef struct { GPIO_TypeDef* port; @@ -63,7 +65,7 @@ typedef struct { gpio_pull_t pull; gpio_polarity_t polarity; gpio_speed_t speed; -} __attribute__ ((packed)) gpio_pin_t; +} __packed gpio_pin_t; void gpio_pin_init(const gpio_pin_t *pin); diff --git a/usb_cdc.c b/usb_cdc.c index 9ac8bea..67b84f8 100644 --- a/usb_cdc.c +++ b/usb_cdc.c @@ -59,7 +59,7 @@ static USART_TypeDef* const usb_cdc_port_usarts[] = { }; static USART_TypeDef* usb_cdc_get_port_usart(int port) { - if (port < (sizeof(usb_cdc_port_usarts) / sizeof(*usb_cdc_port_usarts))){ + if (port < ARRAY_SIZE(usb_cdc_port_usarts)){ return usb_cdc_port_usarts[port]; } return (USART_TypeDef*)0; @@ -77,7 +77,7 @@ static DMA_Channel_TypeDef* usb_cdc_get_port_dma_channel(int port, usb_cdc_port_ { DMA1_Channel6, DMA1_Channel7 }, { DMA1_Channel3, DMA1_Channel2 }, }; - if (port < (sizeof(port_dma_channels) / sizeof(*port_dma_channels)) && + if (port < ARRAY_SIZE(port_dma_channels) && port_dir < usb_cdc_port_direction_last) { return port_dma_channels[port][port_dir]; } @@ -91,14 +91,14 @@ static uint8_t const usb_cdc_port_data_endpoints[] = { }; static uint8_t usb_cdc_get_port_data_ep(int port) { - if (port < (sizeof(usb_cdc_port_data_endpoints) / sizeof(*usb_cdc_port_data_endpoints))) { + if (port < ARRAY_SIZE(usb_cdc_port_data_endpoints)) { return usb_cdc_port_data_endpoints[port]; } return -1; } static int usb_cdc_data_endpoint_port(uint8_t ep_num) { - for (int port = 0; port < (sizeof(usb_cdc_port_data_endpoints) / sizeof(*usb_cdc_port_data_endpoints)); port++) { + for (int port = 0; port < ARRAY_SIZE(usb_cdc_port_data_endpoints); port++) { if (usb_cdc_port_data_endpoints[port] == ep_num) { return port; } @@ -113,7 +113,7 @@ static uint8_t const usb_cdc_port_interrupt_endpoints[] = { }; static uint8_t usb_cdc_get_port_notification_ep(int port) { - if (port < (sizeof(usb_cdc_port_interrupt_endpoints) / sizeof(*usb_cdc_port_interrupt_endpoints))) { + if (port < ARRAY_SIZE(usb_cdc_port_interrupt_endpoints)) { return usb_cdc_port_interrupt_endpoints[port]; } return -1; @@ -124,14 +124,14 @@ static uint8_t const usb_cdc_port_interfaces[] = { }; static int usb_cdc_get_port_interface(int port) { - if (port < (sizeof(usb_cdc_port_interfaces) / sizeof(*usb_cdc_port_interfaces))) { + if (port < ARRAY_SIZE(usb_cdc_port_interfaces)) { return usb_cdc_port_interfaces[port]; } return -1; } static int usb_cdc_get_interface_port(uint8_t if_num) { - for (int port = 0; port < (sizeof(usb_cdc_port_interfaces) / sizeof(*usb_cdc_port_interfaces)); port++) { + for (int port = 0; port < ARRAY_SIZE(usb_cdc_port_interfaces); port++) { if (usb_cdc_port_interfaces[port] == if_num) { return port; } @@ -501,7 +501,7 @@ void DMA1_Channel2_IRQHandler() { /* USART Interrupt Handlers */ -__attribute__((always_inline)) inline static void usb_cdc_usart_irq_handler(int port, USART_TypeDef * usart, +__always_inline inline static void usb_cdc_usart_irq_handler(int port, USART_TypeDef * usart, volatile uint32_t *txa_bitband_clear) { uint32_t wait_rxne = 0; uint32_t status = usart->SR; diff --git a/usb_cdc.h b/usb_cdc.h index f98fa2d..7ad32f5 100644 --- a/usb_cdc.h +++ b/usb_cdc.h @@ -8,6 +8,8 @@ #define USB_CDC_H #include + +#include "aux.h" #include "usb_core.h" /* USB CDC Class Codes */ @@ -15,17 +17,17 @@ typedef enum { usb_class_cdc = 0x02, usb_class_cdc_data = 0x0a, -} __attribute__ ((packed)) usb_class_cdc_t; +} __packed usb_class_cdc_t; typedef enum { usb_subclass_cdc_none = 0x00, usb_subclass_cdc_acm = 0x02, -} __attribute__ ((packed)) usb_subclass_cdc_t; +} __packed usb_subclass_cdc_t; typedef enum { usb_protocol_cdc_none = 0x00, usb_protocol_cdc_v25ter = 0x01, -} __attribute__ ((packed)) usb_protocol_cdc_t; +} __packed usb_protocol_cdc_t; #define USB_PROTOCOL_CDC_DEFAULT usb_protocol_cdc_none @@ -35,7 +37,7 @@ typedef enum { usb_descriptor_subtype_cdc_acm = 0x02, usb_descriptor_subtype_cdc_union = 0x06, usb_descriptor_subtype_cdc_country = 0x07, -} __attribute__ ((packed)) usb_descriptor_subtype_cdc_t; +} __packed usb_descriptor_subtype_cdc_t; #define USB_CDC_ACM_CAPABILITY_COMM_FEATURE 0x01 #define USB_CDC_ACM_CAPABILITY_LINE_CODING 0x02 @@ -51,7 +53,7 @@ typedef struct { uint8_t bDescriptorType; uint8_t bDescriptorSubType; uint16_t bcdCDC; -} __attribute__ ((packed)) usb_cdc_header_desc_t; +} __packed usb_cdc_header_desc_t; /* USB CDC Union Functional Descriptor */ @@ -61,7 +63,7 @@ typedef struct { uint8_t bDescriptorSubType; uint8_t bMasterInterface0; uint8_t bSlaveInterface0; -} __attribute__ ((packed)) usb_cdc_union_desc_t; +} __packed usb_cdc_union_desc_t; typedef struct { uint8_t bFunctionLength; @@ -69,7 +71,7 @@ typedef struct { uint8_t bDescriptorSubType; uint8_t bmCapabilities; uint8_t bDataInterface; -} __attribute__ ((packed)) usb_cdc_call_mgmt_desc_t; +} __packed usb_cdc_call_mgmt_desc_t; /* USB CDC Abstract Control Management Functional Descriptor */ @@ -78,7 +80,7 @@ typedef struct { uint8_t bDescriptorType; uint8_t bDescriptorSubType; uint8_t bmCapabilities; -} __attribute__ ((packed)) usb_cdc_acm_desc_t; +} __packed usb_cdc_acm_desc_t; /* USB CDC Notifications */ @@ -86,7 +88,7 @@ typedef struct { typedef enum { usb_cdc_notification_serial_state = 0x20, -} __attribute__ ((packed)) usb_cdc_notification_type_t; +} __packed usb_cdc_notification_type_t; typedef struct { uint8_t bmRequestType; @@ -95,7 +97,7 @@ typedef struct { uint16_t wIndex; uint16_t wLength; uint8_t data[0]; -} __attribute__ ((packed)) usb_cdc_notification_t; +} __packed usb_cdc_notification_t; /* Serial State Notification Payload */ typedef uint16_t usb_cdc_serial_state_t; @@ -113,7 +115,7 @@ typedef enum { usb_cdc_char_format_1p5_stop_bits = 0x01, usb_cdc_char_format_2_stop_bits = 0x02, usb_cdc_char_format_last -} __attribute__ ((packed)) usb_cdc_char_format_t; +} __packed usb_cdc_char_format_t; typedef enum { usb_cdc_parity_type_none = 0x00, @@ -121,7 +123,7 @@ typedef enum { usb_cdc_parity_type_even = 0x02, usb_cdc_parity_type_mark = 0x03, usb_cdc_parity_type_space = 0x04, -} __attribute__ ((packed)) usb_cdc_parity_type_t; +} __packed usb_cdc_parity_type_t; typedef enum { usb_cdc_data_bits_5 = 0x05, @@ -129,14 +131,14 @@ typedef enum { usb_cdc_data_bits_7 = 0x07, usb_cdc_data_bits_8 = 0x08, usb_cdc_data_bits_16 = 0x10, -} __attribute__ ((packed)) usb_cdc_data_bits_t; +} __packed usb_cdc_data_bits_t; typedef struct { uint32_t dwDTERate; usb_cdc_char_format_t bCharFormat; usb_cdc_parity_type_t bParityType; usb_cdc_data_bits_t bDataBits; -} __attribute__ ((packed)) usb_cdc_line_coding_t; +} __packed usb_cdc_line_coding_t; /* USB CDC Control Line State */ @@ -155,7 +157,7 @@ typedef enum { usb_cdc_request_get_line_coding = 0x21, usb_cdc_request_set_control_line_state = 0x22, usb_cdc_request_send_break = 0x23, -} __attribute__ ((packed)) usb_cdc_request_t; +} __packed usb_cdc_request_t; /* Control Endpoint Request Processing */ @@ -188,7 +190,7 @@ typedef enum { cdc_pin_txa, cdc_pin_unknown, cdc_pin_last = cdc_pin_unknown, -} __attribute__ ((packed)) cdc_pin_t; +} __packed cdc_pin_t; /* Configuration Changed Hooks */ diff --git a/usb_descriptors.h b/usb_descriptors.h index f9f9c55..8d1255f 100644 --- a/usb_descriptors.h +++ b/usb_descriptors.h @@ -8,6 +8,7 @@ #define USB_DESCRIPTORS_H #include +#include "aux.h" #include "usb_core.h" #include "usb_std.h" #include "usb_cdc.h" @@ -29,7 +30,7 @@ typedef enum { usb_string_index_uart_2_interface_name, usb_string_index_uart_3_interface_name, usb_string_index_last, -} __attribute__ ((packed)) usb_string_index_t; +} __packed usb_string_index_t; extern const usb_string_descriptor_t *usb_string_descriptors[usb_string_index_last]; @@ -94,7 +95,7 @@ typedef struct { usb_interface_descriptor_t data_2; usb_endpoint_descriptor_t data_eprx_2; usb_endpoint_descriptor_t data_eptx_2; -} __attribute__((packed)) usb_device_configuration_descriptor_t; +} __packed usb_device_configuration_descriptor_t; extern const usb_device_configuration_descriptor_t usb_configuration_descriptor; diff --git a/usb_io.h b/usb_io.h index 2fd88e4..64f227e 100644 --- a/usb_io.h +++ b/usb_io.h @@ -11,6 +11,8 @@ #include #include + +#include "aux.h" #include "circ_buf.h" #include "usb.h" #include "usb_std.h" @@ -21,7 +23,7 @@ #define USB_PACKET_BUFFER_ALIGNMENT 4 typedef uint16_t pb_word_t; -typedef pb_word_t pb_aligned_word_t __attribute__ ((aligned(USB_PACKET_BUFFER_ALIGNMENT))); +typedef pb_word_t pb_aligned_word_t __aligned(USB_PACKET_BUFFER_ALIGNMENT); typedef struct { pb_aligned_word_t tx_offset; @@ -63,7 +65,7 @@ typedef struct { usb_endpoint_event_handler_t event_handler; } usb_endpoint_t; -#define USB_NUM_ENDPOINTS (sizeof(usb_endpoints)/sizeof(*usb_endpoints)) +#define USB_NUM_ENDPOINTS ARRAY_SIZE(usb_endpoints) #define USB_MAX_ENDPOINTS 8 /* USB IO Initialization */ diff --git a/usb_std.h b/usb_std.h index d538b1d..2554c44 100644 --- a/usb_std.h +++ b/usb_std.h @@ -9,6 +9,8 @@ #include +#include "aux.h" + /* USB Descriptor Types */ typedef enum { @@ -25,7 +27,7 @@ typedef enum { usb_descriptor_type_interface_assoc = 0x0b, usb_descriptor_type_cs_interface = 0x24, usb_descriptor_type_cs_endpoint = 0x25, -} __attribute__ ((packed)) usb_descriptor_type_t; +} __packed usb_descriptor_type_t; /* USB Device Descriptor */ @@ -52,17 +54,17 @@ typedef enum { usb_device_class_misc = 0xef, usb_device_class_application_specific = 0xfe, usb_device_class_vendor_specific = 0xff, -} __attribute__ ((packed)) usb_device_class_t; +} __packed usb_device_class_t; typedef enum { usb_device_subclass_none = 0x00, usb_device_subclass_iad = 0x02, -} __attribute__ ((packed)) usb_device_subclass_t; +} __packed usb_device_subclass_t; typedef enum { usb_device_protocol_none = 0x00, usb_device_protocol_iad = 0x01, -} __attribute__ ((packed)) usb_device_protocol_t; +} __packed usb_device_protocol_t; #define USB_BCD_VERSION(maj, min, rev) (((maj & 0xFF) << 8) | ((min & 0x0F) << 4) | (rev & 0x0F)) @@ -81,7 +83,7 @@ typedef struct { uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; -} __attribute__ ((packed)) usb_device_descriptor_t; +} __packed usb_device_descriptor_t; /* USB Qualifier Descriptor */ @@ -95,7 +97,7 @@ typedef struct { uint8_t bMaxPacketSize0; uint8_t bNumConfigurations; uint8_t bReserved; -} __attribute__((packed)) usb_qualifier_descriptor_t; +} __packed usb_qualifier_descriptor_t; /* USB Configuration Descriptor */ @@ -114,7 +116,7 @@ typedef struct { uint8_t iConfiguration; uint8_t bmAttributes; uint8_t bMaxPower; -} __attribute__((packed)) usb_configuration_descriptor_t; +} __packed usb_configuration_descriptor_t; /* USB Interface Descriptor */ @@ -128,7 +130,7 @@ typedef struct { uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; uint8_t iInterface; -} __attribute__((packed)) usb_interface_descriptor_t; +} __packed usb_interface_descriptor_t; /* USB Interface Association Descriptor */ @@ -141,35 +143,35 @@ typedef struct { uint8_t bFunctionSubClass; uint8_t bFunctionProtocol; uint8_t iFunction; -} __attribute__((packed)) usb_iad_descriptor_t; +} __packed usb_iad_descriptor_t; /* USB Endpoint Descriptor */ typedef enum { usb_endpoint_direction_out = 0x00, usb_endpoint_direction_in = 0x80, -} __attribute__ ((packed)) usb_endpoint_direction_t; +} __packed usb_endpoint_direction_t; typedef enum { usb_endpoint_type_control = 0x00, usb_endpoint_type_isochronous = 0x01, usb_endpoint_type_bulk = 0x02, usb_endpoint_type_interrupt = 0x03, -} __attribute__ ((packed)) usb_endpoint_type_t; +} __packed usb_endpoint_type_t; typedef enum { usb_endpoint_attribute_no_sync = 0x00, usb_endpoint_attribute_async = 0x04, usb_endpoint_attribute_adaptive = 0x08, usb_endpoint_attribute_sync = 0x0c -} __attribute__ ((packed)) usb_endpoint_attribute_t; +} __packed usb_endpoint_attribute_t; typedef enum { usb_endpoint_usage_data = 0x00, usb_endpoint_usage_feedback = 0x10, usb_endpoint_usage_implicit_feedback = 0x20 -} __attribute__ ((packed)) usb_endpoint_usage_t; +} __packed usb_endpoint_usage_t; typedef struct { uint8_t bLength; @@ -178,7 +180,7 @@ typedef struct { uint8_t bmAttributes; uint16_t wMaxPacketSize; uint8_t bInterval; -} __attribute__((packed)) usb_endpoint_descriptor_t; +} __packed usb_endpoint_descriptor_t; /* USB String Descriptor */ @@ -186,7 +188,7 @@ typedef struct { uint8_t bLength; uint8_t bDescriptorType; uint16_t wString[]; -} __attribute__((packed, aligned(2))) usb_string_descriptor_t; +} __spacked usb_string_descriptor_t; #define __CAT(x,y) x ## y #define CAT(x,y) __CAT(x,y) @@ -201,7 +203,7 @@ typedef struct { typedef enum { usb_language_code_en_US = 0x409, -} __attribute__((packed)) usb_language_code_t; +} __packed usb_language_code_t; /* USB Debug Descriptor */ @@ -210,7 +212,7 @@ typedef struct { uint8_t bDescriptorType; uint8_t bDebugInEndpoint; uint8_t bDebugOutEndpoint; -} __attribute__((packed)) usb_debug_descriptor_t; +} __packed usb_debug_descriptor_t; /* USB Control Endpoint Related Definitions */ @@ -248,7 +250,7 @@ typedef struct { uint16_t wIndex; uint16_t wLength; uint8_t payload[0]; -} __attribute__ ((packed)) usb_setup_t; +} __packed usb_setup_t; typedef enum { usb_device_request_get_status = 0x00, From 01290c9344f5eed6bcc6b25ae803bc9daaca94c1 Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Mon, 31 Oct 2022 21:21:40 +0300 Subject: [PATCH 5/7] Introduce referenced gpio pins --- Makefile | 6 +- cdc_config.h | 8 +- cdc_shell.c | 18 ++-- default_config.c | 184 +++++++++++++++++++++++++++++++++++++ default_config.h | 50 +++++++++++ device_config.c | 63 ++----------- device_config.h | 6 +- gpio.c | 34 ++++--- gpio.h | 20 ++++- gpion.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++ gpion.h | 97 ++++++++++++++++++++ main.c | 1 + status_led.c | 10 +-- usb_cdc.c | 43 ++++----- usb_cdc.h | 1 - usb_core.c | 5 ++ usb_uid.c | 2 +- 17 files changed, 664 insertions(+), 114 deletions(-) create mode 100644 default_config.c create mode 100644 default_config.h create mode 100644 gpion.c create mode 100644 gpion.h diff --git a/Makefile b/Makefile index 545a24f..a03d327 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # General Target Settings TARGET = bluepill-serial-monster SRCS = main.c system_clock.c system_interrupts.c status_led.c usb_core.c usb_descriptors.c\ - usb_io.c usb_uid.c usb_panic.c usb_cdc.c cdc_shell.c gpio.c device_config.c + usb_io.c usb_uid.c usb_panic.c usb_cdc.c cdc_shell.c gpio.c gpion.c device_config.c default_config.c # Toolchain & Utils CROSS_COMPILE ?= arm-none-eabi- @@ -24,8 +24,8 @@ STM32_INCLUDES += -I$(STM32CUBE)/Drivers/CMSIS/Device/ST/STM32F1xx/Include DEFINES = -DSTM32F103xB -DHSE_VALUE=8000000U CPUFLAGS = -mthumb -mcpu=cortex-m3 -WARNINGS = -Wall -OPTIMIZATION = -O3 +WARNINGS = -Wall -Werror # -Wextra +OPTIMIZATION = #-O3 DEBUG = -ggdb CFLAGS = $(DEFINES) $(STM32_INCLUDES) $(CPUFLAGS) $(WARNINGS) $(OPTIMIZATION) $(DEBUG) diff --git a/cdc_config.h b/cdc_config.h index 5a43dcd..c180327 100644 --- a/cdc_config.h +++ b/cdc_config.h @@ -7,15 +7,15 @@ #ifndef CDC_CONFIG_H #define CDC_CONFIG_H -#include "gpio.h" +#include "gpion.h" #include "usb_cdc.h" typedef struct { - gpio_pin_t pins[cdc_pin_last]; -} __attribute__ ((packed)) cdc_port_t; + gpion_pin_t pins[cdc_pin_last]; +} cdc_port_t; typedef struct { cdc_port_t port_config[USB_CDC_NUM_PORTS]; -} __attribute__ ((packed)) cdc_config_t; +} cdc_config_t; #endif /* CDC_CONFIG_H */ diff --git a/cdc_shell.c b/cdc_shell.c index d5a5683..c497162 100644 --- a/cdc_shell.c +++ b/cdc_shell.c @@ -70,6 +70,7 @@ static const char cdc_shell_err_uart_invalid_pull_type[] = "Error, in static const char cdc_shell_err_cannot_set_output_type_for_input[] = "Error, cannot set output type for input pin.\r\n"; static const char cdc_shell_err_cannot_change_polarity[] = "Error, cannot change polarity of alternate function pins.\r\n"; static const char cdc_shell_err_cannot_set_pull_for_output[] = "Error, cannot pull type for output pin.\r\n"; +static const char cdc_shell_err_pin_is_detached[] = "Error, pin is detached.\r\n"; static const char *_cdc_uart_signal_names[cdc_pin_last] = { @@ -145,11 +146,12 @@ static void cdc_shell_cmd_uart_show(int port) { cdc_shell_write_string(colon_str); cdc_shell_write_string(cdc_shell_new_line); for (cdc_pin_t pin = 0; pin < cdc_pin_last; pin++) { - const gpio_pin_t *cdc_pin = &cdc_port->pins[pin]; + const gpio_pin_t *cdc_pin = gpion_to_gpio(cdc_port->pins[pin]); + gpio_hal_t hal = gpion_to_hal(cdc_port->pins[pin]); const char *pin_name = _cdc_uart_signal_names[pin]; cdc_shell_write_string(pin_name); cdc_shell_write_string(cdc_shell_delim); - if (cdc_pin->port) { + if (cdc_pin && hal.port) { const char *active_value = _cdc_uart_polarities[cdc_pin->polarity]; if (cdc_pin->dir == gpio_dir_input) { cdc_shell_write_string(in_str); @@ -180,8 +182,10 @@ static int cdc_shell_cmd_uart_set_output_type(int port, cdc_pin_t uart_pin, gpio for (int port_index = ((port == -1) ? 0 : port); port_index < ((port == -1) ? USB_CDC_NUM_PORTS : port + 1); port_index++) { - gpio_pin_t *pin = &device_config_get()->cdc_config.port_config[port_index].pins[uart_pin]; - if (pin->dir == gpio_dir_output) { + gpio_pin_t *pin = gpion_to_gpio(device_config_get()->cdc_config.port_config[port_index].pins[uart_pin]); + if (pin == 0) { + cdc_shell_write_string(cdc_shell_err_pin_is_detached); + } else if (pin->dir == gpio_dir_output) { pin->output = output; usb_cdc_reconfigure_port_pin(port, uart_pin); } else { @@ -196,7 +200,7 @@ static int cdc_shell_cmd_uart_set_polarity(int port, cdc_pin_t uart_pin, gpio_po for (int port_index = ((port == -1) ? 0 : port); port_index < ((port == -1) ? USB_CDC_NUM_PORTS : port + 1); port_index++) { - gpio_pin_t *pin = &device_config_get()->cdc_config.port_config[port_index].pins[uart_pin]; + gpio_pin_t *pin = gpion_to_gpio(device_config_get()->cdc_config.port_config[port_index].pins[uart_pin]); if (pin->func == gpio_func_general && (uart_pin != cdc_pin_rx) && (uart_pin != cdc_pin_cts)) { pin->polarity = polarity; usb_cdc_reconfigure_port_pin(port, uart_pin); @@ -212,7 +216,7 @@ static int cdc_shell_cmd_uart_set_pull_type(int port, cdc_pin_t uart_pin, gpio_p for (int port_index = ((port == -1) ? 0 : port); port_index < ((port == -1) ? USB_CDC_NUM_PORTS : port + 1); port_index++) { - gpio_pin_t *pin = &device_config_get()->cdc_config.port_config[port_index].pins[uart_pin]; + gpio_pin_t *pin = gpion_to_gpio(device_config_get()->cdc_config.port_config[port_index].pins[uart_pin]); if (pin->dir == gpio_dir_input) { pin->pull = pull; usb_cdc_reconfigure_port_pin(port, uart_pin); @@ -352,6 +356,8 @@ static void cdc_shell_cmd_config(int argc, char *argv[]) { static const char cdc_shell_device_version[] = DEVICE_VERSION_STRING; static void cdc_shell_cmd_version(int argc, char *argv[]) { + (void) argc; + (void) argv; cdc_shell_write_string(cdc_shell_device_version); cdc_shell_write_string(cdc_shell_new_line); } diff --git a/default_config.c b/default_config.c new file mode 100644 index 0000000..43a3e3b --- /dev/null +++ b/default_config.c @@ -0,0 +1,184 @@ +/* + * MIT License + * + * Copyright (c) 2020 Kirill Kotyagin + * Copyright (c) 2022 Yury Shvedov + */ + +#include "aux.h" +#include "default_config.h" + +static const default_config_t default_config = { + .status_led_pin = { .pin = gpio_pin_pc13, .dir = gpio_dir_output, .speed = gpio_speed_low, .func = gpio_func_general, .output = gpio_output_od, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + .config_pin = { .pin = gpio_pin_pb5, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + .cdc_config = { + .port_config = { + /* Port 0 */ + { + .pins = + { + [cdc_pin_rx] = { .pin = gpio_pin_pa10, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + [cdc_pin_tx] = { .pin = gpio_pin_pa9, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + [cdc_pin_rts] = { .pin = gpio_pin_pa15, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_cts] = { .pin = gpio_pin_pa11, .dir = gpio_dir_input, .pull = gpio_pull_down, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dsr] = { .pin = gpio_pin_pb7, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dtr] = { .pin = gpio_pin_pa4, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dcd] = { .pin = gpio_pin_pb15, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_ri] = { .pin = gpio_pin_pb3, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_txa] = { .pin = gpio_pin_pb0, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + } + }, + /* Port 1 */ + { + .pins = + { + [cdc_pin_rx] = { .pin = gpio_pin_pa3, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + [cdc_pin_tx] = { .pin = gpio_pin_pa2, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + [cdc_pin_rts] = { .pin = gpio_pin_pa1, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_cts] = { .pin = gpio_pin_pa0, .dir = gpio_dir_input, .pull = gpio_pull_down, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dsr] = { .pin = gpio_pin_pb4, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dtr] = { .pin = gpio_pin_pa5, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dcd] = { .pin = gpio_pin_pb8, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_ri] = { .pin = gpio_pin_pb12, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_txa] = { .pin = gpio_pin_pb1, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + } + }, + /* Port 2 */ + { + .pins = + { + [cdc_pin_rx] = { .pin = gpio_pin_pb11, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + [cdc_pin_tx] = { .pin = gpio_pin_pb10, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + [cdc_pin_rts] = { .pin = gpio_pin_pb14, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_cts] = { .pin = gpio_pin_pb13, .dir = gpio_dir_input, .pull = gpio_pull_down, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dsr] = { .pin = gpio_pin_pb6, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dtr] = { .pin = gpio_pin_pa6, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_dcd] = { .pin = gpio_pin_pb9, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_ri] = { .pin = gpio_pin_pa8, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low, .status = gpio_status_occupied, }, + [cdc_pin_txa] = { .pin = gpio_pin_pa7, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_high, .status = gpio_status_occupied, }, + } + }, + } + }, + .blocked_pins = { + { + .pin = gpio_pin_pa11, + .reason = "usb dm", + }, + { + .pin = gpio_pin_pa12, + .reason = "usb dp", + }, + { + .pin = gpio_pin_pa13, + .reason = "debug swdio", + }, + { + .pin = gpio_pin_pa14, + .reason = "debug swclk", + }, + { + .pin = gpio_pin_pb2, + .reason = "boot control", + }, + + { + .pin = default_blocked_pin_end, + } + }, +}; + +static gpion_pin_t default_config_pin_load(device_config_t *target, const default_gpio_pin_t *source); +static void default_config_pin_last(device_config_t *target, gpion_pin_t pin); + +void default_config_load(device_config_t *target) { + default_gpio_pin_t default_free = { + .dir = gpio_dir_input, + .func = gpio_func_general, + .output = gpio_output_pp, + .pull = gpio_pull_up, + .polarity = gpio_polarity_high, + .speed = gpio_speed_medium, + .status = gpio_status_free, + }; + default_gpio_pin_t default_blocked = { + .dir = gpio_dir_unknown, + .func = gpio_func_alternate, + .output = gpio_output_unknown, + .pull = gpio_pull_unknown, + .polarity = gpio_polarity_unknown, + .speed = gpio_speed_unknown, + .status = gpio_status_blocked, + }; + if (target != 0) { + // reset all gpio pins to free. + for (gpion_pin_t pin = 0; pin < gpio_pin_last; ++pin) { + default_free.pin = pin; + target->gpio_config.pins[pin].status = gpio_status_free; + default_config_pin_load(target, &default_free); + } + // configure system pins + for (int i = 0; default_config.blocked_pins[i].pin != default_blocked_pin_end; ++i) { + gpion_pin_t pin = default_config.blocked_pins[i].pin; + default_blocked.pin = pin; + default_config_pin_load(target, &default_blocked); + } + // configure misc pins + target->status_led_pin = default_config_pin_load(target, &default_config.status_led_pin); + target->config_pin = default_config_pin_load(target, &default_config.config_pin); + // configure uart pins + for (int port = 0; port < ARRAY_SIZE(target->cdc_config.port_config) && port < ARRAY_SIZE(default_config.cdc_config.port_config); ++port) { + const default_port_t *default_port = &default_config.cdc_config.port_config[port]; + cdc_port_t *port_config = &target->cdc_config.port_config[port]; + for (int pin = 0; pin < ARRAY_SIZE(default_port->pins) && pin < ARRAY_SIZE(port_config->pins); ++pin) { + port_config->pins[pin] = default_config_pin_load(target, &default_port->pins[pin]); + } + } + // configure other pins + for (gpion_pin_t pin = 0; pin < gpio_pin_last; ++pin) { + default_config_pin_last(target, pin); + } + } +} + +const char *default_config_get_blocked_reason(gpion_pin_t pin) { + static const char *not_blocked = "pin is not blocked"; + for (int i = 0; default_config.blocked_pins[i].pin != default_blocked_pin_end; ++i) { + if (pin == default_config.blocked_pins[i].pin) { + return default_config.blocked_pins[i].reason; + } + } + return not_blocked; +} + +static gpion_pin_t default_config_pin_load(device_config_t *target, const default_gpio_pin_t *source){ + if (source->pin == gpio_pin_unknown) { + return gpio_pin_unknown; + } + gpio_pin_t *pin = &target->gpio_config.pins[source->pin]; + if (pin->status == gpio_status_blocked) { + return source->pin; + } + + pin->dir = source->dir; + pin->func = source->func; + pin->output = source->output; + pin->pull = source->pull; + pin->polarity = source->polarity; + pin->speed = source->speed; + pin->status = source->status; + + return source->pin; +} + +static void default_config_pin_last(device_config_t *target, gpion_pin_t pinn) { + gpio_pin_t *pin = &target->gpio_config.pins[pinn]; + if (pinn < gpio_pin_last && pin->status == gpio_status_free) { + pin->dir = gpio_dir_unknown; + pin->func = gpio_func_general; + pin->output = gpio_output_unknown; + pin->pull = gpio_pull_unknown; + pin->polarity = gpio_polarity_unknown; + pin->speed = gpio_speed_unknown; + } +} diff --git a/default_config.h b/default_config.h new file mode 100644 index 0000000..1d0487a --- /dev/null +++ b/default_config.h @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (c) 2022 Yury Shvedov + */ + +#ifndef DEFAULT_CONFIG_H +#define DEFAULT_CONFIG_H + +#include "gpion.h" +#include "usb_cdc.h" +#include "device_config.h" + +typedef struct { + gpion_pin_t pin; + gpio_dir_t dir; + gpio_func_t func; + gpio_output_t output; + gpio_pull_t pull; + gpio_polarity_t polarity; + gpio_speed_t speed; + gpio_status_t status; +} default_gpio_pin_t; + +typedef struct { + default_gpio_pin_t pins[cdc_pin_last]; +} default_port_t; + +typedef struct { + default_port_t port_config[USB_CDC_NUM_PORTS]; +} default_cdc_t; + +typedef struct { + gpion_pin_t pin; + const char *reason; +} default_blocked_pin_t; + +#define default_blocked_pin_end gpio_pin_unknown + +typedef struct { + default_gpio_pin_t status_led_pin; + default_gpio_pin_t config_pin; + default_cdc_t cdc_config; + default_blocked_pin_t blocked_pins[]; +} default_config_t; + +void default_config_load(device_config_t *target); +const char *default_config_get_blocked_reason(gpion_pin_t pin); + +#endif /* DEFAULT_CONFIG_H */ diff --git a/device_config.c b/device_config.c index 0ee27ac..799e360 100644 --- a/device_config.c +++ b/device_config.c @@ -8,6 +8,7 @@ #include #include #include "device_config.h" +#include "default_config.h" #define DEVICE_CONFIG_FLASH_SIZE 0x10000UL #define DEVICE_CONFIG_NUM_PAGES 2 @@ -16,60 +17,6 @@ #define DEVICE_CONFIG_BASE_ADDR ((void*)(DEVICE_CONFIG_FLASH_END - DEVICE_CONFIG_NUM_PAGES * DEVICE_CONFIG_PAGE_SIZE)) #define DEVICE_CONFIG_MAGIC 0xDECFDECFUL -static const device_config_t default_device_config = { - .status_led_pin = { .port = GPIOC, .pin = 13, .dir = gpio_dir_output, .speed = gpio_speed_low, .func = gpio_func_general, .output = gpio_output_od, .polarity = gpio_polarity_low }, - .config_pin = { .port = GPIOB, .pin = 5, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, - .cdc_config = { - .port_config = { - /* Port 0 */ - { - .pins = - { - /* rx */ { .port = GPIOA, .pin = 10, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, - /* tx */ { .port = GPIOA, .pin = 9, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high }, - /* rts */ { .port = GPIOA, .pin = 15, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low}, - /* cts */ { .port = 0 }, /* CTS pin is occupied by USB */ - /* dsr */ { .port = GPIOB, .pin = 7, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* dtr */ { .port = GPIOA, .pin = 4, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low }, - /* dcd */ { .port = GPIOB, .pin = 15, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* ri */ { .port = GPIOB, .pin = 3, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* txa */ { .port = GPIOB, .pin = 0, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_high }, - } - }, - /* Port 1 */ - { - .pins = - { - /* rx */ { .port = GPIOA, .pin = 3, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, - /* tx */ { .port = GPIOA, .pin = 2, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high }, - /* rts */ { .port = GPIOA, .pin = 1, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low}, - /* cts */ { .port = GPIOA, .pin = 0, .dir = gpio_dir_input, .pull = gpio_pull_down, .polarity = gpio_polarity_low }, - /* dsr */ { .port = GPIOB, .pin = 4, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* dtr */ { .port = GPIOA, .pin = 5, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low }, - /* dcd */ { .port = GPIOB, .pin = 8, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* ri */ { .port = GPIOB, .pin = 12, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* txa */ { .port = GPIOB, .pin = 1, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_high }, - } - }, - /* Port 2 */ - { - .pins = - { - /* rx */ { .port = GPIOB, .pin = 11, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_high }, - /* tx */ { .port = GPIOB, .pin = 10, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high }, - /* rts */ { .port = GPIOB, .pin = 14, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low }, - /* cts */ { .port = GPIOB, .pin = 13, .dir = gpio_dir_input, .pull = gpio_pull_down, .polarity = gpio_polarity_low }, - /* dsr */ { .port = GPIOB, .pin = 6, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* dtr */ { .port = GPIOA, .pin = 6, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low }, - /* dcd */ { .port = GPIOB, .pin = 9, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* ri */ { .port = GPIOA, .pin = 8, .dir = gpio_dir_input, .pull = gpio_pull_up, .polarity = gpio_polarity_low }, - /* txa */ { .port = GPIOA, .pin = 7, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_high }, - } - }, - } - } -}; - static device_config_t current_device_config; static uint32_t device_config_calc_crc(const device_config_t *device_config) { @@ -111,10 +58,12 @@ void device_config_init() { RCC->AHBENR |= RCC_AHBENR_CRCEN; const device_config_t *stored_config = device_config_get_stored(); if (stored_config == 0) { - stored_config = &default_device_config; + default_config_load(¤t_device_config); + } else { + memcpy(¤t_device_config, stored_config, sizeof(*stored_config)); } - memcpy(¤t_device_config, stored_config, sizeof(*stored_config)); } + device_config_t *device_config_get() { return ¤t_device_config; } @@ -174,6 +123,6 @@ void device_config_save() { } void device_config_reset() { - memcpy(¤t_device_config, &default_device_config, sizeof(default_device_config)); + default_config_load(¤t_device_config); device_config_save(); } diff --git a/device_config.h b/device_config.h index 5395eae..3f1628a 100644 --- a/device_config.h +++ b/device_config.h @@ -9,13 +9,15 @@ #include #include "gpio.h" +#include "gpion.h" #include "cdc_config.h" typedef struct { uint32_t magic; - gpio_pin_t status_led_pin; - gpio_pin_t config_pin; cdc_config_t cdc_config; + gpio_config_t gpio_config; + gpion_pin_t status_led_pin; + gpion_pin_t config_pin; uint32_t crc; /* should be the last member of the struct */ } __wpacked device_config_t; diff --git a/gpio.c b/gpio.c index 86c90bf..8929d6d 100644 --- a/gpio.c +++ b/gpio.c @@ -5,6 +5,7 @@ */ #include "gpio.h" +#include "gpion.h" static void _gpio_enable_port(GPIO_TypeDef *port) { int portnum = (((uint32_t)port - GPIOA_BASE) / (GPIOB_BASE - GPIOA_BASE)); @@ -12,18 +13,19 @@ static void _gpio_enable_port(GPIO_TypeDef *port) { } void gpio_pin_init(const gpio_pin_t *pin) { - if (pin->port) { - volatile uint32_t *crx = &pin->port->CRL + (pin->pin >> 3); - uint8_t crx_offset = (pin->pin & 0x07) << 2; + gpio_hal_t hal = gpio_to_hal(pin); + if (hal.port) { + volatile uint32_t *crx = &hal.port->CRL + (hal.pin >> 3); + uint8_t crx_offset = (hal.pin & 0x07) << 2; uint32_t modecfg = 0; - _gpio_enable_port(pin->port); + _gpio_enable_port(hal.port); *crx &= ~((GPIO_CRL_CNF0 | GPIO_CRL_MODE0) << crx_offset); if (pin->dir == gpio_dir_input) { if (pin->pull == gpio_pull_floating) { modecfg |= GPIO_CRL_CNF0_0; } else { modecfg |= GPIO_CRL_CNF0_1; - pin->port->BSRR = ((pin->pull == gpio_pull_up) ? GPIO_BSRR_BS0 : GPIO_BSRR_BR0) << pin->pin; + hal.port->BSRR = ((pin->pull == gpio_pull_up) ? GPIO_BSRR_BS0 : GPIO_BSRR_BR0) << hal.pin; } } else { switch (pin->speed) { @@ -50,28 +52,36 @@ void gpio_pin_init(const gpio_pin_t *pin) { } void gpio_pin_set(const gpio_pin_t *pin, int is_active) { - if (pin->port) { - pin->port->BSRR = (GPIO_BSRR_BS0 << pin->pin) + gpio_hal_t hal = gpio_to_hal(pin); + if (hal.port) { + hal.port->BSRR = (GPIO_BSRR_BS0 << hal.pin) << (!!is_active != (pin->polarity == gpio_polarity_low) ? 0 : GPIO_BSRR_BR0_Pos); } } int gpio_pin_get(const gpio_pin_t *pin) { - if (pin->port) { - return (!!(pin->port->IDR & (GPIO_IDR_IDR0 << pin->pin))) != (pin->polarity == gpio_polarity_low); + gpio_hal_t hal = gpio_to_hal(pin); + if (hal.port) { + return (!!(hal.port->IDR & (GPIO_IDR_IDR0 << hal.pin))) != (pin->polarity == gpio_polarity_low); } return 0; } volatile uint32_t *gpio_pin_get_bitband_clear_addr(const gpio_pin_t *pin) { volatile uint32_t result = 0; - if (pin->port) { + gpio_hal_t hal = gpio_to_hal(pin); + if (hal.port) { result = PERIPH_BB_BASE; - result += ((uint32_t)(&pin->port->BSRR) - PERIPH_BASE) << 5; - result += pin->pin << 2; + result += ((uint32_t)(&hal.port->BSRR) - PERIPH_BASE) << 5; + result += hal.pin << 2; if (pin->polarity == gpio_polarity_high) { result += GPIO_BSRR_BR0_Pos << 2; } } return (volatile uint32_t*)result; } + +gpio_hal_t gpio_to_hal(const gpio_pin_t *pin) +{ + return gpion_to_hal(gpio_to_gpion(pin)); +} diff --git a/gpio.h b/gpio.h index 66ea8f5..a6597f5 100644 --- a/gpio.h +++ b/gpio.h @@ -56,16 +56,28 @@ typedef enum { gpio_speed_last = gpio_speed_unknown } __packed gpio_speed_t; +typedef enum { + gpio_status_free, + gpio_status_occupied, + gpio_status_blocked, + gpio_status_unknown, + gpio_status_last = gpio_status_unknown, +} gpio_status_t; + typedef struct { - GPIO_TypeDef* port; - uint8_t pin; gpio_dir_t dir; gpio_func_t func; gpio_output_t output; gpio_pull_t pull; gpio_polarity_t polarity; gpio_speed_t speed; -} __packed gpio_pin_t; + gpio_status_t status; +} gpio_pin_t; + +typedef struct { + GPIO_TypeDef *port; + int pin; +} gpio_hal_t; void gpio_pin_init(const gpio_pin_t *pin); @@ -74,4 +86,6 @@ int gpio_pin_get(const gpio_pin_t *pin); volatile uint32_t *gpio_pin_get_bitband_clear_addr(const gpio_pin_t *pin); +gpio_hal_t gpio_to_hal(const gpio_pin_t *pin); + #endif /* GPIO_G */ diff --git a/gpion.c b/gpion.c new file mode 100644 index 0000000..1a381b1 --- /dev/null +++ b/gpion.c @@ -0,0 +1,230 @@ +/* + * MIT License + * + * Copyright (c) 2022 Yury Shvedov + */ + +#include "aux.h" +#include "gpion.h" +#include "device_config.h" +#include "default_config.h" + +#include +#include + +gpio_pin_t *gpion_to_gpio(gpion_pin_t pinn) +{ + device_config_t *device = device_config_get(); + if (device != 0 && pinn < gpio_pin_last) { + return &device->gpio_config.pins[pinn]; + } + return 0; +} + +gpion_pin_t gpio_to_gpion(const gpio_pin_t *pin) +{ + device_config_t *device = device_config_get(); + if (device != 0) { + int pinn = pin - device->gpio_config.pins; + if (0 <= pinn && pinn < (int)gpio_pin_last) { + return (gpion_pin_t) pinn; + } + } + return gpio_pin_unknown; +} + +const char *gpion_to_str(gpion_pin_t pinn){ + static const char *pin_table[] = { + +#define pin_table_record(pin) [gpio_pin_ ## pin] = #pin + + pin_table_record(pa0), + pin_table_record(pa1), + pin_table_record(pa2), + pin_table_record(pa3), + pin_table_record(pa4), + pin_table_record(pa5), + pin_table_record(pa6), + pin_table_record(pa7), + pin_table_record(pa8), + pin_table_record(pa9), + pin_table_record(pa10), + pin_table_record(pa11), + pin_table_record(pa12), + pin_table_record(pa13), + pin_table_record(pa14), + pin_table_record(pa15), + + pin_table_record(pb0), + pin_table_record(pb1), + pin_table_record(pb2), + pin_table_record(pb3), + pin_table_record(pb4), + pin_table_record(pb5), + pin_table_record(pb6), + pin_table_record(pb7), + pin_table_record(pb8), + pin_table_record(pb9), + pin_table_record(pb10), + pin_table_record(pb11), + pin_table_record(pb12), + pin_table_record(pb13), + pin_table_record(pb14), + pin_table_record(pb15), + + pin_table_record(pc13), + pin_table_record(pc14), + pin_table_record(pc15), + + pin_table_record(unknown), +#undef pin_table_record + + }; + + BUILD_BUG_ON(ARRAY_SIZE(pin_table) != gpio_pin_last + 1); + + if (pinn < gpio_pin_last) { + return pin_table[pinn]; + } + + return pin_table[gpio_pin_unknown]; +} + +gpion_pin_t str_to_gpion(const char *str){ + gpion_pin_t port = gpio_pin_unknown; + char *pend = 0; + unsigned long n = 0; + device_config_t *device_config = device_config_get(); + + if (!strcasecmp(str, "led")) { + return device_config->status_led_pin; + } else if (!strcasecmp(str, "shell") || !strcasecmp(str, "control")|| !strcasecmp(str, "config")) { + return device_config->config_pin; + } + +#define check_prefix(prefix) do { \ + if (strncasecmp(str, prefix, sizeof(prefix) - 1) == 0) { \ + str += sizeof(prefix) - 1; \ + } \ +} while (0) + check_prefix("gpio_"); + check_prefix("pin_"); + check_prefix("p"); + +#undef check_prefix + + switch (*str++) { + case 'a': case 'A': port = gpio_pin_pa_first; break; + case 'b': case 'B': port = gpio_pin_pb_first; break; + case 'c': case 'C': port = gpio_pin_pc_first; break; + default: return gpio_pin_unknown; + } + + n = strtoul(str, &pend, 10); + if (pend == 0 || *pend != '\0' || n > 15) { + return gpio_pin_unknown; + } + if (port == gpio_pin_pc_first) { + if (n < 13) { + return gpio_pin_unknown; + } + n -= 13; + } + return port + n; +} + +void gpion_pin_init(gpion_pin_t pinn) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin == 0) return; + gpio_pin_init(pin); +} + + +/* This will work only for occupied pins */ +void gpion_pin_set(gpion_pin_t pinn, int is_active) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin == 0 || pin->status != gpio_status_occupied) return; + gpio_pin_set(pin, is_active); +} + +int gpion_pin_get(gpion_pin_t pin) +{ + return gpion_pin_get_default(pin, 0); +} + +int gpion_pin_get_default(gpion_pin_t pinn, int def) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin == 0 || pin->status != gpio_status_occupied) return def; + return gpio_pin_get(pin); +} + +volatile uint32_t *gpion_pin_get_bitband_clear_addr(gpion_pin_t pinn) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin == 0 || pin->status != gpio_status_occupied) return 0; + return gpio_pin_get_bitband_clear_addr(pin); +} + +/* Set will work only for free pins, get - for free and occupied */ +void gpion_pin_set_free(gpion_pin_t pinn, int is_active) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin == 0 || pin->status != gpio_status_free) return; + gpio_pin_set(pin, is_active); +} + +int gpion_pin_get_free(gpion_pin_t pinn, int def) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin == 0 || (pin->status != gpio_status_free && pin->status != gpio_status_occupied)) return def; + return gpio_pin_get(pin); +} + +gpio_status_t gpion_pin_get_status(gpion_pin_t pinn) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin == 0) return gpio_status_unknown; + return pin->status; +} + +gpio_hal_t gpion_to_hal(gpion_pin_t pin) { + gpio_hal_t result = { 0 }; +#define pin_is(port) (gpio_pin_ ## port ## _first <= pin && pin <= gpio_pin_ ## port ## _last) +#define get_pin_d(port, d) pin - gpio_pin_ ## port ## _first + d; +#define get_pin(port) get_pin_d(port, 0) + if (pin_is(pa)) { + result.port = GPIOA; + result.pin = get_pin(pa); + } else if (pin_is(pb)) { + result.port = GPIOB; + result.pin = get_pin(pb); + } else if (pin_is(pc)) { + result.port = GPIOC; + result.pin = get_pin_d(pc, 13); + } + return result; +#undef get_pin +#undef get_pin_d +#undef pin_is +} + +cdc_pin_ref_t gpion_to_cdc(gpion_pin_t pin) +{ + cdc_pin_ref_t result = { .port = -1, .pin = cdc_pin_unknown, }; + device_config_t *device_config = device_config_get(); + + for (int port = 0; port < USB_CDC_NUM_PORTS; ++port) { + for (cdc_pin_t cpin = 0; cpin < cdc_pin_last; ++cpin) { + if (device_config->cdc_config.port_config[port].pins[cpin] == pin) { + result.port = port; + result.pin = cpin; + return result; + } + } + } + return result; +} + diff --git a/gpion.h b/gpion.h new file mode 100644 index 0000000..2fa7ab4 --- /dev/null +++ b/gpion.h @@ -0,0 +1,97 @@ +/* + * MIT License + * + * Copyright (c) 2022 Yury Shvedov + */ + +#ifndef GPION_H +#define GPION_H + +#include + +#include "gpio.h" +#include "usb_cdc.h" + +typedef enum { + gpio_pin_pa_first = 0, + gpio_pin_pa0 = gpio_pin_pa_first, + gpio_pin_pa1, + gpio_pin_pa2, + gpio_pin_pa3, + gpio_pin_pa4, + gpio_pin_pa5, + gpio_pin_pa6, + gpio_pin_pa7, + gpio_pin_pa8, + gpio_pin_pa9, + gpio_pin_pa10, + gpio_pin_pa11, + gpio_pin_pa12, + gpio_pin_pa13, + gpio_pin_pa14, + gpio_pin_pa15, + gpio_pin_pa_last = gpio_pin_pa15, + + gpio_pin_pb_first = gpio_pin_pa_last + 1, + gpio_pin_pb0 = gpio_pin_pb_first, + gpio_pin_pb1, + gpio_pin_pb2, + gpio_pin_pb3, + gpio_pin_pb4, + gpio_pin_pb5, + gpio_pin_pb6, + gpio_pin_pb7, + gpio_pin_pb8, + gpio_pin_pb9, + gpio_pin_pb10, + gpio_pin_pb11, + gpio_pin_pb12, + gpio_pin_pb13, + gpio_pin_pb14, + gpio_pin_pb15, + gpio_pin_pb_last = gpio_pin_pb15, + + gpio_pin_pc_first = gpio_pin_pb_last + 1, + gpio_pin_pc13 = gpio_pin_pc_first, + gpio_pin_pc14, + gpio_pin_pc15, + gpio_pin_pc_last = gpio_pin_pc15, + + gpio_pin_unknown, + gpio_pin_last = gpio_pin_unknown, +} gpion_pin_t; + +typedef struct { + gpio_pin_t pins [gpio_pin_last]; +} gpio_config_t; + +typedef struct { + int port; + cdc_pin_t pin; +} __packed cdc_pin_ref_t; + +gpio_pin_t *gpion_to_gpio(gpion_pin_t pinn); +gpion_pin_t gpio_to_gpion(const gpio_pin_t *pin); + +const char *gpion_to_str(gpion_pin_t pinn); +gpion_pin_t str_to_gpion(const char *str); + +void gpion_pin_init(gpion_pin_t pin); + +/* This will work only for occupied pins */ +void gpion_pin_set(gpion_pin_t pin, int is_active); +int gpion_pin_get(gpion_pin_t pin); +int gpion_pin_get_default(gpion_pin_t pin, int def); + +volatile uint32_t *gpion_pin_get_bitband_clear_addr(gpion_pin_t pin); + +/* Set will work only for free pins, get - for free and occupied */ +void gpion_pin_set_free(gpion_pin_t pin, int is_active); +int gpion_pin_get_free(gpion_pin_t pin, int def); + +gpio_status_t gpion_pin_get_status(gpion_pin_t pin); + +gpio_hal_t gpion_to_hal(gpion_pin_t pin); + +cdc_pin_ref_t gpion_to_cdc(gpion_pin_t pin); +#endif /* GPION_H */ diff --git a/main.c b/main.c index dc37acd..309d971 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,7 @@ int main() { device_config_init(); status_led_init(); usb_init(); + while (1) { usb_poll(); } diff --git a/status_led.c b/status_led.c index cd5e95e..444e5c8 100644 --- a/status_led.c +++ b/status_led.c @@ -9,15 +9,15 @@ #include "device_config.h" #include "status_led.h" -static gpio_pin_t *status_led_pin; +gpion_pin_t status_led_pin; void status_led_init() { - status_led_pin = &device_config_get()->status_led_pin; - gpio_pin_init(status_led_pin); - gpio_pin_set(status_led_pin, 0); + status_led_pin = device_config_get()->status_led_pin; + gpion_pin_init(status_led_pin); + gpion_pin_set(status_led_pin, 0); } void status_led_set(int on) { (void)status_led_set; /* This function does not have to be used */ - gpio_pin_set(status_led_pin, on); + gpion_pin_set(status_led_pin, on); } diff --git a/usb_cdc.c b/usb_cdc.c index 67b84f8..1eeb9b7 100644 --- a/usb_cdc.c +++ b/usb_cdc.c @@ -196,8 +196,8 @@ static void usb_cdc_notify_port_overrun(int port) { static void usb_cdc_update_port_dtr(int port) { if (port < USB_CDC_NUM_PORTS) { usb_cdc_state_t *cdc_state = &usb_cdc_states[port]; - const gpio_pin_t *dtr_pin = &device_config_get()->cdc_config.port_config[port].pins[cdc_pin_dtr]; - gpio_pin_set(dtr_pin, cdc_state->dtr_active); + gpion_pin_t dtr_pin = device_config_get()->cdc_config.port_config[port].pins[cdc_pin_dtr]; + gpion_pin_set(dtr_pin, cdc_state->dtr_active); } } @@ -211,11 +211,13 @@ static void usb_cdc_set_port_dtr(int port, int dtr_active) { static void usb_cdc_update_port_rts(int port) { if ((port < USB_CDC_NUM_PORTS)) { - const gpio_pin_t *rts_pin = &device_config_get()->cdc_config.port_config[port].pins[cdc_pin_rts]; - usb_cdc_state_t *cdc_state = &usb_cdc_states[port]; - circ_buf_t *rx_buf = &cdc_state->rx_buf; - int rts_active = ((circ_buf_space(rx_buf->head, rx_buf->tail, USB_CDC_BUF_SIZE) > (USB_CDC_BUF_SIZE>>1))) && cdc_state->rts_active; - gpio_pin_set(rts_pin, rts_active); + gpion_pin_t rts_pin = device_config_get()->cdc_config.port_config[port].pins[cdc_pin_rts]; + if (gpion_pin_get_status(rts_pin) == gpio_status_occupied) { + usb_cdc_state_t *cdc_state = &usb_cdc_states[port]; + circ_buf_t *rx_buf = &cdc_state->rx_buf; + int rts_active = ((circ_buf_space(rx_buf->head, rx_buf->tail, USB_CDC_BUF_SIZE) > (USB_CDC_BUF_SIZE>>1))) && cdc_state->rts_active; + gpion_pin_set(rts_pin, rts_active); + } } } @@ -229,8 +231,8 @@ static void usb_cdc_set_port_rts(int port, int rts_active) { static void usb_cdc_update_port_txa(int port) { if (port < USB_CDC_NUM_PORTS) { usb_cdc_state_t *cdc_state = &usb_cdc_states[port]; - const gpio_pin_t *txa_pin = &device_config_get()->cdc_config.port_config[port].pins[cdc_pin_txa]; - gpio_pin_set(txa_pin, cdc_state->txa_active); + const gpion_pin_t txa_pin = device_config_get()->cdc_config.port_config[port].pins[cdc_pin_txa]; + gpion_pin_set(txa_pin, cdc_state->txa_active); } } @@ -472,7 +474,7 @@ static void usb_cdc_port_tx_complete(int port) { usb_cdc_port_start_tx(port); } else { usb_cdc_set_port_txa(port, 0); - usb_cdc_config_mode_process_tx(port); + usb_cdc_config_mode_process_tx(); } } @@ -537,7 +539,7 @@ void USART3_IRQHandler() { void usb_cdc_reconfigure_port_pin(int port, cdc_pin_t pin) { if (port < USB_CDC_NUM_PORTS && pin < cdc_pin_last) { - gpio_pin_init(&device_config_get()->cdc_config.port_config[port].pins[pin]); + gpion_pin_init(device_config_get()->cdc_config.port_config[port].pins[pin]); if (pin == cdc_pin_rts) { usb_cdc_update_port_rts(port); } else if (pin == cdc_pin_dtr) { @@ -545,7 +547,7 @@ void usb_cdc_reconfigure_port_pin(int port, cdc_pin_t pin) { } else if (pin == cdc_pin_txa) { usb_cdc_update_port_txa(port); usb_cdc_states[port].txa_bitband_clear = - gpio_pin_get_bitband_clear_addr(&device_config_get()->cdc_config.port_config[port].pins[cdc_pin_txa]); + gpion_pin_get_bitband_clear_addr(device_config_get()->cdc_config.port_config[port].pins[cdc_pin_txa]); } } } @@ -553,12 +555,12 @@ void usb_cdc_reconfigure_port_pin(int port, cdc_pin_t pin) { static void usb_cdc_configure_port(int port) { const device_config_t *device_config = device_config_get(); for (cdc_pin_t pin = 0; pin < cdc_pin_last; pin++) { - gpio_pin_init(&device_config->cdc_config.port_config[port].pins[pin]); + gpion_pin_init(device_config->cdc_config.port_config[port].pins[pin]); usb_cdc_update_port_rts(port); usb_cdc_update_port_dtr(port); usb_cdc_update_port_txa(port); usb_cdc_states[port].txa_bitband_clear = - gpio_pin_get_bitband_clear_addr(&device_config_get()->cdc_config.port_config[port].pins[cdc_pin_txa]); + gpion_pin_get_bitband_clear_addr(device_config_get()->cdc_config.port_config[port].pins[cdc_pin_txa]); } } @@ -586,7 +588,7 @@ void usb_cdc_reset() { RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; /* Configuration Mode Pin */ - gpio_pin_init(&device_config->config_pin); + gpion_pin_init(device_config->config_pin); /* USART & DMA Reset and Setup */ RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_USART3EN; @@ -652,13 +654,13 @@ void usb_cdc_frame() { for (int port = 0; port < USB_CDC_NUM_PORTS; port++) { const cdc_port_t *port_config = &device_config_get()->cdc_config.port_config[port]; usb_cdc_serial_state_t _state, new_state, control_lines_state = 0; - if (gpio_pin_get(&port_config->pins[cdc_pin_dsr])) { + if (gpion_pin_get_default(port_config->pins[cdc_pin_dsr], 1)) { control_lines_state |= USB_CDC_SERIAL_STATE_DSR; } - if (gpio_pin_get(&port_config->pins[cdc_pin_dcd])) { + if (gpion_pin_get(port_config->pins[cdc_pin_dcd])) { control_lines_state |= USB_CDC_SERIAL_STATE_DCD; } - if (gpio_pin_get(&port_config->pins[cdc_pin_ri])) { + if (gpion_pin_get(port_config->pins[cdc_pin_ri])) { control_lines_state |= USB_CDC_SERIAL_STATE_RI; } do { @@ -667,7 +669,7 @@ void usb_cdc_frame() { new_state |= control_lines_state; } while (!(__sync_bool_compare_and_swap(&usb_cdc_states[port].serial_state, _state, new_state))); } - if (gpio_pin_get(&device_config->config_pin) != usb_cdc_config_mode) { + if (gpion_pin_get_default(device_config->config_pin, 1) != usb_cdc_config_mode) { if (usb_cdc_config_mode) { usb_cdc_config_mode_leave(); } else { @@ -691,7 +693,7 @@ void usb_cdc_data_endpoint_event_handler(uint8_t ep_num, usb_endpoint_event_t ep size_t tx_space_available = circ_buf_space(tx_buf->head, tx_buf->tail, USB_CDC_BUF_SIZE); size_t rx_bytes_available = usb_bytes_available(ep_num); if ((port == USB_CDC_CONFIG_PORT) && usb_cdc_config_mode) { - usb_cdc_config_mode_process_tx(port); + usb_cdc_config_mode_process_tx(); } else { /* Do not receive data until line state change is complete */ if ((tx_space_available < rx_bytes_available) || (cdc_state->line_state_change_pending)) { @@ -707,6 +709,7 @@ void usb_cdc_data_endpoint_event_handler(uint8_t ep_num, usb_endpoint_event_t ep usb_status_t usb_cdc_ctrl_process_request(usb_setup_t *setup, void **payload, size_t *payload_size, usb_tx_complete_cb_t *tx_callback_ptr) { + (void) tx_callback_ptr; if ((setup->type == usb_setup_type_class) && (setup->recepient == usb_setup_recepient_interface)) { int if_num = setup->wIndex; diff --git a/usb_cdc.h b/usb_cdc.h index 7ad32f5..3370b83 100644 --- a/usb_cdc.h +++ b/usb_cdc.h @@ -192,7 +192,6 @@ typedef enum { cdc_pin_last = cdc_pin_unknown, } __packed cdc_pin_t; - /* Configuration Changed Hooks */ void usb_cdc_reconfigure_port_pin(int port, cdc_pin_t pin); diff --git a/usb_core.c b/usb_core.c index c5d7589..e880690 100644 --- a/usb_core.c +++ b/usb_core.c @@ -62,6 +62,7 @@ void usb_device_poll() { usb_status_t usb_control_endpoint_process_get_descriptor(usb_setup_t *setup, void **payload, size_t *payload_size, usb_tx_complete_cb_t *tx_callback_ptr) { + (void) tx_callback_ptr; usb_descriptor_type_t descriptor_type = (setup->wValue >> 8); uint8_t descriptor_index = (setup->wValue & 0xff); switch (descriptor_type) { @@ -137,6 +138,8 @@ usb_status_t usb_control_endpoint_process_device_request(usb_setup_t *setup, usb_status_t usb_control_endpoint_process_interface_request(usb_setup_t *setup, void **payload, size_t *payload_size, usb_tx_complete_cb_t *tx_callback_ptr) { + (void) payload_size; + (void) tx_callback_ptr; if (setup->bRequest == usb_device_request_get_status) { ((uint8_t*)(*payload))[0] = 0; ((uint8_t*)(*payload))[1] = 0; @@ -149,6 +152,8 @@ usb_status_t usb_control_endpoint_process_interface_request(usb_setup_t *setup, usb_status_t usb_control_endpoint_process_endpoint_request(usb_setup_t *setup, void **payload, size_t *payload_size, usb_tx_complete_cb_t *tx_callback_ptr) { + (void) payload_size; + (void) tx_callback_ptr; uint8_t ep_num = setup->wIndex & ~(usb_endpoint_direction_in); usb_endpoint_direction_t ep_direction = setup->wIndex & usb_endpoint_direction_in; if ((setup->bRequest == usb_device_request_set_feature) || diff --git a/usb_uid.c b/usb_uid.c index 216f1b2..0f337a3 100644 --- a/usb_uid.c +++ b/usb_uid.c @@ -13,7 +13,7 @@ usb_string_descriptor_t *usb_get_uid_string_descriptor() { static usb_string_descriptor_t uid_string_descriptor = USB_STRING_DESC("XXXXXXXXXXXXXXXXXXXXXXXX"); uint8_t *uid_p = (uint8_t*)UID_BASE; uint16_t *str_p = uid_string_descriptor.wString; - for (int i=0; i> 4]; *str_p++ = hex_digits[*uid_p++ & 0x0f]; } From c2121013aad1ae02433a2ed751e69dc0452f903c Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Sun, 6 Nov 2022 16:20:18 +0300 Subject: [PATCH 6/7] Introduce disabling the uart ports --- default_config.c | 67 ++++++++++++++++++++++++++++++++++++--------- default_config.h | 2 ++ device_config.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ device_config.h | 3 +++ usb_cdc.c | 70 +++++++++++++++++++++++++++++++++++++++--------- usb_cdc.h | 3 +++ 6 files changed, 188 insertions(+), 26 deletions(-) diff --git a/default_config.c b/default_config.c index 43a3e3b..da0c823 100644 --- a/default_config.c +++ b/default_config.c @@ -88,7 +88,8 @@ static const default_config_t default_config = { }, }; -static gpion_pin_t default_config_pin_load(device_config_t *target, const default_gpio_pin_t *source); +static gpion_pin_t default_config_load_pin_int(device_config_t *target, const default_gpio_pin_t *source); +static void default_config_copy(gpio_pin_t *target, const default_gpio_pin_t *source); static void default_config_pin_last(device_config_t *target, gpion_pin_t pin); void default_config_load(device_config_t *target) { @@ -115,23 +116,23 @@ void default_config_load(device_config_t *target) { for (gpion_pin_t pin = 0; pin < gpio_pin_last; ++pin) { default_free.pin = pin; target->gpio_config.pins[pin].status = gpio_status_free; - default_config_pin_load(target, &default_free); + default_config_load_pin_int(target, &default_free); } // configure system pins for (int i = 0; default_config.blocked_pins[i].pin != default_blocked_pin_end; ++i) { gpion_pin_t pin = default_config.blocked_pins[i].pin; default_blocked.pin = pin; - default_config_pin_load(target, &default_blocked); + default_config_load_pin_int(target, &default_blocked); } // configure misc pins - target->status_led_pin = default_config_pin_load(target, &default_config.status_led_pin); - target->config_pin = default_config_pin_load(target, &default_config.config_pin); + target->status_led_pin = default_config_load_pin_int(target, &default_config.status_led_pin); + target->config_pin = default_config_load_pin_int(target, &default_config.config_pin); // configure uart pins for (int port = 0; port < ARRAY_SIZE(target->cdc_config.port_config) && port < ARRAY_SIZE(default_config.cdc_config.port_config); ++port) { const default_port_t *default_port = &default_config.cdc_config.port_config[port]; cdc_port_t *port_config = &target->cdc_config.port_config[port]; for (int pin = 0; pin < ARRAY_SIZE(default_port->pins) && pin < ARRAY_SIZE(port_config->pins); ++pin) { - port_config->pins[pin] = default_config_pin_load(target, &default_port->pins[pin]); + port_config->pins[pin] = default_config_load_pin_int(target, &default_port->pins[pin]); } } // configure other pins @@ -141,6 +142,51 @@ void default_config_load(device_config_t *target) { } } +void default_config_load_pin(device_config_t *target, gpion_pin_t pinn) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (!pin) { + return; + } + const default_gpio_pin_t *conf = default_config_get_pin(pinn); + if (!conf) { + return; + } + default_config_copy(pin, conf); +} + +const default_gpio_pin_t *default_config_get_pin(gpion_pin_t pinn) +{ + const default_gpio_pin_t *conf = 0; + + if (!conf && default_config.config_pin.pin == pinn) { + conf = &default_config.config_pin; + } + if (!conf && default_config.status_led_pin.pin == pinn) { + conf = &default_config.status_led_pin; + } + for (int port = 0; !conf && port < ARRAY_SIZE(default_config.cdc_config.port_config); ++port) { + const default_port_t *cport = &default_config.cdc_config.port_config[port]; + for (cdc_pin_t cpin = 0; !conf && cpin < cdc_pin_last; ++cpin) { + if (cport->pins[cpin].pin == pinn) { + conf = &cport->pins[cpin]; + } + } + } + + return conf; +} + +static void default_config_copy(gpio_pin_t *target, const default_gpio_pin_t *source) +{ + target->dir = source->dir; + target->func = source->func; + target->output = source->output; + target->pull = source->pull; + target->polarity = source->polarity; + target->speed = source->speed; +} + const char *default_config_get_blocked_reason(gpion_pin_t pin) { static const char *not_blocked = "pin is not blocked"; for (int i = 0; default_config.blocked_pins[i].pin != default_blocked_pin_end; ++i) { @@ -151,7 +197,7 @@ const char *default_config_get_blocked_reason(gpion_pin_t pin) { return not_blocked; } -static gpion_pin_t default_config_pin_load(device_config_t *target, const default_gpio_pin_t *source){ +static gpion_pin_t default_config_load_pin_int(device_config_t *target, const default_gpio_pin_t *source){ if (source->pin == gpio_pin_unknown) { return gpio_pin_unknown; } @@ -160,13 +206,8 @@ static gpion_pin_t default_config_pin_load(device_config_t *target, const defaul return source->pin; } - pin->dir = source->dir; - pin->func = source->func; - pin->output = source->output; - pin->pull = source->pull; - pin->polarity = source->polarity; - pin->speed = source->speed; pin->status = source->status; + default_config_copy(pin, source); return source->pin; } diff --git a/default_config.h b/default_config.h index 1d0487a..0fdb243 100644 --- a/default_config.h +++ b/default_config.h @@ -46,5 +46,7 @@ typedef struct { void default_config_load(device_config_t *target); const char *default_config_get_blocked_reason(gpion_pin_t pin); +void default_config_load_pin(device_config_t *target, gpion_pin_t pinn); +const default_gpio_pin_t *default_config_get_pin(gpion_pin_t); #endif /* DEFAULT_CONFIG_H */ diff --git a/device_config.c b/device_config.c index 799e360..6368039 100644 --- a/device_config.c +++ b/device_config.c @@ -126,3 +126,72 @@ void device_config_reset() { default_config_load(¤t_device_config); device_config_save(); } + +static int cdc_port_set_enable_confugred(int port, int enabled); +static void gpio_pin_alternative_update(int port, gpio_status_t new_status) +{ + device_config_t *device_config = device_config_get(); + cdc_port_t *port_config = &device_config->cdc_config.port_config[port]; + gpio_pin_t *rx = gpion_to_gpio(port_config->pins[cdc_pin_rx]); + gpio_pin_t *tx = gpion_to_gpio(port_config->pins[cdc_pin_tx]); + + if (rx->status == gpio_status_occupied && tx->status == gpio_status_occupied) { + cdc_port_set_enable_confugred(port, 1); + } else if (rx->status != tx->status && new_status == gpio_status_free) { + cdc_port_set_enable_confugred(port, 0); + } +} + +int gpio_pin_set_status(gpion_pin_t pinn, gpio_status_t new_status) +{ + gpio_pin_t *pin = gpion_to_gpio(pinn); + device_config_t *device_config = device_config_get(); + if (!pin) return -1; + if (pin->status == new_status || pin->status == gpio_status_blocked || + (new_status != gpio_status_free && new_status != gpio_status_occupied)) { + return 0; + } + cdc_pin_ref_t cdc_pin = gpion_to_cdc(pinn); + + pin->status = new_status; + if (cdc_pin.port >= 0 && cdc_pin.port < USB_CDC_NUM_PORTS) { + if (new_status == gpio_status_occupied) { + default_config_load_pin(device_config, pinn); + usb_cdc_reconfigure_port_pin(cdc_pin.port, cdc_pin.pin); + } + if (cdc_pin.pin == cdc_pin_rx || cdc_pin.pin == cdc_pin_tx) { + gpio_pin_alternative_update(cdc_pin.port, new_status); + } + } + return 0; +} + +int cdc_port_set_enable(int port, int enabled) +{ + device_config_t *device_config = device_config_get(); + cdc_port_t *port_config = &device_config->cdc_config.port_config[port]; + if (enabled) { + gpio_pin_set_status(port_config->pins[cdc_pin_rx], gpio_status_occupied); + gpio_pin_set_status(port_config->pins[cdc_pin_tx], gpio_status_occupied); + } else { + gpio_pin_set_status(port_config->pins[cdc_pin_rx], gpio_status_free); + gpio_pin_set_status(port_config->pins[cdc_pin_tx], gpio_status_free); + } + return 0; +} + +static int cdc_port_set_enable_confugred(int port, int enabled) +{ + device_config_t *device_config = device_config_get(); + cdc_port_t *port_config = &device_config->cdc_config.port_config[port]; + if (enabled) { + usb_cdc_reconfigure_port(port); + usb_cdc_enable_port(port); + } else { + usb_cdc_suspend_port(port); + for (int pin = 0; pin < cdc_pin_last; ++pin) { + gpio_pin_set_status(port_config->pins[pin], gpio_status_free); + } + } + return 0; +} diff --git a/device_config.h b/device_config.h index 3f1628a..0bcf8b0 100644 --- a/device_config.h +++ b/device_config.h @@ -27,4 +27,7 @@ device_config_t *device_config_get(); void device_config_save(); void device_config_reset(); +int gpio_pin_set_status(gpion_pin_t pin, gpio_status_t new_status); +int cdc_port_set_enable(int port, int enabled); + #endif /* DEVICE_CONFIG_H_ */ diff --git a/usb_cdc.c b/usb_cdc.c index 1eeb9b7..e3d359f 100644 --- a/usb_cdc.c +++ b/usb_cdc.c @@ -32,6 +32,7 @@ static const usb_cdc_line_coding_t usb_cdc_default_line_coding = { }; typedef struct { + int enabled; circ_buf_t rx_buf; uint8_t _rx_data[USB_CDC_BUF_SIZE]; circ_buf_t tx_buf; @@ -71,6 +72,21 @@ typedef enum { usb_cdc_port_direction_last } usb_cdc_port_direction_t; +static int usb_cdc_port_is_enabled(int port) { + if (port < USB_CDC_NUM_PORTS) { + const device_config_t *device_config = device_config_get(); + const cdc_port_t *port_config = &device_config->cdc_config.port_config[port]; + const gpio_pin_t *rx = gpion_to_gpio(port_config->pins[cdc_pin_rx]); + const gpio_pin_t *tx = gpion_to_gpio(port_config->pins[cdc_pin_tx]); + if (rx && tx) { + return !!usb_cdc_states[port].enabled && + rx->status == gpio_status_occupied && + tx->status == gpio_status_occupied; + } + } + return 0; +} + static DMA_Channel_TypeDef* usb_cdc_get_port_dma_channel(int port, usb_cdc_port_direction_t port_dir) { static DMA_Channel_TypeDef* const port_dma_channels[][usb_cdc_port_direction_last] = { { DMA1_Channel5, DMA1_Channel4 }, @@ -470,11 +486,15 @@ static void usb_cdc_port_tx_complete(int port) { cdc_state->line_state_change_ready = 1; } } - if ((port != USB_CDC_CONFIG_PORT) || !usb_cdc_config_mode) { - usb_cdc_port_start_tx(port); - } else { - usb_cdc_set_port_txa(port, 0); + if (port == USB_CDC_CONFIG_PORT && usb_cdc_config_mode) { usb_cdc_config_mode_process_tx(); + usb_cdc_set_port_txa(port, 0); + } else { + if (usb_cdc_port_is_enabled(port)) { + usb_cdc_port_start_tx(port); + } else { + usb_cdc_set_port_txa(port, 0); + } } } @@ -552,7 +572,7 @@ void usb_cdc_reconfigure_port_pin(int port, cdc_pin_t pin) { } } -static void usb_cdc_configure_port(int port) { +void usb_cdc_reconfigure_port(int port) { const device_config_t *device_config = device_config_get(); for (cdc_pin_t pin = 0; pin < cdc_pin_last; pin++) { gpion_pin_init(device_config->cdc_config.port_config[port].pins[pin]); @@ -566,7 +586,7 @@ static void usb_cdc_configure_port(int port) { void usb_cdc_reconfigure() { for (int port = 0; port < USB_CDC_NUM_PORTS; port++) { - usb_cdc_configure_port(port); + usb_cdc_reconfigure_port(port); } } @@ -603,7 +623,7 @@ void usb_cdc_reset() { for (int port=0; portCR1 |= USART_CR1_PEIE | USART_CR1_IDLEIE | USART_CR1_RE | USART_CR1_PEIE; + usb_cdc_enable_port(port); } } void usb_cdc_suspend() { usb_cdc_enabled = 0; for (int port=0; port= 0 && port < USB_CDC_NUM_PORTS) { + USART_TypeDef *usart = usb_cdc_get_port_usart(port); + usb_cdc_states[port].enabled = 1; + usb_cdc_port_start_rx(port); + usart->CR1 |= USART_CR1_PEIE | USART_CR1_IDLEIE | USART_CR1_RE | USART_CR1_PEIE; + } +} + +void usb_cdc_suspend_port(int port) +{ + if (port >= 0 && port < USB_CDC_NUM_PORTS) { USART_TypeDef *usart = usb_cdc_get_port_usart(port); + usb_cdc_states[port].enabled = 0; usart->CR1 &= ~(USART_CR1_UE); } } @@ -700,7 +736,11 @@ void usb_cdc_data_endpoint_event_handler(uint8_t ep_num, usb_endpoint_event_t ep cdc_state->usb_rx_pending_ep = ep_num; } else { usb_circ_buf_read(ep_num, tx_buf, USB_CDC_BUF_SIZE); - usb_cdc_port_start_tx(port); + if (usb_cdc_port_is_enabled(port)) { + usb_cdc_port_start_tx(port); + } else { + usb_cdc_set_port_txa(port, 0); + } } } } @@ -756,7 +796,7 @@ void usb_cdc_poll() { for (int port = 0; port < (USB_CDC_NUM_PORTS); port++) { usb_cdc_state_t *cdc_state = &usb_cdc_states[port]; circ_buf_t *tx_buf = &cdc_state->tx_buf; - if ((port != USB_CDC_CONFIG_PORT) || (usb_cdc_config_mode == 0)) { + if (((port != USB_CDC_CONFIG_PORT) || (usb_cdc_config_mode == 0)) && usb_cdc_port_is_enabled(port)) { usb_cdc_sync_rx_buffer(port); } usb_cdc_notify_port_state_change(port); @@ -771,7 +811,11 @@ void usb_cdc_poll() { size_t rx_bytes_available = usb_bytes_available(cdc_state->usb_rx_pending_ep); if (tx_space_available >= rx_bytes_available) { usb_circ_buf_read(cdc_state->usb_rx_pending_ep, tx_buf, USB_CDC_BUF_SIZE); - usb_cdc_port_start_tx(port); + if (usb_cdc_port_is_enabled(port)) { + usb_cdc_port_start_tx(port); + } else { + usb_cdc_set_port_txa(port, 0); + } cdc_state->usb_rx_pending_ep = 0; } } diff --git a/usb_cdc.h b/usb_cdc.h index 3370b83..14daa6c 100644 --- a/usb_cdc.h +++ b/usb_cdc.h @@ -175,6 +175,8 @@ void usb_cdc_reset(); void usb_cdc_enable(); void usb_cdc_suspend(); void usb_cdc_frame(); +void usb_cdc_enable_port(int port); +void usb_cdc_suspend_port(int port); /* CDC Pins */ @@ -195,6 +197,7 @@ typedef enum { /* Configuration Changed Hooks */ void usb_cdc_reconfigure_port_pin(int port, cdc_pin_t pin); +void usb_cdc_reconfigure_port(int port); void usb_cdc_reconfigure(); /* CDC Device Definitions */ From 19d5735399796853d354c8a02bfa66e0d2a4016a Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Thu, 3 Nov 2022 20:57:15 +0300 Subject: [PATCH 7/7] Introduce gpio shell --- cdc_shell.c | 429 ++++++++++++++++++++++++++++++++++++++++++++++++++++ usb_cdc.c | 2 + 2 files changed, 431 insertions(+) diff --git a/cdc_shell.c b/cdc_shell.c index c497162..1d6fe8a 100644 --- a/cdc_shell.c +++ b/cdc_shell.c @@ -7,10 +7,14 @@ #include #include #include +#include +#include + #include "usb_cdc.h" #include "gpio.h" #include "cdc_config.h" #include "device_config.h" +#include "default_config.h" #include "version.h" #include "cdc_shell.h" @@ -42,6 +46,26 @@ __noinline static void cdc_shell_write_string(const char *buf) { cdc_shell_write(buf, strlen(buf)); } +__noinline static void cdc_shell_msg(const char *fmt, ...) { + char buf[1024]; + int len = 0; + + if (fmt != 0) { + va_list va; + va_start(va, fmt); + len = vsnprintf(buf, sizeof(buf) - 2, fmt, va); + va_end(va); + } + + if (len >= 0) { + if (len < 2 || ( buf[len - 2] != '\r' && buf[len - 2] != '\n')) { + buf[len++] = '\r'; + buf[len++] = '\n'; + } + cdc_shell_write(buf, len); + } +} + static int cdc_shell_invoke_command(int argc, char *argv[], const cdc_shell_cmd_t *commands) { const cdc_shell_cmd_t *shell_cmd = commands; while (shell_cmd->cmd) { @@ -329,6 +353,384 @@ static void cdc_shell_cmd_uart(int argc, char *argv[]) { } } +/* Gpio macro helpers */ + +/* Wrapper on cdc_shell_msg, which prints message about specified pin */ +#define cdc_shell_msg_pin(pinn, fmt, ...) cdc_shell_msg("%6s [%d]: " fmt, \ + gpion_to_str(pinn), gpion_pin_get_free(pinn, 0), \ + ## __VA_ARGS__) + +/* Extra special numbers of pins which specifies the groups of pins. The numbers + * lies after gpio_pin_last and used withing shell processing functions to apply + * massive operations. */ +#define cdc_shell_gpion_pin_ref_all cdc_shell_gpion_pin_ref(1) +#define cdc_shell_gpion_pin_ref_free cdc_shell_gpion_pin_ref(2) +#define cdc_shell_gpion_pin_ref_blocked cdc_shell_gpion_pin_ref(3) +#define cdc_shell_gpion_pin_ref_occupied cdc_shell_gpion_pin_ref(4) +#define cdc_shell_gpion_pin_ref_uart1 cdc_shell_gpion_pin_ref(5) +#define cdc_shell_gpion_pin_ref_uart2 cdc_shell_gpion_pin_ref(6) +#define cdc_shell_gpion_pin_ref_uart3 cdc_shell_gpion_pin_ref(7) +#define cdc_shell_gpion_pin_ref_uart cdc_shell_gpion_pin_ref_uart1 + +/* This macro will check pinn argument and if it equals to one of defined from + * above number, it will call the func for each pinn in group. This macro is + * assumed to be called from void-returning function. If pinn was matched the + * macro will execute return. The func argument must accept the pin number as + * first argument and the extra VA_ARGS will be passed in tail. */ +#define cdc_shell_pin_apply_extras(func, pinn, ...) \ + cdc_shell_pin_declare_extras(cdc_shell_pin_declare_extra_func, func, pinn, \ + ## __VA_ARGS__) + +/* This is helper macro, which check, does the string str match one of gpio + * groups. If match found - it will set pinn to specific value. */ +#define cdc_shell_pin_check_extras(str, pinn) \ + cdc_shell_pin_declare_extras(cdc_shell_pin_check_extra_func, \ + str, pinn) + +/* Helper for defining extra pin groups. */ +#define cdc_shell_gpion_pin_ref(n) BUILD_BUG_ON_RET( \ + ((gpion_pin_t)(gpio_pin_last + n) <= gpio_pin_last), \ + (gpion_pin_t)(gpio_pin_last + n)) + +/* Helper which apply func macro to all pins groups names */ +#define cdc_shell_pin_declare_extras(func, ...) do { \ + func(all, ## __VA_ARGS__); \ + func(free, ## __VA_ARGS__); \ + func(blocked, ## __VA_ARGS__); \ + func(occupied, ## __VA_ARGS__); \ + func(uart1, ## __VA_ARGS__); \ + func(uart2, ## __VA_ARGS__); \ + func(uart3, ## __VA_ARGS__); \ +} while (0) + +/* Next - goes block of helpers for cdc_shell_pin_apply_extras */ + +/* Basic helper, which performs check of pinn variable var and cicles through + * all pins to apply predicate to them to call the func. */ +#define cdc_shell_pin_extra_func(func, var, pred, name, ...) do { \ + if ((var) == cdc_shell_gpion_pin_ref_ ## name) { \ + for (gpion_pin_t __pinn = 0; __pinn < gpio_pin_last; ++__pinn) { \ + if ((pred)) { \ + (void) (func(__pinn, ## __VA_ARGS__)); \ + } \ + } \ + return; \ + } \ +} while (0) + +/* This helper implements predicate for groups based on pins' status field */ +#define cdc_shell_pin_extra_func_status(func, var, status_val, name, ...) do { \ + device_config_t *__device_config = device_config_get(); \ + cdc_shell_pin_extra_func(func, var, \ + __device_config->gpio_config.pins[__pinn].status == status_val, name, \ + ## __VA_ARGS__); \ +} while (0) + +/* This helper implements predicate for groups based on pins' belonging to uart + * port */ +#define cdc_shell_pin_extra_func_uart(func, var, port_num, ...) do { \ + cdc_shell_pin_extra_func(func, var, \ + gpion_to_cdc(__pinn).port == (port_num) - 1, \ + uart ## port_num, ## __VA_ARGS__); \ +} while (0) + +/* Next macros implements the checkers for all available pins groups */ +#define cdc_shell_pin_extra_func_all(func, var, ...) \ + cdc_shell_pin_extra_func(func, var, 1, all, ## __VA_ARGS__) + +#define cdc_shell_pin_extra_func_free(func, var, ...) \ + cdc_shell_pin_extra_func_status(func, var, gpio_status_free, free, \ + ## __VA_ARGS__) + +#define cdc_shell_pin_extra_func_blocked(func, var, ...) \ + cdc_shell_pin_extra_func_status(func, var, gpio_status_blocked, blocked, \ + ## __VA_ARGS__) + +#define cdc_shell_pin_extra_func_occupied(func, var, ...) \ + cdc_shell_pin_extra_func_status(func, var, gpio_status_occupied, occupied, \ + ## __VA_ARGS__) + +#define cdc_shell_pin_extra_func_uart1(func, var, ...) \ + cdc_shell_pin_extra_func_uart(func, var, 1, ## __VA_ARGS__) + +#define cdc_shell_pin_extra_func_uart2(func, var, ...) \ + cdc_shell_pin_extra_func_uart(func, var, 2, ## __VA_ARGS__) + +#define cdc_shell_pin_extra_func_uart3(func, var, ...) \ + cdc_shell_pin_extra_func_uart(func, var, 3, ## __VA_ARGS__) + +/* This helper just calls one of previously defined macros */ +#define cdc_shell_pin_declare_extra_func(name, ...) \ + cdc_shell_pin_extra_func_ ## name(__VA_ARGS__) + +/* Helper for cdc_shell_pin_apply_extras */ +#define cdc_shell_pin_check_extra_func(name, check_var, pin_var) do { \ + if (pin_var == gpio_pin_unknown && !strcmp(check_var, #name)) { \ + (pin_var) = cdc_shell_gpion_pin_ref_ ## name; \ + } \ +} while (0) + + +/* TODO(Shvedov) next macros and function cdc_shell_cmd_gpio_show_pin_controlled + * should be refactored and joined with cdc_shell_cmd_uart_show. */ +#define cdc_shell_gpio_mode_declare_stringify(name, vals) \ +static const char *cdc_shell_gpio_stringify_ ## name(gpio_ ## name ##_t val) { \ + static const char *strs[] = vals; \ + if (val < ARRAY_SIZE(strs)) { \ + return strs[val]; \ + } else { \ + return 0; \ + } \ +} + +#define gpio_mode_dir_strings { [gpio_dir_input] = "in", [gpio_dir_output] = "out", } +cdc_shell_gpio_mode_declare_stringify(dir, gpio_mode_dir_strings) + +#define gpio_mode_func_strings { [gpio_func_general] = "gpio", [gpio_func_alternate] = "alt", } +cdc_shell_gpio_mode_declare_stringify(func, gpio_mode_func_strings) + +#define gpio_mode_output_strings { [gpio_output_pp] = "pp", [gpio_output_od] = "od", } +cdc_shell_gpio_mode_declare_stringify(output, gpio_mode_output_strings) + +#define gpio_mode_pull_strings { [gpio_pull_floating] = "pullfloat", \ + [gpio_pull_up] = "pullup", \ + [gpio_pull_down] = "pulldown", } +cdc_shell_gpio_mode_declare_stringify(pull, gpio_mode_pull_strings) + +#define gpio_mode_polarity_strings { [gpio_polarity_high] = "polar_high", [gpio_polarity_low] = "polar_low", } +cdc_shell_gpio_mode_declare_stringify(polarity, gpio_mode_polarity_strings) + +#define gpio_mode_speed_strings { [gpio_speed_low] = "slow", \ + [gpio_speed_high] = "fast", \ + [gpio_speed_medium] = "speed_medium", } +cdc_shell_gpio_mode_declare_stringify(speed, gpio_mode_speed_strings) + +static void cdc_shell_cmd_gpio_show_pin_controlled(gpion_pin_t pinn, int show_info) { + gpio_pin_t *pin = gpion_to_gpio(pinn); + cdc_pin_ref_t cpin = gpion_to_cdc(pinn); + char info_str[64] = ""; + if (show_info) { + + const char *dir = cdc_shell_gpio_stringify_dir(pin->dir); + const char *func = cdc_shell_gpio_stringify_func(pin->func); + const char *output = cdc_shell_gpio_stringify_output(pin->output); + const char *pull = cdc_shell_gpio_stringify_pull(pin->pull); + const char *speed = cdc_shell_gpio_stringify_speed(pin->speed); + const char *polarity = cdc_shell_gpio_stringify_polarity(pin->polarity); + +#define str_val(var) var ? ", " : "", var ? var : "" +#define str_val_func(var) var ? "" : " invalid func ", var ? var : "" +#define str_mod_fmt "%s%s%s%s%s%s%s%s%s%s%s%s" +#define str_mod_vals str_val_func(func), str_val(dir), str_val(output), \ + str_val(pull), str_val(speed), str_val(polarity) + snprintf(info_str, sizeof(info_str), "\t- " str_mod_fmt, str_mod_vals); + } + + if (pin->status == gpio_status_free) { + cdc_shell_msg_pin(pinn, "free%s", info_str); + } else if (cpin.port < 0 || cpin.port >= USB_CDC_NUM_PORTS || cpin.pin >= cdc_pin_last) { + device_config_t *config = device_config_get(); + if (config->status_led_pin == pinn) { + cdc_shell_msg_pin(pinn, "status led%s", info_str); + } else if (config->config_pin == pinn) { + cdc_shell_msg_pin(pinn, "configuration control%s", info_str); + } else { + cdc_shell_msg_pin(pinn, "got invalid occupied pin"); + } + } else { + cdc_shell_msg_pin(pinn, "uart%d-%s%s", cpin.port + 1, + _cdc_uart_signal_names[cpin.pin], info_str); + } +} +static void cdc_shell_cmd_gpio_show_ex(gpion_pin_t pinn, int show_info) { + cdc_shell_pin_apply_extras(cdc_shell_cmd_gpio_show_ex, pinn, show_info); + gpio_pin_t *pin = gpion_to_gpio(pinn); + + if (!pin) { + cdc_shell_msg("Invalid pin number \"%d\"", pinn); + return; + } + + switch (pin->status) { + case gpio_status_blocked: + cdc_shell_msg_pin(pinn, "%s", default_config_get_blocked_reason(pinn)); + break; + case gpio_status_occupied: + case gpio_status_free: + cdc_shell_cmd_gpio_show_pin_controlled(pinn, show_info); + break; + default: + cdc_shell_msg_pin(pinn, "unknown"); + break; + } +} + +static void cdc_shell_cmd_gpio_count(gpion_pin_t pinn, unsigned *out_count) { + cdc_shell_pin_apply_extras(cdc_shell_cmd_gpio_count, pinn, out_count); + *out_count += 1; +} +static void cdc_shell_cmd_gpio_show(gpion_pin_t pinn) { + unsigned count_pins = 0; + cdc_shell_cmd_gpio_count(pinn, &count_pins); + cdc_shell_cmd_gpio_show_ex(pinn, count_pins <= cdc_pin_last); +} + +static void cdc_shell_cmd_gpio_set_status(gpion_pin_t pinn, gpio_status_t status) { + cdc_shell_pin_apply_extras(cdc_shell_cmd_gpio_set_status, pinn, status); + gpio_pin_set_status(pinn, status); +} + +static void cdc_shell_cmd_gpio_get(gpion_pin_t pinn) { + cdc_shell_pin_apply_extras(cdc_shell_cmd_gpio_get, pinn); + const char *value = "unavailable"; + const gpio_pin_t *pin = gpion_to_gpio(pinn); + if (!pin) { + cdc_shell_msg_pin(pinn, "Invalid pin"); + return; + } + if (pin->status == gpio_status_free || (pin->status == gpio_status_occupied && + pin->func == gpio_func_general)) + { + value = gpio_pin_get(pin) ? "up" : "down"; + } + + cdc_shell_msg_pin(pinn, "%s", value); +} + +static void cdc_shell_cmd_gpio_set(gpion_pin_t pinn, int value) { + if (value < 0) { + return; + } + cdc_shell_pin_apply_extras(cdc_shell_cmd_gpio_set, pinn, value); + gpion_pin_set_free(pinn, value); +} + +#define cdc_shell_declare_mode_set(name) \ +static void cdc_shell_cmd_gpio_##name(gpion_pin_t pinn, gpio_## name ##_t value) \ +{ \ + cdc_shell_pin_apply_extras(cdc_shell_cmd_gpio_##name, pinn, value);\ + gpio_pin_t *pin = gpion_to_gpio(pinn);\ + if (pin->status == gpio_status_free) { \ + pin->name = value;\ + } else { \ + cdc_shell_msg_pin(pinn, "Can not set " #name " on non-free pin"); \ + } \ +} +cdc_shell_declare_mode_set(dir) +cdc_shell_declare_mode_set(output) +cdc_shell_declare_mode_set(pull) +cdc_shell_declare_mode_set(polarity) +cdc_shell_declare_mode_set(speed) + +static void cdc_shell_cmd_gpio_apply_mode(gpion_pin_t pinn) +{ + cdc_shell_pin_apply_extras(cdc_shell_cmd_gpio_apply_mode, pinn); + gpio_pin_t *pin = gpion_to_gpio(pinn); + if (pin->status == gpio_status_free) { + gpio_pin_init(pin); + } +} + +static void cdc_shell_cmd_gpio_mode_usage(void) { + static const char usage[] = + "Usage: gpio PIN set [help|config...]: set configuration value of free pin\r\n" + "\thelp:\t\tshow this text\r\n" + "\tout:\t\tset pin mode to output\r\n" + "\tpp:\t\tset pin output mode to pp\r\n" + "\tod:\t\tset pin output mode to pd\r\n" + "\tpullup:\tset pin pull mode to up\r\n" + "\tpulldown:\tset pin pull mode to down\r\n" + "\tpullfloat:\tset pin pull mode to float\r\n" + "\tlow:\t\tset pin polarity to low\r\n" + "\thigh:\t\tset pin polarity to high\r\n" + "\tslow:\t\tset pin speed to low\r\n" + "\tfast:\t\tset pin speed to high\r\n" + "\tmedium:\t\tset pin speed to medium\r\n" + ; + cdc_shell_write_string(usage); +} + +static void cdc_shell_cmd_gpio_mode(gpion_pin_t pinn, int argc, char *argv[]) { + if (argc == 0 || (argc > 0 && !strcasecmp(argv[0], "help"))) { + cdc_shell_cmd_gpio_mode_usage(); + return; + } + for (int i = 0; i < argc; ++i) { + const char *str = argv[i]; + if (!strcasecmp("out", str)) { + cdc_shell_cmd_gpio_dir(pinn, gpio_dir_output); + } else if (!strcasecmp("in", str)) { + cdc_shell_cmd_gpio_dir(pinn, gpio_dir_input); + } else if (!strcasecmp("pp", str)) { + cdc_shell_cmd_gpio_output(pinn, gpio_output_pp); + } else if (!strcasecmp("od", str)) { + cdc_shell_cmd_gpio_output(pinn, gpio_output_od); + } else if (!strcasecmp("pullup", str)) { + cdc_shell_cmd_gpio_pull(pinn, gpio_pull_up); + } else if (!strcasecmp("pulldown", str)) { + cdc_shell_cmd_gpio_pull(pinn, gpio_pull_down); + } else if (!strcasecmp("pullfloat", str)) { + cdc_shell_cmd_gpio_pull(pinn, gpio_pull_floating); + } else if (!strcasecmp("low", str)) { + cdc_shell_cmd_gpio_polarity(pinn, gpio_polarity_low); + } else if (!strcasecmp("high", str)) { + cdc_shell_cmd_gpio_polarity(pinn, gpio_polarity_high); + } else if (!strcasecmp("slow", str)) { + cdc_shell_cmd_gpio_speed(pinn, gpio_speed_low); + } else if (!strcasecmp("fast", str)) { + cdc_shell_cmd_gpio_speed(pinn, gpio_speed_high); + } else if (!strcasecmp("medium", str)) { + cdc_shell_cmd_gpio_speed(pinn, gpio_speed_medium); + } else { + cdc_shell_msg("Invalid mode: \"%s\"", str); + } + } + cdc_shell_cmd_gpio_apply_mode(pinn); +} + +static void cdc_shell_cmd_gpio(int argc, char *argv[]) { + gpion_pin_t pin = cdc_shell_gpion_pin_ref_all; + const char *cmd = "show"; + if (argc > 0) + { + pin = gpio_pin_unknown; + cdc_shell_pin_check_extras(argv[0], pin); + if (pin == gpio_pin_unknown) { + pin = str_to_gpion(argv[0]); + if (pin == gpio_pin_unknown) { + if (argc == 1 && !strcmp(argv[0], "set")) { + cdc_shell_cmd_gpio_mode_usage(); + } else { + cdc_shell_msg("Invalid pin '%s'", argv[0]); + } + return; + } + } + } + if (argc > 1) { + cmd = argv[1]; + } + if (!strcmp(cmd, "show")) { + return cdc_shell_cmd_gpio_show(pin); + } else if (!strcmp(cmd, "free")) { + return cdc_shell_cmd_gpio_set_status(pin, gpio_status_free); + } else if (!strcmp(cmd, "occupy")) { + return cdc_shell_cmd_gpio_set_status(pin, gpio_status_occupied); + } else if (!strcmp(cmd, "get")) { + return cdc_shell_cmd_gpio_get(pin); + } else if (!strcmp(cmd, "up")) { + return cdc_shell_cmd_gpio_set(pin, 1); + } else if (!strcmp(cmd, "down")) { + return cdc_shell_cmd_gpio_set(pin, 0); + } else if (!strcmp(cmd, "set")) { + if (argc > 2) { + return cdc_shell_cmd_gpio_mode(pin, argc - 2, argv + 2); + } + } else { + cdc_shell_msg("Invalid gpio command '%s'", cmd); + } +} + static const char cdc_shell_err_config_missing_arguments[] = "Error, invalid or missing arguments, use \"help config\" for the list of arguments.\r\n"; @@ -394,6 +796,33 @@ static const cdc_shell_cmd_t cdc_shell_commands[] = { "Example: \"uart 1 tx output od\" sets UART1 TX output type to open-drain\r\n" "Example: \"uart 3 rts active high dcd active high pull down\" allows to set multiple parameters at once.", }, + { + .cmd = "gpio", + .handler = cdc_shell_cmd_gpio, + .description = "set and view GPIO parameters", + .usage = "Usage: gpio [pin-name|all|free|blocked|occupied|uartN [command [command_ops]]]\r\n" + "pin-name is [gpio_][pin_][p]XN, where X is port name a|b|c, N is pin number in port \r\n" + "\tall(default):\tapply command to all gpio pins \r\n" + "\tfree:\t\tapply command to all free pins \r\n" + "\tblocked:\tapply command to all blocked pins \r\n" + "\toccupied:\tapply command to all occupied pins \r\n" + "\tuartN:\t\tapply command to all pins, which may be used by uartN, N is one of 1,2,3 \r\n" + "\tled:\t\talias for pb13\r\n" + "\tshell:\r\n" + "\tcontrol:\r\n" + "\tconfig:\t\taliases for pb5\r\n" + "commands are:\r\n" + "\tshow(default):\tshow current usage of pin\r\n" + "\tfree:\t\tmake pin free from uart port\r\n" + "\toccupy:\t\tattach pin to its uart port\r\n" + "\tget:\t\tget value of pin if available\r\n" + "\tup:\t\tset free pin up\r\n" + "\tdown:\t\tset free pin down\r\n" + "\tset [help|config...]: set configuration value of free pin\r\n" + "Example: \"gpio\" shows all gpio pins and their status\r\n" + "Example: \"gpio all free\" detach all non-blocked pins from their functions\r\n" + "Example: \"uart pin_a10 up\" sets gpio pin pa10 up", + }, { .cmd = "version", .handler = cdc_shell_cmd_version, diff --git a/usb_cdc.c b/usb_cdc.c index e3d359f..3afb939 100644 --- a/usb_cdc.c +++ b/usb_cdc.c @@ -396,6 +396,7 @@ void usb_cdc_config_mode_enter() { cdc_state->tx_buf.tail = cdc_state->tx_buf.head = 0; usart->CR1 &= ~(USART_CR1_RE); dma_tx_ch->CCR &= ~(DMA_CCR_EN); + cdc_port_set_enable(USB_CDC_CONFIG_PORT, 0); cdc_shell_init(); usb_cdc_config_mode = 1; } @@ -408,6 +409,7 @@ void usb_cdc_config_mode_leave() { cdc_state->rx_buf.tail = cdc_state->rx_buf.head = dma_head; cdc_state->tx_buf.tail = cdc_state->tx_buf.head = 0; usart->CR1 |= USART_CR1_RE; + cdc_port_set_enable(USB_CDC_CONFIG_PORT, 1); usb_cdc_config_mode = 0; }