mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #20020 from gompper/periph/freqm
drivers/include/periph: add FREQM peripheral driver
This commit is contained in:
commit
c93a5b84a3
@ -18,6 +18,7 @@ config BOARD_SAME54_XPRO
|
||||
select HAS_PERIPH_RTC
|
||||
select HAS_PERIPH_RTT
|
||||
select HAS_PERIPH_PWM
|
||||
select HAS_PERIPH_FREQM
|
||||
select HAS_PERIPH_SDMMC
|
||||
select HAS_PERIPH_SPI
|
||||
select HAS_PERIPH_TIMER
|
||||
|
@ -14,6 +14,7 @@ FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_usbdev
|
||||
FEATURES_PROVIDED += periph_freqm
|
||||
|
||||
# Put other features for this board (in alphabetical order)
|
||||
FEATURES_PROVIDED += riotboot
|
||||
|
@ -3,4 +3,11 @@
|
||||
# debugger.
|
||||
TTY_BOARD_FILTER := --model 'EDBG CMSIS-DAP'
|
||||
|
||||
# Overwrite GCLK definitions, so that GCLK_IO[2..7] can be connected to GPIOs.
|
||||
# This way the frequency of signals, connected to these pins, can be measured
|
||||
# with the FREQM peripheral.
|
||||
CFLAGS += -DSAM0_GCLK_TIMER=8
|
||||
CFLAGS += -DSAM0_GCLK_PERIPH=9
|
||||
CFLAGS += -DSAM0_GCLK_100MHZ=10
|
||||
|
||||
include $(RIOTMAKE)/boards/sam0.inc.mk
|
||||
|
@ -406,6 +406,18 @@ static const sam0_common_gmac_config_t sam_gmac_config[] = {
|
||||
};
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name FREQM peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
static const freqm_config_t freqm_config[] = {
|
||||
{
|
||||
.pin = GPIO_PIN(PB, 17),
|
||||
.gclk_src = SAM0_GCLK_32KHZ
|
||||
}
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -945,6 +945,14 @@ typedef struct {
|
||||
*/
|
||||
#define WDT_HAS_INIT (1)
|
||||
|
||||
/**
|
||||
* @brief Frequency meter configuration
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_t pin; /**< GPIO at which the frequency is to be measured */
|
||||
uint8_t gclk_src; /**< GCLK source select for reference */
|
||||
} freqm_config_t;
|
||||
|
||||
#if defined(REV_DMAC) || DOXYGEN
|
||||
/**
|
||||
* @name sam0 DMA peripheral
|
||||
|
259
cpu/sam0_common/periph/freqm.c
Normal file
259
cpu/sam0_common/periph/freqm.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2023 ML!PA Consulting GmbH
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_sam0_common
|
||||
* @ingroup drivers_periph_freqm
|
||||
* @{
|
||||
*
|
||||
* @file freqm.c
|
||||
* @brief Frequency meter driver implementation
|
||||
*
|
||||
* @author Urs Gompper <urs.gompper@ml-pa.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "periph/freqm.h"
|
||||
|
||||
/* TODO: Remove defines when Microchip vendor files (which include these
|
||||
* defines) get updated.
|
||||
*/
|
||||
/* FREQM_GCLK_ID_REF is defined in newer versions of vendor header files */
|
||||
#ifndef FREQM_GCLK_ID_REF
|
||||
#define FREQM_GCLK_ID_REF (FREQM_GCLK_ID_MSR + 1)
|
||||
#endif
|
||||
|
||||
/* Channel Enable Mask */
|
||||
#define GCLK_PCHCTRL_CHEN_Msk (_U_(0x1) << GCLK_PCHCTRL_CHEN_Pos)
|
||||
/* Enable Mask */
|
||||
#define FREQM_CTRLA_ENABLE_Msk (_U_(0x1) << FREQM_CTRLA_ENABLE_Pos)
|
||||
/* Start Measurement Mask */
|
||||
#define FREQM_CTRLB_START_Msk (_U_(0x1) << FREQM_CTRLB_START_Pos)
|
||||
/* Measurement Done Interrupt Enable Mask */
|
||||
#define FREQM_INTENSET_DONE_Msk (_U_(0x1) << FREQM_INTENSET_DONE_Pos)
|
||||
/* Measurement Done Mask */
|
||||
#define FREQM_INTFLAG_DONE_Msk (_U_(0x1) << FREQM_INTFLAG_DONE_Pos)
|
||||
/* FREQM Status Mask */
|
||||
#define FREQM_STATUS_BUSY_Msk (_U_(0x1) << FREQM_STATUS_BUSY_Pos)
|
||||
/* Sticky Count Value Overflow Mask */
|
||||
#define FREQM_STATUS_OVF_Msk (_U_(0x1) << FREQM_STATUS_OVF_Pos)
|
||||
|
||||
/* check if pin has peripheral function GCLK */
|
||||
static int _freqm_pin(gpio_t pin)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(gclk_io_pins); ++i) {
|
||||
if (gclk_io_pins[i] == pin) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _gclk_connect(uint8_t id, uint8_t src, uint32_t flags)
|
||||
{
|
||||
GCLK->GENCTRL[id].reg = GCLK_GENCTRL_SRC(src) | GCLK_GENCTRL_GENEN | flags | GCLK_GENCTRL_IDC;
|
||||
while (GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL(id)) {}
|
||||
}
|
||||
|
||||
static int _freqm_gpio_init(gpio_t msr_gpio_src, uint8_t *gclk_io_id)
|
||||
{
|
||||
/* Check if selected pin has peripheral function GCLK */
|
||||
int index = _freqm_pin(msr_gpio_src);
|
||||
|
||||
/* Fail assertion if pin has no peripheral function GCLK */
|
||||
assert(index > 0);
|
||||
|
||||
/* Lookup which GCLK_IO[x] must be used */
|
||||
*gclk_io_id = gclk_io_ids[index];
|
||||
/* GCLK_IO[0] and GCLK_IO[1] can't be used here. They are associated with
|
||||
GCLKGEN[0] and GCLKGEN[1] respectively. These in turn are used by
|
||||
SAM0_GCLK_MAIN and SAM0_GCLK_32KHZ respectively */
|
||||
assert(*gclk_io_id > 1);
|
||||
|
||||
/* Initialize GPIO as input */
|
||||
gpio_init(msr_gpio_src, GPIO_IN);
|
||||
/* Enable peripheral function GCLK/IO on GPIO */
|
||||
gpio_init_mux(msr_gpio_src, GPIO_MUX_M);
|
||||
/* Connect GCLK_IO[*gclk_io_id] with input pin */
|
||||
_gclk_connect(*gclk_io_id, GCLK_SOURCE_GCLKIN, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _freqm_clock_init(uint8_t pin, uint8_t gclk_src)
|
||||
{
|
||||
/* Selection of the Generator and write Lock for FREQM_MSR */
|
||||
GCLK->PCHCTRL[FREQM_GCLK_ID_MSR].reg = GCLK_PCHCTRL_GEN(pin) | GCLK_PCHCTRL_CHEN_Msk;
|
||||
/* Wait for synchronization */
|
||||
while ((GCLK->PCHCTRL[FREQM_GCLK_ID_MSR].reg & GCLK_PCHCTRL_CHEN_Msk) !=
|
||||
GCLK_PCHCTRL_CHEN_Msk) {}
|
||||
|
||||
/* Selection of the Generator and write Lock for FREQM_REF */
|
||||
GCLK->PCHCTRL[FREQM_GCLK_ID_REF].reg = GCLK_PCHCTRL_GEN(gclk_src) | GCLK_PCHCTRL_CHEN_Msk;
|
||||
/* Wait for synchronization */
|
||||
while ((GCLK->PCHCTRL[FREQM_GCLK_ID_REF].reg & GCLK_PCHCTRL_CHEN_Msk) !=
|
||||
GCLK_PCHCTRL_CHEN_Msk) {}
|
||||
}
|
||||
|
||||
static struct {
|
||||
freqm_cb_t callback;
|
||||
void *context;
|
||||
freqm_t idx;
|
||||
uint8_t period_cnt;
|
||||
} freqm_obj;
|
||||
|
||||
struct _sync_ctx {
|
||||
mutex_t lock; /**< Mutex for blocking till measurement is done */
|
||||
uint32_t hz; /**< Measured frequency in Hz */
|
||||
bool overflow; /**< Overflow in FREQM counter */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Mutex for locking the FREQM device
|
||||
*/
|
||||
static mutex_t msr_lock = MUTEX_INIT;
|
||||
|
||||
static void _freqm_enable(uint8_t refnum)
|
||||
{
|
||||
mutex_lock(&msr_lock);
|
||||
|
||||
/* Save refnum for frequency calculation */
|
||||
freqm_obj.period_cnt = refnum;
|
||||
|
||||
FREQM->CFGA.reg = (uint16_t)(FREQM_CFGA_REFNUM(refnum));
|
||||
|
||||
/* Enable DONE Interrupt */
|
||||
FREQM->INTENSET.reg = FREQM_INTENSET_DONE_Msk;
|
||||
|
||||
/* Enable FREQM */
|
||||
FREQM->CTRLA.reg = FREQM_CTRLA_ENABLE_Msk;
|
||||
|
||||
/* Wait for Sync */
|
||||
while ((FREQM->SYNCBUSY.reg) != 0U) {}
|
||||
}
|
||||
|
||||
static void _freqm_disable(void)
|
||||
{
|
||||
/* Disable DONE Interrupt */
|
||||
FREQM->INTENCLR.reg = FREQM_INTENCLR_MASK;
|
||||
/* Disable FREQM */
|
||||
FREQM->CTRLA.reg &= ~FREQM_CTRLA_ENABLE_Msk;
|
||||
/* Wait for Sync */
|
||||
while ((FREQM->SYNCBUSY.reg) != 0U) {}
|
||||
|
||||
mutex_unlock(&msr_lock);
|
||||
}
|
||||
|
||||
bool _freqm_get_measurement(uint32_t *result)
|
||||
{
|
||||
const freqm_config_t *config = &freqm_config[freqm_obj.idx];
|
||||
|
||||
/* Calculate measured frequency */
|
||||
uint64_t result_tmp = FREQM->VALUE.reg * (uint64_t)(sam0_gclk_freq(config->gclk_src));
|
||||
|
||||
result_tmp = result_tmp / freqm_obj.period_cnt;
|
||||
*result = (uint32_t)result_tmp;
|
||||
|
||||
/* Read overflow status */
|
||||
bool overflow_condition = ((int)FREQM->STATUS.reg & FREQM_STATUS_OVF_Msk);
|
||||
|
||||
/* Clear overflow status */
|
||||
FREQM->STATUS.reg = FREQM_STATUS_OVF_Msk;
|
||||
|
||||
return overflow_condition;
|
||||
}
|
||||
|
||||
uint32_t _us_to_ref_clock_counts(uint32_t period_us, uint8_t clock_id)
|
||||
{
|
||||
uint64_t clk_cnt = (uint64_t)period_us * sam0_gclk_freq(clock_id) / US_PER_SEC;
|
||||
|
||||
if (clk_cnt > UINT8_MAX) {
|
||||
return UINT8_MAX;
|
||||
}
|
||||
else if (clk_cnt == 0) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return clk_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
static void _sync_cb(uint32_t res, bool overflow, void *_ctx)
|
||||
{
|
||||
struct _sync_ctx *ctx = _ctx;
|
||||
|
||||
ctx->hz = res;
|
||||
ctx->overflow = overflow;
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
int freqm_frequency_get(freqm_t idx, uint32_t *result, uint32_t period_us)
|
||||
{
|
||||
struct _sync_ctx ctx = { .lock = MUTEX_INIT_LOCKED };
|
||||
|
||||
/* Invoke non-blocking FREQM measure function */
|
||||
freqm_frequency_get_async(idx, _sync_cb, &ctx, period_us);
|
||||
|
||||
/* Block until measurement is done */
|
||||
mutex_lock(&ctx.lock);
|
||||
|
||||
*result = ctx.hz;
|
||||
return ctx.overflow ? -EOVERFLOW : 0;
|
||||
}
|
||||
|
||||
void freqm_frequency_get_async(freqm_t idx, freqm_cb_t freqm_cb, void *context, uint32_t period_us)
|
||||
{
|
||||
const freqm_config_t *config = &freqm_config[idx];
|
||||
|
||||
uint8_t refnum = _us_to_ref_clock_counts(period_us, config->gclk_src);
|
||||
|
||||
_freqm_enable(refnum);
|
||||
|
||||
/* Register callback function */
|
||||
freqm_obj.callback = freqm_cb;
|
||||
freqm_obj.context = context;
|
||||
freqm_obj.idx = idx;
|
||||
|
||||
/* Clear the Done Interrupt flag */
|
||||
FREQM->INTFLAG.reg = FREQM_INTFLAG_DONE_Msk;
|
||||
|
||||
/* Start measurement */
|
||||
FREQM->CTRLB.reg = FREQM_CTRLB_START_Msk;
|
||||
}
|
||||
|
||||
void irq_freqm(void)
|
||||
{
|
||||
/* Clear the Done Interrupt flag */
|
||||
FREQM->INTFLAG.reg = FREQM_INTFLAG_DONE_Msk;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
bool overflow_condition = _freqm_get_measurement(&result);
|
||||
|
||||
/* Invoke the callback function */
|
||||
freqm_obj.callback(result, overflow_condition, freqm_obj.context);
|
||||
|
||||
_freqm_disable();
|
||||
}
|
||||
|
||||
void freqm_init(freqm_t idx)
|
||||
{
|
||||
uint8_t gclk_io_id = 0;
|
||||
const freqm_config_t *config = &freqm_config[idx];
|
||||
|
||||
/* Sanity check configuration */
|
||||
assert(config->gclk_src <= GCLK_GEN_NUM_MSB);
|
||||
|
||||
_freqm_gpio_init(config->pin, &gclk_io_id);
|
||||
_freqm_clock_init(gclk_io_id, config->gclk_src);
|
||||
|
||||
/* Enable interrupt */
|
||||
NVIC_EnableIRQ(FREQM_IRQn);
|
||||
}
|
@ -325,6 +325,9 @@ void cpu_init(void)
|
||||
#ifdef MODULE_PERIPH_PM
|
||||
| MCLK_APBAMASK_PM
|
||||
#endif
|
||||
#ifdef MODULE_PERIPH_FREQM
|
||||
| MCLK_APBAMASK_FREQM
|
||||
#endif
|
||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||
| MCLK_APBAMASK_EIC
|
||||
#endif
|
||||
|
@ -70,13 +70,19 @@ enum {
|
||||
* @name SAMD5x GCLK definitions
|
||||
* @{
|
||||
*/
|
||||
enum {
|
||||
SAM0_GCLK_MAIN = 0, /**< 120 MHz main clock */
|
||||
SAM0_GCLK_32KHZ, /**< 32 kHz clock */
|
||||
SAM0_GCLK_TIMER, /**< 4-8 MHz clock for xTimer */
|
||||
SAM0_GCLK_PERIPH, /**< 12-48 MHz (DFLL) clock */
|
||||
SAM0_GCLK_100MHZ, /**< 100MHz FDPLL clock */
|
||||
};
|
||||
#define SAM0_GCLK_MAIN 0 /**< 120 MHz main clock */
|
||||
#ifndef SAM0_GCLK_32KHZ
|
||||
#define SAM0_GCLK_32KHZ 1 /**< 32 kHz clock */
|
||||
#endif
|
||||
#ifndef SAM0_GCLK_TIMER
|
||||
#define SAM0_GCLK_TIMER 2 /**< 4-8 MHz clock for xTimer */
|
||||
#endif
|
||||
#ifndef SAM0_GCLK_PERIPH
|
||||
#define SAM0_GCLK_PERIPH 3 /**< 12-48 MHz (DFLL) clock */
|
||||
#endif
|
||||
#ifndef SAM0_GCLK_100MHZ
|
||||
#define SAM0_GCLK_100MHZ 4 /**< 100MHz FDPLL clock */
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -198,6 +204,28 @@ static const gpio_t rtc_tamper_pins[RTC_NUM_OF_TAMPERS] = {
|
||||
GPIO_PIN(PC, 0), GPIO_PIN(PC, 1)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Pins that have peripheral function GCLK
|
||||
*/
|
||||
static const gpio_t gclk_io_pins[] = {
|
||||
GPIO_PIN(PA, 10), GPIO_PIN(PA, 11), GPIO_PIN(PA, 14),
|
||||
GPIO_PIN(PA, 15), GPIO_PIN(PA, 16), GPIO_PIN(PA, 17),
|
||||
GPIO_PIN(PA, 27), GPIO_PIN(PA, 30), GPIO_PIN(PB, 10),
|
||||
GPIO_PIN(PB, 11), GPIO_PIN(PB, 12), GPIO_PIN(PB, 13),
|
||||
GPIO_PIN(PB, 14), GPIO_PIN(PB, 15), GPIO_PIN(PB, 16),
|
||||
GPIO_PIN(PB, 17), GPIO_PIN(PB, 18), GPIO_PIN(PB, 19),
|
||||
GPIO_PIN(PB, 20), GPIO_PIN(PB, 21), GPIO_PIN(PB, 22),
|
||||
GPIO_PIN(PB, 23)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GCLK IDs of pins that have peripheral function GCLK - This maps
|
||||
* directly to gclk_io_pins.
|
||||
*/
|
||||
static const uint8_t gclk_io_ids[] = {
|
||||
4, 5, 0, 1, 2, 3, 1, 0, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief NVM User Page Mapping - Dedicated Entries
|
||||
* Config values will be applied at power-on.
|
||||
|
1
dist/tools/doccheck/generic_exclude_patterns
vendored
1
dist/tools/doccheck/generic_exclude_patterns
vendored
@ -20,6 +20,7 @@ warning: Member EPD_BW_SPI_DISPLAY_UPDATE_OPTION_[A-Z0-9_]* \(macro definition\)
|
||||
warning: Member EPD_BW_SPI_WAIT_[A-Z0-9_]* \(macro definition\) of
|
||||
warning: Member F_CPU \(macro definition\) of
|
||||
warning: Member F_RC_OSCILLATOR \(macro definition\) of
|
||||
warning: Member freqm_config\[\] \(variable\) of
|
||||
warning: Member FXOS8700_PARAM_ADDR \(macro definition\) of
|
||||
warning: Member FXOS8700_PARAM_I2C \(macro definition\) of
|
||||
warning: Member FXOS8700_PARAM_RENEW_INTERVAL \(macro definition\) of
|
||||
|
100
drivers/include/periph/freqm.h
Normal file
100
drivers/include/periph/freqm.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2023 ML!PA Consulting GmbH
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_periph_freqm FREQM
|
||||
* @ingroup drivers_periph
|
||||
* @brief FREQM peripheral driver interface
|
||||
*
|
||||
* This interface allows to configure and use the Frequency Meter (FREQM)
|
||||
* peripheral.
|
||||
*
|
||||
* The Frequency Meter uses the frequency of a known reference clock to
|
||||
* determine the frequency of a signal connected via GPIO.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief FREQM peripheral driver interface definitions
|
||||
*
|
||||
* @author Urs Gompper <urs.gompper@ml-pa.com>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_FREQM_H
|
||||
#define PERIPH_FREQM_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <mutex.h>
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "time_units.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Frequency meter callback function.
|
||||
* When a measurement is done the callbackfunction is called.
|
||||
*
|
||||
* @param result measured frequency in hz
|
||||
* @param overflow overflow in sticky counter
|
||||
* @param context pointer to user defined context data
|
||||
*/
|
||||
typedef void (*freqm_cb_t)(uint32_t result, bool overflow, void *context);
|
||||
|
||||
/**
|
||||
* @brief Define default Frequency meter type identifier
|
||||
*/
|
||||
#ifndef HAVE_FREQM_T
|
||||
typedef uint_fast8_t freqm_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the frequency meter
|
||||
*
|
||||
* @param[in] idx index of the configuration
|
||||
*/
|
||||
void freqm_init(freqm_t idx);
|
||||
|
||||
/**
|
||||
* @brief Read number of periods of measured clock and calculate its frequency
|
||||
*
|
||||
* This function returns after triggering the measurement and calls
|
||||
* @p freqm_callback , with the calculated result and @p context , when the
|
||||
* measurement is done.
|
||||
*
|
||||
* @param[in] idx index of the configuration
|
||||
* @param[in] freqm_cb callback function when measurement is ready
|
||||
* @param[in] context context for the callback function
|
||||
* @param[in] period_us measurement duration in microseconds
|
||||
*/
|
||||
void freqm_frequency_get_async(freqm_t idx, freqm_cb_t freqm_cb, void *context,
|
||||
uint32_t period_us);
|
||||
|
||||
/**
|
||||
* @brief Read number of periods of measured clock and calculate its frequency
|
||||
*
|
||||
* This function uses a blocking mutex to wait for the measurement to finish.
|
||||
*
|
||||
* @param[in] idx index of the configuration
|
||||
* @param[out] result calculated frequency
|
||||
* @param[in] period_us measurement duration in microseconds
|
||||
*
|
||||
* @return -EOVERFLOW if FREQM sticky counter has an overflow
|
||||
* @return 0 on success
|
||||
*/
|
||||
int freqm_frequency_get(freqm_t idx, uint32_t *result, uint32_t period_us);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
#endif /* PERIPH_FREQM_H */
|
@ -139,6 +139,10 @@ config MODULE_PERIPH_RTT
|
||||
depends on HAS_PERIPH_RTT
|
||||
select MODULE_PERIPH_COMMON
|
||||
|
||||
config MODULE_PERIPH_FREQM
|
||||
bool "Frequency Meter driver"
|
||||
depends on HAS_PERIPH_FREQM
|
||||
|
||||
config MODULE_PERIPH_RTT_SET_COUNTER
|
||||
bool "rtc_set_counter() implementation in the RTT peripheral driver"
|
||||
depends on HAS_PERIPH_RTT_SET_COUNTER && MODULE_PERIPH_RTT
|
||||
|
@ -263,6 +263,11 @@ config HAS_PERIPH_FLASHPAGE_RWEE
|
||||
help
|
||||
Indicates that the Flashpage peripheral is of the Read While Write.
|
||||
|
||||
config HAS_PERIPH_FREQM
|
||||
bool
|
||||
help
|
||||
Indicates that a Frequency Meter peripheral is present.
|
||||
|
||||
config HAS_PERIPH_GPIO
|
||||
bool
|
||||
help
|
||||
|
7
tests/periph/freqm/Makefile
Normal file
7
tests/periph/freqm/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
BOARD ?= same54-xpro
|
||||
|
||||
include ../Makefile.periph_common
|
||||
|
||||
USEMODULE += periph_freqm
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
14
tests/periph/freqm/README.md
Normal file
14
tests/periph/freqm/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
Peripheral FREQM Test Application
|
||||
=====================================
|
||||
|
||||
This application tests the frequency meter (FREQM) functionality. This is done
|
||||
by measuring the frequency of a clock, connected to a GPIO, with an internal
|
||||
clock as reference.
|
||||
|
||||
Expected Output on Success
|
||||
--------------------------
|
||||
|
||||
main(): This is RIOT! (Version: <INSERT VERSION HERE>)
|
||||
FREQM peripheral driver test
|
||||
Measured clock frequency: <MEASURED CLOCK FREQUENCY> Hz
|
||||
Test run finished.
|
52
tests/periph/freqm/main.c
Normal file
52
tests/periph/freqm/main.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2023 ML!PA Consulting GmbH
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Application to test functionality of the frequency meter
|
||||
* peripheral
|
||||
*
|
||||
* @author Urs Gompper <urs.gompper@ml-pa.com>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "periph/freqm.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("FREQM peripheral driver test");
|
||||
|
||||
/* Initialize frequency meter peripheral */
|
||||
freqm_init(0);
|
||||
|
||||
uint32_t period_us = UINT32_MAX;
|
||||
uint32_t freq_hz = 0;
|
||||
|
||||
/* Measure in blocking mode */
|
||||
if (!freqm_frequency_get(0, &freq_hz, period_us)) {
|
||||
printf("Measured Clock Frequency: %ld Hz\n", freq_hz);
|
||||
}
|
||||
else {
|
||||
puts("Overflow occurred to the FREQM value counter!");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
puts("Test run finished.");
|
||||
|
||||
/* main thread exits */
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user