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

stdin over USB not responding #699

Closed
aleopardstail opened this issue Jan 4, 2022 · 11 comments
Closed

stdin over USB not responding #699

aleopardstail opened this issue Jan 4, 2022 · 11 comments

Comments

@aleopardstail
Copy link

Have written some code to communicate over the USB serial link, I can send data by writing to stdout using putc(), fwrite() etc, that works. However I have been unable to read data from the serial input using any of the following calls:

  • getc() - this stalls and never returns
  • getc_timeout_us() - this returns '-1' after the timeout interval
  • fread()

to check it wasn't my code I modified the cmake file for the uart_advanced example and rebuilt that, with the same result - the Pi Pico never sees or responds to input - this trying to talk to a Pi400 over Minicom and a Windows 10 PC using PuTTY as well as a C# test programme that confirms data is being sent - connecting that same application to a test Arduino using the same leads indicates data is being sent, just not seen

modified example files attached, is there some further incantation required?

CMakeLists.txt
uart_advanced.c.txt

@kilograham
Copy link
Contributor

Modifying uart_advanced for USB makes no sense... it deals with UART h/w not stdio.

maybe share your actual example.

r u using the latest SDK version?

@aleopardstail
Copy link
Author

modified that one as the other serial examples only sent stuff out, not read it back, I can write to stdout fine, just not read from stdin with getc() etc.
KerbalSimpit_PiPico.cpp.txt

how do I find out what SDK version I have?

actual files being used attached, they also talk to a file for an ILI9341 driver (hence the name)

configuration routine:
[code]
KerbalSimpit::KerbalSimpit(uart_inst_t* uart_id, uint tx_pin, uint rx_pin, uint baudrate)
{
// configure the serial port
_port = uart_id;
_baudrate = baudrate;
_tx_pin = tx_pin;
_rx_pin = rx_pin;

stdio_init_all();
uart_init(_port, _baudrate);

gpio_set_function(_tx_pin, GPIO_FUNC_UART);
gpio_set_function(_rx_pin, GPIO_FUNC_UART);

}
[/code]

the function trying to read is

[code]
uint KerbalSimpit::init(ILI9341 *tft)
{

// First, empty the receiving buffer to avoid looking into it looking for the SYNACK
while (getchar_timeout_us(0) != PICO_ERROR_TIMEOUT)
{
	//uint8_t ch = uart_getc(_port);
}

// Format and send a SYN packet
_outboundBuffer[0] = 0x00;
uint8_t i;
for (i=0; i<sizeof(KERBALSIMPIT_VERSION); i++) 
{
	_outboundBuffer[i+1] = KERBALSIMPIT_VERSION[i];
}
i++;
_receiveState = WaitingFirstByte;

_send(0x00, _outboundBuffer, i); // Send SYN

// Read all the bytes available and look for the SYNACK
//while(uart_is_readable(_port))
int c = getchar_timeout_us(10000);			// should grab a character, waiting up to 100us, returns PICO_ERROR_TIMEOUT if none

char Buffer[40] = {0};
sprintf(Buffer, "%d", c);
tft->drawFilledRectangle(0,8,20,8, 0xFFFF);	// clear previous
tft->drawString(0,8 - tft->getFontHeight(tft->getFont()), tft->getColour(0, 0, 0),Buffer);
tft->display();

while (c != PICO_ERROR_TIMEOUT)
{
	uint8_t B[40];
	uint8_t msgSize;
	uint8_t msgType;
	
	fread(B, 1, 1, stdin);
	
	if (B[0] == 0xAA)		// 1st byte of header
	{
		while(!uart_is_readable(_port)) {}
		fread(B, 1, 1, stdin);
		
		if (B[0] == 0x50)	// 2nd byte of header
		{
			while(!uart_is_readable(_port)) {}
			fread(B, 1, 1, stdin);
			
			msgSize = B[0];		// read message size
			
			while(!uart_is_readable(_port)) {}
			fread(B, 1, 1, stdin);
			
			msgType = B[0];		// read message type
			
			fread(B, 1, msgSize, stdin);	// read the rest of the message
			
			if (B[0] == 0x01)
			{
				_outboundBuffer[0] = 0x02;
				_send(0x00, _outboundBuffer, i); // Send ACK
				
				return 0;
			}
		}
	}
}

return -1;

}
[/code]

