r2axz / bluepill-serial-monster Goto Github PK
View Code? Open in Web Editor NEWUSB to 3 Port Serial (UART) adapter firmware for STM32 Blue Pill.
License: MIT License
USB to 3 Port Serial (UART) adapter firmware for STM32 Blue Pill.
License: MIT License
where can I donate??!!
Seriously I've been head banging for weeks... trying to get a working USB-UART bridge, given that CH340g board seems to have electrical problems thus garbling all its TX, and replacement FT2232 is a long way from arriving.
I've tried other projects, only to find that the buffers overrun after 30 bytes. I tried myself, but gave up short of figuring out how to read the dtr/rts pins from USB (which is the whole point). Then I finally got your binary flashed. It didn't work the first time, so I lost several days, until I realized my stm32f103c8t6 boards (11 in total), were a mix of various clones. 5 were secretely stm32f103c6, and 3 were 128kb variants, and almost every one had its own set of codes printed on the MCU chip itself. I finally figured out which was vanilla, and now it works like charm!
Technically, so satisfy the category of "issues" (so nobody bites my head off), I'd like to mention its important to disconnect the ST-Link before testing the board, otherwise the LED will blink, but still no communication will happen. That one almost made me give up at the last breath.
Lacks probably some explanation regarding <stm32f1xx.h>. Where do i find the right version for this here? Where do i have to copy it? What compiler do i need?
size_t usb_send(uint8_t ep_num, const void *buf, size_t count) {
ep_reg_t *ep_reg = ep_regs(ep_num);
usb_pbuffer_data_t *ep_buf = (usb_pbuffer_data_t *)(USB_PMAADDR + (usb_btable[ep_num].tx_offset<<1));
pb_word_t *buf_p = (pb_word_t*)buf;
pb_word_t words_left = count >> 1;
size_t tx_space_available = usb_endpoints[ep_num].tx_size;
if (count > tx_space_available) {
count = tx_space_available;
}
while (words_left--) {
(ep_buf++)->data = *buf_p++;
}
if (count & 0x01) {
(ep_buf)->data = (uint8_t)*buf_p;
}
usb_btable[ep_num].tx_count = count;
*ep_reg = ((*ep_reg ^ USB_EP_TX_VALID) & (USB_EPREG_MASK | USB_EPTX_STAT)) | (USB_EP_CTR_RX | USB_EP_CTR_TX);
return count;
}
words_left
is initialized before count > tx_space_available
check, which leads to writing past the ep tx buffer. Surprisingly, this does not cause any major problems because usb_send is mostly used during the device USB enumeration phase and its circular buffer sibling (usb_circ_buf_send
) does not have this issue.
Code does not check is CDC BULK IN endpoint is ready to transmit before sending ZLP packets. This leads to RX data corruption. Surprisingly, nobody reported this behavior, but this issue is very visible when doing stress tests.
What is your experience to building project with various versions of gcc-arm-none-eabi?
I tried gcc-arm-none-eabi-10-2020-q4-major
and have some warnings:
usb_cdc.c: In function 'usb_cdc_port_start_tx':
usb_cdc.c:447:41: warning: array subscript '<unknown>' is outside the bounds of an interior zero-length array 'uint8_t[0]' {aka 'unsigned char[]'} [-Wzero-length-bounds]
447 | dma_tx_ch->CMAR = (uint32_t)&tx_buf->data[tx_buf->tail];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from usb_cdc.c:10:
circ_buf.h:15:13: note: while referencing 'data'
15 | uint8_t data[0];
| ^~~~
usb_cdc.c: In function 'DMA1_Channel4_IRQHandler':
usb_cdc.c:447:41: warning: array subscript '<unknown>' is outside the bounds of an interior zero-length array 'uint8_t[0]' {aka 'unsigned char[]'} [-Wzero-length-bounds]
447 | dma_tx_ch->CMAR = (uint32_t)&tx_buf->data[tx_buf->tail];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from usb_cdc.c:10:
circ_buf.h:15:13: note: while referencing 'data'
15 | uint8_t data[0];
| ^~~~
usb_cdc.c: In function 'DMA1_Channel7_IRQHandler':
usb_cdc.c:447:41: warning: array subscript '<unknown>' is outside the bounds of an interior zero-length array 'uint8_t[0]' {aka 'unsigned char[]'} [-Wzero-length-bounds]
447 | dma_tx_ch->CMAR = (uint32_t)&tx_buf->data[tx_buf->tail];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from usb_cdc.c:10:
circ_buf.h:15:13: note: while referencing 'data'
15 | uint8_t data[0];
| ^~~~
usb_cdc.c: In function 'DMA1_Channel2_IRQHandler':
usb_cdc.c:447:41: warning: array subscript '<unknown>' is outside the bounds of an interior zero-length array 'uint8_t[0]' {aka 'unsigned char[]'} [-Wzero-length-bounds]
447 | dma_tx_ch->CMAR = (uint32_t)&tx_buf->data[tx_buf->tail];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from usb_cdc.c:10:
circ_buf.h:15:13: note: while referencing 'data'
15 | uint8_t data[0];
| ^~~~
usb_cdc.c: In function 'usb_cdc_poll':
usb_cdc.c:331:36: warning: array subscript '<unknown>' is outside the bounds of an interior zero-length array 'uint8_t[0]' {aka 'unsigned char[]'} [-Wzero-length-bounds]
331 | uint8_t *buf_ptr = &rx_buf->data[rx_buf->tail];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from usb_cdc.c:10:
circ_buf.h:15:13: note: while referencing 'data'
15 | uint8_t data[0];
| ^~~~
Maybe exists version of gcc-arm-none-eabi which works fine w/o these warnings?
Hi
Currently Pull-Up resistor is 1KΩ(?) and unchangeable, which I found is too small for receiving signals from some weak open-drain output.
In my case, I used the bluepill with another board with max 50mA output current. When the baud rate is 920k the bluepill can't receive message correctly. The current for switching from 0 to 1 is too big to finish in 1/920k second.
Finally I solved this issue by disabling the PU and put a external 10K PU.
Hope there will be an advanced option for changing PU value
thanks
Sorry for my newbie question, I'm not electrical engineer.
From README
When configured as an output, none of the STM32F103C8T6 pins is 5 V tolerant. Make sure you don't accidentally get more than 4.0 V on such pin or damage may occur.
If I connect TX of BluePill to pin RX of a device powered at 5V, can I broken the STM32F103C8T6? RX should be high impedance or doesn't matter?
Other connection should be ok because RX on bluepill is 5V tolerant except for UART2.
I used bluepill for serialudpi where RX and TX are shorted with a resistor and a diode.
I powered the MCU at 3.3V and works no damage, but if I power the MCU at 5V damage may occur?
My 50 cents for improve User eXperience with Serial Monster:
As I can see in current moment Serial Monster used single LED to tell us any activity on UART ports (TX&RX).
I find very useful to use the second LED to help us to separating activity indication, e.g.:
To make accessability of second LED (by default use as POWER LED) we should move corresponding resistor.
So, LED1 already available on PC13 pin, and LED2 will be available on PC14 pin (in proposed setup).
Here is my example to moving resistor:
Hope this HW mod will be easy and useful for most Serial Monster's users.
Hi,
This GPLed project depends on a non-free library (SMT32CubeF1), where the USB stack is licensed under the ST SLA0044:
https://github.com/STMicroelectronics/STM32CubeF1/blob/master/License.md
Like we did for the DirtyJTAG project, you could use free libraries like the unicore-mx or libopencm3.
I could try to change the underlying library.
Tested on W7 and W8. It seems, driver .inf file is necessary to extend usable OS range.
Thank you
Tadas LY1CE
Hi,
is it possible to add to configuration option to invert RX and TX or there is hardware limitation?
Hi,
Is it possible to add support for STM32F103VET6 to gain 5 Serial Ports?
Thanks
From the spec:
This request sends special carrier modulation that generates an RS-232 style break.
The wValue field contains the length of time, in milliseconds, of the break signal. If wValue contains a
value of FFFFh, then the device will send a break until another SendBreak request is received with the
wValue of 0000h.
The code that follows is my hacky attempt at implementing the functionality. I call it "hacky" because I used a loop to implement the delay time (which IIRC isn't accurate at all--I don't remember exactly because it's been almost 18 months since I last worked on this), and the pin mode change involves using memcpy to clone the old TX pin configuration, change it to GPIO, and then use the modified configuration to re-init the pin. Also, I'm not sure if it's a good idea to handle the delay inside the USB control endpoint event handler, since the delay can in theory be up to 65.534 seconds long. Also, now that I've thought about this more, if the delay was done outside of the event handler, what should be done if an indefinite SendBreak is sent, and then TX data is sent? Since the break is just holding the TX line low, if that data was transmitted during that time it would all be lost.
If anyone knows a better way to implement this, please let me know.
diff --git a/usb_cdc.c b/usb_cdc.c
index b48f4b5..300466c 100644
--- a/usb_cdc.c
+++ b/usb_cdc.c
@@ -241,6 +241,27 @@ static void usb_cdc_set_port_txa(int port, int txa_active) {
}
}
+static usb_status_t usb_cdc_send_break(int port, uint16_t duration_ms) {
+ if (port < USB_CDC_NUM_PORTS) {
+ const gpio_pin_t *tx_pin = &device_config_get()->cdc_config.port_config[port].pins[cdc_pin_tx];
+ if (duration_ms != 0) {
+ gpio_pin_t tx_pin_new = { 0 };
+ memcpy(&tx_pin_new, tx_pin, sizeof(gpio_pin_t));
+ tx_pin_new.func = gpio_func_general;
+ gpio_pin_init(&tx_pin_new);
+ gpio_pin_set(tx_pin, 0);
+ }
+ if (duration_ms != 0xffff) {
+ for (int i=0; i < 8000*duration_ms; i++) {
+ __NOP();
+ }
+ gpio_pin_set(tx_pin, 1);
+ gpio_pin_init(tx_pin);
+ }
+ }
+ return usb_status_ack;
+}
+
static usb_status_t usb_cdc_set_control_line_state(int port, uint16_t state) {
usb_cdc_set_port_dtr(port, (state & USB_CDC_CONTROL_LINE_STATE_DTR_MASK));
usb_cdc_set_port_rts(port, (state & USB_CDC_CONTROL_LINE_STATE_RTS_MASK));
@@ -741,6 +762,8 @@ usb_status_t usb_cdc_ctrl_process_request(usb_setup_t *setup, void **payload,
return usb_status_ack;
}
break;
+ case usb_cdc_request_send_break:
+ return usb_cdc_send_break(port, setup->wValue);
default:
;
}
diff --git a/usb_cdc.h b/usb_cdc.h
index c37bc7c..86b01eb 100644
--- a/usb_cdc.h
+++ b/usb_cdc.h
@@ -42,7 +42,7 @@ typedef enum {
#define USB_CDC_ACM_CAPABILITY_SEND_BREAK 0x04
#define USB_CDC_ACM_CAPABILITY_NETWORK_CONNECTION 0x08
-#define USB_CDC_ACM_CAPABILITIES (USB_CDC_ACM_CAPABILITY_LINE_CODING)
+#define USB_CDC_ACM_CAPABILITIES (USB_CDC_ACM_CAPABILITY_SEND_BREAK | USB_CDC_ACM_CAPABILITY_LINE_CODING)
/* USB CDC Header Functional Descriptor */
The code in the usb_cdc.c:usb_cdc_port_send_rx_usb() function looks a little bit suspicious: in the 7-bits data mode it clears MSB of received data in the circular buffer treating it as linear buffer. Since the amount of affected bytes calculated as total number of bytes stored, this may lead buf_ptr pointer to run out of circular buffer bounds.
RTS can operate only by hardware ? CwType, for example, need both RTS and DTR software controled
The usb_descriptors.c file at line 333 refers to the usb_endpoints parameters array via usb_endpoint_address_cdc_0_interrupt constant, which is a bit suspicious because this is done in the descriptor of third UART. This doesn't affect current functionality because parameters of control endpoints happens to match, but introduces minor inconsistency.
Если есть возможность просьба добавить возможность управление несколькими GPIO в режиме In/Out и чтение с нескольких входов АЦП.
Hi, I cloned the repo locally and did slight modifications on the device config to enable some more features :
Hi and thanks for that great work.
It seems nice to have fourth COM port (virtual UART) for configuration purposes instead of jumper manipulation with PB5 pin.
The 4th COM doesn't required custom resources (like bandtwidth or latency) - will not affected to performance of remaining three UARTs.
Happy hacking!
Здравствуйте. Я вообще, на самом деле, не очень разбираюсь в теме работы с последовательным портом, определенно понимаю немного, потому может задаю тупой вопрос:
хочу использовать устройство для создания игрового устройства, которое использует 2 UART порта для связи с игрой Hatsune Miku Project Diva Arcade Future Tone и к Blue Pill подключается два устройсва, одно Arduino Micro, чтоб была возможность использования прерываний по последовательному порту, а второе плата на основе микроконтроллера Cypress cy8c4246azi-m445, с помощью которой работает сенсорная панель по последовательному порту (вот этот проект https://github.com/Project-Alpaca/LKP ) . Проблема в том, что по отдельности все проверенно работает, с STM32 Arduino работает без проблем, точно также как и плата сенсорной панели рабоатает без проблем с USB-TTL конвертером на основе CP2102, а вот при подключении к STM32 сенсорная панель определяется, но по сути не работает, ибо отзыв получается неверноятно медленно, раз в 5 секунд может быть. Я думал, что может быть проблема в UART, пробовал переключать между 1 и 3 портами (устройство работает от 5В, так что тут мне доступны только 1 и 3 порты, правильно?), также пробовал все предыдущие версии прошивок вплоть до 2.0, чтоб проверить, не временная ли это ошибка? Для подключения используется только RX/TX пины, ну и питание соответственно. Может доступные какие-то еще настройки или что-то в этом роде, потому что, как я уже писал, через CP2102 работает безукоризненно, потому не ожидал, что столкнусь с проблемами. На что обратить внимание? Заранее спасибо :)
Hi!
I'm currently trying to integrate serial monster into the Maple DFU bootloader (https://github.com/rogerclarkmelbourne/STM32duino-bootloader).
Is it planned into future releases or are there some hidden problems? I think it can be really useful feature.
Thanks!
Здравствуйте. Спасибо за прошивку с кастомным USB стеком. Докачал частично STM32CubeF1 для CMSIS/Core/Include и Device/ST и собрал бинарник в 20 КиБ, который шьётся и работает на bluepill с загрузчиком BMPBootloader (смещение 0x08002000).
Максимальная скорость передачи данных обусловлена ограничениями APB1 36MHz, на которой висят USART2, USART3, и 36M/16=2250000 бод. Однако есть же ещё и APB2 72MHz с USART1 (и SPI1), так что 72M/16=4500000 бод.
У меня вопрос, почему для первого самого быстрого порта в проекте изначально заложен маленький буфер пакетной памяти?
bluepill-serial-monster/usb_descriptors.c
Lines 14 to 19 in 7ca8ddb
Когда я гоняю loopback тесты через cbrake/linux-serial-test, да или даже rx-only, tx-only, то по осциллографу на USB FS D+/D- (и USART Tx/Rx) видно, что прошивка справляется без пропусков. При этом, как только открываю второй порт на прослушивание тишины (да и третий тоже), хост начинает опрашивать несколько эндпоинтов, и по Nak вставляет паузу в 20 микросекунд. Это снижает скорость передачи данных с 450000 Байт/с чуть ли не в два раза. 12MHz/8*0.000020s=30 байт (без учёта служебных бит формата пакетов Bulk).
Окей, поменял размеры местами, с 32-64-64 на 64-64-32, пересобрал и залил через dfu-util, стало работать без заиканий даже с занятым USART1 и прослушиваемыми USART2,3. Также потом проверил external loopback с перемычкой между контактами USART2_RX <=>USART3_TX, гоняет данные на 2250000 нормально. Все три порта на максимальной частоте одновременно, конечно, не работают.
Прошу пересмотреть выделенные размеры wMaxPacketSize и bEndpointSize. Я заметил по прошлым Issue, что USB FSDEV PMA пакетная память практически вся уже занята, но я не предлагаю 64-64-64. Также я не предлагаю делать несимметричные буферы, как это сделано в других проектах, то есть USART Rx (DMA) 64 для непрерывного приёма, но USART Tx 32 или даже 16 (без DMA?) для медленного интерактивного ввода с клавиатуры -- пускай пока работает как есть.
Вопрос вдогонку, а что если прошить это на GD32F103CB, которая может работать на 108 96 MHz с делителем USB48 DIV2, предварительно подкрутив настройки PLL? Будет ли max baudrate APB2 96M/16=6000000 baud? Мой случай применения примерно такой, что мне нужны нескольно медленных UART портов (два) в одном флаконе, но ещё я веду захват трассировки TraceSWO NRZ-encoded, и этот проект отлично подходит.
To reproduce: connect PB5 to GND and connect the USB cable. Open a screen
session to the first serial port, observe some garbage data, no banner:
*ed
Error, unknown command, use "help" to get the list of available commands.
>
>Ee eree
This is reliably reproducible in my setup. Hitting enter does bring up the command prompt and the console can be used normally, the problem is just the garbage data at the beginning. Reproduces with main
and r2axz-re-enumerate-on-reset
.
Works OK if PB5 is connected to GND after the board has booted up and enumerated on the USB bus.
Maybe I'm doing something wrong, but while toying with the project I noticed that if I hit the reset button on the pill the host doesn't notice anything has happened. I have to pull the USB cable out to see the "USB disconnect" event in the kernel log. I don't have an STLink or other power source connected, bluepill is powered over the USB connector.
This is on linux 5.13.6. Everything else works fine otherwise.
73 de LZ1CK
All this of course is very good, but is there a way to compile it in Windows, preferable with known instruments: Cube, Keil, IAR...?
Please create a release and upload the compiled firmware in .bin or .hex format.
You do not always want to build a project to get a binary.
what is the maximum baud rate you have achieved on a uart?
I would like to avoid buying an expensive ftdi ft232h.
Thank you
.clang-format is not currently used by this project. What's worse, it does not match the existing coding style, which confuses those who try to use it. I believe it should be removed for now and possibly re-introduced later, when I figure out how to make the one that matches my coding style.
Its my understanding that the two chips are pretty close together in features and capabilities.
Would be fun to extend this to support both, if possible.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.