@@ -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,182 @@ 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+ #error "HAL only supports little endian machines at this moment."
402+ #endif
403+
404+ // This is a define so we don't export it to other code.
405+ // It is undef'ed after we're done with it.
406+ // FIXME: Get rid of the 32-bit types when we have upgraded everything using
407+ // getter/setter access only so we have guaranteed content.
408+ #define __HAL_MAPPED_TYPE union __hal_mapped_type { \
409+ volatile rtapi_bool _b; \
410+ volatile rtapi_s32 _ss; \
411+ volatile rtapi_u32 _su; \
412+ volatile rtapi_sint _s; \
413+ volatile rtapi_uint _u; \
414+ volatile rtapi_real _r; \
415+ }
416+
417+
418+ #if 0
419+ // The port change must be done later
420+ // A 'hal_port_t' is a pin/param reference which content represents
421+ // the integer offset in the HAL shared memory segment to a
422+ // hal_port_shm_t structure.
423+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_get_port (hal_port_t ref ) {
424+ __HAL_MAPPED_TYPE ;
425+ // cppcheck-suppress dangerousTypeCast
426+ return ((union __hal_mapped_type * )ref )-> _s ;
427+ }
428+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_set_port (hal_port_t ref , rtapi_sint val ) {
429+ __HAL_MAPPED_TYPE ;
430+ // cppcheck-suppress dangerousTypeCast
431+ ((union __hal_mapped_type * )ref )-> _s = val ; // Store in the larger type
432+ return val ;
433+ }
434+ #endif
435+ //
436+ // The hal_{get,set}_si32() and hal_{get,set}_ui32() are only present for
437+ // compatibility. They may be removed when all the remaining code has been
438+ // updated properly. However, there is a case for letting them remain as
439+ // they will simply use implicit truncation.
440+ // The hal_get_{s,u}i32_clamped() functions will not truncate but clamp the
441+ // read value to the appropriate min/max of the 32-bit type.
442+ //
443+ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_get_si32_clamped (const hal_sint_t ref ) {
444+ __HAL_MAPPED_TYPE ;
445+ // Down conversion from the larger type
446+ // cppcheck-suppress dangerousTypeCast
447+ rtapi_sint val = ((union __hal_mapped_type * )ref )-> _s ;
448+ if (val <= RTAPI_INT32_MIN ) return RTAPI_INT32_MIN ;
449+ if (val >= RTAPI_INT32_MAX ) return RTAPI_INT32_MAX ;
450+ return (rtapi_s32 )val ;
451+ }
452+ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_get_si32 (const hal_sint_t ref ) {
453+ __HAL_MAPPED_TYPE ;
454+ // Implicitly Truncated from the larger type
455+ // cppcheck-suppress dangerousTypeCast
456+ return ((union __hal_mapped_type * )ref )-> _ss ;
457+ }
458+ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_set_si32 (hal_sint_t ref , rtapi_s32 val ) {
459+ __HAL_MAPPED_TYPE ;
460+ // cppcheck-suppress dangerousTypeCast
461+ ((union __hal_mapped_type * )ref )-> _s = val ; // Store in the larger type
462+ return val ;
463+ }
464+ static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_get_ui32_clamped (const hal_uint_t ref ) {
465+ __HAL_MAPPED_TYPE ;
466+ // Down conversion from the larger type
467+ // cppcheck-suppress dangerousTypeCast
468+ rtapi_uint val = ((union __hal_mapped_type * )ref )-> _u ;
469+ if (val >= RTAPI_UINT32_MAX ) return RTAPI_UINT32_MAX ;
470+ return (rtapi_u32 )val ;
471+ }
472+ static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_get_ui32 (const hal_uint_t ref ) {
473+ __HAL_MAPPED_TYPE ;
474+ // Implicitly Truncated from the larger type
475+ // cppcheck-suppress dangerousTypeCast
476+ return ((union __hal_mapped_type * )ref )-> _su ;
477+ }
478+ static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_set_ui32 (hal_uint_t ref , rtapi_u32 val ) {
479+ __HAL_MAPPED_TYPE ;
480+ // cppcheck-suppress dangerousTypeCast
481+ ((union __hal_mapped_type * )ref )-> _u = val ; // Store in the larger type
482+ return val ;
483+ }
484+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_get_sint (const hal_sint_t ref ) {
485+ __HAL_MAPPED_TYPE ;
486+ // cppcheck-suppress dangerousTypeCast
487+ return ((union __hal_mapped_type * )ref )-> _s ;
488+ }
489+ static inline __HAL_ALWAYS_INLINE rtapi_sint hal_set_sint (hal_sint_t ref , rtapi_sint val ) {
490+ __HAL_MAPPED_TYPE ;
491+ // cppcheck-suppress dangerousTypeCast
492+ ((union __hal_mapped_type * )ref )-> _s = val ;
493+ return val ;
494+ }
495+ static inline __HAL_ALWAYS_INLINE rtapi_uint hal_get_uint (const hal_uint_t ref ) {
496+ __HAL_MAPPED_TYPE ;
497+ // cppcheck-suppress dangerousTypeCast
498+ return ((union __hal_mapped_type * )ref )-> _u ;
499+ }
500+ static inline __HAL_ALWAYS_INLINE rtapi_uint hal_set_uint (hal_uint_t ref , rtapi_uint val ) {
501+ __HAL_MAPPED_TYPE ;
502+ // cppcheck-suppress dangerousTypeCast
503+ ((union __hal_mapped_type * )ref )-> _u = val ;
504+ return val ;
505+ }
506+ static inline __HAL_ALWAYS_INLINE rtapi_real hal_get_real (const hal_real_t ref ) {
507+ __HAL_MAPPED_TYPE ;
508+ // cppcheck-suppress dangerousTypeCast
509+ return ((union __hal_mapped_type * )ref )-> _r ;
510+ }
511+ static inline __HAL_ALWAYS_INLINE rtapi_real hal_set_real (hal_real_t ref , rtapi_real val ) {
512+ __HAL_MAPPED_TYPE ;
513+ // cppcheck-suppress dangerousTypeCast
514+ ((union __hal_mapped_type * )ref )-> _r = val ;
515+ return val ;
516+ }
517+ static inline __HAL_ALWAYS_INLINE rtapi_bool hal_get_bool (const hal_bool_t ref ) {
518+ __HAL_MAPPED_TYPE ;
519+ // cppcheck-suppress dangerousTypeCast
520+ return ((union __hal_mapped_type * )ref )-> _b ;
521+ }
522+ static inline __HAL_ALWAYS_INLINE rtapi_bool hal_set_bool (hal_bool_t ref , rtapi_bool val ) {
523+ __HAL_MAPPED_TYPE ;
524+ // 'val' is declared bool and will therefore store a one (1)
525+ // or a zero (0) in the larger target. This still works if the
526+ // call is made using an integer type as original argument.
527+ // cppcheck-suppress dangerousTypeCast
528+ ((union __hal_mapped_type * )ref )-> _u = val ;
529+ return val ;
530+ }
531+ #undef __HAL_ALWAYS_INLINE
532+ #undef __HAL_MAPPED_TYPE
533+
534+ #define __HAL_PFMT (a ,b ) __attribute__((format(printf,a,b)))
535+ 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 );
536+ 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 );
537+ 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 );
538+ 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 );
539+ 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 );
540+ 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 );
541+ // Note: port has no initial default as it is an 'internal' reference
542+ //int hal_pin_new_port(int compid, hal_pin_dir_t dir, hal_port_t *ref, const char *fmt, ...) __HAL_PFMT(4,5);
543+
544+ 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 );
545+ 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 );
546+ 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 );
547+ 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 );
548+ 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 );
549+ 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 );
550+ #undef __HAL_PFMT
551+
342552/***********************************************************************
343553* "LOCKING" FUNCTIONS *
344554************************************************************************/
0 commit comments