diff options
Diffstat (limited to 'tests/usb-serial-rs485')
-rw-r--r-- | tests/usb-serial-rs485/Makefile.stm32f103-generic | 38 | ||||
-rw-r--r-- | tests/usb-serial-rs485/Makefile.stm32f4-disco | 38 | ||||
-rw-r--r-- | tests/usb-serial-rs485/README | 33 | ||||
-rw-r--r-- | tests/usb-serial-rs485/main-stm32f103-generic.c | 204 | ||||
-rw-r--r-- | tests/usb-serial-rs485/main-stm32f4-disco.c | 199 | ||||
-rw-r--r-- | tests/usb-serial-rs485/ringb.c | 59 | ||||
-rw-r--r-- | tests/usb-serial-rs485/ringb.h | 60 | ||||
-rw-r--r-- | tests/usb-serial-rs485/syscfg.h | 59 | ||||
-rw-r--r-- | tests/usb-serial-rs485/usb_cdcacm-arch.c | 82 | ||||
-rw-r--r-- | tests/usb-serial-rs485/usb_cdcacm.c | 363 | ||||
-rw-r--r-- | tests/usb-serial-rs485/usb_cdcacm.h | 74 |
11 files changed, 0 insertions, 1209 deletions
diff --git a/tests/usb-serial-rs485/Makefile.stm32f103-generic b/tests/usb-serial-rs485/Makefile.stm32f103-generic deleted file mode 100644 index 747238d..0000000 --- a/tests/usb-serial-rs485/Makefile.stm32f103-generic +++ /dev/null @@ -1,38 +0,0 @@ -## -## This file is part of the libopencm3 project. -## -## This library is free software: you can redistribute it and/or modify -## it under the terms of the GNU Lesser General Public License as published by -## the Free Software Foundation, either version 3 of the License, or -## (at your option) any later version. -## -## This library is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU Lesser General Public License for more details. -## -## You should have received a copy of the GNU Lesser General Public License -## along with this library. If not, see <http://www.gnu.org/licenses/>. -## - -BOARD = stm32f103-generic -PROJECT = usb-serial-rs485-$(BOARD) -BUILD_DIR = bin-$(BOARD) - -SHARED_DIR = ../../shared - -CFILES = main-$(BOARD).c -CFILES += usb_cdcacm.c usb_cdcacm-arch.c -CFILES += ringb.c -CFILES += trace.c trace_stdio.c - -VPATH += $(SHARED_DIR) -INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR)) -OPENCM3_DIR=../../libopencm3 - -# Copy this to some arch shared? -DEVICE=stm32f103c8 -OOCD_FILE= ../../openocd/openocd.stm32f4-disco.cfg - -include ../../rules.mk - diff --git a/tests/usb-serial-rs485/Makefile.stm32f4-disco b/tests/usb-serial-rs485/Makefile.stm32f4-disco deleted file mode 100644 index 1c60091..0000000 --- a/tests/usb-serial-rs485/Makefile.stm32f4-disco +++ /dev/null @@ -1,38 +0,0 @@ -## -## This file is part of the libopencm3 project. -## -## This library is free software: you can redistribute it and/or modify -## it under the terms of the GNU Lesser General Public License as published by -## the Free Software Foundation, either version 3 of the License, or -## (at your option) any later version. -## -## This library is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU Lesser General Public License for more details. -## -## You should have received a copy of the GNU Lesser General Public License -## along with this library. If not, see <http://www.gnu.org/licenses/>. -## - -BOARD = stm32f4-disco -PROJECT = usb-serial-rs485-$(BOARD) -BUILD_DIR = bin-$(BOARD) - -SHARED_DIR = ../../shared - -CFILES = main-$(BOARD).c -CFILES += usb_cdcacm.c usb_cdcacm-arch.c -CFILES += ringb.c -CFILES += trace.c trace_stdio.c - -VPATH += $(SHARED_DIR) -INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR)) -OPENCM3_DIR=../../libopencm3 - -# Copy this to some arch shared? -DEVICE=stm32f405xg -OOCD_FILE= ../../openocd/openocd.stm32f4-disco.cfg - -include ../../rules.mk - diff --git a/tests/usb-serial-rs485/README b/tests/usb-serial-rs485/README deleted file mode 100644 index 0e5b2cd..0000000 --- a/tests/usb-serial-rs485/README +++ /dev/null @@ -1,33 +0,0 @@ ------------------------------------------------------------------------------- -README ------------------------------------------------------------------------------- - -current status: -f1: frootloop3 gets corrupt data in rx path, _after_ serial rx, -but the usb in packets (wireshark) show the corruption. (LA on serial lines is clean) -f4: frootloop3 tests clean -=> suspect libopecm3 usb bug? - -frootloop3: github.com/karlp/frootloop3 - - - -This implements a USB CDC-ACM device, connected to USART2 (PA2-tx/PA3-rx) -An interrupt driven tx ring buffer is used for usb->serial, and a similar -interrupt driven rx ring buffer is used for serial->usb. -Baud rates from 2400-460800 are tested with zmodem transfers in both directions. - -Parity not yet finished, and baudrates below 1200 need fiddling with clock prescalers. -When it's finished, rs485 support should be available via the TC interrupt. - -A GPIO is toggled around USART transmissions to control an RS485 line -transceiver, following ST's app note. The RS485 driver enable line is, -by default, just the onboard red LEDs. - -The orange/blue LEDs indicate tx/rx activity, but especially for the rx line, -you won't really see it without heavy data rates. - -This example is heavily based on the existing usb_cdcacm and usart demos. - - -KARL - check https://github.com/dhylands/libopencm3-usb-serial/blob/master/usb.c to see if it passes the same tests or not diff --git a/tests/usb-serial-rs485/main-stm32f103-generic.c b/tests/usb-serial-rs485/main-stm32f103-generic.c deleted file mode 100644 index 415a18b..0000000 --- a/tests/usb-serial-rs485/main-stm32f103-generic.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2014 Karl Palsson <karlp@tweak.net.au> - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <libopencm3/cm3/nvic.h> -#include <libopencm3/stm32/gpio.h> -#include <libopencm3/stm32/rcc.h> -#include <libopencm3/stm32/usart.h> - -#include <stdio.h> -#include "syscfg.h" -#include "usb_cdcacm.h" -#include "ringb.h" -#include "trace.h" - -#define ER_DEBUG -#ifdef ER_DEBUG -#define ER_DPRINTF(fmt, ...) \ - do { printf(fmt, ## __VA_ARGS__); } while (0) -#else -#define ER_DPRINTF(fmt, ...) \ - do { } while (0) -#endif - -static inline void gpio_really(uint32_t port, uint16_t pin, const bool set) -{ - int shift = set ? 0 : 16; - GPIO_BSRR(port) = pin << shift; -} - - -extern struct ringb rx_ring, tx_ring; -static void usart_setup(void) -{ - /* Enable the USART2 interrupt. */ - nvic_enable_irq(NVIC_USART2_IRQ); - - /* USART2 pins are on port A */ - rcc_periph_clock_enable(RCC_GPIOA); - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX); - gpio_set_mode(GPIOA, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, GPIO_USART2_RX); - - /* Enable clocks for USART2. */ - rcc_periph_clock_enable(RCC_USART2); - - /* Setup USART2 parameters. */ - usart_set_baudrate(USART2, 115200); - usart_set_databits(USART2, 8); - usart_set_stopbits(USART2, USART_STOPBITS_1); - usart_set_mode(USART2, USART_MODE_TX_RX); - usart_set_parity(USART2, USART_PARITY_NONE); - usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE); - - /* Enable USART2 Receive interrupt. */ - usart_enable_rx_interrupt(USART2); - - /* Finally enable the USART. */ - usart_enable(USART2); -} - -void usart2_isr(void) -{ - gpio_really(GPIOA, GPIO5, 1); - // usbser-rxne() - /* Check if we were called because of RXNE. */ - if (usart_get_interrupt_source(USART2, USART_SR_RXNE)) { - gpio_set(LED_RX_PORT, LED_RX_PIN); - uint8_t c = usart_recv(USART2); - if (ringb_put(&rx_ring, c)) { - // good, - } else { - // fatal, you should always have drained by now. - // (when you've got it all ironed out, _actually_ - // just drop and count drops), but not yet... - ER_DPRINTF("rx buffer full\n"); - while(1); - } - trace_send8(STIMULUS_RING_PUSH, c); - gpio_clear(LED_RX_PORT, LED_RX_PIN); - } - // usbser-irq-txe() - if (usart_get_interrupt_source(USART2, USART_SR_TXE)) { - if (ringb_depth(&tx_ring) == 0) { - // turn off tx empty interrupts, nothing left to send - cdcacm_arch_txirq(0, 0); - ER_DPRINTF("OFF\n"); - // Turn on tx complete interrupts, for rs485 de - USART_CR1(USART2) |= USART_CR1_TCIE; - } else { - int c = ringb_get(&tx_ring); - usart_send(USART2, c); - } - } - // usbser-irq-txc? rs485 is auto on some devices, but can be emulated anyway - if (usart_get_interrupt_source(USART2, USART_SR_TC)) { - ER_DPRINTF("TC"); - // turn off the complete irqs, we're done now. - USART_CR1(USART2) &= ~USART_CR1_TCIE; - USART_SR(USART2) &= ~USART_SR_TC; - cdcacm_arch_pin(0, CDCACM_PIN_RS485DE, 0); - } - gpio_really(GPIOA, GPIO5, 0); -} - -void usb_cdcacm_setup_pre_arch(void) -{ - // Hack to reenumerate - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); - gpio_clear(GPIOA, GPIO12); - for (unsigned int i = 0; i < 800000; i++) { - __asm__("nop"); - } -} - -void usb_cdcacm_setup_post_arch(usbd_device *dev) -{ - (void)dev; -} - -void cdcacm_arch_pin(int port, enum cdcacm_pin pin, bool set) -{ - (void)port; // TODO if you want to handle multiple ports - switch (pin) { - case CDCACM_PIN_LED_TX: - gpio_really(LED_TX_PORT, LED_TX_PIN, set); - break; - case CDCACM_PIN_LED_RX: - gpio_really(LED_RX_PORT, LED_RX_PIN, set); - break; - case CDCACM_PIN_RS485DE: - gpio_really(RS485DE_PORT, RS485DE_PIN, set); - break; - default: - break; - } -} - -void cdcacm_arch_txirq(int port, bool set) { - (void)port; //FIXME if you make this multi port - if (set) { - usart_enable_tx_interrupt(USART2); - } else { - usart_disable_tx_interrupt(USART2); - } -} - -void cdcacm_arch_set_line_state(int port, uint8_t dtr, uint8_t rts) -{ - (void)port; // FIXME if you want multiple ports - (void) dtr; - (void) rts; - // LM4f has an implementation of this if you're keen -} - - - - -int main(void) -{ - rcc_clock_setup_in_hse_8mhz_out_72mhz(); - ER_DPRINTF("And we're alive!\n"); - /* Led */ - rcc_periph_clock_enable(RCC_GPIOC); - gpio_set_mode(LED_RX_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, LED_RX_PIN); - // IRQ timing - rcc_periph_clock_enable(RCC_GPIOA); - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO5); - gpio_set_mode(RS485DE_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, RS485DE_PIN); - - usart_setup(); - - usb_cdcacm_setup_pre_arch(); - usbd_device *usbd_dev = usb_cdcacm_init(&st_usbfs_v1_usb_driver, - "stm32f103-generic"); - usb_cdcacm_setup_post_arch(usbd_dev); - - - ER_DPRINTF("Looping...\n"); - volatile int i = 0; - while (1) { - usbd_poll(usbd_dev); - usb_cdcacm_poll(usbd_dev); - } - -} - diff --git a/tests/usb-serial-rs485/main-stm32f4-disco.c b/tests/usb-serial-rs485/main-stm32f4-disco.c deleted file mode 100644 index ac3cdff..0000000 --- a/tests/usb-serial-rs485/main-stm32f4-disco.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2014 Karl Palsson <karlp@tweak.net.au> - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <libopencm3/cm3/nvic.h> -#include <libopencm3/stm32/gpio.h> -#include <libopencm3/stm32/rcc.h> -#include <libopencm3/stm32/usart.h> - -#include <stdio.h> -#include "syscfg.h" -#include "usb_cdcacm.h" -#include "ringb.h" -#include "trace.h" - -#define ER_DEBUG -#ifdef ER_DEBUG -#define ER_DPRINTF(fmt, ...) \ - do { printf(fmt, ## __VA_ARGS__); } while (0) -#else -#define ER_DPRINTF(fmt, ...) \ - do { } while (0) -#endif - -static inline void gpio_really(uint32_t port, uint16_t pin, const bool set) -{ - int shift = set ? 0 : 16; - GPIO_BSRR(port) = pin << shift; -} - -extern struct ringb rx_ring, tx_ring; -static void usart_setup(void) -{ - /* Enable the USART2 interrupt. */ - nvic_enable_irq(NVIC_USART2_IRQ); - - /* USART2 pins are on port A */ - rcc_periph_clock_enable(RCC_GPIOA); - gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3); - gpio_set_af(GPIOA, GPIO_AF7, GPIO2 | GPIO3); - - /* Enable clocks for USART2. */ - rcc_periph_clock_enable(RCC_USART2); - - /* Setup USART2 parameters. */ - usart_set_baudrate(USART2, 115200); - usart_set_databits(USART2, 8); - usart_set_stopbits(USART2, USART_STOPBITS_1); - usart_set_mode(USART2, USART_MODE_TX_RX); - usart_set_parity(USART2, USART_PARITY_NONE); - usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE); - - /* Enable USART2 Receive interrupt. */ - usart_enable_rx_interrupt(USART2); - - /* Finally enable the USART. */ - usart_enable(USART2); -} - -void usart2_isr(void) -{ - gpio_really(GPIOA, GPIO5, 1); - // usbser-rxne() - /* Check if we were called because of RXNE. */ - if (usart_get_flag(USART2, USART_SR_RXNE)) { - gpio_set(LED_RX_PORT, LED_RX_PIN); - uint8_t c = usart_recv(USART2); - if (ringb_put(&rx_ring, c)) { - // good, - } else { - // fatal, you should always have drained by now. - // (when you've got it all ironed out, _actually_ - // just drop and count drops), but not yet... - ER_DPRINTF("rx buffer full\n"); - while(1); - } - gpio_clear(LED_RX_PORT, LED_RX_PIN); - } - // usbser-irq-txe() - if (usart_get_flag(USART2, USART_SR_TXE)) { - if (ringb_depth(&tx_ring) == 0) { - // turn off tx empty interrupts, nothing left to send - usart_disable_tx_interrupt(USART2); - ER_DPRINTF("OFF\n"); - // Turn on tx complete interrupts, for rs485 de -// USART_CR1(USART2) |= ~USART_CR1_TCIE; - } else { - int c = ringb_get(&tx_ring); - usart_send(USART2, c); - } - } - // usbser-irq-txc? rs485 is auto on some devices, but can be emulated anyway -// if (usart_get_flag(USART2, USART_SR_TC)) { -// ER_DPRINTF("TC"); -// // turn off the complete irqs, we're done now. -// USART_SR(USART2) &= ~USART_SR_TC; -// USART_CR1(USART2) &= ~USART_CR1_TCIE; -// gpio_clear(LED_TX_PORT, LED_TX_PIN); -// gpio_clear(RS485DE_PORT, RS485DE_PIN); -// } - gpio_really(GPIOA, GPIO5, 0); -} - -void usb_cdcacm_setup_pre_arch(void) -{ - rcc_periph_clock_enable(RCC_GPIOA); - rcc_periph_clock_enable(RCC_OTGFS); - - gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, - GPIO9 | GPIO11 | GPIO12); - gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); - -} - -void usb_cdcacm_setup_post_arch(usbd_device *dev) -{ - (void)dev; -} - - -void cdcacm_arch_pin(int port, enum cdcacm_pin pin, bool set) -{ - (void)port; // TODO if you want to handle multiple ports - switch (pin) { - case CDCACM_PIN_LED_TX: - gpio_really(LED_TX_PORT, LED_TX_PIN, set); - break; - case CDCACM_PIN_LED_RX: - gpio_really(LED_RX_PORT, LED_RX_PIN, set); - break; - case CDCACM_PIN_RS485DE: - gpio_really(RS485DE_PORT, RS485DE_PIN, set); - break; - default: - break; - } -} - -void cdcacm_arch_txirq(int port, bool set) { - (void)port; //FIXME if you make this multi port - if (set) { - usart_enable_tx_interrupt(USART2); - } else { - usart_disable_tx_interrupt(USART2); - } -} - -void cdcacm_arch_set_line_state(int port, uint8_t dtr, uint8_t rts) -{ - (void)port; // FIXME if you want multiple ports - (void) dtr; - (void) rts; - // LM4f has an implementation of this if you're keen -} - - -int main(void) -{ - rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]); - ER_DPRINTF("And we're alive!\n"); - /* Leds and rs485 are on port D */ - rcc_periph_clock_enable(RCC_GPIOD); - gpio_mode_setup(LED_RX_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, - LED_RX_PIN | LED_TX_PIN); - gpio_mode_setup(RS485DE_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, - RS485DE_PIN); - - rcc_periph_clock_enable(RCC_GPIOA); - gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO5); - - usart_setup(); - usb_cdcacm_setup_pre_arch(); - usbd_device *usbd_dev = usb_cdcacm_init(&otgfs_usb_driver, "stm32f4-disco"); - usb_cdcacm_setup_post_arch(usbd_dev); - - ER_DPRINTF("Looping...\n"); - volatile int i = 0; - while (1) { - usbd_poll(usbd_dev); - usb_cdcacm_poll(usbd_dev); - } - -} - diff --git a/tests/usb-serial-rs485/ringb.c b/tests/usb-serial-rs485/ringb.c deleted file mode 100644 index 245325b..0000000 --- a/tests/usb-serial-rs485/ringb.c +++ /dev/null @@ -1,59 +0,0 @@ - -#include "ringb.h" -void ringb_init(struct ringb *ring, uint8_t *buf, int len) -{ - ring->buf_len = len; - ring->buf = buf; - ring->idx_r = 0; - ring->idx_w = 0; -} - -int ringb_get(struct ringb *ring) { -#if 1 - int rval; - if (ring->idx_r != ring->idx_w) { - rval = ring->buf[ring->idx_r]; - ring->idx_r = (ring->idx_r + 1) % ring->buf_len; - return rval; - } - return -1; -#else - if (((ring->idx_w - ring->idx_r) % ring->buf_len) >= 0) { - int rval = ring->buf[ring->idx_r]; - ring->idx_r = (ring->idx_r + 1) % ring->buf_len; - return rval; - } else { - return -1; - } -#endif -} - -bool ringb_put(struct ringb *ring, uint8_t c) { -#if 1 - unsigned int next = (ring->idx_w + 1) % ring->buf_len; - if (next != ring->idx_r) { - ring->buf[ring->idx_w] = c; - ring->idx_w = next; - return true; - } - return false; -#else - if (((ring->idx_w - ring->idx_r) % ring->buf_len) == 0) { - return false; - } - ring->buf[ring->idx_w] = c; - ring->idx_w = (ring->idx_w + 1) % ring->buf_len; - return true; -#endif - -} - - -void ringb_flush(struct ringb *ring) { - ring->idx_r = 0; - ring->idx_w = 0; -} - -int ringb_depth(struct ringb *ring) { - return ((unsigned int)(ring->idx_w - ring->idx_r) % ring->buf_len); -}
\ No newline at end of file diff --git a/tests/usb-serial-rs485/ringb.h b/tests/usb-serial-rs485/ringb.h deleted file mode 100644 index c3d5356..0000000 --- a/tests/usb-serial-rs485/ringb.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Karl Palsson <karlp@tweak.net.au> - * Considered to be released under your choice of: - * MIT/ISC/Apache2/BSD2Clause/GPLv2 - * If you're looking for elegant compact performance you've come to the wrong - * place hombre. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdbool.h> -#include <stdint.h> - -struct ringb { - volatile unsigned int idx_r; - volatile unsigned int idx_w; - uint8_t *buf; - int buf_len; -}; - -/** - * Load up a ring buffer. Always suceeds - * @param ring struct saving state, provided by the user - * @param buf where the data will be kept - * @param len size of buf in in elements. - */ -void ringb_init(struct ringb *ring, uint8_t *buf, int len); - -/** - * push data in - * @param ring - * @param c - * @return true if space was available - */ -bool ringb_put(struct ringb *ring, uint8_t c); - -/** - * pull data out - * @param ring - * @return -1 for no data, uint8_t range for valid. - */ -int ringb_get(struct ringb *ring); - -/** - * Toss data and reset to empty - * @param ring - */ -void ringb_flush(struct ringb *ring); - -int ringb_depth(struct ringb *ring); - - - -#ifdef __cplusplus -} -#endif diff --git a/tests/usb-serial-rs485/syscfg.h b/tests/usb-serial-rs485/syscfg.h deleted file mode 100644 index d643af1..0000000 --- a/tests/usb-serial-rs485/syscfg.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2014 Karl Palsson <karlp@tweak.net.au> - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef SYSCFG_H -#define SYSCFG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define STIMULUS_RING_DRAIN 2 -#define STIMULUS_RING_PUSH 3 -#define STIMULUS_TXC 4 -#define STIMULUS_TX 5 - -#if defined STM32F1 -#define LED_RX_PORT GPIOC -#define LED_RX_PIN GPIO13 -#define LED_TX_PORT GPIOC -#define LED_TX_PIN GPIO13 -#define RS485DE_PORT GPIOA -#define RS485DE_PIN GPIO8 -/* TODO: should really make a stm32f4discovery.h file... */ -#elif defined STM32F4 - -#define LED_RX_PORT GPIOD -#define LED_RX_PIN GPIO15 /* Blue, but you won't see this one much */ -#define LED_TX_PORT GPIOD -#define LED_TX_PIN GPIO13 /* orange */ -/* On stm32f4 discovery, this is actually another led... */ -#define RS485DE_PORT GPIOD -#define RS485DE_PIN GPIO14 /* red */ - -#define STREAM_USART2_TX 6 -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* SYSCFG_H */ - diff --git a/tests/usb-serial-rs485/usb_cdcacm-arch.c b/tests/usb-serial-rs485/usb_cdcacm-arch.c deleted file mode 100644 index e868861..0000000 --- a/tests/usb-serial-rs485/usb_cdcacm-arch.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2014 Karl Palsson <karlp@tweak.net.au> - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <libopencm3/cm3/nvic.h> -#include <libopencm3/stm32/dma.h> -#include <libopencm3/stm32/gpio.h> -#include <libopencm3/stm32/rcc.h> -#include <libopencm3/stm32/usart.h> - -#include "usb_cdcacm.h" -#include "syscfg.h" -#include "ringb.h" - - - -int glue_set_line_coding_cb(uint32_t baud, uint8_t databits, - enum usb_cdc_line_coding_bParityType cdc_parity, - enum usb_cdc_line_coding_bCharFormat cdc_stopbits) -{ - int uart_parity; - int uart_stopbits; - - if (databits < 8 || databits > 9) { - return 0; - } - - /* Be careful here, ST counts parity as a data bit */ - switch (cdc_parity) { - case USB_CDC_NO_PARITY: - uart_parity = USART_PARITY_NONE; - break; - case USB_CDC_ODD_PARITY: - uart_parity = USART_PARITY_ODD; - databits++; - break; - case USB_CDC_EVEN_PARITY: - uart_parity = USART_PARITY_EVEN; - databits++; - break; - default: - return 0; - } - - switch (cdc_stopbits) { - case USB_CDC_1_STOP_BITS: - uart_stopbits = USART_STOPBITS_1; - break; - case USB_CDC_2_STOP_BITS: - uart_stopbits = USART_STOPBITS_2; - break; - default: - return 0; - } - - /* Disable the UART while we mess with its settings */ - usart_disable(USART2); - /* Set communication parameters */ - usart_set_baudrate(USART2, baud); - usart_set_databits(USART2, databits); - usart_set_parity(USART2, uart_parity); - usart_set_stopbits(USART2, uart_stopbits); - /* Back to work. */ - usart_enable(USART2); - - return 1; -} diff --git a/tests/usb-serial-rs485/usb_cdcacm.c b/tests/usb-serial-rs485/usb_cdcacm.c deleted file mode 100644 index 099c4ad..0000000 --- a/tests/usb-serial-rs485/usb_cdcacm.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz> - * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com> - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - */ -/* - * This package is _meant_ to be platform independent, just a full - * cdc-acm impl, with callbacks - */ - -#include "usb_cdcacm.h" - -#include <stdio.h> -#include <stdlib.h> -#include <libopencm3/usb/usbd.h> -#include <libopencm3/usb/cdc.h> -#include <libopencm3/cm3/scb.h> -// NOTHING ELSE! this file _does_ not know about part specifics! - -#include "syscfg.h" -#include "ringb.h" - -#define ER_DEBUG -#ifdef ER_DEBUG -#define ER_DPRINTF(fmt, ...) \ - do { printf(fmt, ## __VA_ARGS__); } while (0) -#else -#define ER_DPRINTF(fmt, ...) \ - do { } while (0) -#endif - - -static uint8_t usbd_control_buffer[128]; -static usbd_device *acm_dev; - -static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x2000, - .bDeviceClass = USB_CLASS_CDC, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .bMaxPacketSize0 = 64, - .idVendor = 0xc03e, - .idProduct = 0xb007, - .bcdDevice = 0x2000, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, -}; - -/* - * This notification endpoint isn't implemented. According to CDC spec it's - * optional, but its absence causes a NULL pointer dereference in the - * Linux cdc_acm driver. - */ -static const struct usb_endpoint_descriptor comm_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x83, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 16, - .bInterval = 1, -}}; - -static const struct usb_endpoint_descriptor data_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 1, -}}; - -static const struct { - struct usb_cdc_header_descriptor header; - struct usb_cdc_call_management_descriptor call_mgmt; - struct usb_cdc_acm_descriptor acm; - struct usb_cdc_union_descriptor cdc_union; -} __attribute__ ((packed)) cdcacm_functional_descriptors = { - .header = { - .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_HEADER, - .bcdCDC = 0x0110, - }, - .call_mgmt = { - .bFunctionLength = - sizeof(struct usb_cdc_call_management_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, - .bmCapabilities = 0, - .bDataInterface = 1, - }, - .acm = { - .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_ACM, - .bmCapabilities = (1 << 1), - }, - .cdc_union = { - .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 0, - .bSubordinateInterface0 = 1, - } -}; - -static const struct usb_interface_descriptor comm_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, - .iInterface = 0, - - .endpoint = comm_endp, - - .extra = &cdcacm_functional_descriptors, - .extralen = sizeof(cdcacm_functional_descriptors) -}}; - -static const struct usb_interface_descriptor data_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - - .endpoint = data_endp, -}}; - -static const struct usb_interface ifaces[] = {{ - .num_altsetting = 1, - .altsetting = comm_iface, -}, { - .num_altsetting = 1, - .altsetting = data_iface, -}}; - -static const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, - .bNumInterfaces = 2, - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0x80, - .bMaxPower = 0x32, - - .interface = ifaces, -}; - -static char serial[] = "none"; -static const char *usb_strings[] = { - "libopencm3", - "usb_to_serial_cdcacm", - serial, - "DEMO", -}; - -struct ringb rx_ring; -static uint8_t rx_ring_data[64]; -struct ringb tx_ring; -static uint8_t tx_ring_data[128]; -bool nakked = false; - - -static int cdcacm_control_request(usbd_device *usbd_dev, - struct usb_setup_data *req, uint8_t **buf, - uint16_t *len, - void (**complete) (usbd_device *usbd_dev, - struct usb_setup_data * - req)) -{ - uint8_t dtr, rts; - - (void) complete; - (void) buf; - (void) usbd_dev; - - switch (req->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - { - /* - * This Linux cdc_acm driver requires this to be implemented - * even though it's optional in the CDC spec, and we don't - * advertise it in the ACM functional descriptor. - */ - - dtr = (req->wValue & (1 << 0)) ? 1 : 0; - rts = (req->wValue & (1 << 1)) ? 1 : 0; - ER_DPRINTF("CTRLRQ:%d Set Line state: dtr:%d rts: %d\n", req->wIndex, dtr, rts); - - // FIXME - need to get port based on wIndex I believe? - cdcacm_arch_set_line_state(0, dtr, rts); - - return 1; - } - case USB_CDC_REQ_SET_LINE_CODING: - { - struct usb_cdc_line_coding *coding; - - if (*len < sizeof (struct usb_cdc_line_coding)) - return 0; - - coding = (struct usb_cdc_line_coding *) *buf; - ER_DPRINTF("CTRLRQ: line coding: %lu(%u:%u:%u)\n", coding->dwDTERate, - coding->bDataBits, coding->bParityType, coding->bCharFormat); - return glue_set_line_coding_cb(coding->dwDTERate, - coding->bDataBits, - coding->bParityType, - coding->bCharFormat); - } - } - return 0; -} - -static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep) -{ - uint8_t buf[64]; - /* nak right now, we're not sure whether we'll be able to even process this!*/ - usbd_ep_nak_set(usbd_dev, ep, 1); - int len = usbd_ep_read_packet(usbd_dev, ep, buf, 64); - ER_DPRINTF("Hrx%db\n", len); - cdcacm_arch_pin(0, CDCACM_PIN_LED_TX, 1); - cdcacm_arch_pin(0, CDCACM_PIN_RS485DE, 1); - for (int x = 0; x < len; x++) { - if (!ringb_put(&tx_ring, buf[x])) { - // failed to process usb traffic properly. - // should _never_ happen, means we failed to nak in time. - // this is _never_recoverable beyond watchdog reset. - while(1); - } - // look up port to suart mapping which side? - cdcacm_arch_txirq(0, 1); - } - if (ringb_depth(&tx_ring) < 64) { - ER_DPRINTF("ACK\n"); - usbd_ep_nak_set(usbd_dev, ep, 0); - } else { - nakked = true; - } -} - -static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue) -{ - (void) wValue; - - usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, - cdcacm_data_rx_cb); - usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); - usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - - usbd_register_control_callback(usbd_dev, - USB_REQ_TYPE_CLASS | - USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | - USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); -} - -/* FIXME - need to report this! */ -void cdcacm_line_state_changed_cb(uint8_t linemask) -{ - const int size = sizeof (struct usb_cdc_notification) + 2; - uint8_t buf[size]; - - struct usb_cdc_notification *notify = (void *) buf; - notify->bmRequestType = 0xa1; - notify->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; - notify->wValue = 0; - notify->wIndex = 1; - notify->wLength = 2; - uint16_t *data = (void *) &buf[sizeof (struct usb_cdc_notification)]; - *data = linemask; - - while (usbd_ep_write_packet(acm_dev, 0x83, buf, size) == size); -} - - -/* Y0, moron, nothing's stopping rx irqs from happening, have fun when you overflow temp buffer! */ -static void task_drain_rx(struct ringb *r) { - uint8_t zero_copy_is_for_losers[sizeof(rx_ring_data)]; - int zci = 0; - int c = ringb_get(r); - while (c >= 0) { - //trace_send8(STIMULUS_RING_DRAIN, c); - zero_copy_is_for_losers[zci++] = c; - c = ringb_get(r); - } - if (zci) { - //trace_send16(STIMULUS_RING_DRAIN, zci); - ER_DPRINTF("Drx %db\n", zci); - usbd_ep_write_packet(acm_dev, 0x82, zero_copy_is_for_losers, zci); - } -} - - -usbd_device * usb_cdcacm_init(const usbd_driver *driver, const char *userserial) -{ - ringb_init(&rx_ring, rx_ring_data, sizeof(rx_ring_data)); - ringb_init(&tx_ring, tx_ring_data, sizeof(tx_ring_data)); - if (userserial) { - usb_strings[2] = userserial; - } - - acm_dev = usbd_init(driver, &dev, &config, usb_strings, 4, - usbd_control_buffer, sizeof (usbd_control_buffer)); - usbd_register_set_config_callback(acm_dev, cdcacm_set_config); - return acm_dev; -} - - -void usb_cdcacm_poll(usbd_device *usbd_dev) // FIXME -drop to acm_dev internal -{ - // Originally, calling this every 50 times caused some rx character droppage, - // and every 500 times caused _none_. _probably_ needs to be tied to - // a timer and something like the current baud rate and the inter character time - static int i = 0; - if (i++ > 500) { - // hacktastic - if (ringb_depth(&tx_ring) < 64 && nakked) { - usbd_ep_nak_set(usbd_dev, 1, 0); - nakked = false; - } - - task_drain_rx(&rx_ring); - i = 0; - } - - -}
\ No newline at end of file diff --git a/tests/usb-serial-rs485/usb_cdcacm.h b/tests/usb-serial-rs485/usb_cdcacm.h deleted file mode 100644 index d4e47e0..0000000 --- a/tests/usb-serial-rs485/usb_cdcacm.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2014 Karl Palsson <karlp@tweak.net.au> - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - */ -/* - * This is the header file for a usb_cdcacm implmentation, usb_cdcacm.c is the - * platform independent portion, and usb_cdcacm-arch.c should be re-implemented - * for other platforms. - */ - -#ifndef USB_CDCACM_H -#define USB_CDCACM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <libopencm3/usb/usbd.h> -#include <libopencm3/usb/cdc.h> - - enum cdcacm_pin { - CDCACM_PIN_NONE, - CDCACM_PIN_LED_TX, - CDCACM_PIN_LED_RX, - CDCACM_PIN_RS485DE, - }; - - usbd_device * usb_cdcacm_init(const usbd_driver *driver, const char *userserial); - void usb_cdcacm_setup_pre_arch(void); - void usb_cdcacm_setup_post_arch(usbd_device *dev); - void usb_cdcacm_poll(usbd_device *usbd_dev); - void cdcacm_line_state_changed_cb(uint8_t linemask); - - /** - * Called by the cdcacm core to toggle pins as need be - * @param port which serial port, 0 normally - * @param pin logical pin - * @param set set or clear - */ - void cdcacm_arch_pin(int port, enum cdcacm_pin pin, bool set); - - /** - * enable the tx emmpty irq for the logical port - * @param port - * @param set - */ - void cdcacm_arch_txirq(int port, bool set); - - void cdcacm_arch_set_line_state(int port, uint8_t dtr, uint8_t rts); - - int glue_set_line_coding_cb(uint32_t baud, uint8_t databits, - enum usb_cdc_line_coding_bParityType cdc_parity, - enum usb_cdc_line_coding_bCharFormat cdc_stopbits); - -#ifdef __cplusplus -} -#endif - -#endif /* USB_CDCACM_H */ - |