Working uart bridging
This commit is contained in:
parent
65b14f399a
commit
111c5f7200
7
Makefile
7
Makefile
|
@ -3,12 +3,13 @@ OOCD_INTERFACE ?= stlink-v2
|
|||
OOCD_TARGET ?= stm32f4x
|
||||
BMP_PORT ?= /dev/ttyBmpGdb
|
||||
|
||||
CFLAGS=-g -O0 -std=c99 -pedantic -Wall
|
||||
CXXFLAGS=-g -O0 -std=c++17 -pedantic -Wall
|
||||
CFLAGS=-g -O2 -std=c99 -pedantic -Wall
|
||||
CXXFLAGS=-g -O2 -std=c++17 -pedantic -Wall
|
||||
|
||||
OBJS = usb.o
|
||||
OBJS = usb.o adc.o ringbuffer.o uart.o
|
||||
BINARY ?= main
|
||||
DEVICE=STM32F405RG
|
||||
#DEVICE=STM32F411CE
|
||||
|
||||
include ../rules.mk
|
||||
|
||||
|
|
26
adc.c
Normal file
26
adc.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "adc.h"
|
||||
|
||||
static uint32_t bat_voltage_mv;
|
||||
|
||||
void adc_setup(void) {
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_ADC1);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO3);
|
||||
adc_power_off(ADC1);
|
||||
adc_disable_scan_mode(ADC1);
|
||||
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_480CYC);
|
||||
adc_set_continuous_conversion_mode(ADC1);
|
||||
|
||||
uint8_t channel = 3;
|
||||
adc_set_regular_sequence(ADC1, 1, &channel);
|
||||
|
||||
adc_power_on(ADC1);
|
||||
adc_start_conversion_regular(ADC1);
|
||||
}
|
||||
|
||||
uint32_t adc_bat_voltage(void) {
|
||||
if (adc_get_flag(ADC1, ADC_SR_EOC)) {
|
||||
bat_voltage_mv = adc_read_regular(ADC1);
|
||||
}
|
||||
return bat_voltage_mv;
|
||||
}
|
10
adc.h
Normal file
10
adc.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef ADC_H
|
||||
#define ADC_H
|
||||
#include <libopencm3/stm32/adc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void adc_setup(void);
|
||||
uint32_t adc_bat_voltage(void);
|
||||
#endif
|
90
main.c
90
main.c
|
@ -1,13 +1,103 @@
|
|||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "adc.h"
|
||||
#include "usb.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "uart.h"
|
||||
|
||||
volatile uint32_t tick = 0;
|
||||
RINGBUFFER_STORAGE(usb_to_uart_buf, 64)
|
||||
RINGBUFFER_STORAGE(uart_to_usb_buf, 64)
|
||||
RINGBUFFER_STORAGE(comm_in_buf, 64)
|
||||
RINGBUFFER_STORAGE(comm_out_buf, 64)
|
||||
|
||||
static void sys_tick_setup(void);
|
||||
|
||||
static void sys_tick_setup() {
|
||||
systick_set_reload(168000);
|
||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
||||
systick_counter_enable();
|
||||
systick_interrupt_enable();
|
||||
}
|
||||
|
||||
void sys_tick_handler() {
|
||||
tick++;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
#if 0
|
||||
rcc_clock_setup_pll(&rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_84MHZ]);
|
||||
#else
|
||||
rcc_clock_setup_pll(&rcc_hse_12mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
|
||||
#endif
|
||||
|
||||
RINGBUFFER_INIT(uart_to_usb_buf, 64);
|
||||
RINGBUFFER_INIT(usb_to_uart_buf, 64);
|
||||
RINGBUFFER_INIT(comm_in_buf, 64);
|
||||
RINGBUFFER_INIT(comm_out_buf, 64);
|
||||
|
||||
usb_setup();
|
||||
adc_setup();
|
||||
uart_setup();
|
||||
sys_tick_setup();
|
||||
|
||||
nvic_enable_irq(NVIC_USART3_IRQ);
|
||||
|
||||
while (1) {
|
||||
/* Handle control messages through the comms CDC */
|
||||
char buf[64];
|
||||
unsigned buf_len = 0;
|
||||
for (char c; ringbuffer_get(comm_in_buf, (void*)&c, 1); ) {
|
||||
switch (c) {
|
||||
case 'B':
|
||||
buf_len =
|
||||
snprintf(buf, sizeof(buf), "%lu\r\n",
|
||||
(unsigned long)adc_bat_voltage());
|
||||
ringbuffer_add(comm_out_buf, buf, buf_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send replies */
|
||||
if ((buf_len = ringbuffer_peek(comm_out_buf, &buf[0], sizeof buf))) {
|
||||
if (usb_write_cdcacm(ACM_COMM, (void*)buf, buf_len, 1)) {
|
||||
ringbuffer_skip(comm_out_buf, buf_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send any available data to the NFC CDC */
|
||||
if (!ringbuffer_empty(uart_to_usb_buf)) {
|
||||
unsigned len = ringbuffer_peek(uart_to_usb_buf, &buf[0], sizeof buf);
|
||||
if(usb_write_cdcacm(ACM_NFC, buf, len, 1)) {
|
||||
ringbuffer_skip(uart_to_usb_buf, len);
|
||||
}
|
||||
}
|
||||
if (!ringbuffer_empty(usb_to_uart_buf)) {
|
||||
usart_enable_tx_interrupt(USART3);
|
||||
}
|
||||
|
||||
usbd_poll(g_usbd_dev);
|
||||
__asm__("wfi");
|
||||
}
|
||||
}
|
||||
|
||||
void usart3_isr() {
|
||||
while (USART_SR(USART3) & USART_SR_RXNE) {
|
||||
uint8_t c = usart_recv(USART3);
|
||||
ringbuffer_add(uart_to_usb_buf, (void *)&c, 1);
|
||||
}
|
||||
while (USART_SR(USART3) & USART_SR_TXE) {
|
||||
if (ringbuffer_empty(usb_to_uart_buf)) {
|
||||
usart_disable_tx_interrupt(USART3);
|
||||
break;
|
||||
} else {
|
||||
uint8_t c;
|
||||
ringbuffer_get(usb_to_uart_buf, &c, 1);
|
||||
usart_send(USART3, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
89
ringbuffer.c
Normal file
89
ringbuffer.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include "ringbuffer.h"
|
||||
#include <string.h>
|
||||
|
||||
unsigned ringbuffer_capacity(ringbuffer *buf) {
|
||||
return buf->size;
|
||||
}
|
||||
|
||||
unsigned ringbuffer_free(ringbuffer *buf) {
|
||||
unsigned head = buf->head;
|
||||
unsigned tail = buf->tail;
|
||||
unsigned size = buf->size;
|
||||
|
||||
if (head >= tail) {
|
||||
return size - (head - tail) - 1;
|
||||
}
|
||||
|
||||
return tail - head - 1;
|
||||
}
|
||||
|
||||
unsigned ringbuffer_level(ringbuffer *buf) {
|
||||
unsigned head = buf->head;
|
||||
unsigned tail = buf->tail;
|
||||
|
||||
if (head >= tail) {
|
||||
return head - tail;
|
||||
}
|
||||
|
||||
unsigned size = buf->size;
|
||||
return size - tail + head;
|
||||
}
|
||||
|
||||
unsigned ringbuffer_add(ringbuffer *buf, uint8_t *dat, unsigned len) {
|
||||
unsigned rem = ringbuffer_free(buf);
|
||||
unsigned head = buf->head;
|
||||
unsigned written = 0;
|
||||
const unsigned size = buf->size;
|
||||
|
||||
if (len > rem) {
|
||||
len = rem;
|
||||
}
|
||||
|
||||
if (head + len > size) {
|
||||
written = size - head;
|
||||
memcpy(buf->data + head, dat, written);
|
||||
len -= written;
|
||||
head = buf->head = 0;
|
||||
dat += written;
|
||||
}
|
||||
memcpy(buf->data + head, dat, len);
|
||||
buf->head = (head + len) % buf->size;
|
||||
return written + len;
|
||||
}
|
||||
|
||||
unsigned ringbuffer_empty(ringbuffer *buf) {
|
||||
return buf->head == buf->tail;
|
||||
}
|
||||
|
||||
unsigned ringbuffer_peek(ringbuffer *buf, uint8_t *dst, unsigned len) {
|
||||
unsigned level = ringbuffer_level(buf);
|
||||
unsigned size = buf->size;
|
||||
unsigned tail = buf->tail;
|
||||
unsigned written = 0;
|
||||
if (len > level) {
|
||||
len = level;
|
||||
}
|
||||
if (tail + len > size) {
|
||||
written = size - tail;
|
||||
memcpy(dst, buf->data + tail, written);
|
||||
tail = 0;
|
||||
dst += written;
|
||||
len -= written;
|
||||
}
|
||||
memcpy(dst, buf->data + tail, len);
|
||||
return len + written;
|
||||
}
|
||||
|
||||
void ringbuffer_skip(ringbuffer *buf, unsigned len) {
|
||||
buf->tail = (buf->tail + len) % (buf->size);
|
||||
}
|
||||
|
||||
unsigned ringbuffer_get(ringbuffer *buf, uint8_t *dst, unsigned len) {
|
||||
len = ringbuffer_peek(buf, dst, len);
|
||||
ringbuffer_skip(buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
void ringbuffer_rst(ringbuffer *buf) {
|
||||
buf->head = buf->tail = 0;
|
||||
}
|
38
ringbuffer.h
Normal file
38
ringbuffer.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef RINGBUFFER_H
|
||||
#define RINGBUFFER_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t head;
|
||||
uint32_t tail;
|
||||
uint32_t size;
|
||||
uint8_t data[];
|
||||
} ringbuffer;
|
||||
|
||||
#define RINGBUFFER_STORAGE(NAME, SIZE) uint8_t buf_##NAME##__LINE__[sizeof(ringbuffer) + SIZE]; ringbuffer *NAME = (ringbuffer*)buf_##NAME##__LINE__;
|
||||
#define RINGBUFFER_INIT(NAME, SIZE) NAME->head = NAME->tail = 0; NAME->size = SIZE;
|
||||
#define RINGBUFFER(NAME, SIZE) \
|
||||
RINGBUFFER_STORAGE(NAME, SIZE); \
|
||||
RINGBUFFER_INIT(NAME, SIZE);
|
||||
|
||||
void ringbuffer_rst(ringbuffer *buf);
|
||||
|
||||
unsigned ringbuffer_capacity(ringbuffer *buf);
|
||||
unsigned ringbuffer_free(ringbuffer *buf);
|
||||
unsigned ringbuffer_level(ringbuffer *buf);
|
||||
|
||||
unsigned ringbuffer_empty(ringbuffer *buf);
|
||||
|
||||
unsigned ringbuffer_add(ringbuffer *buf, uint8_t *dat, unsigned len);
|
||||
|
||||
unsigned ringbuffer_get(ringbuffer *buf, uint8_t *dst, unsigned len);
|
||||
unsigned ringbuffer_peek(ringbuffer *buf, uint8_t *dst, unsigned len);
|
||||
void ringbuffer_skip(ringbuffer *buf, unsigned len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
24
uart.c
Normal file
24
uart.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "uart.h"
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
|
||||
void uart_setup() {
|
||||
rcc_periph_clock_enable(RCC_GPIOB);
|
||||
rcc_periph_clock_enable(RCC_USART3);
|
||||
|
||||
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO10 | GPIO11);
|
||||
gpio_set_af(GPIOB, GPIO_AF7, GPIO10 | GPIO11);
|
||||
|
||||
usart_set_baudrate(USART3, 115200);
|
||||
usart_set_databits(USART3, 8);
|
||||
usart_set_stopbits(USART3, USART_STOPBITS_1);
|
||||
usart_set_mode(USART3, USART_MODE_TX_RX);
|
||||
usart_set_parity(USART3, USART_PARITY_NONE);
|
||||
usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE);
|
||||
usart_enable(USART3);
|
||||
|
||||
usart_disable_tx_complete_interrupt(USART3);
|
||||
usart_enable_tx_interrupt(USART3);
|
||||
usart_enable_rx_interrupt(USART3);
|
||||
}
|
7
uart.h
Normal file
7
uart.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef UART_H
|
||||
#define UART_H
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
|
||||
void uart_setup(void);
|
||||
|
||||
#endif
|
37
usb.c
37
usb.c
|
@ -7,10 +7,16 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#include "usb.h"
|
||||
#include "ringbuffer.h"
|
||||
|
||||
extern ringbuffer *usb_to_uart_buf, *comm_in_buf;
|
||||
|
||||
/* Number of serial devices we want to provide. */
|
||||
#define NUM_SERIAL 2
|
||||
|
||||
static const uint8_t EP_COMM = 1 + 2 * ACM_COMM;
|
||||
static const uint8_t EP_NFC = 1 + 2 * ACM_NFC;
|
||||
|
||||
/* CDC-ACM devices need a functional descriptor that looks like this */
|
||||
struct usb_cdcacm_functional_descriptor {
|
||||
struct usb_cdc_header_descriptor header;
|
||||
|
@ -27,11 +33,11 @@ static char serial[24];
|
|||
* In descriptors, indices are 1-based, and 0 is an empty string.
|
||||
*/
|
||||
static char const *usb_strings[] = {
|
||||
"Imaginaerraum.de",
|
||||
"DoorControl",
|
||||
serial,
|
||||
"RFID",
|
||||
"Other"
|
||||
"Imaginaerraum.de",
|
||||
"DoorControl",
|
||||
serial,
|
||||
[3 + ACM_COMM] = "Comm",
|
||||
[3 + ACM_NFC] = "RFID",
|
||||
};
|
||||
|
||||
usbd_device *g_usbd_dev;
|
||||
|
@ -135,14 +141,21 @@ static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
|
|||
/* Read some data from the endpoint */
|
||||
int len = usbd_ep_read_packet(usbd_dev, ep, buf, 64);
|
||||
|
||||
if (len) {
|
||||
/* Write it back */
|
||||
while (usbd_ep_write_packet(usbd_dev, ep | 0x80, buf, len) == 0);
|
||||
if (ep == EP_NFC) {
|
||||
ringbuffer_add(usb_to_uart_buf, (void*)buf, len);
|
||||
} else if (ep == EP_COMM) {
|
||||
ringbuffer_add(comm_in_buf, (void*)buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
|
||||
{
|
||||
int usb_write_cdcacm(uint8_t acm, uint8_t *data, size_t len, int tries) {
|
||||
int i = 0;
|
||||
while (usbd_ep_write_packet(g_usbd_dev, (1 + 2 * acm) | 0x80, data, len) == 0 && ++i < tries)
|
||||
;
|
||||
return i < tries;
|
||||
}
|
||||
|
||||
static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue) {
|
||||
(void)wValue;
|
||||
|
||||
for (int i = 0; i < NUM_SERIAL; i++) {
|
||||
|
@ -309,7 +322,7 @@ void usb_setup() {
|
|||
usbd_register_set_config_callback(g_usbd_dev, cdcacm_set_config);
|
||||
|
||||
/* And use interrupts instead of polling. */
|
||||
nvic_enable_irq(NVIC_OTG_FS_IRQ);
|
||||
// nvic_enable_irq(NVIC_OTG_FS_IRQ);
|
||||
}
|
||||
|
||||
void otg_fs_isr() { usbd_poll(g_usbd_dev); }
|
||||
//void __attribute__((weak)) otg_fs_isr() { }
|
||||
|
|
Loading…
Reference in New Issue
Block a user