ChibiOS 21.11.4
ICU Driver

Generic ICU Driver. More...

Detailed Description

Generic ICU Driver.

This module implements a generic ICU (Input Capture Unit) driver. The purpose of the driver is to measure period and duty cycle of an input digital signal (PWM input).

Precondition
In order to use the ICU driver the HAL_USE_ICU option must be enabled in halconf.h.

Driver State Machine

The driver implements a state machine internally, not all the driver functionalities can be used in any moment, any transition not explicitly shown in the following diagram has to be considered an error and shall be captured by an assertion (if enabled).

dot_inline_dotgraph_11.png

ICU Operations.

This driver abstracts a generic Input Capture Unit composed of:

  • A clock prescaler.
  • A main up counter.
  • Two capture registers triggered by the rising and falling edges on the sampled input.

The ICU unit can be programmed to synchronize on the rising or falling edge of the sample input:

  • ICU_INPUT_ACTIVE_HIGH, a rising edge is the start signal.
  • ICU_INPUT_ACTIVE_LOW, a falling edge is the start signal.

Callbacks are optionally invoked when:

  • On the PWM de-activation edge.
  • On the PWM activation edge, measurements for the previous cycle are available from this callback and can be retrieved using icuGetPeriodX() and icuGetWidthX().
Collaboration diagram for ICU Driver:

Macro Functions

#define icuStartCaptureI(icup)
 Starts the input capture.
#define icuStopCaptureI(icup)
 Stops the input capture.
#define icuEnableNotificationsI(icup)
 Enables notifications.
#define icuDisableNotificationsI(icup)
 Disables notifications.
#define icuAreNotificationsEnabledX(icup)
 Check on notifications status.
#define icuGetWidthX(icup)
 Returns the width of the latest pulse.
#define icuGetPeriodX(icup)
 Returns the width of the latest cycle.

Low level driver helper macros

#define _icu_isr_invoke_width_cb(icup)
 Common ISR code, ICU width event.
#define _icu_isr_invoke_period_cb(icup)
 Common ISR code, ICU period event.
#define _icu_isr_invoke_overflow_cb(icup)
 Common ISR code, ICU timer overflow event.

PLATFORM configuration options

#define PLATFORM_ICU_USE_ICU1   FALSE
 ICUD1 driver enable switch.

Data Structures

struct  ICUConfig
 Driver configuration structure. More...
struct  ICUDriver
 Structure representing an ICU driver. More...

Macros

#define ICU_USE_OVERFLOW_SCALING   FALSE
#define icu_lld_get_width(icup)
 Returns the width of the latest pulse.
#define icu_lld_get_period(icup)
 Returns the width of the latest cycle.
#define icu_lld_are_notifications_enabled(icup)
 Check on notifications status.

Typedefs

typedef struct ICUDriver ICUDriver
 Type of a structure representing an ICU driver.
typedef void(* icucallback_t) (ICUDriver *icup)
 ICU notification callback type.
typedef uint32_t icufreq_t
 ICU frequency type.
typedef uint32_t icucnt_t
 ICU counter type.

Enumerations

enum  icustate_t {
  ICU_UNINIT = 0 , ICU_STOP = 1 , ICU_READY = 2 , ICU_WAITING = 3 ,
  ICU_ACTIVE = 4
}
 Driver state machine possible states. More...
enum  icumode_t { ICU_INPUT_ACTIVE_HIGH = 0 , ICU_INPUT_ACTIVE_LOW = 1 }
 ICU driver mode. More...

Functions

void icuInit (void)
 ICU Driver initialization.
void icuObjectInit (ICUDriver *icup)
 Initializes the standard part of a ICUDriver structure.
msg_t icuStart (ICUDriver *icup, const ICUConfig *config)
 Configures and activates the ICU peripheral.
void icuStop (ICUDriver *icup)
 Deactivates the ICU peripheral.
void icuStartCapture (ICUDriver *icup)
 Starts the input capture.
bool icuWaitCapture (ICUDriver *icup)
 Waits for a completed capture.
void icuStopCapture (ICUDriver *icup)
 Stops the input capture.
void icuEnableNotifications (ICUDriver *icup)
 Enables notifications.
void icuDisableNotifications (ICUDriver *icup)
 Disables notifications.
void icu_lld_init (void)
 Low level ICU driver initialization.
void icu_lld_start (ICUDriver *icup)
 Configures and activates the ICU peripheral.
void icu_lld_stop (ICUDriver *icup)
 Deactivates the ICU peripheral.
void icu_lld_start_capture (ICUDriver *icup)
 Starts the input capture.
bool icu_lld_wait_capture (ICUDriver *icup)
 Waits for a completed capture.
void icu_lld_stop_capture (ICUDriver *icup)
 Stops the input capture.
void icu_lld_enable_notifications (ICUDriver *icup)
 Enables notifications.
void icu_lld_disable_notifications (ICUDriver *icup)
 Disables notifications.

Variables

ICUDriver ICUD1
 ICUD1 driver identifier.

Macro Definition Documentation

◆ ICU_USE_OVERFLOW_SCALING

#define ICU_USE_OVERFLOW_SCALING   FALSE

Definition at line 39 of file hal_icu.h.

◆ icuStartCaptureI

#define icuStartCaptureI ( icup)
Value:
do { \
icu_lld_start_capture(icup); \
(icup)->state = ICU_WAITING; \
} while (false)
@ ICU_WAITING
Definition hal_icu.h:57

Starts the input capture.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
This is an I-Class API, this function can be invoked from within a system lock zone by both threads and interrupt handlers.

Definition at line 90 of file hal_icu.h.

Referenced by icuStartCapture().

◆ icuStopCaptureI

#define icuStopCaptureI ( icup)
Value:
do { \
icu_lld_stop_capture(icup); \
(icup)->state = ICU_READY; \
} while (false)
@ ICU_READY
Definition hal_icu.h:56

Stops the input capture.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
This is an I-Class API, this function can be invoked from within a system lock zone by both threads and interrupt handlers.

Definition at line 102 of file hal_icu.h.

Referenced by icuStopCapture().

◆ icuEnableNotificationsI

#define icuEnableNotificationsI ( icup)
Value:
void icu_lld_enable_notifications(ICUDriver *icup)
Enables notifications.

Enables notifications.

Precondition
The ICU unit must have been activated using icuStart() and the capture started using icuStartCapture().
Note
If the notification is already enabled then the call has no effect.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
This is an I-Class API, this function can be invoked from within a system lock zone by both threads and interrupt handlers.

Definition at line 117 of file hal_icu.h.

Referenced by icuEnableNotifications().

◆ icuDisableNotificationsI

#define icuDisableNotificationsI ( icup)
Value:
void icu_lld_disable_notifications(ICUDriver *icup)
Disables notifications.

Disables notifications.

Precondition
The ICU unit must have been activated using icuStart() and the capture started using icuStartCapture().
Note
If the notification is already disabled then the call has no effect.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
This is an I-Class API, this function can be invoked from within a system lock zone by both threads and interrupt handlers.

Definition at line 129 of file hal_icu.h.

Referenced by icuDisableNotifications().

◆ icuAreNotificationsEnabledX

#define icuAreNotificationsEnabledX ( icup)
Value:
#define icu_lld_are_notifications_enabled(icup)
Check on notifications status.

Check on notifications status.

Parameters
[in]icuppointer to the ICUDriver object
Returns
The notifications status.
Return values
falseif notifications are not enabled.
trueif notifications are enabled.
Function Class:
Not an API, this function is for internal use only.

Definition at line 141 of file hal_icu.h.

Referenced by icuWaitCapture().

◆ icuGetWidthX

#define icuGetWidthX ( icup)
Value:
#define icu_lld_get_width(icup)
Returns the width of the latest pulse.

Returns the width of the latest pulse.

The pulse width is defined as number of ticks between the start edge and the stop edge.

Note
This function is meant to be invoked from the width capture callback.
Parameters
[in]icuppointer to the ICUDriver object
Returns
The number of ticks.
Function Class:
This is an X-Class API, this function can be invoked from any context.

Definition at line 156 of file hal_icu.h.

◆ icuGetPeriodX

#define icuGetPeriodX ( icup)
Value:
#define icu_lld_get_period(icup)
Returns the width of the latest cycle.

Returns the width of the latest cycle.

The cycle width is defined as number of ticks between a start edge and the next start edge.

Note
This function is meant to be invoked from the width capture callback.
Parameters
[in]icuppointer to the ICUDriver object
Returns
The number of ticks.
Function Class:
This is an X-Class API, this function can be invoked from any context.

Definition at line 170 of file hal_icu.h.

◆ _icu_isr_invoke_width_cb

#define _icu_isr_invoke_width_cb ( icup)
Value:
do { \
if (((icup)->state == ICU_ACTIVE) && \
((icup)->config->width_cb != NULL)) \
(icup)->config->width_cb(icup); \
} while (0)
@ ICU_ACTIVE
Definition hal_icu.h:58

Common ISR code, ICU width event.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Not an API, this function is for internal use only.

Definition at line 184 of file hal_icu.h.

◆ _icu_isr_invoke_period_cb

#define _icu_isr_invoke_period_cb ( icup)
Value:
do { \
if (((icup)->state == ICU_ACTIVE) && \
((icup)->config->period_cb != NULL)) \
(icup)->config->period_cb(icup); \
(icup)->state = ICU_ACTIVE; \
} while (0)

Common ISR code, ICU period event.

Note
A period event brings the driver into the ICU_ACTIVE state.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Not an API, this function is for internal use only.

Definition at line 198 of file hal_icu.h.

◆ _icu_isr_invoke_overflow_cb

#define _icu_isr_invoke_overflow_cb ( icup)
Value:
do { \
if ((icup)->config->overflow_cb != NULL && (icup)->state == ICU_ACTIVE) \
(icup)->config->overflow_cb(icup); \
else \
(icup)->state = ICU_WAITING; \
} while (0)

Common ISR code, ICU timer overflow event.

Note
An overflow when in ICU_ACTIVE state with a callback set executes the callback code (supports overflow scaling). Otherwise overflow brings the driver back to the ICU_WAITING state.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Not an API, this function is for internal use only.

Definition at line 216 of file hal_icu.h.

◆ PLATFORM_ICU_USE_ICU1

#define PLATFORM_ICU_USE_ICU1   FALSE

ICUD1 driver enable switch.

If set to TRUE the support for ICUD1 is included.

Note
The default is FALSE.

Definition at line 48 of file hal_icu_lld.h.

◆ icu_lld_get_width

#define icu_lld_get_width ( icup)
Value:
0

Returns the width of the latest pulse.

The pulse width is defined as number of ticks between the start edge and the stop edge.

Parameters
[in]icuppointer to the ICUDriver object
Returns
The number of ticks.
Function Class:
Not an API, this function is for internal use only.

Definition at line 140 of file hal_icu_lld.h.

◆ icu_lld_get_period

#define icu_lld_get_period ( icup)
Value:
0

Returns the width of the latest cycle.

The cycle width is defined as number of ticks between a start edge and the next start edge.

Parameters
[in]icuppointer to the ICUDriver object
Returns
The number of ticks.
Function Class:
Not an API, this function is for internal use only.

Definition at line 152 of file hal_icu_lld.h.

◆ icu_lld_are_notifications_enabled

#define icu_lld_are_notifications_enabled ( icup)
Value:
false

Check on notifications status.

Parameters
[in]icuppointer to the ICUDriver object
Returns
The notifications status.
Return values
falseif notifications are not enabled.
trueif notifications are enabled.
Function Class:
Not an API, this function is for internal use only.

Definition at line 164 of file hal_icu_lld.h.

Typedef Documentation

◆ ICUDriver

typedef struct ICUDriver ICUDriver

Type of a structure representing an ICU driver.

Definition at line 64 of file hal_icu.h.

◆ icucallback_t

typedef void(* icucallback_t) (ICUDriver *icup)

ICU notification callback type.

Parameters
[in]icuppointer to a ICUDriver object

Definition at line 71 of file hal_icu.h.

◆ icufreq_t

typedef uint32_t icufreq_t

ICU frequency type.

Definition at line 71 of file hal_icu_lld.h.

◆ icucnt_t

typedef uint32_t icucnt_t

ICU counter type.

Definition at line 76 of file hal_icu_lld.h.

Enumeration Type Documentation

◆ icustate_t

enum icustate_t

Driver state machine possible states.

Enumerator
ICU_UNINIT 

Not initialized.

ICU_STOP 

Stopped.

ICU_READY 

Ready.

ICU_WAITING 

Waiting for first front.

ICU_ACTIVE 

First front detected.

Definition at line 53 of file hal_icu.h.

◆ icumode_t

enum icumode_t

ICU driver mode.

Enumerator
ICU_INPUT_ACTIVE_HIGH 

Trigger on rising edge.

ICU_INPUT_ACTIVE_LOW 

Trigger on falling edge.

Definition at line 63 of file hal_icu_lld.h.

Function Documentation

◆ icuInit()

void icuInit ( void )

ICU Driver initialization.

Note
This function is implicitly invoked by halInit(), there is no need to explicitly initialize the driver.
Function Class:
Object or module nitializer function.

Definition at line 56 of file hal_icu.c.

References icu_lld_init().

Referenced by halInit().

Here is the call graph for this function:

◆ icuObjectInit()

void icuObjectInit ( ICUDriver * icup)

Initializes the standard part of a ICUDriver structure.

Parameters
[out]icuppointer to the ICUDriver object
Function Class:
Object or module nitializer function.

Definition at line 68 of file hal_icu.c.

References ICUDriver::config, ICU_STOP, and ICUDriver::state.

Referenced by icu_lld_init().

◆ icuStart()

msg_t icuStart ( ICUDriver * icup,
const ICUConfig * config )

Configures and activates the ICU peripheral.

Parameters
[in]icuppointer to the ICUDriver object
[in]configpointer to the ICUConfig object
Returns
The operation status.
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 83 of file hal_icu.c.

References ICUDriver::config, HAL_RET_SUCCESS, icu_lld_start(), ICU_READY, ICU_STOP, osalDbgAssert, osalDbgCheck, osalSysLock(), osalSysUnlock(), and ICUDriver::state.

Here is the call graph for this function:

◆ icuStop()

void icuStop ( ICUDriver * icup)

Deactivates the ICU peripheral.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 120 of file hal_icu.c.

References ICUDriver::config, icu_lld_stop(), ICU_READY, ICU_STOP, osalDbgAssert, osalDbgCheck, osalSysLock(), osalSysUnlock(), and ICUDriver::state.

Here is the call graph for this function:

◆ icuStartCapture()

void icuStartCapture ( ICUDriver * icup)

Starts the input capture.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 143 of file hal_icu.c.

References ICU_READY, icuStartCaptureI, osalDbgAssert, osalDbgCheck, osalSysLock(), osalSysUnlock(), and ICUDriver::state.

Here is the call graph for this function:

◆ icuWaitCapture()

bool icuWaitCapture ( ICUDriver * icup)

Waits for a completed capture.

Note
The operation could be performed in polled mode depending on.
In order to use this function notifications must be disabled.
Precondition
The driver must be in ICU_WAITING or ICU_ACTIVE states.
Postcondition
After the capture is available the driver is in ICU_ACTIVE state. If a capture fails then the driver is in ICU_WAITING state.
Parameters
[in]icuppointer to the ICUDriver object
Returns
The capture status.
Return values
falseif the capture is successful.
trueif a timer overflow occurred.
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 169 of file hal_icu.c.

References ICU_ACTIVE, icu_lld_wait_capture(), ICU_WAITING, icuAreNotificationsEnabledX, osalDbgAssert, osalDbgCheck, osalSysLock(), osalSysUnlock(), and ICUDriver::state.

Here is the call graph for this function:

◆ icuStopCapture()

void icuStopCapture ( ICUDriver * icup)

Stops the input capture.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 193 of file hal_icu.c.

References ICU_ACTIVE, ICU_READY, ICU_WAITING, icuStopCaptureI, osalDbgAssert, osalDbgCheck, osalSysLock(), osalSysUnlock(), and ICUDriver::state.

Here is the call graph for this function:

◆ icuEnableNotifications()

void icuEnableNotifications ( ICUDriver * icup)

Enables notifications.

Precondition
The ICU unit must have been activated using icuStart() and the capture started using icuStartCapture().
Note
If the notification is already enabled then the call has no effect.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 215 of file hal_icu.c.

References ICU_ACTIVE, ICU_WAITING, icuEnableNotificationsI, osalDbgAssert, osalDbgCheck, osalSysLock(), osalSysUnlock(), and ICUDriver::state.

Here is the call graph for this function:

◆ icuDisableNotifications()

void icuDisableNotifications ( ICUDriver * icup)

Disables notifications.

Precondition
The ICU unit must have been activated using icuStart() and the capture started using icuStartCapture().
Note
If the notification is already disabled then the call has no effect.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 236 of file hal_icu.c.

References ICU_ACTIVE, ICU_WAITING, icuDisableNotificationsI, osalDbgAssert, osalDbgCheck, osalSysLock(), osalSysUnlock(), and ICUDriver::state.

Here is the call graph for this function:

◆ icu_lld_init()

void icu_lld_init ( void )

Low level ICU driver initialization.

Function Class:
Not an API, this function is for internal use only.

Definition at line 66 of file hal_icu_lld.c.

References ICUD1, and icuObjectInit().

Referenced by icuInit().

Here is the call graph for this function:

◆ icu_lld_start()

void icu_lld_start ( ICUDriver * icup)

Configures and activates the ICU peripheral.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Not an API, this function is for internal use only.

Definition at line 81 of file hal_icu_lld.c.

References ICU_STOP, ICUD1, and ICUDriver::state.

Referenced by icuStart().

◆ icu_lld_stop()

void icu_lld_stop ( ICUDriver * icup)

Deactivates the ICU peripheral.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Not an API, this function is for internal use only.

Definition at line 100 of file hal_icu_lld.c.

References ICU_READY, ICUD1, and ICUDriver::state.

Referenced by icuStop().

◆ icu_lld_start_capture()

void icu_lld_start_capture ( ICUDriver * icup)

Starts the input capture.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Not an API, this function is for internal use only.

Definition at line 119 of file hal_icu_lld.c.

◆ icu_lld_wait_capture()

bool icu_lld_wait_capture ( ICUDriver * icup)

Waits for a completed capture.

Note
The operation is performed in polled mode.
In order to use this function notifications must be disabled.
Parameters
[in]icuppointer to the ICUDriver object
Returns
The capture status.
Return values
falseif the capture is successful.
trueif a timer overflow occurred.
Function Class:
Not an API, this function is for internal use only.

Definition at line 136 of file hal_icu_lld.c.

Referenced by icuWaitCapture().

◆ icu_lld_stop_capture()

void icu_lld_stop_capture ( ICUDriver * icup)

Stops the input capture.

Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Not an API, this function is for internal use only.

Definition at line 150 of file hal_icu_lld.c.

◆ icu_lld_enable_notifications()

void icu_lld_enable_notifications ( ICUDriver * icup)

Enables notifications.

Precondition
The ICU unit must have been activated using icuStart() and the capture started using icuStartCapture().
Note
If the notification is already enabled then the call has no effect.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 165 of file hal_icu_lld.c.

◆ icu_lld_disable_notifications()

void icu_lld_disable_notifications ( ICUDriver * icup)

Disables notifications.

Precondition
The ICU unit must have been activated using icuStart() and the capture started using icuStartCapture().
Note
If the notification is already disabled then the call has no effect.
Parameters
[in]icuppointer to the ICUDriver object
Function Class:
Normal API, this function can be invoked by regular system threads but not from within a lock zone.

Definition at line 180 of file hal_icu_lld.c.

Variable Documentation

◆ ICUD1

ICUDriver ICUD1

ICUD1 driver identifier.

Note
The driver ICUD1 allocates the complex timer TIM1 when enabled.

Definition at line 42 of file hal_icu_lld.c.

Referenced by icu_lld_init(), icu_lld_start(), and icu_lld_stop().