Skip to content

Commit 7726780

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

6 files changed

Lines changed: 586 additions & 126 deletions

File tree

src/hal/hal.h

Lines changed: 241 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,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

Comments
 (0)