Skip to content

Commit 2869532

Browse files
committed
hal: Add new types and API framework for the getter/setter change.
1 parent b677997 commit 2869532

6 files changed

Lines changed: 590 additions & 126 deletions

File tree

src/hal/hal.h

Lines changed: 245 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
//
296311
typedef 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"
318355
typedef volatile bool hal_bit_t;
319356
typedef volatile rtapi_u32 hal_u32_t;
320357
typedef volatile rtapi_s32 hal_s32_t;
321358
typedef volatile rtapi_u64 hal_u64_t;
322359
typedef volatile rtapi_s64 hal_s64_t;
360+
typedef volatile real_t hal_float_t;
323361
typedef 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

Comments
 (0)