all I get is the port timeout response, have tried a few other bits that just work with the serial port, literally read in, echo back, they can write out but nothing when reading in

[CMakeLists.txt](h
KerbalSimpit_PiPico.h.txt
ttps://github.com/raspberrypi/pico-sdk/files/7815902/CMakeLists.txt)
myILI9341_test.cpp.txt

@kilograham
Copy link
Contributor

kilograham commented Jan 5, 2022

If you are using USB then you should not be using any uart_ calls

you have a 10ms timeout waiting for the first character. i'm not surprised that is timing out (especially if the USB connection hasn't been established - which takes a moment)

you can set compile defintion PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS=1000 in your CMakeLists.txt to wait for one second (or set it to 0 to wait indefinitely) for a USB connection to be established before stdio_init_allreturns or check stdio_usb_connected() function

@aleopardstail
Copy link
Author

code calls my init() routine over and over with a second delay so if it catches nothing the first time it should get it the second time around. have added a 1s delay though after the stdio_init_all which seems to be working

if you can't use the uart_is_readable() call how do you check if there is something waiting to be read? or indeed how much is sat in the buffer? or is this just a case of using getc() (or the timeout version) and managing a buffer myself?

I do now seem to be getting something back, so need to investigate further this side now

it may be worth adapting the "hello world" example to make it clearer that changing from uart to usb is a bit more than changing the cmake file though as the implication is this is all you need to do and then uart0 talks to the usb serial interface which is pretty obviously not true - does this mean that uart0 is still available to use as well as the usb serial port?

many thanks

@lurch
Copy link
Contributor

lurch commented Jan 6, 2022

does this mean that uart0 is still available to use as well as the usb serial port?

Correct - uart0 (and uart1) and the usb serial port are all independent, and the stdio support in pico-sdk allows stdio to be configured over just uart0, over just the usb serial port, or over both at the same time. See Chapter 4 in https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

@FilipDominec
Copy link

FilipDominec commented Jan 18, 2022

Just a tip. This solution for receiving data over USB seems quite elegant and 100% reliable: https://github.com/MrYsLab/Telemetrix4RpiPico/blob/master/Telemetrix4RpiPico.c#L795 It requires periodic polling (no IRQ), but this is not a big problem.

Perhaps a minimalistic listener-responder reference implementation could be added to https://github.com/raspberrypi/pico-examples/tree/master/usb/device

@aleopardstail
Copy link
Author

have had a quick look and I like that method, have the thing responding reliably now, works around a few other issues too - though for what I need a system that could wait for "x" bytes in the buffer (ala Arduino Serial.available()) would be nice, since we don't have that its read byte by byte to build the packet then act on it when completed to avoid blocking. in effect read the bytes with no timeout and just fall through if nothing there.

do agree a full, if basic, two way example would be useful - specifically showing the initialisation steps

@lurch
Copy link
Contributor

lurch commented Jan 21, 2022

BTW I just noticed your previous comment:

changing from uart to usb is a bit more than changing the cmake file though as the implication is this is all you need to do

That is the case - compare https://github.com/raspberrypi/pico-examples/blob/master/hello_world/serial/hello_serial.c to https://github.com/raspberrypi/pico-examples/blob/master/hello_world/usb/hello_usb.c 😃

@aleopardstail
Copy link
Author

except the code that talks to the uart hardware does not remap, which was the case of the problem as thats not clear

what gets remapped is stdin & stdout, which if accessed via those funtions is fine but the docs imply you are remapping the serial port, which you are not

I've got it working now but I have to say an example of reading & writing binary data to both would be quite useful - I started with those exact examples and the code to talk to the uart..

@lurch
Copy link
Contributor

lurch commented Jan 21, 2022

but the docs imply you are remapping the serial port, which you are not

Please open an issue at https://github.com/raspberrypi/pico-feedback/issues detailing exactly which parts of the documentation you found confusing/misleading.

@kilograham
Copy link
Contributor

closing this as i'm still confused why this mentions USB and deals with UART, however see #918 for a USB getchar() related fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants