Skip to content

Commit

Permalink
ADD: use bit banding to reset TXA
Browse files Browse the repository at this point in the history
  • Loading branch information
r2axz committed Dec 2, 2020
1 parent 2be6e0e commit 70b8a3d
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 9 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ Note: **5 V** tolerant input pins are shown **in bold**.
**TXA** (**TX** **A**ctive) is active when UART is transmitting data and
can be used to control **DE** and **/RE** pins of RS-485 transceivers.

**TXA** goes inactive within 1 us after the transmission is complete,
which meets RS-485 and IO-link timing requirements at speeds up to 460 kBaud
**TXA** goes inactive within 0.6 us after the transmission is complete,
which meets RS-485 and IO-link timing requirements at speeds up to 920 kBaud
with at least double safety margin.

**DSR**, **DTR**, and **DCD**, **RI** are connected to the internal _weak pull-up_
Expand Down
13 changes: 13 additions & 0 deletions gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,16 @@ int gpio_pin_get(const gpio_pin_t *pin) {
}
return 0;
}

volatile uint32_t *gpio_pin_get_bitband_clear_addr(const gpio_pin_t *pin) {
volatile uint32_t result = 0;
if (pin->port) {
result = PERIPH_BB_BASE;
result += ((uint32_t)(&pin->port->BSRR) - PERIPH_BASE) << 5;
result += pin->pin << 2;
if (pin->polarity == gpio_polarity_high) {
result += GPIO_BSRR_BR0_Pos << 2;
}
}
return (volatile uint32_t*)result;
}
2 changes: 2 additions & 0 deletions gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ void gpio_pin_init(const gpio_pin_t *pin);
void gpio_pin_set(const gpio_pin_t *pin, int is_active);
int gpio_pin_get(const gpio_pin_t *pin);

volatile uint32_t *gpio_pin_get_bitband_clear_addr(const gpio_pin_t *pin);

#endif /* GPIO_G */
18 changes: 11 additions & 7 deletions usb_cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ typedef struct {
uint8_t rts_active;
uint8_t dtr_active;
uint8_t txa_active;
gpio_pin_t *txa_pin;
volatile uint32_t *txa_bitband_clear;
} usb_cdc_state_t;

static usb_cdc_state_t usb_cdc_states[USB_CDC_NUM_PORTS];
Expand Down Expand Up @@ -522,11 +522,12 @@ void DMA1_Channel2_IRQHandler() {

/* USART Interrupt Handlers */

__attribute__((always_inline)) inline static void usb_cdc_usart_irq_handler(int port, USART_TypeDef * usart, gpio_pin_t *txa_pin, uint8_t dma_irqn) {
__attribute__((always_inline)) inline static void usb_cdc_usart_irq_handler(int port, USART_TypeDef * usart,
volatile uint32_t *txa_bitband_clear, uint8_t dma_irqn) {
uint32_t wait_rxne = 0;
uint32_t status = usart->SR;
if (status & USART_SR_TC) {
gpio_pin_set(txa_pin, 0);
*txa_bitband_clear = 1;
usart->CR1 &= ~(USART_CR1_TCIE);
}
/* Synchronization is not required, no one can interrupt us */
Expand All @@ -543,17 +544,17 @@ __attribute__((always_inline)) inline static void usb_cdc_usart_irq_handler(int

void USART1_IRQHandler() {
(void)USART1_IRQHandler;
usb_cdc_usart_irq_handler(0, usb_cdc_port_usarts[0], usb_cdc_states[0].txa_pin, DMA1_Channel5_IRQn);
usb_cdc_usart_irq_handler(0, usb_cdc_port_usarts[0], usb_cdc_states[0].txa_bitband_clear, DMA1_Channel5_IRQn);
}

void USART2_IRQHandler() {
(void)USART2_IRQHandler;
usb_cdc_usart_irq_handler(1, usb_cdc_port_usarts[1], usb_cdc_states[1].txa_pin, DMA1_Channel6_IRQn);
usb_cdc_usart_irq_handler(1, usb_cdc_port_usarts[1], usb_cdc_states[1].txa_bitband_clear, DMA1_Channel6_IRQn);
}

void USART3_IRQHandler() {
(void)USART3_IRQHandler;
usb_cdc_usart_irq_handler(2, usb_cdc_port_usarts[2], usb_cdc_states[2].txa_pin, DMA1_Channel3_IRQn);
usb_cdc_usart_irq_handler(2, usb_cdc_port_usarts[2], usb_cdc_states[2].txa_bitband_clear, DMA1_Channel3_IRQn);
}

/* Port Configuration & Control Lines Functions */
Expand All @@ -567,6 +568,8 @@ void usb_cdc_reconfigure_port_pin(int port, cdc_pin_t pin) {
usb_cdc_update_port_dtr(port);
} 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]);
}
}
}
Expand All @@ -578,6 +581,8 @@ static void usb_cdc_configure_port(int port) {
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]);
}
}

Expand Down Expand Up @@ -642,7 +647,6 @@ void usb_cdc_reset() {
dma_rx_ch->CNDTR = USB_CDC_BUF_SIZE;
dma_tx_ch->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE;
dma_tx_ch->CPAR = (uint32_t)&usart->DR;
usb_cdc_states[port].txa_pin = &device_config_get()->cdc_config.port_config[port].pins[cdc_pin_txa];
}
NVIC_SetPriority(USART1_IRQn, SYSTEM_INTERRUTPS_PRIORITY_CRITICAL);
NVIC_EnableIRQ(USART1_IRQn);
Expand Down

0 comments on commit 70b8a3d

Please sign in to comment.