From c2121013aad1ae02433a2ed751e69dc0452f903c Mon Sep 17 00:00:00 2001 From: Yury Shvedov Date: Sun, 6 Nov 2022 16:20:18 +0300 Subject: [PATCH] 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 */