Skip to content

Commit

Permalink
Introduce disabling the uart ports
Browse files Browse the repository at this point in the history
  • Loading branch information
ein-shved committed Nov 10, 2022
1 parent 01290c9 commit c212101
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 26 deletions.
67 changes: 54 additions & 13 deletions default_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand All @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions default_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
69 changes: 69 additions & 0 deletions device_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,72 @@ void device_config_reset() {
default_config_load(&current_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;
}
3 changes: 3 additions & 0 deletions device_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
70 changes: 57 additions & 13 deletions usb_cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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);
}
}
}

Expand Down Expand Up @@ -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]);
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -603,7 +623,7 @@ void usb_cdc_reset() {
for (int port=0; port<USB_CDC_NUM_PORTS; port++) {
(void)usb_cdc_states[port]._rx_data;
(void)usb_cdc_states[port]._tx_data;
usb_cdc_configure_port(port);
usb_cdc_reconfigure_port(port);
USART_TypeDef *usart = usb_cdc_get_port_usart(port);
DMA_Channel_TypeDef *dma_rx_ch = usb_cdc_get_port_dma_channel(port, usb_cdc_port_direction_rx);
DMA_Channel_TypeDef *dma_tx_ch = usb_cdc_get_port_dma_channel(port, usb_cdc_port_direction_tx);
Expand Down Expand Up @@ -631,16 +651,32 @@ void usb_cdc_reset() {
void usb_cdc_enable() {
usb_cdc_enabled = 1;
for (int port=0; port<USB_CDC_NUM_PORTS; port++) {
USART_TypeDef *usart = usb_cdc_get_port_usart(port);
usb_cdc_port_start_rx(port);
usart->CR1 |= 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<USB_CDC_NUM_PORTS; port++) {
usb_cdc_suspend_port(port);
}
}

void usb_cdc_enable_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 = 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);
}
}
Expand Down Expand Up @@ -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);
}
}
}
}
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
}
Expand Down
3 changes: 3 additions & 0 deletions usb_cdc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -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 */
Expand Down

0 comments on commit c212101

Please sign in to comment.