Attempt fix some UART timeouts, should also allow lower devices to be detected.
This commit is contained in:
parent
ba37313cb8
commit
53c8917353
1 changed files with 36 additions and 20 deletions
|
@ -32,11 +32,11 @@ typedef struct {
|
||||||
term_info tiNew; // Terminal info during the transaction
|
term_info tiNew; // Terminal info during the transaction
|
||||||
} serial_port_unix;
|
} serial_port_unix;
|
||||||
|
|
||||||
// timeval struct that define timeout delay for serial port
|
// timeval struct that define timeout delay for serial port:
|
||||||
static struct timeval default_timeout = {
|
// first is constant and currently related to PN53x response delay
|
||||||
.tv_sec = 0, // 0 second
|
static const unsigned long int uiTimeoutStatic = 15000; // 15 ms to allow device to respond
|
||||||
.tv_usec = 60000 // 60 ms
|
// second is a per-byte timeout (sets when setting baudrate)
|
||||||
};
|
static unsigned long int uiTimeoutPerByte = 0;
|
||||||
|
|
||||||
// Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
|
// Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
|
||||||
# define CCLAIMED 0x80000000
|
# define CCLAIMED 0x80000000
|
||||||
|
@ -84,15 +84,25 @@ uart_open (const char *pcPortName)
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Remove PN53x related timeout
|
/**
|
||||||
#define UART_TIMEOUT(X) ((X * 7) + 15000) // where X is 1-byte duration (µs): X * 6+1 bytes (PN53x's ACK + 1 other chance) + 15 ms (PN532 Tmax to reply ACK)
|
* @note This define convert a Baud rate in a per-byte duration (in µs)
|
||||||
// UART_SPEED_T0_TIME(X) convert baud rate to interval between 2 bytes (in us)
|
* Bauds are "symbols per second", so each symbol is bit here.
|
||||||
#define UART_SPEED_T0_TIME(X) ((1000000 * 9)/ X) // 8,n,1 => 9 bits => data rate ~= bauds/9 (bytes/s); ex: 8N1@9600 ~= 1066 bytes/s
|
* We want to convert Bd to bytes/s in first time,
|
||||||
|
* 1 serial-transmitted byte is (in 8N1):
|
||||||
|
* - 1 start bit,
|
||||||
|
* - 8 data bits,
|
||||||
|
* - 1 stop bit.
|
||||||
|
*
|
||||||
|
* In 8N1 mode, byte-rate = baud-rate / 10
|
||||||
|
*/
|
||||||
|
#define UART_BAUDRATE_T0_BYTE_DURATION(X) ((1000000 * 10)/ X)
|
||||||
|
|
||||||
void
|
void
|
||||||
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
||||||
{
|
{
|
||||||
long int iTimeout = UART_TIMEOUT(UART_SPEED_T0_TIME(uiPortSpeed));
|
// Set per-byte timeout
|
||||||
DBG ("Serial port speed requested to be set to %d bauds (%ld µs).", uiPortSpeed, iTimeout);
|
uiTimeoutPerByte = UART_BAUDRATE_T0_BYTE_DURATION(uiPortSpeed);
|
||||||
|
DBG ("Serial port speed requested to be set to %d bauds (%lu µs).", uiPortSpeed, uiTimeoutPerByte);
|
||||||
const serial_port_unix *spu = (serial_port_unix *) sp;
|
const serial_port_unix *spu = (serial_port_unix *) sp;
|
||||||
|
|
||||||
// Portability note: on some systems, B9600 != 9600 so we have to do
|
// Portability note: on some systems, B9600 != 9600 so we have to do
|
||||||
|
@ -133,8 +143,6 @@ uart_set_speed (serial_port sp, const uint32_t uiPortSpeed)
|
||||||
uiPortSpeed);
|
uiPortSpeed);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// Set default timeout
|
|
||||||
default_timeout.tv_usec = iTimeout;
|
|
||||||
|
|
||||||
// Set port speed (Input and Output)
|
// Set port speed (Input and Output)
|
||||||
cfsetispeed ((struct termios *) &(spu->tiNew), stPortSpeed);
|
cfsetispeed ((struct termios *) &(spu->tiNew), stPortSpeed);
|
||||||
|
@ -205,16 +213,21 @@ uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
|
||||||
int res;
|
int res;
|
||||||
int byteCount;
|
int byteCount;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
|
||||||
|
int iExpectedByteCount = (int)*pszRx;
|
||||||
|
struct timeval tvTimeout = {
|
||||||
|
.tv_sec = 0,
|
||||||
|
.tv_usec = uiTimeoutStatic + (uiTimeoutPerByte * iExpectedByteCount),
|
||||||
|
};
|
||||||
|
struct timeval tv = tvTimeout;
|
||||||
|
|
||||||
// Reset the output count
|
// Reset the output count
|
||||||
*pszRx = 0;
|
*pszRx = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
DBG( "Expecting %d bytes (in %lu µs)", iExpectedByteCount, tv.tv_usec );
|
||||||
// Reset file descriptor
|
// Reset file descriptor
|
||||||
FD_ZERO (&rfds);
|
FD_ZERO (&rfds);
|
||||||
FD_SET (((serial_port_unix *) sp)->fd, &rfds);
|
FD_SET (((serial_port_unix *) sp)->fd, &rfds);
|
||||||
tv = default_timeout;
|
|
||||||
res = select (((serial_port_unix *) sp)->fd + 1, &rfds, NULL, NULL, &tv);
|
res = select (((serial_port_unix *) sp)->fd + 1, &rfds, NULL, NULL, &tv);
|
||||||
|
|
||||||
// Read error
|
// Read error
|
||||||
|
@ -226,7 +239,7 @@ uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (*pszRx == 0) {
|
if (*pszRx == 0) {
|
||||||
// Error, we received no data
|
// Error, we received no data
|
||||||
DBG ("RX time-out (%ld µs), buffer empty.", default_timeout.tv_usec);
|
DBG ("RX time-out (%lu µs), buffer empty.", tvTimeout.tv_usec);
|
||||||
return DETIMEOUT;
|
return DETIMEOUT;
|
||||||
} else {
|
} else {
|
||||||
// We received some data, but nothing more is available
|
// We received some data, but nothing more is available
|
||||||
|
@ -240,6 +253,7 @@ uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
|
||||||
}
|
}
|
||||||
// There is something available, read the data
|
// There is something available, read the data
|
||||||
res = read (((serial_port_unix *) sp)->fd, pbtRx + (*pszRx), byteCount);
|
res = read (((serial_port_unix *) sp)->fd, pbtRx + (*pszRx), byteCount);
|
||||||
|
iExpectedByteCount -= byteCount;
|
||||||
|
|
||||||
// Stop if the OS has some troubles reading the data
|
// Stop if the OS has some troubles reading the data
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
|
@ -247,8 +261,9 @@ uart_receive (serial_port sp, byte_t * pbtRx, size_t * pszRx)
|
||||||
}
|
}
|
||||||
|
|
||||||
*pszRx += res;
|
*pszRx += res;
|
||||||
|
DBG( "Remaining %d bytes (%lu µs remains in tv)", iExpectedByteCount, tv.tv_usec );
|
||||||
} while (byteCount);
|
tv.tv_usec = uiTimeoutPerByte * (iExpectedByteCount>16?16:iExpectedByteCount) ;
|
||||||
|
} while (byteCount && (iExpectedByteCount > 0));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -265,12 +280,13 @@ uart_send (serial_port sp, const byte_t * pbtTx, const size_t szTx)
|
||||||
size_t szPos = 0;
|
size_t szPos = 0;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
const struct timeval tvDefault = { .tv_sec = 0, .tv_usec = 20000 };
|
||||||
|
|
||||||
while (szPos < szTx) {
|
while (szPos < szTx) {
|
||||||
// Reset file descriptor
|
// Reset file descriptor
|
||||||
FD_ZERO (&rfds);
|
FD_ZERO (&rfds);
|
||||||
FD_SET (((serial_port_unix *) sp)->fd, &rfds);
|
FD_SET (((serial_port_unix *) sp)->fd, &rfds);
|
||||||
tv = default_timeout;
|
tv = tvDefault;
|
||||||
res = select (((serial_port_unix *) sp)->fd + 1, NULL, &rfds, NULL, &tv);
|
res = select (((serial_port_unix *) sp)->fd + 1, NULL, &rfds, NULL, &tv);
|
||||||
|
|
||||||
// Write error
|
// Write error
|
||||||
|
|
Loading…
Add table
Reference in a new issue