@@ -134,9 +134,11 @@ RTAPI_BEGIN_DECLS
134134#include <signal.h>
135135#endif
136136
137+ #include "rtapi_stdint.h"
138+ #include "rtapi_bool.h"
137139#include "rtapi_errno.h"
138140
139- #define HAL_NAME_LEN 47 /* length for pin, signal, etc, names */
141+ #define HAL_NAME_LEN 55 /* length for pin, signal, etc, names */
140142
141143/** These locking codes define the state of HAL locking, are used by most functions */
142144/** The functions locked will return a -EPERM error message **/
@@ -290,46 +292,78 @@ typedef enum {
290292 HAL_TYPE_MAX ,
291293} hal_type_t ;
292294
293- /** HAL pins have a direction attribute. A pin may be an input to
294- the HAL component, an output, or it may be bidirectional.
295- Any number of HAL_IN or HAL_IO pins may be connected to the same
296- signal, but only one HAL_OUT pin is permitted. This is equivalent
297- to connecting two output pins together in an electronic circuit.
298- (HAL_IO pins can be thought of as tri-state outputs.)
299- */
300-
295+ #define HAL_BOOL HAL_BIT
296+ #define HAL_REAL HAL_FLOAT
297+ #define HAL_SINT HAL_S64
298+ #define HAL_UINT HAL_U64
299+
300+ //
301+ // hal_pdir_t - Unified HAL pin/param direction type. Specifies the direction
302+ // of the pins and params while simultaneously allowing us to deduce whether we
303+ // are dealing with a pin or a param.
304+ //
305+ // HAL pins have a direction attribute. A pin may be an input to the HAL
306+ // component, an output, or it may be bidirectional. Any number of HAL_IN or
307+ // HAL_IO pins may be connected to the same signal, but only one HAL_OUT pin is
308+ // permitted. This is equivalent to connecting two output pins together in an
309+ // electronic circuit. (HAL_IO pins can be thought of as tri-state outputs.)
310+ //
311+ // HAL parameters also have a direction attribute. For parameters, the
312+ // attribute determines whether the user can write the value of the parameter,
313+ // or simply read it. HAL_RO parameters are read-only, and HAL_RW ones are
314+ // writable with 'halcmd setp'.
315+ //
301316typedef enum {
302317 HAL_DIR_UNSPECIFIED = -1 ,
303- HAL_IN = 16 ,
304- HAL_OUT = 32 ,
305- HAL_IO = (HAL_IN | HAL_OUT ),
306- } hal_pin_dir_t ;
307-
308- /** HAL parameters also have a direction attribute. For parameters,
309- the attribute determines whether the user can write the value
310- of the parameter, or simply read it. HAL_RO parameters are
311- read-only, and HAL_RW ones are writable with 'halcmd setp'.
312- */
318+ HAL_IN = (1 << 4 ),
319+ HAL_OUT = (1 << 5 ),
320+ HAL_IO = (HAL_IN | HAL_OUT ),
321+ HAL_RO = (1 << 6 ),
322+ HAL_WO = (1 << 7 ), // Actually fake value not enforced
323+ HAL_RW = (HAL_RO | HAL_WO ),
324+ } hal_pdir_t ;
325+
326+ // Map both old direction types to the new combined type
327+ // FIXME: These should be retired at some point
328+ typedef hal_pdir_t hal_pin_dir_t ;
329+ typedef hal_pdir_t hal_param_dir_t ;
330+
331+ #define __HAL_ALWAYS_INLINE __attribute__((always_inline))
332+
333+ //
334+ // bool hal_pdir_is_pin(hal_pdir_t)
335+ // bool hal_pdir_is_param(hal_pdir_t)
336+ // bool hal_pdir_is_neither(hal_pdir_t)
337+ //
338+ // Determine whether an I/O direction is a pin, a param or neither.
339+ //
340+ static inline __HAL_ALWAYS_INLINE bool hal_pdir_is_pin (hal_pdir_t v ) {
341+ // No other bits than in HAL_IO may be set
342+ return (0 == (v & ~HAL_IO )) && (0 != (v & HAL_IO ));
343+ }
344+ static inline __HAL_ALWAYS_INLINE bool hal_pdir_is_param (hal_pdir_t v ) {
345+ // No other bits than in HAL_RW may be set
346+ return (0 == (v & ~HAL_RW )) && (0 != (v & HAL_RW ));
347+ }
348+ static inline __HAL_ALWAYS_INLINE bool hal_pdir_is_neither (hal_pdir_t v ) {
349+ // Any other bits than in HAL_IO|HAL_RW set or none of the set's bits
350+ return (0 != (v & ~(HAL_IO |HAL_RW ))) || (0 == (v & (HAL_IO |HAL_RW )));
351+ }
313352
314- typedef enum {
315- HAL_RO = 64 ,
316- HAL_RW = HAL_RO | 128 /* HAL_WO */ ,
317- } hal_param_dir_t ;
353+ // FIXME: These alignment attributes should be removed.
354+ // HAL now allocates on an 8-byte boundary and the rest should be left to the
355+ // compiler.
356+ // ==> Remove when we get rid of old hal_*_t typedefs. <==
357+ typedef rtapi_real real_t ;
358+ typedef rtapi_u64 ireal_t __attribute__((aligned (8 ))); // integral type as wide as real_t / hal_float_t
318359
319- /* Use these for x86 machines, and anything else that can write to
320- individual bytes in a machine word. */
321- #include "rtapi_bool.h"
322- #include "rtapi_stdint.h"
323360typedef volatile bool hal_bit_t ;
324361typedef volatile rtapi_u32 hal_u32_t ;
325362typedef volatile rtapi_s32 hal_s32_t ;
326363typedef volatile rtapi_u64 hal_u64_t ;
327364typedef volatile rtapi_s64 hal_s64_t ;
365+ typedef volatile real_t hal_float_t ;
328366typedef volatile int hal_port_t ;
329- typedef double real_t __attribute__((aligned (8 )));
330- typedef rtapi_u64 ireal_t __attribute__((aligned (8 ))); // integral type as wide as real_t / hal_float_t
331-
332- #define hal_float_t volatile real_t
333367
334368/** HAL "data union" structure
335369 ** This structure may hold any type of hal data
@@ -344,6 +378,186 @@ typedef union {
344378 hal_u64_t lu ;
345379} hal_data_u ;
346380
381+ // Fake forward declarations so we can make opaque pointers
382+ struct __hal_stype_bool_t ;
383+ struct __hal_stype_sint_t ;
384+ struct __hal_stype_uint_t ;
385+ struct __hal_stype_real_t ;
386+ struct __hal_stype_port_t ;
387+
388+ typedef struct __hal_stype_bool_t * hal_bool_t ;
389+ typedef struct __hal_stype_sint_t * hal_sint_t ;
390+ typedef struct __hal_stype_uint_t * hal_uint_t ;
391+ typedef struct __hal_stype_real_t * hal_real_t ;
392+ //typedef struct __hal_stype_port_t *hal_port_t;
393+
394+ typedef union {
395+ hal_bool_t b ;
396+ hal_sint_t s ;
397+ hal_uint_t u ;
398+ hal_real_t r ;
399+ //hal_port_t p;
400+ } hal_refs_u ;
401+
402+ // We rely on little-endian memory layout in the union where the smaller
403+ // types are overlapping the larger type's least significant part.
404+ #include "rtapi_byteorder.h"
405+
406+ // The 'defined()' clause is specifically added for cppcheck 2.13.0, used in
407+ // Ubuntu 24.04, which appears to fail somewhere in including rtapi_byteorder.h
408+ // and hits the #error directive.
409+ #if defined(RTAPI_LITTLE_ENDIAN ) && !RTAPI_LITTLE_ENDIAN
410+ #error "HAL only supports little endian machines at this moment."
411+ #endif
412+
413+ // This is a define so we don't export it to other code.
414+ // It is undef'ed after we're done with it.
415+ // FIXME: Get rid of the 32-bit types when we have upgraded everything using
416+ // getter/setter access only so we have guaranteed content.
417+ #define __HAL_MAPPED_TYPE union __hal_mapped_type { \
418+ volatile rtapi_bool _b; \
419+ volatile rtapi_s32 _ss; \
420+ volatile rtapi_u32 _su; \
421+ volatile rtapi_sint _s; \
422+ volatile rtapi_uint _u; \
423+ volatile rtapi_real _r; \
424+ }
425+
426+
427+ #if 0
428+ // The port change must be done later
429+ // A 'hal_port_t' is a pin/param reference which content represents
430+ // the integer offset in the HAL shared memory segment to a
431+ // hal_port_shm_t structure.
432+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_get_port (hal_port_t ref ) {
433+ __HAL_MAPPED_TYPE ;
434+ // cppcheck-suppress dangerousTypeCast
435+ return ((union __hal_mapped_type * )ref )-> _s ;
436+ }
437+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_set_port (hal_port_t ref , rtapi_sint val ) {
438+ __HAL_MAPPED_TYPE ;
439+ // cppcheck-suppress dangerousTypeCast
440+ ((union __hal_mapped_type * )ref )-> _s = val ; // Store in the larger type
441+ return val ;
442+ }
443+ #endif
444+ //
445+ // The hal_{get,set}_si32() and hal_{get,set}_ui32() are only present for
446+ // compatibility. They may be removed when all the remaining code has been
447+ // updated properly. However, there is a case for letting them remain as
448+ // they will simply use implicit truncation.
449+ // The hal_get_{s,u}i32_clamped() functions will not truncate but clamp the
450+ // read value to the appropriate min/max of the 32-bit type.
451+ //
452+ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_get_si32_clamped (const hal_sint_t ref ) {
453+ __HAL_MAPPED_TYPE ;
454+ // Down conversion from the larger type
455+ // cppcheck-suppress dangerousTypeCast
456+ rtapi_sint val = ((union __hal_mapped_type * )ref )-> _s ;
457+ if (val <= RTAPI_INT32_MIN ) return RTAPI_INT32_MIN ;
458+ if (val >= RTAPI_INT32_MAX ) return RTAPI_INT32_MAX ;
459+ return (rtapi_s32 )val ;
460+ }
461+ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_get_si32 (const hal_sint_t ref ) {
462+ __HAL_MAPPED_TYPE ;
463+ // Implicitly Truncated from the larger type
464+ // cppcheck-suppress dangerousTypeCast
465+ return ((union __hal_mapped_type * )ref )-> _ss ;
466+ }
467+ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_set_si32 (hal_sint_t ref , rtapi_s32 val ) {
468+ __HAL_MAPPED_TYPE ;
469+ // cppcheck-suppress dangerousTypeCast
470+ ((union __hal_mapped_type * )ref )-> _s = val ; // Store in the larger type
471+ return val ;
472+ }
473+ static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_get_ui32_clamped (const hal_uint_t ref ) {
474+ __HAL_MAPPED_TYPE ;
475+ // Down conversion from the larger type
476+ // cppcheck-suppress dangerousTypeCast
477+ rtapi_uint val = ((union __hal_mapped_type * )ref )-> _u ;
478+ if (val >= RTAPI_UINT32_MAX ) return RTAPI_UINT32_MAX ;
479+ return (rtapi_u32 )val ;
480+ }
481+ static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_get_ui32 (const hal_uint_t ref ) {
482+ __HAL_MAPPED_TYPE ;
483+ // Implicitly Truncated from the larger type
484+ // cppcheck-suppress dangerousTypeCast
485+ return ((union __hal_mapped_type * )ref )-> _su ;
486+ }
487+ static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_set_ui32 (hal_uint_t ref , rtapi_u32 val ) {
488+ __HAL_MAPPED_TYPE ;
489+ // cppcheck-suppress dangerousTypeCast
490+ ((union __hal_mapped_type * )ref )-> _u = val ; // Store in the larger type
491+ return val ;
492+ }
493+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_get_sint (const hal_sint_t ref ) {
494+ __HAL_MAPPED_TYPE ;
495+ // cppcheck-suppress dangerousTypeCast
496+ return ((union __hal_mapped_type * )ref )-> _s ;
497+ }
498+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_set_sint (hal_sint_t ref , rtapi_sint val ) {
499+ __HAL_MAPPED_TYPE ;
500+ // cppcheck-suppress dangerousTypeCast
501+ ((union __hal_mapped_type * )ref )-> _s = val ;
502+ return val ;
503+ }
504+ static inline __HAL_ALWAYS_INLINE rtapi_uint hal_get_uint (const hal_uint_t ref ) {
505+ __HAL_MAPPED_TYPE ;
506+ // cppcheck-suppress dangerousTypeCast
507+ return ((union __hal_mapped_type * )ref )-> _u ;
508+ }
509+ static inline __HAL_ALWAYS_INLINE rtapi_uint hal_set_uint (hal_uint_t ref , rtapi_uint val ) {
510+ __HAL_MAPPED_TYPE ;
511+ // cppcheck-suppress dangerousTypeCast
512+ ((union __hal_mapped_type * )ref )-> _u = val ;
513+ return val ;
514+ }
515+ static inline __HAL_ALWAYS_INLINE rtapi_real hal_get_real (const hal_real_t ref ) {
516+ __HAL_MAPPED_TYPE ;
517+ // cppcheck-suppress dangerousTypeCast
518+ return ((union __hal_mapped_type * )ref )-> _r ;
519+ }
520+ static inline __HAL_ALWAYS_INLINE rtapi_real hal_set_real (hal_real_t ref , rtapi_real val ) {
521+ __HAL_MAPPED_TYPE ;
522+ // cppcheck-suppress dangerousTypeCast
523+ ((union __hal_mapped_type * )ref )-> _r = val ;
524+ return val ;
525+ }
526+ static inline __HAL_ALWAYS_INLINE rtapi_bool hal_get_bool (const hal_bool_t ref ) {
527+ __HAL_MAPPED_TYPE ;
528+ // cppcheck-suppress dangerousTypeCast
529+ return ((union __hal_mapped_type * )ref )-> _b ;
530+ }
531+ static inline __HAL_ALWAYS_INLINE rtapi_bool hal_set_bool (hal_bool_t ref , rtapi_bool val ) {
532+ __HAL_MAPPED_TYPE ;
533+ // 'val' is declared bool and will therefore store a one (1)
534+ // or a zero (0) in the larger target. This still works if the
535+ // call is made using an integer type as original argument.
536+ // cppcheck-suppress dangerousTypeCast
537+ ((union __hal_mapped_type * )ref )-> _u = val ;
538+ return val ;
539+ }
540+ #undef __HAL_ALWAYS_INLINE
541+ #undef __HAL_MAPPED_TYPE
542+
543+ #define __HAL_PFMT (a ,b ) __attribute__((format(printf,a,b)))
544+ int hal_pin_new_bool (int compid , hal_pdir_t dir , hal_bool_t * ref , rtapi_bool def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
545+ int hal_pin_new_si32 (int compid , hal_pdir_t dir , hal_sint_t * ref , rtapi_s32 def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
546+ int hal_pin_new_ui32 (int compid , hal_pdir_t dir , hal_uint_t * ref , rtapi_u32 def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
547+ int hal_pin_new_sint (int compid , hal_pdir_t dir , hal_sint_t * ref , rtapi_sint def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
548+ int hal_pin_new_uint (int compid , hal_pdir_t dir , hal_uint_t * ref , rtapi_uint def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
549+ int hal_pin_new_real (int compid , hal_pdir_t dir , hal_real_t * ref , rtapi_real def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
550+ // Note: port has no initial default as it is an 'internal' reference
551+ //int hal_pin_new_port(int compid, hal_pin_dir_t dir, hal_port_t *ref, const char *fmt, ...) __HAL_PFMT(4,5);
552+
553+ int hal_param_new_bool (int compid , hal_pdir_t dir , hal_bool_t * ref , rtapi_bool def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
554+ int hal_param_new_si32 (int compid , hal_pdir_t dir , hal_sint_t * ref , rtapi_s32 def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
555+ int hal_param_new_ui32 (int compid , hal_pdir_t dir , hal_uint_t * ref , rtapi_u32 def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
556+ int hal_param_new_sint (int compid , hal_pdir_t dir , hal_sint_t * ref , rtapi_sint def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
557+ int hal_param_new_uint (int compid , hal_pdir_t dir , hal_uint_t * ref , rtapi_uint def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
558+ int hal_param_new_real (int compid , hal_pdir_t dir , hal_real_t * ref , rtapi_real def , const char * fmt , ...) __HAL_PFMT (5 ,6 );
559+ #undef __HAL_PFMT
560+
347561/***********************************************************************
348562* "LOCKING" FUNCTIONS *
349563************************************************************************/
0 commit comments