Difference between revisions of "Xenomai RTSerial"
(17 intermediate revisions by one other user not shown) | |||
Line 24: | Line 24: | ||
<!-- /*********************************************************************************************************/ --> | <!-- /*********************************************************************************************************/ --> | ||
{{:Templateimpl:using | initials=MW | title=Xenomai RTSerial | desc=Xenomai RTSerial | project=OE 5.0 }} | {{:Templateimpl:using | initials=MW | title=Xenomai RTSerial | desc=Xenomai RTSerial | project=OE 5.0 }} | ||
− | Given the RTDM serial port driver | + | Given the RTDM serial port driver exists and is loaded for the target on hand, it will provide device nodes at <code>/dev/rtdm/rtserX</code> where X is replaced by the number of each port. |
− | + | The device nodes are then accessed to configured and communicate the underlying serial ports. The following subsections will outline loading the driver, configuring the port, and performing basic serial transactions. | |
=== Loading the driver === | === Loading the driver === | ||
− | Typically there will be a Linux kernel driver associated with the port. If desired device is associated with a Linux driver the driver must be unloaded or the device must be unbound from the driver. Below are examples of loading the RTDM driver for some supported targets. | + | Typically there will be a Linux kernel driver associated with the serial port by default. If the desired device is associated with a Linux driver the driver must be unloaded or the device must be unbound from the driver. Below are examples of loading the RTDM driver for some supported targets. |
==== x86 16550A ==== | ==== x86 16550A ==== | ||
==== iMX6 rt_imx_uart ==== | ==== iMX6 rt_imx_uart ==== | ||
+ | <syntaxhighlight lang="console"> | ||
+ | root@somimx6-xenomai:~# echo 2020000.serial > /sys/bus/platform/drivers/imx-uart/unbind | ||
+ | root@somimx6-xenomai:~# echo 21e8000.serial > /sys/bus/platform/drivers/imx-uart/unbind | ||
+ | root@somimx6-xenomai:~# modprobe xeno_imx_uart | ||
+ | root@somimx6-xenomai:~# dmesg | tail | ||
+ | . | ||
+ | . | ||
+ | [ 462.425158] console [ttymxc1] disabled | ||
+ | [ 528.025034] rtser0 on IMX UART0: membase=0xc0c10000 irq=58 uartclk=80000000 | ||
+ | [ 528.025700] rtser1 on IMX UART1: membase=0xc0c18000 irq=59 uartclk=80000000 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== AT91 atmel_rt_serial ==== | ||
+ | <syntaxhighlight lang="console"> | ||
+ | COMA | ||
+ | root@som9x25:~# echo f8040000.serial > /sys/bus/platform/drivers/atmel_usart/unbind | ||
+ | COMD | ||
+ | root@som9x25:~# echo f8024000.serial > /sys/bus/platform/drivers/atmel_usart/unbind | ||
+ | root@som9x25:~# modprobe atmel_rt_serial | ||
+ | rtser0 on ATMEL UART-1: membase=0xc8dd0000 irq=29 uartclk=133333333 | ||
+ | rtser1 on ATMEL UART-1: membase=0xc8dd2000 irq=30 uartclk=133333333 | ||
+ | </syntaxhighlight> | ||
=== Configuring the serial port === | === Configuring the serial port === | ||
+ | <syntaxhighlight lang="c"> | ||
+ | static const struct rtser_config my_config = { | ||
+ | .config_mask = 0xFFFF, | ||
+ | .baud_rate = 115200, | ||
+ | .parity = RTSER_DEF_PARITY, | ||
+ | .data_bits = RTSER_DEF_BITS, | ||
+ | .stop_bits = RTSER_DEF_STOPB, | ||
+ | .handshake = RTSER_DEF_HAND, | ||
+ | .fifo_depth = RTSER_DEF_FIFO_DEPTH, | ||
+ | .rx_timeout = RTSER_DEF_TIMEOUT, | ||
+ | .tx_timeout = RTSER_DEF_TIMEOUT, | ||
+ | .event_timeout = 1000000000, /* 1 s */ | ||
+ | .timestamp_history = RTSER_RX_TIMESTAMP_HISTORY, | ||
+ | .event_mask = RTSER_EVENT_RXPEND, | ||
+ | }; | ||
+ | ... | ||
+ | int fd; | ||
+ | int err; | ||
+ | ... | ||
+ | fd = open("/dev/rtdm/rtser0", 0); | ||
+ | |||
+ | if (fd < 0) { | ||
+ | printf("open error %s\n", strerror(errno)); | ||
+ | return -errno; | ||
+ | } | ||
+ | ... | ||
+ | err = ioctl(fd, RTSER_RTIOC_SET_CONFIG, &my_config); | ||
+ | if (err) { | ||
+ | printf("ioctl error %s\n", strerror(errno)); | ||
+ | goto error; | ||
+ | } | ||
+ | ... | ||
+ | </syntaxhighlight> | ||
=== Performing serial transactions === | === Performing serial transactions === | ||
+ | Performing serial transactions is as simple as reading and write to the rtser file descriptor. | ||
+ | |||
+ | Sending the contents of a buffer over the serial port: | ||
+ | <syntaxhighlight lang="c"> | ||
+ | ret = write(fd, buffer, sizeof(buffer)); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Receiving serial port input data into buffer: | ||
+ | <syntaxhighlight lang="c"> | ||
+ | ret = read(fd, buffer, sizeof(buffer)); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | When reading from the serial it is useful to wait for an event to occur before reading: | ||
+ | <syntaxhighlight lang="c"> | ||
+ | err = ioctl(read_fd, RTSER_RTIOC_WAIT_EVENT, &rx_event); | ||
+ | if (err) { | ||
+ | printf("ioctl error on RTSER_RTIOC_WAIT_EVENT %s\n", | ||
+ | strerror(errno)); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
<!-- /*********************************************************************************************************/ --> | <!-- /*********************************************************************************************************/ --> | ||
Line 41: | Line 116: | ||
<!-- /*********************************************************************************************************/ --> | <!-- /*********************************************************************************************************/ --> | ||
{{:Templateimpl:examples | initials=MW | title=Xenomai RTSerial | desc=Xenomai RTSerial | project=OE 5.0 }} | {{:Templateimpl:examples | initials=MW | title=Xenomai RTSerial | desc=Xenomai RTSerial | project=OE 5.0 }} | ||
− | Xenomai provides an example called cross-link which provides an easy way to test serial ports. Essentially the demo | + | Xenomai provides an example called cross-link which provides an easy way to test serial ports. Essentially the demo sends data from one serial port and receives it on another. To run the demo make sure the RTDM driver is loaded and connect the first two ports via a NULL modem cable. |
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
root@somimx6-xenomai:~# /usr/demo/cross-link | root@somimx6-xenomai:~# /usr/demo/cross-link | ||
Line 62: | Line 137: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | == External Links == | |
− | + | * https://xenomai.org/documentation/xenomai-3/html/xeno3prm/group__rtdm__serial.html | |
− | + | * https://xenomai.org/documentation/xenomai-3/html/xeno3prm/rtdm_2uapi_2serial_8h.html | |
− | + | * https://xenomai.org/documentation/xenomai-3/html/xeno3prm/cross-link_8c-example.html | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Latest revision as of 16:16, 6 February 2018
Contents
General Information
Xenomai provides a RTDM profile for serial device drivers enabling real-time UART serial communication. The RTDM serial driver provides the necessary user-space API to perform serial port configuration and communication. The following sections will outline the use of the user-space interface and provide basic examples.
Xenomai RTSerial
Given the RTDM serial port driver exists and is loaded for the target on hand, it will provide device nodes at /dev/rtdm/rtserX
where X is replaced by the number of each port.
The device nodes are then accessed to configured and communicate the underlying serial ports. The following subsections will outline loading the driver, configuring the port, and performing basic serial transactions.
Loading the driver
Typically there will be a Linux kernel driver associated with the serial port by default. If the desired device is associated with a Linux driver the driver must be unloaded or the device must be unbound from the driver. Below are examples of loading the RTDM driver for some supported targets.
x86 16550A
iMX6 rt_imx_uart
root@somimx6-xenomai:~# echo 2020000.serial > /sys/bus/platform/drivers/imx-uart/unbind
root@somimx6-xenomai:~# echo 21e8000.serial > /sys/bus/platform/drivers/imx-uart/unbind
root@somimx6-xenomai:~# modprobe xeno_imx_uart
root@somimx6-xenomai:~# dmesg | tail
.
.
[ 462.425158] console [ttymxc1] disabled
[ 528.025034] rtser0 on IMX UART0: membase=0xc0c10000 irq=58 uartclk=80000000
[ 528.025700] rtser1 on IMX UART1: membase=0xc0c18000 irq=59 uartclk=80000000
AT91 atmel_rt_serial
COMA
root@som9x25:~# echo f8040000.serial > /sys/bus/platform/drivers/atmel_usart/unbind
COMD
root@som9x25:~# echo f8024000.serial > /sys/bus/platform/drivers/atmel_usart/unbind
root@som9x25:~# modprobe atmel_rt_serial
rtser0 on ATMEL UART-1: membase=0xc8dd0000 irq=29 uartclk=133333333
rtser1 on ATMEL UART-1: membase=0xc8dd2000 irq=30 uartclk=133333333
Configuring the serial port
static const struct rtser_config my_config = {
.config_mask = 0xFFFF,
.baud_rate = 115200,
.parity = RTSER_DEF_PARITY,
.data_bits = RTSER_DEF_BITS,
.stop_bits = RTSER_DEF_STOPB,
.handshake = RTSER_DEF_HAND,
.fifo_depth = RTSER_DEF_FIFO_DEPTH,
.rx_timeout = RTSER_DEF_TIMEOUT,
.tx_timeout = RTSER_DEF_TIMEOUT,
.event_timeout = 1000000000, /* 1 s */
.timestamp_history = RTSER_RX_TIMESTAMP_HISTORY,
.event_mask = RTSER_EVENT_RXPEND,
};
...
int fd;
int err;
...
fd = open("/dev/rtdm/rtser0", 0);
if (fd < 0) {
printf("open error %s\n", strerror(errno));
return -errno;
}
...
err = ioctl(fd, RTSER_RTIOC_SET_CONFIG, &my_config);
if (err) {
printf("ioctl error %s\n", strerror(errno));
goto error;
}
...
Performing serial transactions
Performing serial transactions is as simple as reading and write to the rtser file descriptor.
Sending the contents of a buffer over the serial port:
ret = write(fd, buffer, sizeof(buffer));
Receiving serial port input data into buffer:
ret = read(fd, buffer, sizeof(buffer));
When reading from the serial it is useful to wait for an event to occur before reading:
err = ioctl(read_fd, RTSER_RTIOC_WAIT_EVENT, &rx_event);
if (err) {
printf("ioctl error on RTSER_RTIOC_WAIT_EVENT %s\n",
strerror(errno));
}
Examples
Xenomai provides an example called cross-link which provides an easy way to test serial ports. Essentially the demo sends data from one serial port and receives it on another. To run the demo make sure the RTDM driver is loaded and connect the first two ports via a NULL modem cable.
root@somimx6-xenomai:~# /usr/demo/cross-link
main : write-file opened
main : write-config written
main : read-file openedmain : read-config written
main : write-task createdmain : read-task created
main : starting write-task
main : starting read-task
Nr | write->irq | irq->read | write->read |
-----------------------------------------------------------
0 |18446744041591572624 | 32118717325 | 738333
1 |18446744041591563290 | 32118715326 | 727000
2 |18446744041591563957 | 32118716326 | 728667
3 |18446744041591561291 | 32118714658 | 724333
4 |18446744041591562624 | 32118715992 | 727000
5 |18446744041591560290 | 32118715326 | 724000
.
.