Rs485 Support in Pxa255

RS485: Inappropriate ioctl for device

As mentioned in the comment by @Richard Chambers you are using the structure uninitialised. You should do

struct serial_rs485 rs485conf = {0};

However, as discussed that didn't solve the problem.

Quoting from the Kernel document you referenced

Some CPUs/UARTs (e.g., Atmel AT91 or 16C950 UART) contain a built-in
half-duplex mode capable of automatically controlling line direction by
toggling RTS or DTR signals. That can be used to control external
half-duplex hardware like an RS485 transceiver...

However this device has a dedicated pin called TXDEN for that. Quoting from the Data sheet section 4.3.3

With RS485, the transmitter
is only enabled when a character is being transmitted from the UART. The TXDEN pins on the FT4232H are
provided for exactly that purpose, and so the transmitter enables are wired to the TXDEN

and you can see that the RS232 outputs RTS / DTR not connected in RS485, this is in contrast to devices where RTS becomes TXDEN which would require an intervention by the driver.

If we pick apart struct serial_rs485 we can see that it is mostly about controlling RTS for this purpose. Since this device has a dedicated TXDEN pin, those control fields are irrelevant.

Another flag that is used in this structure:

  /* Set this flag if you want to receive data even whilst sending data */
rs485conf.flags |= SER_RS485_RX_DURING_TX;

And yes looking at the circuit, what you put out on the line you will also receive. Looks like you cannot turn that off. RS485 is multidrop, so you should be filtering out messages that were not addressed to you anyway. The fact that some of those messages may have originated from you doesn't matter.

Finally (and firstly) we have this

/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;

That's really saying "enable all the RS485-specific stuff that's controlled by this structure". Except that we've just made all that stuff irrelevant, so enabling it has no effect.

This is why the ioctl is not implemented for that UART.

You have a number of options, these are just suggestions so pick what suits you

  • Delete this section of the initializtion code as it's not needed
  • Compile it conditionally #if RS485_IOCTLS
  • Run it conditionally
  • Treat that errno value ENOTTY as indicating that, in this context the ioctl was not required and you can in fact proceed as if there was no error

Windows XP embedded - RS485 problems

RTS_CONTROL_TOGGLE does not work (has a variable 1-15 millisecond delay before turning it off after transmit) on our embedded XP platform. It's possible I could get that down if I altered the time quantum to 1 ms using timeBeginPeriod(1), etc, but I doubt it would be reliable or enough to matter. (The device responds @ 1 millisecond sometimes)

The final solution is really ugly but it works on this hardware. I would not use it on anything where the hardware is not fixed in stone.

Basically:

1) set the FIFOs on the serial port's device manager page to off or 1 character deep

2) send your message + 2 extra bytes using this code:

int WriteFile485(HANDLE hPort, void* pvBuffer, DWORD iLength, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped)
{
int iOldClass = GetPriorityClass(GetCurrentProcess());
int iOldPriority = GetThreadPriority(GetCurrentThread());
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

EscapeCommFunction(hPort, SETRTS);

BOOL bRet = WriteFile(hPort, pvBuffer, iLength, pdwWritten, lpOverlapped);

EscapeCommFunction(hPort, CLRRTS);

SetPriorityClass(GetCurrentProcess(), iOldClass);
SetThreadPriority(GetCurrentThread(), iOldPriority);

return bRet;
}

The WriteFile() returns when the last byte or two have been written to the serial port. They have NOT gone out the port yet, thus the need to send 2 extra bytes. One or both of them will get trashed when you do CLRRTS.

Like I said... it's ugly.

Find two consecutive rows

Assuming the rows have sequential IDs, something like this may be what you're looking for:

select top 1 * 
from
Bills b1
inner join Bills b2 on b1.id = b2.id - 1
where
b1.IsEstimate = 1 and b2.IsEstimate = 1
order by
b1.BillDate desc


Related Topics



Leave a reply



Submit