Sida 1 av 1

Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 14:41:09
av Marta
När något skrivs med write(serieport, &data, #bytes); så antar jag att data först läggs i en buffer, innan den sänds och att write() återvänder i princip omedelbart.

Finns det något sätt att få sändningen att starta direkt, utan att vänta på mer data, samt att veta när allt är sänt? Programmet körs på en RPi 0W. När allt är sänt skall porten switchas via GPIO och en extern grind. Det blir segt av att vänta så sändningen säkert har skett.

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 14:44:01
av AndLi
Det låter som du vill göra ungefär det som en del RS485 implementationer gör för att switcha riktning på drivaren. Implementeras ofta i kärndrivrutinen för serieporten.
Skulle inte bli förvånad om det finns någon som patchat in ett sådant stöd för RPi 0W

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 14:46:50
av hawkan
Något i stil med att sätta porten i raw mode och läsa/skriva byte efter byte?

Edit
Annars är det vanligt att ställa in porten i rätt mode, och ha en select() som lyssnar på fil-numret om det finns data färdigt eller om det är möjligt att skicka.

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 15:39:40
av MiaM
Det kanske vore bra att lägga till vilket OS du eventuellt kör, eller om du kör direkt på hårdvaran? (Det kanske är underförstått av funktionsnamnet att det är Linux, eller?)

Tänker att det här är väl ett typiskt fall där man antagligen helt enkelt vill göra något som slår av multitaskingen och sen gå direkt på hårdvaran från userapplikationen ifall man inte är sugen på att ev peta på kärnan (förutsatt att kärnan inte redan fixar detta). Vet inte i vilken mån det ens går i Linux. (Som jämförelse så på en Amiga så finns paren Disable()/Enable() och Forbid()/Permit(), där ena varianten enbart slår av task schedulern och den andra slår av alla hårdvaruinterrupter.

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 15:57:33
av Marta
Det är givetvis Linux och jag vill inte rota med hårdvaran direct. Det är för övrigt Broadcom, så dokumentation är förmodligen obefintlig för vanligt folk.

Hade hoppats där skulle finnas en eller flera i kombination IOCTL e.dyl. som kan användas för att antingen direkt skicka tecken för tecken, eller ännu hellre starta sändning och blocka tills sändning är klar.

Det är seriell ut som skall kunna växlas att antingen sända till en PIC på samma kort, eller en utgång till något vid sidan av kortet.

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 16:14:37
av rvl
Går det att sparka igång omedelbar buffertömning med flush? Allt är ju filer i unix...

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 17:01:36
av Marta
Den enda flush jag hittat innebär att droppa buffrarna. tcflush med olika parametrar, dock ingen för omedelbar sändning.
Fast det kanske bara är vid USB som den väntar? inns ju ingen anledning till det när det är en vanlig serieport.
I å fall återstår "bara" att veta när den sänt färdigt.

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 17:48:28
av ie
Nu var det länge sen jag skrev den här koden, men jag tror att det gör det du vill. Körs på RPI. Inte så väl dokumenterat, men kan kanske ge dig tips på vad du ska leta efter.

Kod: Markera allt

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>

FILE *uart_linux_str;

/* Use this variable to remember original terminal attributes. */
struct termios saved_attributes;

/* Set the O_NONBLOCK flag of desc if value is nonzero,
or clear the flag if value is 0.
Return 0 on success, or -1 on error with errno set. */
int set_nonblock_flag (int desc, int value)
{
	int oldflags = fcntl(desc, F_GETFL, 0);

	/* If reading the flags failed, return error indication now. */
	if (oldflags == -1)
		return -1;

	/* Set just the flag we want to set. */
	if (value != 0)
		oldflags |= O_NONBLOCK;
	else
		oldflags &= ~O_NONBLOCK;

	/* Store modified flag word in the descriptor. */
	return fcntl (desc, F_SETFL, oldflags);
}

int uart_linux_init(void)
{
	int uart_linux_str_fd;
	struct termios tattr;
	
	if (!(uart_linux_str = fopen("/dev/ttyAMA0","w+b")))
	{
		fputs("Error can't create uart_linux stream\n",stderr);
		return -1;
	}	

	uart_linux_str_fd = fileno(uart_linux_str);
	set_nonblock_flag (uart_linux_str_fd,1);
	tcgetattr(uart_linux_str_fd, &tattr);
	cfmakeraw(&tattr);
	cfsetospeed(&tattr,B9600);
	tcsetattr(uart_linux_str_fd, TCSAFLUSH, &tattr);
	
	return 0;
}

Re: Exakt kontroll av serieport i gcc?

Postat: 19 september 2023, 20:55:52
av MiaM
Den här frågan verkar ta upp delvis samma sak. Ett av svaren länkar vidare till vad som antagligen är en bra guide också.

https://stackoverflow.com/questions/322 ... -is-called