pcnt: support esp32c6

pull/9803/head
morris 2022-08-31 18:31:47 +08:00
rodzic 631cef47f6
commit 6539aa2275
11 zmienionych plików z 544 dodań i 6 usunięć

Wyświetl plik

@ -281,8 +281,11 @@ TEST_CASE("pcnt_quadrature_decode_event", "[pcnt]")
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_point(unit, 50));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_point(unit, 100));
// Clear internal counter, and make the watch points take effect
#if !SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
// the above added watch point won't take effect at once, unless we clear the internal counter manually
TEST_ESP_OK(pcnt_unit_clear_count(unit));
#endif
// start unit should fail if it's not enabled yet
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_start(unit));
TEST_ESP_OK(pcnt_unit_enable(unit));

Wyświetl plik

@ -24,6 +24,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
return PCR_SARADC_CLK_EN;
case PERIPH_RMT_MODULE:
return PCR_RMT_CLK_EN;
case PERIPH_PCNT_MODULE:
return PCR_PCNT_CLK_EN;
case PERIPH_LEDC_MODULE:
return PCR_LEDC_CLK_EN;
case PERIPH_UART0_MODULE:
@ -88,6 +90,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
return PCR_SARADC_RST_EN;
case PERIPH_RMT_MODULE:
return PCR_RMT_RST_EN;
case PERIPH_PCNT_MODULE:
return PCR_PCNT_RST_EN;
case PERIPH_LEDC_MODULE:
return PCR_LEDC_RST_EN;
case PERIPH_UART0_MODULE:
@ -176,6 +180,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
return PCR_SARADC_CONF_REG;
case PERIPH_RMT_MODULE:
return PCR_RMT_CONF_REG;
case PERIPH_PCNT_MODULE:
return PCR_PCNT_CONF_REG;
case PERIPH_LEDC_MODULE:
return PCR_LEDC_CONF_REG;
case PERIPH_UART0_MODULE:
@ -226,6 +232,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
return PCR_SARADC_CONF_REG;
case PERIPH_RMT_MODULE:
return PCR_RMT_CONF_REG;
case PERIPH_PCNT_MODULE:
return PCR_PCNT_CONF_REG;
case PERIPH_LEDC_MODULE:
return PCR_LEDC_CONF_REG;
case PERIPH_UART0_MODULE:

Wyświetl plik

@ -0,0 +1,426 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32-C6 PCNT register operations
#pragma once
#include <limits.h>
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
#include "hal/pcnt_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL)
#define PCNT_LL_MAX_GLITCH_WIDTH 1023
#define PCNT_LL_MAX_LIM SHRT_MAX
#define PCNT_LL_MIN_LIN SHRT_MIN
typedef enum {
PCNT_LL_WATCH_EVENT_INVALID = -1,
PCNT_LL_WATCH_EVENT_THRES1,
PCNT_LL_WATCH_EVENT_THRES0,
PCNT_LL_WATCH_EVENT_LOW_LIMIT,
PCNT_LL_WATCH_EVENT_HIGH_LIMIT,
PCNT_LL_WATCH_EVENT_ZERO_CROSS,
PCNT_LL_WATCH_EVENT_MAX
} pcnt_ll_watch_event_id_t;
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
/**
* @brief Set PCNT channel edge action
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param channel PCNT channel number
* @param pos_act Counter action when detecting positive edge
* @param neg_act Counter action when detecting negative edge
*/
static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act)
{
if (channel == 0) {
hw->conf_unit[unit].conf0.ch0_pos_mode = pos_act;
hw->conf_unit[unit].conf0.ch0_neg_mode = neg_act;
} else {
hw->conf_unit[unit].conf0.ch1_pos_mode = pos_act;
hw->conf_unit[unit].conf0.ch1_neg_mode = neg_act;
}
}
/**
* @brief Set PCNT channel level action
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param channel PCNT channel number
* @param high_act Counter action when control signal is high level
* @param low_act Counter action when control signal is low level
*/
static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act)
{
if (channel == 0) {
hw->conf_unit[unit].conf0.ch0_hctrl_mode = high_act;
hw->conf_unit[unit].conf0.ch0_lctrl_mode = low_act;
} else {
hw->conf_unit[unit].conf0.ch1_hctrl_mode = high_act;
hw->conf_unit[unit].conf0.ch1_lctrl_mode = low_act;
}
}
/**
* @brief Get pulse counter value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit Pulse Counter unit number
* @return PCNT count value (a signed integer)
*/
__attribute__((always_inline))
static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit)
{
pcnt_un_cnt_reg_t cnt_reg = hw->cnt_unit[unit];
int16_t value = cnt_reg.pulse_cnt;
return value;
}
/**
* @brief Pause PCNT counter of PCNT unit
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
*/
__attribute__((always_inline))
static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit)
{
hw->ctrl.val |= 1 << (2 * unit + 1);
}
/**
* @brief Resume counting for PCNT counter
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number, select from uint32_t
*/
__attribute__((always_inline))
static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit)
{
hw->ctrl.val &= ~(1 << (2 * unit + 1));
}
/**
* @brief Clear PCNT counter value to zero
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number, select from uint32_t
*/
__attribute__((always_inline))
static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit)
{
hw->ctrl.val |= 1 << (2 * unit);
hw->ctrl.val &= ~(1 << (2 * unit));
}
/**
* @brief Enable PCNT interrupt for PCNT unit
* @note Each PCNT unit has five watch point events that share the same interrupt bit.
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit_mask PCNT units mask
* @param enable True to enable interrupt, False to disable interrupt
*/
static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable)
{
if (enable) {
hw->int_ena.val |= unit_mask;
} else {
hw->int_ena.val &= ~unit_mask;
}
}
/**
* @brief Get PCNT interrupt status
*
* @param hw Peripheral PCNT hardware instance address.
* @return Interrupt status word
*/
__attribute__((always_inline))
static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw)
{
return hw->int_st.val;
}
/**
* @brief Clear PCNT interrupt status
*
* @param hw Peripheral PCNT hardware instance address.
* @param status value to clear interrupt status
*/
__attribute__((always_inline))
static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
{
hw->int_clr.val = status;
}
/**
* @brief Enable PCNT high limit event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.thr_h_lim_en = enable;
}
/**
* @brief Enable PCNT low limit event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.thr_l_lim_en = enable;
}
/**
* @brief Enable PCNT zero cross event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.thr_zero_en = enable;
}
/**
* @brief Enable PCNT threshold event
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param thres Threshold ID
* @param enable true to enable, false to disable
*/
static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable)
{
if (thres == 0) {
hw->conf_unit[unit].conf0.thr_thres0_en = enable;
} else {
hw->conf_unit[unit].conf0.thr_thres1_en = enable;
}
}
/**
* @brief Disable all PCNT threshold events
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit unit number
*/
static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit)
{
hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_WATCH_EVENT_MASK << 11);
}
/**
* @brief Set PCNT high limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param value PCNT high limit value
*/
static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
{
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
conf2_reg.cnt_h_lim = value;
hw->conf_unit[unit].conf2 = conf2_reg;
}
/**
* @brief Set PCNT low limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param value PCNT low limit value
*/
static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
{
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
conf2_reg.cnt_l_lim = value;
hw->conf_unit[unit].conf2 = conf2_reg;
}
/**
* @brief Set PCNT threshold value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param thres Threshold ID
* @param value PCNT threshold value
*/
static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value)
{
pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1;
if (thres == 0) {
conf1_reg.cnt_thres0 = value;
} else {
conf1_reg.cnt_thres1 = value;
}
hw->conf_unit[unit].conf1 = conf1_reg;
}
/**
* @brief Get PCNT high limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return PCNT high limit value
*/
static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit)
{
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
int16_t value = conf2_reg.cnt_h_lim ;
return value;
}
/**
* @brief Get PCNT low limit value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return PCNT high limit value
*/
static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit)
{
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
int16_t value = conf2_reg.cnt_l_lim ;
return value;
}
/**
* @brief Get PCNT threshold value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param thres Threshold ID
* @return PCNT threshold value
*/
static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres)
{
int16_t value;
pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1;
if (thres == 0) {
value = conf1_reg.cnt_thres0 ;
} else {
value = conf1_reg.cnt_thres1 ;
}
return value;
}
/**
* @brief Get PCNT unit runtime status
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return PCNT unit runtime status
*/
static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit)
{
return hw->status_unit[unit].val;
}
/**
* @brief Get PCNT zero cross mode
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return Zero cross mode
*/
__attribute__((always_inline))
static inline pcnt_unit_zero_cross_mode_t pcnt_ll_get_zero_cross_mode(pcnt_dev_t *hw, uint32_t unit)
{
return hw->status_unit[unit].val & 0x03;
}
/**
* @brief Get PCNT event status
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return Event status word
*/
__attribute__((always_inline))
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit)
{
return hw->status_unit[unit].val >> 2;
}
/**
* @brief Set PCNT glitch filter threshold
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
* Any pulses lasting shorter than this will be ignored when the filter is enabled.
*/
static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val)
{
hw->conf_unit[unit].conf0.filter_thres = filter_val;
}
/**
* @brief Get PCNT glitch filter threshold
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @return glitch filter threshold
*/
static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit)
{
return hw->conf_unit[unit].conf0.filter_thres ;
}
/**
* @brief Enable PCNT glitch filter
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param enable True to enable the filter, False to disable the filter
*/
static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable)
{
hw->conf_unit[unit].conf0.filter_en = enable;
}
/**
* @brief Get interrupt status register address.
*
* @param hw Beginning address of the peripheral registers.
*
* @return Interrupt status register address
*/
static inline volatile void *pcnt_ll_get_intr_status_reg(pcnt_dev_t *hw)
{
return &hw->int_st.val;
}
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -7,6 +7,7 @@ set(srcs
"interrupts.c"
"spi_periph.c"
"ledc_periph.c"
"pcnt_periph.c"
"rmt_periph.c"
"i2s_periph.c"
"i2c_periph.c"

Wyświetl plik

@ -7,6 +7,10 @@ config SOC_GDMA_SUPPORTED
bool
default y
config SOC_PCNT_SUPPORTED
bool
default y
config SOC_BT_SUPPORTED
bool
default y
@ -343,6 +347,26 @@ config SOC_MPU_REGION_WO_SUPPORTED
bool
default n
config SOC_PCNT_GROUPS
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int
default 4
config SOC_PCNT_CHANNELS_PER_UNIT
int
default 2
config SOC_PCNT_THRES_POINT_PER_UNIT
int
default 2
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y
config SOC_RMT_GROUPS
int
default 1

Wyświetl plik

@ -11,8 +11,8 @@
extern "C" {
#endif
#define GPIO_MATRIX_CONST_ONE_INPUT (0x1E)
#define GPIO_MATRIX_CONST_ZERO_INPUT (0x1F)
#define GPIO_MATRIX_CONST_ONE_INPUT (0x38)
#define GPIO_MATRIX_CONST_ZERO_INPUT (0x3C)
#ifdef __cplusplus
}

Wyświetl plik

@ -21,6 +21,7 @@ typedef enum {
PERIPH_TIMG1_MODULE,
PERIPH_UHCI0_MODULE,
PERIPH_RMT_MODULE,
PERIPH_PCNT_MODULE,
PERIPH_SPI_MODULE, //SPI1
PERIPH_SPI2_MODULE, //SPI2
PERIPH_TWAI0_MODULE,

Wyświetl plik

@ -28,6 +28,7 @@
// #define SOC_ADC_SUPPORTED 1 // TODO: IDF-5310
// #define SOC_DEDICATED_GPIO_SUPPORTED 1 // TODO: IDF-5331
#define SOC_GDMA_SUPPORTED 1
#define SOC_PCNT_SUPPORTED 1
// #define SOC_TWAI_SUPPORTED 1 // TODO: IDF-5313
#define SOC_BT_SUPPORTED 1
#define SOC_ASYNC_MEMCPY_SUPPORTED 1
@ -206,6 +207,13 @@
#define SOC_MPU_REGION_RO_SUPPORTED 0
#define SOC_MPU_REGION_WO_SUPPORTED 0
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS 1U
#define SOC_PCNT_UNITS_PER_GROUP 4
#define SOC_PCNT_CHANNELS_PER_UNIT 2
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
// TODO: IDF-5320 (Copy from esp32c3, need check)
/*--------------------------- RMT CAPS ---------------------------------------*/
#define SOC_RMT_GROUPS 1U /*!< One RMT group */

Wyświetl plik

@ -0,0 +1,67 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/pcnt_periph.h"
#include "soc/gpio_sig_map.h"
const pcnt_signal_conn_t pcnt_periph_signals = {
.groups = {
[0] = {
.module = PERIPH_PCNT_MODULE,
.irq = ETS_PCNT_INTR_SOURCE,
.units = {
[0] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN0_IDX,
.pulse_sig = PCNT_SIG_CH0_IN0_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN0_IDX,
.pulse_sig = PCNT_SIG_CH1_IN0_IDX
}
}
},
[1] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN1_IDX,
.pulse_sig = PCNT_SIG_CH0_IN1_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN1_IDX,
.pulse_sig = PCNT_SIG_CH1_IN1_IDX
}
}
},
[2] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN2_IDX,
.pulse_sig = PCNT_SIG_CH0_IN2_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN2_IDX,
.pulse_sig = PCNT_SIG_CH1_IN2_IDX
}
}
},
[3] = {
.channels = {
[0] = {
.control_sig = PCNT_CTRL_CH0_IN3_IDX,
.pulse_sig = PCNT_SIG_CH0_IN3_IDX
},
[1] = {
.control_sig = PCNT_CTRL_CH1_IN3_IDX,
.pulse_sig = PCNT_SIG_CH1_IN3_IDX
}
}
}
}
}
}
};

Wyświetl plik

@ -500,8 +500,8 @@ config SOC_MCPWM_SWSYNC_CAN_PROPAGATE
default y
config SOC_PCNT_GROUPS
bool
default y
int
default 1
config SOC_PCNT_UNITS_PER_GROUP
int

Wyświetl plik

@ -209,7 +209,7 @@
#include "mpu_caps.h"
/*-------------------------- PCNT CAPS ---------------------------------------*/
#define SOC_PCNT_GROUPS (1)
#define SOC_PCNT_GROUPS (1U)
#define SOC_PCNT_UNITS_PER_GROUP (4)
#define SOC_PCNT_CHANNELS_PER_UNIT (2)
#define SOC_PCNT_THRES_POINT_PER_UNIT (2)