Using custom serial port (UART) protocol for IO
04 Jan 2024 10:52 #289751
by awpe
Using custom serial port (UART) protocol for IO was created by awpe
Hello,
I want to avoid reinventing the wheel with serial port communication for IO extension so is further described functionality already available or I can proceed?
I know there is SERPORT module that uses individual pins of COM port for IO giving 8 output and 3 input ports total, but using normal data transfers it is possible to greatly extend number of IO.
My idea is to create component (shared library registered in hal config) with rtapi_* registered function and exposed variable like int32, that component will be registered with 1ms period. Upon start it will create and fill global variable to store descriptor to some com port. Upon update call each 1ms as requested (or how HAL scheduler decides) it will poll for data from com port in chunks of 4 bytes (32bit total) and latest 4 bytes will go into global int32 variable. That int32 will then be splitted bit per bit into 32 input pins in hal ini.
On the hardware side I have a lot of stm32 dev boards that I want to use for monitoring different switch sensors (limit switches, spindle ON, errors on servos, end probe etc) and then send data as 4 bytes via uart as soon as any change was observed.
So at the end that linuxcnc module will "see" latest state of observable pins with period of 1ms or anything hal subsystem scheduler decides best time to poll that component for data.
What do you think about approach and does some ready component comes to your mind?
Thanks.
I want to avoid reinventing the wheel with serial port communication for IO extension so is further described functionality already available or I can proceed?
I know there is SERPORT module that uses individual pins of COM port for IO giving 8 output and 3 input ports total, but using normal data transfers it is possible to greatly extend number of IO.
My idea is to create component (shared library registered in hal config) with rtapi_* registered function and exposed variable like int32, that component will be registered with 1ms period. Upon start it will create and fill global variable to store descriptor to some com port. Upon update call each 1ms as requested (or how HAL scheduler decides) it will poll for data from com port in chunks of 4 bytes (32bit total) and latest 4 bytes will go into global int32 variable. That int32 will then be splitted bit per bit into 32 input pins in hal ini.
On the hardware side I have a lot of stm32 dev boards that I want to use for monitoring different switch sensors (limit switches, spindle ON, errors on servos, end probe etc) and then send data as 4 bytes via uart as soon as any change was observed.
So at the end that linuxcnc module will "see" latest state of observable pins with period of 1ms or anything hal subsystem scheduler decides best time to poll that component for data.
What do you think about approach and does some ready component comes to your mind?
Thanks.
Please Log in or Create an account to join the conversation.
04 Jan 2024 11:17 #289760
by andypugh
Replied by andypugh on topic Using custom serial port (UART) protocol for IO
Do you envisage this component as running in realtime or userspace?
The latter is likely to be easier as flow control will (probably) be handled automatically, you would just write to the required node in /dev
In realtime you would probably need to define the port address on the loadrt command line (like with the parport driver) and then send data with rtapi_inb() and rtapi_outb().
linuxcnc.org/docs/stable/html/man/man3/rtapi_outb.3rtapi.html
The existing serport driver is probably a good starting point:
github.com/LinuxCNC/linuxcnc/blob/master...drivers/serport.comp
Be aware that a HAL realtime driver can't wait, it needs to exit immediately every time it is called. This is normally handled with a state machine, see for example this switch statement for one way to handle that: github.com/LinuxCNC/linuxcnc/blob/master...a_modbus.c.tmpl#L492
The latter is likely to be easier as flow control will (probably) be handled automatically, you would just write to the required node in /dev
In realtime you would probably need to define the port address on the loadrt command line (like with the parport driver) and then send data with rtapi_inb() and rtapi_outb().
linuxcnc.org/docs/stable/html/man/man3/rtapi_outb.3rtapi.html
The existing serport driver is probably a good starting point:
github.com/LinuxCNC/linuxcnc/blob/master...drivers/serport.comp
Be aware that a HAL realtime driver can't wait, it needs to exit immediately every time it is called. This is normally handled with a state machine, see for example this switch statement for one way to handle that: github.com/LinuxCNC/linuxcnc/blob/master...a_modbus.c.tmpl#L492
The following user(s) said Thank You: awpe
Please Log in or Create an account to join the conversation.
04 Jan 2024 11:38 - 04 Jan 2024 11:45 #289764
by awpe
Replied by awpe on topic Using custom serial port (UART) protocol for IO
Maybe I ended up with some misconception... I thought if I have RTAI kernel then linuxcnc should interact with it in realtime manner, so when I have some registered(hal_export_functf) function like "update(void*arg, int period){...}" it will be called by scheduler in correct timeframes so I can poll without wait on some device like /dev/ttyS0 to check if there is any data available and return result immediately possibly changing state of globaly defined exported varaible that is used in hal config, am I missing something? Are those rtapi_inb/outb used to work with some virtual port shared among different components?
Last edit: 04 Jan 2024 11:45 by awpe.
Please Log in or Create an account to join the conversation.
05 Jan 2024 11:18 #289850
by andypugh
All the HAL drivers that I have written use port access, with the exception of hal_gpio which uses the lib_gpiod character interface.
Try it? See what happens. It might be fine.
Replied by andypugh on topic Using custom serial port (UART) protocol for IO
Realtime code typically runs in kernel space (it doesn't have to, this is a hangover from when kernel-mode RTAI was the only supported reatlime system). This means that realtime components in LinuxCNC typically do not have access to the file system. Which might, or might not, include /devMaybe I ended up with some misconception... I thought if I have RTAI kernel then linuxcnc should interact with it in realtime manner, so when I have some registered(hal_export_functf) function like "update(void*arg, int period){...}" it will be called by scheduler in correct timeframes so I can poll without wait on some device like /dev/ttyS0
All the HAL drivers that I have written use port access, with the exception of hal_gpio which uses the lib_gpiod character interface.
Try it? See what happens. It might be fine.
Please Log in or Create an account to join the conversation.
05 Jan 2024 12:23 - 05 Jan 2024 12:37 #289855
by awpe
Replied by awpe on topic Using custom serial port (UART) protocol for IO
I've seen code for modbus and SERPORT, SERPORT is looking into current pins state using port address so it like direct hardware access to port, and modbus is relying on mesa firmware if I got it right so you get data from queue prepared by mesa firmware. I wanted to use ready solutions for reading/writing data from/to COM port...
Ok I think I've found what I need:
So RTAI itself through its serial kernel module will handle low level stuff and linuxcnc component will just interpret incomming data.
Here is the interface for RTAI serial, I can just poll for RX buffer to not wait.
RTAI serial module interface
Ok I think I've found what I need:
Warning: Spoiler!
#include <rtai.h>
#include <rtai_fifos.h>
#include <rtai_serial.h>
SERIAL_PORT *port;
int init_module(void) {
// Open serial port (e.g., COM1 which is typically ttys0 in Linux)
port = rt_spopen(COM1, BAUD_9600, PARITY_NONE, 8, 1, RTS_ON | CTS_ON);
if (port == NULL) {
// Error handling
return -1;
}
// ... (additional initialization code)
return 0;
}
void cleanup_module(void) {
rt_spclose(port);
// ... (additional cleanup code)
}
So RTAI itself through its serial kernel module will handle low level stuff and linuxcnc component will just interpret incomming data.
Here is the interface for RTAI serial, I can just poll for RX buffer to not wait.
RTAI serial module interface
Last edit: 05 Jan 2024 12:37 by awpe.
Please Log in or Create an account to join the conversation.
05 Jan 2024 13:28 #289860
by andypugh
Replied by andypugh on topic Using custom serial port (UART) protocol for IO
Are you using RTAI?
Just to clear up a possible amibuity:
LinuxCNC offers the rtapi (realtime api) which offers a range of functions.
Depending on the realtime version that LinuxCNC is compiled against (basically userspace for preemp-rt, and for Xemomai and RTAI using LXRT) or RTAI for kernel-mode RTAI these functions map to different realtime APIs.
Depending on how portable you want your driver to be, you could consider conditional comilation and using rtai_serial for kernel-mode RTAI and /dev/ access for preempt-rt (I am ignoring LXRT for the moment as I haven't figured out how to force compilation of the LXRT helper apps rtai_uspace and xenomai_uspace )
Just to clear up a possible amibuity:
LinuxCNC offers the rtapi (realtime api) which offers a range of functions.
Depending on the realtime version that LinuxCNC is compiled against (basically userspace for preemp-rt, and for Xemomai and RTAI using LXRT) or RTAI for kernel-mode RTAI these functions map to different realtime APIs.
Depending on how portable you want your driver to be, you could consider conditional comilation and using rtai_serial for kernel-mode RTAI and /dev/ access for preempt-rt (I am ignoring LXRT for the moment as I haven't figured out how to force compilation of the LXRT helper apps rtai_uspace and xenomai_uspace )
Please Log in or Create an account to join the conversation.
05 Jan 2024 15:07 - 05 Jan 2024 15:10 #289872
by awpe
Replied by awpe on topic Using custom serial port (UART) protocol for IO
To my understanding using RTAI api for serial port might be overkill if it is used for limit switches, servo errors flags etc, as checking without any wait on /dev/ttyUSB* (without RTAI for usb-com dongles due to lack or RT drivers for ft232 and clones) and/or /dev/ttyS0 (possibly with RTAI) each one ms should be OK. I will now focus on finishing router build and wiring, and then will be back trying approach using latest image.
I have a lga1155 4 core PC with PCI-e extension card which offers 1 LPT and 2 serial ports which I want to use in this build that is why I started to investigate how I can use serial ports for full speed data transfer and not just few more additional pins...
I have a lga1155 4 core PC with PCI-e extension card which offers 1 LPT and 2 serial ports which I want to use in this build that is why I started to investigate how I can use serial ports for full speed data transfer and not just few more additional pins...
Last edit: 05 Jan 2024 15:10 by awpe.
Please Log in or Create an account to join the conversation.
Time to create page: 0.241 seconds