USB Serial echos characters into the input (i.e. keyboard)

Post here all questions related to LibMaple core if you can't find a relevant section!
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

USB Serial echos characters into the input (i.e. keyboard)

Post by ag123 »

STM32F103C8 (an old blue pill)
There seemed to be some bugs which I can't find where is the problem

Code: Select all

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

void loop() {
	int c;
	print("hello world");
	println();
	if( Serial.available() > 0)
	  c = Serial.read();
	  // echo the character typed
	  Serial.print((char) c); 
	}
	delay(1000);
}
While this isn't the actual codes, but that the character stream "hello world" gets echoed into the keyboard input.
I dug around the codes and don't seem to find the problem, I'm not sure if there could be some variable leaks that causes the tx and rx pointers to be swapped etc. When reviewing the codes, the rx and tx buffers (circular buffer) are separately defined. So it seemed strange that it happened.
I tried turning off terminal echo from my console and verified that that isn't due to terminal echo, i.e. the problem persist even if terminal echo is turned off.

A strange thing is this is not persistent, it happens at the start after reset, but after a while the problem seemed to resolve itself and the output to input echo did not happen.
Last edited by ag123 on Mon Jul 10, 2023 9:38 am, edited 1 time in total.
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by ag123 »

This problem is puzzling and it seemed to be a hardware related issue.

The problem can be resolved by simply defining setup() as

Code: Select all

void setup() {

	while(! Serial);
	
	Serial.begin();
}

void loop() {
	Serial.print("hello world");
	delay(1000);
}
The trouble with the above is that it would stall waiting for a terminal to connect. If that

Code: Select all

while(! Serial);
is removed, characters from the

Code: Select all

Serial.print("hello world");
gets echoed into the input when a terminal monitor connects.
And interestingly, it doesn't repeat and only the 1st line get echoed.

Another fix is

Code: Select all

void loop() {
	if (Serial)
		Serial.print("hello world");
	delay(1000);
}
This works as well but avoids the stall waiting for a terminal monitor to connect.
Last edited by ag123 on Mon Jul 10, 2023 10:22 am, edited 1 time in total.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by stevestrong »

Have you tried without

Code: Select all

Serial.begin();
?
Because that is done during start-up in the core.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by stevestrong »

ag123 wrote: Wed Jul 05, 2023 12:26 pm the character stream "hello world" gets echoed into the keyboard input.
Which board / Bootloader?
Which console app?
Have you tried another console application? I cannot reproduce with Arduino Serial console.
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by ag123 »

I tried putty and minicom, both exhibits the same symptoms.
Then other things I tried is to use usb mon
https://docs.kernel.org/usb/usbmon.html
and I checked the comms for usb cdc acm and verified that the host (i.e. PC) did not send any of the characters 'echoed', rather those are coming from usb 'bulk in' data, which indicates that the 'echoing' is on the device side.

for now lets not worry too much about it.
just that for anyone who see a similar issue, either use

Code: Select all

void setup() {
	while(! Serial);
	...
}
which would wait for a serial terminal to connect.
or

Code: Select all

if(Serial) {
	Serial.println( "bla bla bla" );
}
which would alleviate the problem.
If this is after all due to hardware or initialization, it'd probably not help much tweaking the core codes.
Last edited by ag123 on Mon Jul 10, 2023 10:06 am, edited 1 time in total.
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by ag123 »

stevestrong wrote: Mon Jul 10, 2023 9:29 am Have you tried without

Code: Select all

Serial.begin();
?
Because that is done during start-up in the core.
I tried without that

Code: Select all

Serial.begin();
, didn't work similar behavior

Code: Select all

Vref int (1.2v):1511
temp sensor:1896
mvolt:1505
temp:42.44
Vref int (1.2v):1508
temp sensor:1898
mvolt:1510
temp:43.60
Vref int (1.2v):1508
temp sensor:1898
mvolt:1510
temp:43.60
Vref int (1.2v):1507
temp sensor:1899
mvolt:1512
temp:44.07
Vref int (1.2v)VVref int (1.2v):1506
               ^
temp sensor:1899
mvolt:1513
temp:44.30
rVref int (1.2v):1508
^
temp sensor:1897
mvolt:1509
temp:43.37
efVref int (1.2v):1506
^^
temp sensor:1894
mvolt:1509
temp:43.37
 Vref int (1.2v):1506
