Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 62 additions & 12 deletions docs/src/config/python-hal-interface.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ Message level constants:
* `hal.MSG_DBG` - Additionally include debugging information
* `hal.MSG_ALL` - Print all messages encountered, disregarding level

Realtime type constants:

* `hal.REALTIME_TYPE_UNINITIALIZED` - Real time module not running
* `hal.REALTIME_TYPE_NONE` - No realtime available
* `hal.REALTIME_TYPE_UNKNOWN` - Only used when LINUXCNC_FORCE_REALTIME=1 is set. Unknown, no PREEMPT_DYNAMIC but SCHED_FIFO is available. Not recommended.
* `hal.REALTIME_TYPE_PREEMPT_DYNAMIC` - Preempt dynamic: available in vanilla kernel. Only used when LINUXCNC_FORCE_REALTIME=1 is set. Not recommended.
* `hal.REALTIME_TYPE_PREEMPT_RT` - Preempt RT
* `hal.REALTIME_TYPE_RTAI` - RTAI kernel mode
* `hal.REALTIME_TYPE_LXRT` - LXRT, userspace implementation for RTAI
* `hal.REALTIME_TYPE_XENOMAI` - Xenomai 3
* `hal.REALTIME_TYPE_XENOMAI_EVL` - Xenomai 4 aka Xenomai EVL

System information:

* `hal.is_kernelspace` - One (1) if RTAPI runs in the kernel, otherwise zero (0)
Expand All @@ -59,12 +71,40 @@ System information:

=== hal methods

hal.is_initialized()::
Returns a boolean to indicate whether hal is initialized. The hal is initialized when there is
at least one component. If this is not the case, many of the following functions will throw
a `RuntimeError` exception: `Cannot call before creating component`

.Example:
[source,python]
----
#The hal must be initialized to use many of the hal functions
#If it is not initialized, create a component which will initialize it
#The component will be cleaned up after comp goes out of scope
#Use pid as component identifier, so it is unlikely to collide
#with existing components
comp_name = f"halpy{os.getpid()}"
if not hal.is_initialized():
comp = hal.component(comp_name)

type = hal.get_realtime_type()
----

hal.get_realtime_type()::
Returns the type of the running realtime system.
Might return `hal.REALTIME_TYPE_UNINITIALIZED` if `rtapi_app` is not running.
See xref:_hal_constants[realtime type constants]. +
Throws a `RuntimeError` exception if HAL is not initialized.

hal.component_exists(_name_:string)::
Returns a boolean to indicate whether or not the specified component exist at this time.
Returns a boolean to indicate whether or not the specified component exist at this time. +
Throws a `RuntimeError` exception if HAL is not initialized.

hal.component_is_ready(_name_:string)::
Returns a boolean to indicate whether or not the specified component is in the ready state.
Also returns False if the component does not exist.
Also returns False if the component does not exist. +
Throws a `RuntimeError` exception if HAL is not initialized.

.Example:
[source,python]
Expand All @@ -86,7 +126,8 @@ See 'hal.set_msg_level()' and xref:_hal_constants[message constants] for list of
hal.new_sig(_name_:string, _type_:enum)::
Create a new signal (net) called _name_.
The signal can carry information of _type_ content.
Returns `True` on success.
Returns `True` on success. +
Throws a `RuntimeError` exception if HAL is not initialized.

.Example:
[source,python]
Expand All @@ -98,7 +139,8 @@ if not hal.new_sig("signalname", hal.HAL_BIT):
hal.connect(_pinname_:string, _signame_:string)::
Connect the pin _pinname_ to signal _signame_.
Both signal and pin must exist and both pin and signal must be of the same type.
Returns `True` on success.
Returns `True` on success. +
Throws a `RuntimeError` exception if HAL is not initialized.

.Example:
[source,python]
Expand All @@ -110,7 +152,8 @@ if not hal.connect("mycomp.pinname", "signalname"):
hal.disconnect(_pinname_:string, _signame_:string)::
Disconnect the pin _pinname_ from signal _signame_.
Both signal and pin must exist.
Returns `True` on success.
Returns `True` on success. +
Throws a `RuntimeError` exception if HAL is not initialized.

