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