^ 
temp sensor:1898
mvolt:1512
temp:44.07
iVref int (1.2v):1508
^
temp sensor:1899
mvolt:1511
temp:43.84
nVref int (1.2v):1509
^
temp sensor:1898
mvolt:1509
temp:43.37
tRTC timestamp: 1970-1-1, 00:00:31
^
last adj:RTC timestamp: 1970-1-1, 00:00:00
init adj:RTC timestamp: 1970-1-1, 00:00:00
drift duration, number of seconds for the stm32 rtc to drift 1 secs (faster):0
BKP_RTCCR:0
Vref int (1.2v):1509
temp sensor:1901
mvolt:1511
temp:43.84
 Vref int (1.2v):1508
^
temp sensor:1897
mvolt:1509
temp:43.37
(Vref int (1.2v):1510
^
temp sensor:1900
mvolt:1509
temp:43.37
the thing is this goes away after a while and it is normal after a while, that "RTC timestamp" is the result of executing the command 't' which prints the current RTC time, that 't' gets 'echoed' into input from previous outputs.

actual source codes is like such (long)

Code: Select all

#include "Arduino.h"
#include <usb_serial.h>
#include "rtadjust.h"
#include <libmaple/usb_cdcacm.h>

/* note that the adjustment functions needs this RTClock
 * if you rename variable rt, update rtadjust.h so that the
 * extern refers to this RTClock*/
RTClock rt(RTCSEL_LSE); // initialise

#define BUFLEN 100
uint8_t ind = 0;
char cmd = 0;
char buf[BUFLEN];
tm_t tm;

enum LineState {
	KEY,
	LINE
} state;

//#define ledPin PC13 //blue pill

//int ledPin = PB1; // LED connected to 'pin' 33 / PB1 on maple mini
int ledPin = PC13; // blue pill
//int ledPin = 6; // LED connected to 'pin' PA5 olimexino
//int ledPin = LED_BUILTIN;

bool issystick = false;
bool print = true;

void checkcmd(void);
void sleep(uint32_t delay);
void processkey();
void showtime();
void synctime(char *buf, int len);
void settime(char *buf, int len);
void calibrate(char *buf, int len);
void setdriftdur(char *buf, int len);
void help();
void clearbuf();
extern "C" void _init(void);

void _init(){};

static void systickhook() {
	issystick = true;
}

void setup() {

	state = LineState::KEY;

	// toggle issystick
	systick_attach_callback(systickhook);

	/* initialise access to backup registers,
	 * this is necessary due to the use of backup registers */
	bkp_init();

	/* adjust rtc */
	adjtime();

	//initialize the digital pin as an output:
	pinMode(ledPin, OUTPUT);

	// test for tone
	//pinMode(PB7, OUTPUT);
	//Serial.begin();

	// vcc / battery pin
//   pinMode(PA3, INPUT_ANALOG);

	// vrefint
	adc_reg_map *regs = ADC1->regs;
	regs->CR2 |= ADC_CR2_TSVREFE;    // enable VREFINT and temp sensor
	regs->SMPR1 = ADC_SMPR1_SMP17;  // sample rate for VREFINT ADC channel

}

//the loop() method runs over and over again, 
//as long as maple has power
void loop() {
	int i;

	for (i = 0; i < 10; i++) {
		digitalWrite(ledPin, HIGH);
		//delay(100);
		sleep(100);
		digitalWrite(ledPin, LOW);
		//delay(100);
		sleep(100);
	}
	checkcmd();
	for (i = 0; i < 10; i++) {
		digitalWrite(ledPin, HIGH);

//    Serial.print("freq:");
//    Serial.print(i*500);
//    Serial.println("hz");
//    tone(PB7,i*500,1000);

		if (print) {

			uint16_t vrefint = adc_read(ADC1, 17);
			Serial.print(F("Vref int (1.2v):"));
			Serial.print(vrefint);
			Serial.println();

			uint16_t vtemp = adc_read(ADC1, 16);
			Serial.print(F("temp sensor:"));
			Serial.print(vtemp);
			Serial.println();

			uint16_t mv = (1200 * vtemp) / vrefint;
			Serial.print(F("mvolt:"));
			Serial.print(mv);
			Serial.println();

			// specs 5.3.19 temp sensor characteristics
			// V 25 deg ~ 1.43v
			// slope 4.3 mv/C
			float temp = (mv - 1430) * 1.0 / 4.3 + 25.0;
			Serial.print(F("temp:"));
			Serial.print(temp);
			Serial.println();

			/*
			 uint16_t vcc = analogRead(PA3);
			 Serial.print(F("Vcc:"));
			 Serial.print(vcc);
			 Serial.println();

			 mv = ( 1200 * vcc ) / vrefint;
			 Serial.print(F("mvolt:"));
			 Serial.print(mv);
			 Serial.println();
			 */

		}

		//delay(1000);
		sleep(1000);
		digitalWrite(ledPin, LOW);
		//delay(1000);
		sleep(1000);
		checkcmd();

	}
}


void checkcmd() {

	if (Serial.available())
		processkey();
}


void processkey() {
	int c = Serial.read();

	//echo the char;
	Serial.print((char) c);
	if( state == LineState::LINE ) {
		if (ind < BUFLEN && c != '\r') {
			if(c == 8 || c == 127 ) // backspace
				ind--;
			else
				buf[ind++] = c; // copy the chars into buf
		} else {
			Serial.println();
			switch(cmd) {
			case 's':
				synctime(buf,ind);
				break;
			case 'T':
				settime(buf,ind);
				break;
			case 'c':
				calibrate(buf,ind);
				break;
			case 'x':
				setdriftdur(buf,ind);
				break;
			default:
				break;
			}
			state = LineState::KEY;
			cmd = 0;
			clearbuf();
		}
	} else {
		switch(c) {
		case 't':
			showtime();
			break;
		case 's':
			state = LineState::LINE;
			clearbuf();
			cmd = 's';
			break;
		case 'T':
			state = LineState::LINE;
			clearbuf();
			cmd = 'T';
			break;
		case 'c':
			state = LineState::LINE;
			clearbuf();
			cmd = 'c';
			break;
		case 'x':
			state = LineState::LINE;
			clearbuf();
			cmd = 'x';
			break;
		case 'p':
			print = ! print;
			break;
		case 'h':
		case 'H':
		case '?':
			help();
			break;
		default:
			break;
		}
	}
}


void showtime() {
    // get and print actual RTC timestamp
    rt.breakTime(rt.now(), tm);
    memset(buf,0,BUFLEN);
    sprintf(buf, "RTC timestamp: %u-%u-%u, %02u:%02u:%02u",
    		tm.year+1970, tm.month, tm.day, tm.hour, tm.minute, tm.second);
    Serial.println(buf);
    clearbuf();

    Serial.print("last adj:");
    rt.breakTime(getbkptime(), tm);
    memset(buf,0,BUFLEN);
    sprintf(buf, "RTC timestamp: %u-%u-%u, %02u:%02u:%02u",
    		tm.year+1970, tm.month, tm.day, tm.hour, tm.minute, tm.second);
    Serial.println(buf);
    clearbuf();

#ifdef INCR_CALIBRATE
    Serial.print("init adj:");
    rt.breakTime(getinitadjtime(), tm);
    memset(buf,0,BUFLEN);
    sprintf(buf, "RTC timestamp: %u-%u-%u, %02u:%02u:%02u",
    		tm.year+1970, tm.month, tm.day, tm.hour, tm.minute, tm.second);
    Serial.println(buf);
    clearbuf();
#endif

    Serial.print(F("drift duration, number of seconds for the stm32 rtc to drift 1 secs (faster):"));
    Serial.println(getdrift());

    Serial.print(F("BKP_RTCCR:"));
    Serial.println(getrtccr());
}

void synctime(char *buf, int len) {
	if (len == BUFLEN) buf[BUFLEN-1] = 0; //terminate the string for safety
	if(parsetimestamp(buf, tm) <0) {
		Serial.println(F("invalid date/time"));
		return;
	}

	time_t time = rt.makeTime(tm);
	/* this call the actual function to set the RTC and update
	 * the last adjusted time simultaneously
	 */
	synctime(time);
}



void calibrate(char *buf, int len) {
	if (len == BUFLEN) buf[BUFLEN-1] = 0; //terminate the string for safety
	if(parsetimestamp(buf, tm) <0) {
		Serial.println(F("invalid date/time"));
		return;
	}

	time_t time = rt.makeTime(tm);

	/* this call the calibratertc() function to calculate
	 * the drift duration
	 */
	calibratertc(time);
}

/*
 * this function sets the rtc directly by-passing all the adjustments
 *
 * note that this function is used during tests to simulate drifts etc
 * hence it is not featured in help();
 *
 * in a normal context use synctime() to set the RTC time so that
 * the last adjustment date/time is updated as well
 */
void settime(char *buf, int len) {
	if (len == BUFLEN) buf[BUFLEN-1] = 0; //terminate the string for safety
	if(parsetimestamp(buf, tm) <0) {
		Serial.println(F("invalid date/time"));
		return;
	}

	rt.setTime(tm);
}

void setdriftdur(char *buf, int len) {
	if (len == BUFLEN) buf[BUFLEN-1] = 0; //terminate the string for safety
	int16_t drift_dur = atoi(buf);
	/* this funciton updates the drift duration directly */
	setbkpdrift(drift_dur);
}

void help() {
	Serial.println(F("h, H, ? - display help, this message"));
	Serial.println(F("t - current time"));
	Serial.println(F("sYYYY-MM-DD HH:MM:SS - sync/set time"));
	Serial.println(F("cYYYY-MM-DD HH:MM:SS - calibrate rtc"));
	Serial.println(F("where YYYY-MM-DD HH:MM_SS - is the current accurate time"));
	Serial.println(F("xnnnn - set the drift duration where nnnn is the drift duration"));
	Serial.println(F("        number of seconds for the stm32 rtc to drift 1 secs (faster)"));
	Serial.println(F("the s, c, x commands needs to end with a carriage return at the end of line"));
	Serial.println();
}

void clearbuf() {
	ind = 0;
	memset(buf,0,BUFLEN);
}


void sleep(uint32_t delay) {

	while(delay > 0) {
		asm("wfi");
		if(issystick) {
			issystick = false;
			delay--;
		}
	}
}
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by ag123 »

stevestrong wrote: Mon Jul 10, 2023 9:32 am
ag123 wrote: Wed Jul 05, 2023 12:26 pm the character stream "hello world" gets echoed into the keyboard input.
Which board / Bootloader?
Which console app?
Have you tried another console application? I cannot reproduce with Arduino Serial console.
board: an old blue pill stm32f103c8
bootloader: the old (but roger's) maple DFU bootloader
for now doubt it is directly related, to test without that would have to go by st-link etc, would try that at a different sitting.
app is mentioned prior and in Linux.
gcc is gcc-arm-none-eabi-8-2018-q4-major
it is uncertain if a different / more recent gcc could have resolved the issue, this is possible and maybe the compile flags I used could affect that as well.
if others don't see a similar issue, maybe it is related to gcc and/or the flags.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by stevestrong »

@ag123
Please do not mix here several issues.
Which is actually the sketch with which you can replicate the issue? Please keep the examples as simple as possible.

And please describe in details how do you proceed, which steps you take and what you see in each step.

Also, how exactly get characters "echoed" in keyboard input? What kind of input do you mean? Where?
Some screenshots whould be helpful.

And finally, have you tried to use Arduino? Does the issue still persist there as well?
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by ag123 »

I managed to reproduce the problem with this sketch

Code: Select all

#include <Arduino.h>

void setup() {

	Serial.begin();

	pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {

	Serial.println("hello world");

	if(Serial.available()) {
		int c = Serial.read();
		Serial.println((char) c);
	}

	digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

	delay(1000);
}
sample output as follows:

Code: Select all

hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello hello world
hhello world
ehello world
lhello world
lhello world
ohello world
 hello world
whello world
ohello world
rhello world
lhello world
dhello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
for the above board is STM32F103C8 blue pill using the generic_stm32f103c variant.
I'm using 'roger's bootloader' maple DFU bootloader
https://github.com/rogerclarkmelbourne/ ... bootloader
using specifially [generic_boot20_pc13.bin](https://github.com/rogerclarkmelbourne/ ... 0_pc13.bin)

below reproduced on maple mini clone STM32F103CB using the maple_mini variant.

Code: Select all

hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
h
hello world
e
hello world
l
hello world
l
hello world
o
hello world

hello world
w
hello world
o
hello world
r
hello world
l
hello world
d
hello world
hello world
hello world
hello world
hello world
the serial monitor is Putty
https://www.chiark.greenend.org.uk/~sgt ... atest.html
and note that the OS environment is Linux
In addition, to reproduce the issue, connect the board e.g. maple mini or blue pill let it run for the 1st few seconds, then run the terminal monitor and connect. That 'few seconds' is normally after connecting, then it takes that little while to search for the app, launch it, selecting the menus and connect (no need to rush with this).

Note however that I'm using a makefile
viewtopic.php?t=37
there is a bunch of flags I'm using and it is mostly in the makeffile

and it isn't arduino IDE that builds the bin file.
gcc is old:
gcc-arm-none-eabi-8-2018-q4-major

the bulid output summary using the makefile looks like this

Code: Select all

   text	   data	    bss	    dec	    hex	filename
  12088	   1176	   1032	  14296	   37d8	bin/maple_mini.elf

-rwxr-xr-x 1 andrew users 13264 Jul 12 23:18 bin/maple_mini.bin

bin/maple_mini.elf:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00002ba4  08002000  08002000  00002000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .text.align   00000004  08004ba4  08004ba4  00004ba4  2**0
                  ALLOC, CODE
  2 .ARM.exidx    00000008  08004ba8  08004ba8  00004ba8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .data         00000498  20000000  08004bb0  00010000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .rodata       00000388  08005048  08005048  00015048  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .bss          00000408  20000498  20000498  00020498  2**2
                  ALLOC
  6 .debug_aranges 00001208  00000000  00000000  000153d0  2**3
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_info   00005602  00000000  00000000  000165d8  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_abbrev 00002267  00000000  00000000  0001bbda  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_line   00007932  00000000  00000000  0001de41  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_frame  00002994  00000000  00000000  00025774  2**2
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_str    0000390e  00000000  00000000  00028108  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .ARM.attributes 0000002b  00000000  00000000  0002ba16  2**0
                  CONTENTS, READONLY
 13 .debug_ranges 00001d80  00000000  00000000  0002ba41  2**0
                  CONTENTS, READONLY, DEBUGGING
 14 .comment      00000075  00000000  00000000  0002d7c1  2**0
                  CONTENTS, READONLY

Source dirs
src
./STM32F1/cores/maple
./STM32F1/variants/maple_mini

src/
src/rtc/
src/spi/
src/spiflash/
./STM32F1/cores/maple/
./STM32F1/cores/maple/avr/
./STM32F1/cores/maple/libmaple/
./STM32F1/cores/maple/libmaple/stm32f1/performance/
./STM32F1/cores/maple/libmaple/usb/stm32f1/
./STM32F1/cores/maple/libmaple/usb/usb_lib/
./STM32F1/cores/maple/stm32f1/
./STM32F1/variants/maple_mini/
./STM32F1/variants/maple_mini/wirish/

Includes
-ISTM32F1/cores/maple/
-ISTM32F1/system/libmaple/
-ISTM32F1/system/libmaple/include/
-ISTM32F1/system/libmaple/stm32f1/include
-ISTM32F1/system/libmaple/stm32f1/include/series/
-ISTM32F1/system/libmaple/usb/stm32f1/
-ISTM32F1/system/libmaple/usb/usb_lib/
-ISTM32F1/variants/maple_mini/
-Isrc/rtc/
-Isrc/spi/
-Isrc/spiflash/

Defines
-DMCU_STM32F103CB
-D__STM32F1__
-DVECT_TAB_ADDR=0x8002000
-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG
-DDEBUG_LEVEL=DEBUG_NONE
-DF_CPU=72000000L
-DSERIAL_USB
-DUSB_VID=0x1EAF
-DUSB_PID=0x0004
-DUSB_MANUFACTURER="Unknown"
-DSPI_HAS_TRANSACTION
the codes for STM32F1 folder is from a recent clone from github on 5 July 2023.
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: USB Serial echos characters into the input (i.e. keyboard)

Post by ag123 »

I've not tried re-doing this in Arduino (Gui) yet. It is possibly related to the custom compile.
Like you mentioned, at this point, it can't be deemed a 'bug' (or better 'feature' :D ) yet unless practically everyone can reproduce that 'feature'.
it is a little puzzling, if amusing, but that it can be *resolved* by simply checking for

Code: Select all

void setup() {
	while( ! Serial );
}
which blocks waiting for the serial terminal to connect, some apps may literally want this behavior.

and in other cases

Code: Select all

void loop() {
	if( Serial ) Serial.print("bla bla bla");
}
That fixes the problem as we don't have a 'before initialization' , 'after initialization' (i.e. that Serial variable) issue.
The feeling is that something changed the moment the serial terminal (i.e. app / software) from the host connect, because the device (blue pill or maple mini) is blinking away, connected via usb even prior the serial terminal connecting. And that practically, it happens for one of the

Code: Select all

Serial.println("hello world");
instance at the point the terminal app connects.

it can't be ruled out that there may be a problem with usb on my pc, quite old several years aged. For now, this 'symptom' is basically occurring as described in the last comment.
Post Reply

Return to “General discussion”