.Example:
[source,python]
Expand All @@ -121,7 +164,8 @@ if not hal.disconnect("mycomp.pinname"):

hal.pin_has_writer(_pinname_:string)::
Returns `True` if pin with name _pinname_ is attached to a signal and there is at least one writer.
Otherwise, `False` is returned.
Otherwise, `False` is returned. +
Throws a `RuntimeError` exception if HAL is not initialized.

.Example:
[source,python]
Expand All @@ -135,8 +179,9 @@ else:
hal.set_p(_name_:string, _value_:mixed)::
Sets the pin or param called _name_ to _value_.
The _name_ is the full name of the pin or param.
The search order is pin names first, then parameter names.
The search order is pin names first, then parameter names. +
Throws a `RuntimeError` exception if the _name_ is not found. +
Throws a `RuntimeError` exception if HAL is not initialized. +
The type of _value_ depends on the type of the pin or param.
Integer scalar types may use integers or a textual representation of an integer to set the value.
Floating point type may use both integer, floating point and textual representation thereof to set the value.
Expand All @@ -158,14 +203,16 @@ The same rules for _value_ apply to 'set_s()' as to 'set_p()'. +
+
The 'set_s()' method has one special case when the signal is of type `hal.HAL_PORT` and it is fully connected.
In that case, the call uses the _value_ to set the port's queue size and it must be a positive integer.
See below xref:_hal_port_pipes[on configuring a port].
See below xref:_hal_port_pipes[on configuring a port]. +
Throws a `RuntimeError` exception if HAL is not initialized.

hal.get_value(_name_:string)::
Returns the value of the pin, param or signal with _name_, searched in that order.
Boolean types return `True` or `False`.
Integer scalar types return an integer.
Floating point types return a float.
A `RuntimeError` exception is thrown if no pin, param or signal is found by that name.
A `RuntimeError` exception is thrown if no pin, param or signal is found by that name. +
Throws a `RuntimeError` exception if HAL is not initialized.

.Example:
[source,python]
Expand All @@ -174,13 +221,16 @@ value = hal.get_value("iocontrol.0.emc-enable-in")
----

hal.get_info_pins()::
Returns a list of dictionary tuples as in `{"NAME":"pinname", "VALUE":<bool|int|float>, "TYPE":<int>, "DIRECTION":<int>}`.
Returns a list of dictionary tuples as in `{"NAME":"pinname", "VALUE":<bool|int|float>, "TYPE":<int>, "DIRECTION":<int>}`. +
Throws a `RuntimeError` exception if HAL is not initialized.

hal.get_info_params()::
Returns a list of dictionary tuples as in `{"NAME":"paramname", "VALUE":<bool|int|float>, "TYPE":<int>, "DIRECTION":<int>}`.
Returns a list of dictionary tuples as in `{"NAME":"paramname", "VALUE":<bool|int|float>, "TYPE":<int>, "DIRECTION":<int>}`. +
Throws a `RuntimeError` exception if HAL is not initialized.

hal.get_info_signals()::
Returns a list of dictionary tuples as in `{"NAME":"signame", "VALUE":<bool|int|float>, "TYPE":<int>, "DRIVER":"name"|None}`.
Returns a list of dictionary tuples as in `{"NAME":"signame", "VALUE":<bool|int|float>, "TYPE":<int>, "DRIVER":"name"|None}`. +
Throws a `RuntimeError` exception if HAL is not initialized.

.Example:
[source,python]
Expand Down
21 changes: 21 additions & 0 deletions docs/src/man/man3/hal_get_realtime_type.3.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
:manvolnum: 3

= hal_get_realtime_type(3)

== NAME

hal_get_realtime_type - Get the type of the running realtime

== SYNTAX

hal_realtime_type_t hal_get_realtime_type()

== RETURN VALUE

*hal_get_realtime_type* returns the type of the running realtime system or a HAL status code on failure.

For uspace, this returns *REALTIME_TYPE_UNINITIALIZED* if *rtapi_app* is not running. It is safe to assume
this never happens in realtime components. But userspace components can be loaded without *rtapi_app* being
started.

For rtai, this always returns *REALTIME_TYPE_RTAI*.
15 changes: 9 additions & 6 deletions docs/src/man/man3/rtapi_is.3.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ rtapi_is - details of rtapi configuration
[source,c]
----
int rtapi_is_kernelspace();
int rtapi_is_realtime();
int rtapi_is_realtime(); (DEPRECATED)
----

== DESCRIPTION
Expand All @@ -18,15 +18,18 @@ int rtapi_is_realtime();
and zero when they run in userspace (e.g., under uspace).

*rtapi_is_realtime()* returns nonzero when capable of running with realtime guarantees.

(DEPRECATED) use *hal_get_realtime_type()* instead. *rtapi_is_realtime()* works only in realtime context.

For rtai, this always returns nonzero (but actually loading realtime modules will fail if not running under the appropriate kernel).
For uspace, this returns nonzero when the running kernel indicates it is capable of realtime performance.
If *rtapi_app* is not setuid root,
this returns nonzero even though *rtapi_app* will not be able to obtain realtime scheduling or hardware access,
so e.g., attempting to *loadrt* a hardware driver will fail.
For uspace, this returns nonzero when the running kernel indicates it is capable of realtime performance and *rtapi_app* has the
required capabilities or is setuid root.
If *rtapi_app* is not setuid root or setcap with the proper capabilities,
this returns zero.

== REALTIME CONSIDERATIONS

May be called from non-realtime or from realtime setup code.
May only be called from realtime setup code.
*rtapi_is_realtime()* may perform filesystem I/O.

== RETURN VALUE
Expand Down
37 changes: 31 additions & 6 deletions scripts/realtime.in
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ CheckStatus(){
case $RTPREFIX in
uspace)
if [ -z "$($PS -o stat= -o comm= -C rtapi_app | $GREP -v '^Z')" ]; then
exit 1
echo rtapi_app is not running
return 1
else
exit 0
echo rtapi_app is running
return 0
fi ;;
*)
# check loaded/unloaded status of modules
Expand All @@ -138,9 +140,9 @@ CheckStatus(){
fi
done
if [ -z "$NOTLOADED" ]; then
exit 0
return 0
else
exit 1
return 1
fi
esac
}
Expand Down Expand Up @@ -222,6 +224,25 @@ Unload(){
done
}

Verify(){
HAS_REALTIME=false
case $RTPREFIX in
uspace)
rtapi_app check_rt && HAS_REALTIME=true
;;
(*rtai*)
HAS_REALTIME=true
esac

if [ $HAS_REALTIME = true ]; then
echo "realtime detected"
return 0
else
echo "WARNING: no realtime detected"
return 1
fi
}

CheckUnloaded(){
# checks to see if all modules were unloaded
STATUS=
Expand Down Expand Up @@ -260,10 +281,14 @@ case "$CMD" in
;;
status)
CheckConfig
CheckStatus
CheckStatus || exit $?
;;
verify)
CheckConfig
Verify || exit $?
;;
*)
echo "Usage: $0 {start|load|stop|unload|restart|force-reload|status}" >&2
echo "Usage: $0 {start|load|stop|unload|restart|force-reload|status|verify}" >&2
exit 1
;;
esac
Expand Down
1 change: 1 addition & 0 deletions src/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,7 @@ AC_DEFINE_UNQUOTED([EMC2_LANG_DIR], "$EMC2_LANG_DIR", [Directory for tcl transla
AC_DEFINE_UNQUOTED([EMC2_PO_DIR], "$EMC2_PO_DIR", [Directory for po/mo translation files])
AC_DEFINE_UNQUOTED([EMC2_NCFILES_DIR], "$EMC2_NCFILES_DIR", [Directory for nc files])
AC_DEFINE_UNQUOTED([EMC2_IMAGE_DIR], "$EMC2_IMAGE_DIR", [Directory for images])
AC_DEFINE_UNQUOTED([EMC2_REALTIME], "$REALTIME", [Path of realtime script])

AC_SUBST([EMC2_TMP_DIR])
AC_SUBST([EMC2_BIN_DIR])
Expand Down
5 changes: 5 additions & 0 deletions src/hal/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ extern int hal_unready(int comp_id);
*/
extern char* hal_comp_name(int comp_id);

/** hal_get_realtime_type() returns the type of the running real time
*/
typedef rtapi_realtime_type_t hal_realtime_type_t;
extern hal_realtime_type_t hal_get_realtime_type(void);

/** The HAL maintains lists of variables, functions, and so on in
a central database, located in shared memory so all components
can access it. To prevent contention, functions that may
Expand Down
16 changes: 16 additions & 0 deletions src/hal/hal_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

*/

#define RTAPI_HAL_PRIV /* Use rtapi/hal private functions */
#include <rtapi.h> /* RTAPI realtime OS API */
Comment on lines 55 to 57

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either you publish enums and functions or you do not.

Everything in rtapi.h hal.h is available and should not be hidden by any define construct. If you need it such construct, then something is wrong.
What is private remains private. What is public is always public.

#include "hal.h" /* HAL public API decls */
#include "hal_priv.h" /* HAL private decls */
Expand Down Expand Up @@ -537,6 +538,15 @@ char *hal_comp_name(int comp_id)
return result;
}

hal_realtime_type_t hal_get_realtime_type() {
if (hal_data == 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"HAL: ERROR: hal_get_realtime_type called before init\n");
return -EINVAL;
}
return hal_data->realtime_type;
}

/***********************************************************************
* "LOCKING" FUNCTIONS *
************************************************************************/
Expand Down Expand Up @@ -3111,13 +3121,18 @@ int rtapi_app_main(void)
/* done */
rtapi_print_msg(RTAPI_MSG_DBG,
"HAL_LIB: kernel lib installed successfully\n");

hal_data->realtime_type = rtapi_get_realtime_type();

return 0;
}

void rtapi_app_exit(void)
{
hal_thread_t *thread;

hal_data->realtime_type = REALTIME_TYPE_UNINITIALIZED;

rtapi_print_msg(RTAPI_MSG_DBG, "HAL_LIB: removing kernel lib\n");
hal_proc_clean();
/* grab mutex before manipulating list */
Expand Down Expand Up @@ -3275,6 +3290,7 @@ static int init_hal_data(void)
list_init_entry(&(hal_data->funct_entry_free));
hal_data->thread_free_ptr = 0;
hal_data->exact_base_period = 0;
hal_data->realtime_type = REALTIME_TYPE_UNINITIALIZED;
/* set up for shmalloc_xx() */
hal_data->shmem_bot = sizeof(hal_data_t);
hal_data->shmem_top = HAL_SIZE;
Expand Down
3 changes: 2 additions & 1 deletion src/hal/hal_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
*/

#define HAL_KEY 0x48414C32 /* key used to open HAL shared memory */
#define HAL_VER 0x00000010 /* version code */
#define HAL_VER 0x00000011 /* version code */
#define HAL_SIZE (256*4096)
#define HAL_PSEUDO_COMP_PREFIX "__" /* prefix to identify a pseudo component */

Expand Down Expand Up @@ -275,6 +275,7 @@ typedef struct hal_data_t {
SHMFIELD(hal_thread_t) thread_free_ptr; /* list of free thread structs */
int exact_base_period; /* if set, pretend that rtapi satisfied our
period request exactly */
rtapi_realtime_type_t realtime_type; /* reflects the running realtime type */
unsigned char lock; /* hal locking, can be one of the HAL_LOCK_* types */
} hal_data_t;

Expand Down
Loading
Loading