Skip to content

HardwareSerial::setPins does not unset previous pin #8607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task done
LupinIII opened this issue Sep 6, 2023 · 4 comments · Fixed by #8719
Closed
1 task done

HardwareSerial::setPins does not unset previous pin #8607

LupinIII opened this issue Sep 6, 2023 · 4 comments · Fixed by #8719
Assignees
Labels
Peripheral: UART Status: Review needed Issue or PR is awaiting review Type: Bug 🐛 All bugs

Comments

@LupinIII
Copy link

LupinIII commented Sep 6, 2023

Board

NodeMCU ESP-C3-13

Device Description

similar to ESP32-C3-DevKitC-02/ESP32-C3-DevKitM-01

Hardware Configuration

No

Version

v2.0.11

IDE Name

PlatformIO

Operating System

Windows 10

Flash frequency

40MHz

PSRAM enabled

yes

Upload speed

460800

Description

When using HardwareSerial::setPins (e.g. "Serial.setPins(2,3,-1,-1)") the TX pin previously set for that port does not get "unset". In the example below all the pins will output serial data at the same time. When checking on the logic analyzer, you can see that at startup only one pin outputs data (the "0b10101010" pattern). One after another a pin starts outputting data. After the for loop has completed, all pins output the same serial data. I also confirmed that when connecting an USB-TTL-converter to any of those pins, the data can be read.

This is not specific to "Serial", but also happens for "Serial1". And it does not depend on specific pins either.

I could not reproduce the same behavior for RX.

Sketch

#include <Arduino.h>

#define SERIAL0_BAUD 19200
#define SERIAL0_PARAM SERIAL_8N1
#define SERIAL0_RXPIN 4
#define SERIAL0_TXPIN 0

static const uint8_t pins[] = {2,9,3,10,18,19,20,21}; // pins to set TX to (chosen for no other reason than that they are on one side of the dev board and the logic analyzer is easier to connect to)

void setup() {
	Serial.begin(SERIAL0_BAUD, SERIAL0_PARAM, SERIAL0_RXPIN, SERIAL0_TXPIN);
}

void loop() {
	for (auto pin: pins) {
		Serial.setPins(-1, pin, -1, -1); // only change TX pin
		Serial.write(0b10101010);
		delay(1); // give UART time to send the byte
	}
}

Debug Message

I don't have a cmsis-dap device, which PlatformIO expects me to have when trying to debug.

Other Steps to Reproduce

As a workaround (although a lot slower) calling Serial.end() followed by a Serial.begin() with the new pin works as expected (the data output switched from pin to pin).

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@LupinIII LupinIII added the Status: Awaiting triage Issue is waiting for triage label Sep 6, 2023
@VojtechBartoska
Copy link
Contributor

hello, can you retest this with latest version 2.0.12 please?

@VojtechBartoska VojtechBartoska added Peripheral: UART Resolution: Awaiting response Waiting for response of author and removed Status: Awaiting triage Issue is waiting for triage labels Sep 7, 2023
@LupinIII
Copy link
Author

LupinIII commented Sep 7, 2023

I would have to wait for PlatformIO to update to that version. But I am 99.9% sure that it will not change the behavior as none of the relevant files (cores/esp32/HardwareSerial.cpp, cores/esp32/esp32-hal-uart.c) have changed from 2.0.11 to 2.0.12 (assuming I used github correctly) and the underlying IDF stayed the same (both based on 4.4.5).

I found another workaround instead of the "Serial.end() and Serial.begin()". A pin can be cleared from outputting the data by temporarily setting that pin as the RX pin.

#define RXPIN 4
#define TXPIN_A 2
#define TXPIN_B 3

Serial.begin(BAUD, PARAM, RXPIN, TXPIN_A);
Serial.write(0xff); // will appear on pin 2 (TXPIN_A)

Serial.setPins(-1, TXPIN_B, -1, -1); // only change TX pin
Serial.write(0xff); // will appear on pin 2 (TXPIN_A) AND pin 3 (TXPIN_B)

Serial.setPins(TXPIN_A, -1, -1, -1); // only change RX pin, but use the pin you want to no longer be used as TX
Serial.write(0xff); // will appear on pin 3 (TXPIN_B) only, as pin 2 (TXPIN_A) is now used as RX; obviously the real RXPIN isn't working now

Serial.setPins(RXPIN, -1, -1, -1); // only change RX pin, restore the original RX
Serial.write(0xff); // will appear on pin 3 (TXPIN_B) and RX is back on pin 4 (RXPIN) again

Setting a pin as RX for a short time shouldn't harm anything connected to it.

Btw. slightly unrelated to that (but within the HardwareSerial::setPins definition in HardwareSerial.cpp) there are the lines:

    if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) {
        _txPin = _txPin >= 0 ? txPin : _txPin;
        _rxPin = _rxPin >= 0 ? rxPin : _rxPin;
        _rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin;
        _ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin;
    } else {

Shouldn't those be _txPin = txPin >= 0 ? txPin : _txPin; (removed the underscore character on the second txPin; other lines respectively)? The original lines don't make much sense IMHO.

@SuGlider SuGlider self-assigned this Sep 7, 2023
@SuGlider SuGlider added Type: Bug 🐛 All bugs and removed Resolution: Awaiting response Waiting for response of author labels Sep 7, 2023
@SuGlider
Copy link
Collaborator

SuGlider commented Sep 7, 2023

@LupinIII
This is a bug, indded.
Thanks for reporting!

@SuGlider
Copy link
Collaborator

@LupinIII - Please try Arduino Core 2.0.13. It shall sove this issue. Please let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment