Skip to content
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

Issue with using UART1 on GD32F130C8 #76

Open
imeshsps opened this issue Aug 12, 2022 · 17 comments
Open

Issue with using UART1 on GD32F130C8 #76

imeshsps opened this issue Aug 12, 2022 · 17 comments
Labels
Component: Serial Regarding UART / Serial component

Comments

@imeshsps
Copy link

I was trying to run the following code to test two serial ports and I was having this issue.

void setup() { Serial.begin(9600); Serial1.begin(9600); }
void loop() { Serial.println("looping S1"); Serial1.println("looping S2"); delay(1000); }

The issue I'm having is I'm getting the output for both serial print lines on the first serial output.

debug screen

Then I tried to run SPL example with changed parameters to check whether it is a issue with my PCB but after I made same changes, I was able to use UART1.

uart1 settings

Then I tried to use only Serial1 with the following code and on the debug mode I noticed the following.

void setup() { Serial1.begin(9600); } void loop() { Serial1.println("looping S2"); delay(1000); }

2nd serial port

It seems like it is still passing the same parameters for 1st serial port. Please can you help me to fix this ? Any help is really appreciated.

Thanks.

@maxgerhardt
Copy link
Member

maxgerhardt commented Aug 12, 2022

  1. We have a misdesign of the Serial buffers where they use the exact same buffer. This was already fixed in a fork, but I haven't imported the fix yet, so independent hardware serial's don't yet work. I'll have a look.
  2. I think though in this case though Serial is a macro for Serial1 and hence you access the same object? See

#if !defined(Serial)
#if defined(USE_USART0_SERIAL)
#define Serial Serial1

So that's clear why it's outputting the same stuff.

It seems like it is still passing the same parameters for 1st serial port

If you want to change the default parameters for the hardware serial, you would have to change them in your variant, e.g.

/* USART definitions */
#define SERIAL_HOWMANY 1
#define USE_USART0_SERIAL
#define PIN_SERIAL_RX PA10
#define PIN_SERIAL_TX PA9
#define SERIAL0_RX PA10
#define SERIAL0_TX PA9

We don't yet have a good system of multiple hardware serials, but work on it.

To be clear, what you want is Serial1 on PA2 + PA3 (using USART0) and a Serial2 on some other pins using the USART1 peripheral? (And Serial will always be a macro to the default serial, either the first hardware serial or USB serial.)

@imeshsps
Copy link
Author

Thanks for quick reply.

To be clear, what you want is Serial1 on PA2 + PA3 (using USART0) and a Serial2 on some other pins using the USART1 peripheral? (And Serial will always be a macro to the default serial, either the first hardware serial or USB serial.)

Yes. to use two hardware serials on different pins.

I think though in this case though Serial is a macro for Serial1 and hence you access the same object. See

It should be. But I tried using Serial2, it says it is not defined.

If you want to change the default parameters for the hardware serial, you would have to change them in your variant.

I'll give this a try. Thanks for your support. Hope to see them working soon.

@maxgerhardt
Copy link
Member

We can keep the issue open until it is properly resolved in code.

@maxgerhardt maxgerhardt reopened this Aug 12, 2022
@maxgerhardt
Copy link
Member

maxgerhardt commented Aug 12, 2022

PR #77 in conjunction with CommunityGD32Cores/platform-gd32@52cb1be have exposed all hardware serial ports of the board as Serial1, Serial2, et cetera. (Serial is macro for Serial1 if no USB is enabled, your chip doesn't have that implemented yet).

I've also added an official PlatformIO example at https://github.com/CommunityGD32Cores/gd32-pio-projects/tree/main/gd32-arduino-serials and personally tested it on a GD32F303CC board.

Can you test this on your F130C8? If you need help with configuring your serial port pins, let me know. By default, you have Serial1 (=Serial) on TX=PA9, RX=PA10, and Serial2 on TX=PA2, RX=PA3, as per here, with these other pins being usable. I hope the README I wrote in the linked projects explains it well.

To update your Arduino core version, please open a CLI and execute

pio pkg update -g -p "https://github.com/CommunityGD32Cores/platform-gd32.git"

in it.

Alternatively, delete C:\Users\<user>\.platformio\packages\framework-arduinogd32 and build the project again.

@imeshsps
Copy link
Author

Thank you, I'm out for today and I'll test it tomorrow and let you know.

I really appreciate the time and effort you are putting into this.

@imeshsps
Copy link
Author

imeshsps commented Aug 14, 2022

Hey @maxgerhardt ,

I was able to test it today and it was working with my GD32F130C8.

Screenshot 2022-08-14 102725

After that, I wanted to connect the Neo6M GPS receiver and I noticed this. When I was writing to Serial1 with the FTDI module it was showing on the serial monitor. But when I connect the GPS module, it was not showing anything. Later I found that when connecting it for a very short period of time and disconnecting it, it was showing GPS data. But when I keep it connected, it freezes after a few seconds. I needed to restart the chip to get the serial working back.

Screenshot 2022-08-14 104812

It seemed to me that this was due to the long timeout period and after I reduced the timeout, it was working fine. And by adding the same "trick" to software serial as the following code, I was able to get TinyGPSPlus running.

SoftwareSerial ss(PB11, PB10); ss.begin(9600); ss.setTimeout(250);

Screenshot 2022-08-14 112836

Thank you very much and I really appreciate the time and effort you are putting into this.

@maxgerhardt
Copy link
Member

When I was writing to Serial1 with the FTDI module it was showing on the serial monitor. But when I connect the GPS module, it was not showing anything. Later I found that when connecting it for a very short period of time and disconnecting it, it was showing GPS data. But when I keep it connected, it freezes after a few seconds. I needed to restart the chip to get the serial working back.

Seems like the RX buffer got full and there's an error in handling that somewhere -- it should never crash, at most discard the bytes that weren't fitting anymore at the front or back in the ringbuffer.

I'll try and reproduce this by sending lots of data to the chip and see how long it survives.

@Candas1
Copy link

Candas1 commented May 26, 2023

Hi,

I use the same code with a GD32F103 and a GD32F130, but the GD32F130 RX stops working after a few seconds.
I have working SPL code for the GD32F130 so it could probably help resolve the issue.

@maxgerhardt
Copy link
Member

How can I reproduce the issue? Would a simple loopback like

#include <Arduino.h>

void setup() {
    Serial.begin(115200);
}

void loop() {
    if(Serial.available() > 0) {
        char buf[SERIAL_RX_BUFFER_SIZE + 1];
        size_t numRead = Serial.readBytes(buf, sizeof(buf));
        buf[numRead] = '\0';
        Serial.print("Received: ");
        Serial.println(buf);
    }
}

suffice?

@Candas1
Copy link

Candas1 commented May 29, 2023

Hi,

Sorry for the delayed reply.
I created a simple project with only this code today, the only change I did is using Serial2 instead of Serial.
A hoverboard mainboard is sending binary data every 10ms.
It stops receiving after some time on the GD32F130, but works on STM32F103.

Please let me know if there is anything else I can do to help.
I tried to compare with some working SPL examples I know of, but it seems those use DMA.

@maxgerhardt
Copy link
Member

Do you have an estimate of how many bytes get sent every 10ms? What is the approximate timespan after which it stops receiving?

@Candas1
Copy link

Candas1 commented May 30, 2023

18 bytes
I will measure this when I am back home this evening.

@maxgerhardt maxgerhardt added the Component: Serial Regarding UART / Serial component label Jun 4, 2023
@Candas1
Copy link

Candas1 commented Jun 8, 2023

Sorry for not providing feedback earlier.
It fails after a minute or so, but I will experiment more and come back when I find the root cause and if I am sure it's due to arduino-gd32

@maxgerhardt
Copy link
Member

I have a setup right now with a GD32F130C8 and a USB-to-serial adapter connected to it's Serial (PA9, PA10). I'm using this sketch

#include <Arduino.h>
#define LED PC13

void setup(void) {
    pinMode(LED, OUTPUT);
    Serial.begin(115200);
}

void loop(void) {
    Serial.println("Test");
    digitalWrite(LED, HIGH);
    if(Serial.available() > 0) {
        char buf[SERIAL_RX_BUFFER_SIZE + 1];
        size_t numRead = Serial.readBytes(buf, min(Serial.available(), sizeof(buf)));
        buf[numRead] = '\0';
        Serial.print("Received: ");
        Serial.println(buf);
    }
    delay(100);
    digitalWrite(LED, LOW);
    delay(100);
}

and I'm using hterm to do infinite-loop sending of data with 100ms time in between. So far, no crashes for 290 seconds.

grafik

@maxgerhardt
Copy link
Member

maxgerhardt commented Jun 8, 2023

Now I've played around with it quite a lot and written a custom python script to pump data faster into the chip than what hterm can do.

I indeed observed some weird behavior. It seems that after resets, the board can receive garbage data when the uart signals are already pumping at full speed during reset and initialization phase. Additionally I had a case where it would stop receiving data at all.

I've pushed 32030ad and corrected some mistakes in the UART code. Specifically it resets the error flags (frame error, overrun error, parity error, noise error) properly per datasheet instructions (by clearing interrupt flags, not just reading the RDATA register). Since then I didn't have the situation of "stops receiving at all" anymore.

There still is the issue of receiving a bunch of garbaga data after reset for a few iterations (about 3 in my case) that I have not yet solved and are also running out if ideas... It may be due to the properties of UART itself.

grafik

(I am only ever sending 'A' so no P or other weird characters should ever ocurr...)

However, this commit may already be enough to resolve your issues. Can you retest your firmware?

And btw, updating is done with the PlatformIO Core CLI and

pio pkg update -g -p gd32

@maxgerhardt
Copy link
Member

This reset issue is really weird. I've debugged it further and the hardware flags at the time of the RX interrupt are all fine: None of the error flags set, valid reception, and the UART0->RDATA register really contains 0x05 or 0x50 although 'A' (0x41) is only being sent. There are no bits set by the hardware to indicate that the RX data is bad. I think with some timing offset, when the MCU boots up / enables the UART in the middle of a UART transmission it may interepret the data transmission of 0x41 in the middle as a start bit, starts sampling in the middle of data, by chance gets a valid stop bit and returns that data. The HW can't tell the difference because time-shifted it may look like.

In any case, you may not be suffering from that reset issue when all microcontrollers in that system are turned on at the same time and when one sends, the other is ready to receive properly.

@Candas1
Copy link

Candas1 commented Jun 13, 2023

Sorry I was abroad and just came back.
I tested my firmware again after your fixes and it ran without RX problems for 30 minutes so the issue is fixed for me.
About the garbage you receive, can it be just transmission errors?
In my firmware we use a Start frame and a XOR checksum to reject bad frames.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Serial Regarding UART / Serial component
Projects
None yet
Development

No branches or pull requests

3 participants