Re: [PATCH 1/2] tty: add bits to manage multidrop mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 04/21/17 00:14, Stuart Longland wrote:
On 21/04/17 02:17, Rodolfo Giometti wrote:
AFAIK the multidrop mode is supported also by Freescale (IMX6 and maybe
IMX7) even if by using directly 9 bits transmission. The SENDA trick
(that is autogically sending the next first byte as an address while the
following ones as data) is Atmel specific. Atmel solution is really
smart (even if limited to 1 byte addresses long) because it allows
developers to send a message without any delay between the address and
the data bytes.

I've seen similar features on the NXP LPC81x series of microcontrollers.

http://www.nxp.com/documents/user_manual/UM10601.pdf page 187 onwards
covers the USART for these chips.  The data register is natively 32-bits
wide, so can accommodate the 9th bit easily.

On Atmel AVR, I've also seen it, there the 9th bit is held in a separate
register from what I recall, don't have a datasheet in front of me to
look it up.

Yes, Atmel CPUs can handle multidrop in two manners: the first one is by using the 9bits transmission while the second is by using the SENDA bit. The latter is obviously less versatile and less general then the former but it really better fits into actual Linux TTY subsystem.

The 9-bit mode sounded like a good idea, and I thought of how to
possibly implement it, but then I had to contend with where would I put
the extra bit in an 8-bit byte?

This is exactly the problem I notice in adding multidrop support in Linux trying to avoid the two calls of the tcsetattr() function which introduce a delay between the address and data bytes.

Given its use as an address, maybe one option is if the kernel could
have a small table of address bytes/masks that it could watch for on
receive and the ability to set a "preamble" to prepend to packets.  Sort
of like subnets in IP; only the mask can be any arrangement of bits.

Supposing we had a userspace program that communicated on RS-485 and
used two bytes for addressing; one being the destination address and the
other being a command.

In that way, the userspace program can tell the kernel:

- Preamble length: 2 bytes
- MSB denotes preamble byte
- Ignore all received packets except those starting with 0x0000 (mask
0xff00) and 0x1200 (mask 0xff00)
- For all future frames, send preamble 0x12ff

IF the kernel driver hears:
  [1] 0100 0111  [1] 0001 0110  [0] 0011 0000 …

it'll ignore the frame until it sees another byte with an initial MSB,
because 0x4716 & 0xff00 ≠ 0x1200.

If it hears:
  [1] 0001 0010  [1] 0001 0110  [0] 0011 0000 …
we pass the preamble and any subsequent non-preamble bytes to userspace
(minus MSBs).  Perhaps we can have an IOCTL call or something that can
tell the userspace before a read how many bytes are part of the preamble.

In the Atmel example above, the driver can use the SENDA feature if the
preamble length is 1 byte.

Food for thought?

IMHO the best solution would be using 9bits transmission (CS9 define):

	term.c_cflag &= ~CSIZE;
	term.c_cflag |= CS9;
        ret = tcsetattr(fd, TCSADRAIN, &term);
        ...

        /* Write data */
        n = 0;
        buf[n++] = 0x100;
        buf[n++] = 0x01c;
        buf[n++] = 0x001;
        buf[n++] = 0x001;
        buf[n++] = 0x000;
        buf[n++] = 0x001;
        buf[n++] = 0x0de;
        buf[n++] = 0x0d4;
        ret = writen(fd, buf, 2*n);
        ...

However doing something like this will require huge modifications into Linux TTY subsystem. Then my solution tries to keep it simple just still using 8bits transmission but adding a system call to define how many address bytes we have into next message:

         /* Transmission: enable parity multidrop */
        term.c_cflag |= PARENB | CMSPAR | PARMD;
        ret = tcsetattr(fd, TCSADRAIN, &term);
	...

	mdrop.addr_len = 1;
	ret = ioctl(fd, TCSSENDA, &mdrop);
	...

        /* Write data */
        n = 0;
        buf[n++] = 0x00;
        buf[n++] = 0x1c;
        buf[n++] = 0x01;
        buf[n++] = 0x01;
        buf[n++] = 0x00;
        buf[n++] = 0x01;
        buf[n++] = 0xde;
        buf[n++] = 0xd4;
        ret = writen(fd, buf, n);
	...

[Note that Atmel CPUs support only 1 byte for address length]

Since multidrop is used with RS485 we can think to add all these stuff into TIOCSRS485 ioctl() as below:

        rs485conf.flags |= SER_MULTIDROP_ENABLED;
        rs485conf.delay_rts_after_send = 0;

        ret = ioctl(fd, TIOCSRS485, &rs485conf);
	...

However we still need and ioctl() command to state when new address bytes should be sent in the data stream...

We can use different solutions but the real problem is avoiding a delay between the address and data bytes and to do so we must find a way to completely support 9 bits transmission or tricks as the SENDA bit.

Ciao,

Rodolfo

--

HCE Engineering                      e-mail: giometti@xxxxxxxxxxxxxxxxxxx
GNU/Linux Solutions                          giometti@xxxxxxxxxxxx
Linux Device Driver                          giometti@xxxxxxxx
Embedded Systems                     phone:  +39 349 2432127
UNIX programming                     skype:  rodolfo.giometti
Cosino Project - the quick prototyping embedded system - www.cosino.io
Freelance ICT Italia - Consulente ICT Italia - www.consulenti-ict.it
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux