mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
gpio: support etm extension
This commit is contained in:
parent
fb26d0e11f
commit
494516d5f3
@ -65,6 +65,10 @@ if(CONFIG_SOC_PCNT_SUPPORTED)
|
||||
list(APPEND srcs "pulse_cnt.c" "deprecated/pcnt_legacy.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_GPIO_SUPPORT_ETM)
|
||||
list(APPEND srcs "gpio/gpio_etm.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_SDMMC_HOST_SUPPORTED)
|
||||
list(APPEND srcs "sdmmc_transaction.c" "sdmmc_host.c")
|
||||
endif()
|
||||
|
305
components/driver/gpio/gpio_etm.c
Normal file
305
components/driver/gpio/gpio_etm.c
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_ETM_ENABLE_DEBUG_LOG
|
||||
// The local log level must be defined before including esp_log.h
|
||||
// Set the maximum log level for this source file
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#endif
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/gpio_etm.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "hal/gpio_etm_ll.h"
|
||||
#include "esp_private/etm_interface.h"
|
||||
|
||||
#define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
|
||||
static const char *TAG = "gpio-etm";
|
||||
|
||||
typedef struct gpio_etm_task_t gpio_etm_task_t;
|
||||
typedef struct gpio_etm_event_t gpio_etm_event_t;
|
||||
|
||||
typedef struct gpio_etm_group_t {
|
||||
portMUX_TYPE spinlock;
|
||||
gpio_etm_dev_t *dev;
|
||||
gpio_etm_task_t *tasks[SOC_GPIO_ETM_TASKS_PER_GROUP];
|
||||
gpio_etm_event_t *events[SOC_GPIO_ETM_EVENTS_PER_GROUP];
|
||||
} gpio_etm_group_t;
|
||||
|
||||
struct gpio_etm_event_t {
|
||||
esp_etm_event_t base;
|
||||
int chan_id;
|
||||
gpio_etm_group_t *group;
|
||||
};
|
||||
|
||||
struct gpio_etm_task_t {
|
||||
esp_etm_task_t base;
|
||||
int chan_id;
|
||||
gpio_etm_group_t *group;
|
||||
size_t num_of_gpios; // record the number of GPIOs that are bound to the etm task
|
||||
};
|
||||
|
||||
static gpio_etm_group_t s_gpio_etm_group = {
|
||||
.dev = &GPIO_ETM,
|
||||
.spinlock = portMUX_INITIALIZER_UNLOCKED,
|
||||
};
|
||||
|
||||
static esp_err_t gpio_etm_event_register_to_group(gpio_etm_event_t *event)
|
||||
{
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
int chan_id = -1;
|
||||
// loop to search free one in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < SOC_GPIO_ETM_EVENTS_PER_GROUP; j++) {
|
||||
if (!group->events[j]) {
|
||||
chan_id = j;
|
||||
group->events[j] = event;
|
||||
break;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free event channel");
|
||||
event->group = group;
|
||||
event->chan_id = chan_id;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_task_register_to_group(gpio_etm_task_t *task)
|
||||
{
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
int chan_id = -1;
|
||||
// loop to search free one in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < SOC_GPIO_ETM_TASKS_PER_GROUP; j++) {
|
||||
if (!group->tasks[j]) {
|
||||
chan_id = j;
|
||||
group->tasks[j] = task;
|
||||
break;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free task channel");
|
||||
task->group = group;
|
||||
task->chan_id = chan_id;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void gpio_etm_event_unregister_from_group(gpio_etm_event_t *event)
|
||||
{
|
||||
gpio_etm_group_t *group = event->group;
|
||||
int chan_id = event->chan_id;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->events[chan_id] = NULL;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
}
|
||||
|
||||
static void gpio_etm_task_unregister_from_group(gpio_etm_task_t *task)
|
||||
{
|
||||
gpio_etm_group_t *group = task->group;
|
||||
int chan_id = task->chan_id;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->tasks[chan_id] = NULL;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_event_destroy(gpio_etm_event_t *event)
|
||||
{
|
||||
if (event->group) {
|
||||
gpio_etm_event_unregister_from_group(event);
|
||||
}
|
||||
free(event);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_task_destroy(gpio_etm_task_t *task)
|
||||
{
|
||||
if (task->group) {
|
||||
gpio_etm_task_unregister_from_group(task);
|
||||
}
|
||||
free(task);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_del_etm_event(esp_etm_event_t *event)
|
||||
{
|
||||
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
|
||||
gpio_etm_group_t *group = gpio_event->group;
|
||||
// disable event channel
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
gpio_etm_event_destroy(gpio_event);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_del_etm_task(esp_etm_task_t *task)
|
||||
{
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
// make sure user has called `gpio_etm_task_rm_gpio` to clean the etm task channel
|
||||
ESP_RETURN_ON_FALSE(gpio_task->num_of_gpios == 0, ESP_ERR_INVALID_STATE, TAG, "some GPIO till bounded to the etm task");
|
||||
gpio_etm_task_destroy(gpio_task);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event)
|
||||
{
|
||||
#if CONFIG_ETM_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
esp_err_t ret = ESP_OK;
|
||||
gpio_etm_event_t *event = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
|
||||
event = heap_caps_calloc(1, sizeof(gpio_etm_event_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(event, ESP_ERR_NO_MEM, err, TAG, "no mem for event channel");
|
||||
// register the event channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_event_register_to_group(event), err, TAG, "register event channel to group failed");
|
||||
int chan_id = event->chan_id;
|
||||
|
||||
uint32_t event_id = 0;
|
||||
switch (config->edge) {
|
||||
case GPIO_ETM_EVENT_EDGE_ANY:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_ANY_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_POS:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_POS_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_NEG:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_NEG_EDGE(chan_id);
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid edge");
|
||||
}
|
||||
|
||||
event->base.del = gpio_del_etm_event;
|
||||
event->base.event_id = event_id;
|
||||
event->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", chan_id=%d", event, event_id, chan_id);
|
||||
*ret_event = &event->base;
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (event) {
|
||||
gpio_etm_event_destroy(event);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task)
|
||||
{
|
||||
#if CONFIG_ETM_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
esp_err_t ret = ESP_OK;
|
||||
gpio_etm_task_t *task = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_task, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
|
||||
task = heap_caps_calloc(1, sizeof(gpio_etm_task_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(task, ESP_ERR_NO_MEM, err, TAG, "no mem for task channel");
|
||||
// register the task channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_task_register_to_group(task), err, TAG, "register task channel to group failed");
|
||||
int chan_id = task->chan_id;
|
||||
|
||||
uint32_t task_id = 0;
|
||||
switch (config->action) {
|
||||
case GPIO_ETM_TASK_ACTION_SET:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_SET(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_CLR:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_CLR(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_TOG:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_TOG(chan_id);
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid action");
|
||||
}
|
||||
|
||||
task->base.del = gpio_del_etm_task;
|
||||
task->base.task_id = task_id;
|
||||
task->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
ESP_LOGD(TAG, "new task @%p, task_id=%"PRIu32", chan_id=%d", task, task_id, chan_id);
|
||||
*ret_task = &task->base;
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (task) {
|
||||
gpio_etm_task_destroy(task);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(event->trig_periph == ETM_TRIG_PERIPH_GPIO, ESP_ERR_INVALID_ARG, TAG, "not a gpio etm event");
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not input capable");
|
||||
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
|
||||
gpio_etm_group_t *group = gpio_event->group;
|
||||
// disable gpio etm event channel first
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
// then set the gpio number
|
||||
gpio_ll_etm_event_channel_set_gpio(group->dev, gpio_event->chan_id, gpio_num);
|
||||
// enable gpio etm event channel again
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, true);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_etm_task_add_gpio(esp_etm_task_handle_t task, int gpio_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(task->trig_periph == ETM_TRIG_PERIPH_GPIO, ESP_ERR_INVALID_ARG, TAG, "not a gpio etm task");
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
gpio_etm_group_t *group = gpio_task->group;
|
||||
bool gpio_not_enabled = true;
|
||||
// use spinlock as this function may be called with different task object in different threads
|
||||
// and the gpio_num might reside in the same register
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the gpio has been enabled
|
||||
if (!gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num)) {
|
||||
gpio_ll_etm_gpio_set_task_channel(group->dev, gpio_num, gpio_task->chan_id);
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, true);
|
||||
} else {
|
||||
gpio_not_enabled = false;
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(gpio_not_enabled, ESP_ERR_INVALID_STATE, TAG, "gpio already enabled by other task channel");
|
||||
gpio_task->num_of_gpios++;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_etm_task_rm_gpio(esp_etm_task_handle_t task, int gpio_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
gpio_etm_group_t *group = gpio_task->group;
|
||||
bool gpio_enabled_by_this_task = true;
|
||||
// use spinlock as this function may be called with different task object in different threads
|
||||
// and the gpio_num might reside in the same register
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the gpio is managed by this etm task channel
|
||||
if (gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num) &&
|
||||
(gpio_ll_etm_gpio_get_task_channel(group->dev, gpio_num) == gpio_task->chan_id)) {
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, false);
|
||||
} else {
|
||||
gpio_enabled_by_this_task = false;
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(gpio_enabled_by_this_task, ESP_ERR_INVALID_STATE, TAG, "gpio is not enabled by this task channel");
|
||||
gpio_task->num_of_gpios--;
|
||||
return ESP_OK;
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "driver/gpio_etm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -150,7 +151,7 @@ esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
|
||||
int gpio_get_level(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief GPIO set direction
|
||||
* @brief GPIO set direction
|
||||
*
|
||||
* Configure GPIO direction,such as output_only,input_only,output_and_input
|
||||
*
|
||||
@ -480,7 +481,7 @@ esp_err_t gpio_sleep_sel_en(gpio_num_t gpio_num);
|
||||
esp_err_t gpio_sleep_sel_dis(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief GPIO set direction at sleep
|
||||
* @brief GPIO set direction at sleep
|
||||
*
|
||||
* Configure GPIO direction,such as output_only,input_only,output_and_input
|
||||
*
|
||||
|
132
components/driver/include/driver/gpio_etm.h
Normal file
132
components/driver/include/driver/gpio_etm.h
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_etm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPIO edges that can be used as ETM event
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_ETM_EVENT_EDGE_POS, /*!< A rising edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
|
||||
} gpio_etm_event_edge_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO ETM event configuration
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
|
||||
} gpio_etm_event_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create an ETM event object for the GPIO peripheral
|
||||
*
|
||||
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
|
||||
* @note The newly created ETM event object is not bind to any GPIO, you need to call `gpio_etm_event_bind_gpio` to bind the wanted GPIO
|
||||
*
|
||||
* @param[in] config GPIO ETM event configuration
|
||||
* @param[out] ret_event Returned ETM event handle
|
||||
* @return
|
||||
* - ESP_OK: Create ETM event successfully
|
||||
* - ESP_ERR_INVALID_ARG: Create ETM event failed because of invalid argument
|
||||
* - ESP_ERR_NO_MEM: Create ETM event failed because of out of memory
|
||||
* - ESP_ERR_NOT_FOUND: Create ETM event failed because all events are used up and no more free one
|
||||
* - ESP_FAIL: Create ETM event failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event);
|
||||
|
||||
/**
|
||||
* @brief Bind the GPIO with the ETM event
|
||||
*
|
||||
* @note Calling this function multiple times with different GPIO number can override the previous setting immediately.
|
||||
* @note Only GPIO ETM object can call this function
|
||||
*
|
||||
* @param[in] event ETM event handle that created by `gpio_new_etm_event`
|
||||
* @param[in] gpio_num GPIO number that can trigger the ETM event
|
||||
* @return
|
||||
* - ESP_OK: Set the GPIO for ETM event successfully
|
||||
* - ESP_ERR_INVALID_ARG: Set the GPIO for ETM event failed because of invalid argument, e.g. GPIO is not input capable, ETM event is not of GPIO type
|
||||
* - ESP_FAIL: Set the GPIO for ETM event failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num);
|
||||
|
||||
/**
|
||||
* @brief GPIO actions that can be taken by the ETM task
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_ETM_TASK_ACTION_SET, /*!< Set the GPIO level to high */
|
||||
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
|
||||
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
|
||||
} gpio_etm_task_action_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO ETM task configuration
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_etm_task_action_t action; /*!< Which action to take by the ETM task module */
|
||||
} gpio_etm_task_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create an ETM task object for the GPIO peripheral
|
||||
*
|
||||
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
|
||||
* @note The GPIO ETM task works like a container, a newly created ETM task object doesn't have GPIO members to be managed.
|
||||
* You need to call `gpio_etm_task_add_gpio` to put one or more GPIOs to the container.
|
||||
*
|
||||
* @param[in] config GPIO ETM task configuration
|
||||
* @param[out] ret_task Returned ETM task handle
|
||||
* @return
|
||||
* - ESP_OK: Create ETM task successfully
|
||||
* - ESP_ERR_INVALID_ARG: Create ETM task failed because of invalid argument
|
||||
* - ESP_ERR_NO_MEM: Create ETM task failed because of out of memory
|
||||
* - ESP_ERR_NOT_FOUND: Create ETM task failed because all tasks are used up and no more free one
|
||||
* - ESP_FAIL: Create ETM task failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task);
|
||||
|
||||
/**
|
||||
* @brief Add GPIO to the ETM task.
|
||||
*
|
||||
* @note You can call this function multiple times to add more GPIOs
|
||||
* @note Only GPIO ETM object can call this function
|
||||
*
|
||||
* @param[in] task ETM task handle that created by `gpio_new_etm_task`
|
||||
* @param[in] gpio_num GPIO number that can be controlled by the ETM task
|
||||
* @return
|
||||
* - ESP_OK: Add GPIO to the ETM task successfully
|
||||
* - ESP_ERR_INVALID_ARG: Add GPIO to the ETM task failed because of invalid argument, e.g. GPIO is not output capable, ETM task is not of GPIO type
|
||||
* - ESP_ERR_INVALID_STATE: Add GPIO to the ETM task failed because the GPIO is used by other ETM task already
|
||||
* - ESP_FAIL: Add GPIO to the ETM task failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_etm_task_add_gpio(esp_etm_task_handle_t task, int gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Remove the GPIO from the ETM task
|
||||
*
|
||||
* @note Before deleting the ETM task, you need to remove all the GPIOs from the ETM task by this function
|
||||
* @note Only GPIO ETM object can call this function
|
||||
*
|
||||
* @param[in] task ETM task handle that created by `gpio_new_etm_task`
|
||||
* @param[in] gpio_num GPIO number that to be remove from the ETM task
|
||||
* @return
|
||||
* - ESP_OK: Remove the GPIO from the ETM task successfully
|
||||
* - ESP_ERR_INVALID_ARG: Remove the GPIO from the ETM task failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Remove the GPIO from the ETM task failed because the GPIO is not controlled by this ETM task
|
||||
* - ESP_FAIL: Remove the GPIO from the ETM task failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_etm_task_rm_gpio(esp_etm_task_handle_t task, int gpio_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,6 +1,9 @@
|
||||
set(srcs "test_app_main.c"
|
||||
"test_etm_core.c")
|
||||
|
||||
if(CONFIG_SOC_GPIO_SUPPORT_ETM)
|
||||
list(APPEND srcs "test_gpio_etm.c")
|
||||
endif()
|
||||
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
|
92
components/esp_hw_support/test_apps/etm/main/test_gpio_etm.c
Normal file
92
components/esp_hw_support/test_apps/etm/main/test_gpio_etm.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "unity.h"
|
||||
#include "unity_test_utils.h"
|
||||
#include "esp_attr.h"
|
||||
#include "driver/gpio_etm.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
TEST_CASE("gpio_etm_self_trigger", "[etm]")
|
||||
{
|
||||
// GPIO any edge ---> EMT channel ---> GPIO toggle
|
||||
const uint32_t input_gpio = 0;
|
||||
const uint32_t output_gpio = 1;
|
||||
printf("allocate etm channels\r\n");
|
||||
esp_etm_channel_config_t etm_config = {};
|
||||
esp_etm_channel_handle_t etm_channel_a = NULL;
|
||||
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a));
|
||||
|
||||
printf("allocate GPIO etm event and task\r\n");
|
||||
esp_etm_task_handle_t gpio_task = NULL;
|
||||
esp_etm_event_handle_t gpio_event = NULL;
|
||||
gpio_etm_event_config_t gpio_event_config = {
|
||||
.edge = GPIO_ETM_EVENT_EDGE_ANY,
|
||||
};
|
||||
TEST_ESP_OK(gpio_new_etm_event(&gpio_event_config, &gpio_event));
|
||||
gpio_etm_task_config_t gpio_task_config = {
|
||||
.action = GPIO_ETM_TASK_ACTION_TOG,
|
||||
};
|
||||
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config, &gpio_task));
|
||||
|
||||
// bind GPIO to the event and task
|
||||
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event, input_gpio));
|
||||
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task, output_gpio));
|
||||
|
||||
printf("initialize gpio\r\n");
|
||||
gpio_config_t task_gpio_config = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to read the GPIO value, so it should be input and output
|
||||
.pin_bit_mask = 1ULL << output_gpio,
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&task_gpio_config));
|
||||
// set the initial level
|
||||
TEST_ESP_OK(gpio_set_level(output_gpio, 0));
|
||||
|
||||
gpio_config_t event_gpio_config = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to simulate the edge signal by software, so it should be input and output
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.pin_bit_mask = 1ULL << input_gpio,
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&event_gpio_config));
|
||||
|
||||
printf("connect event and task to the channel\r\n");
|
||||
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, gpio_event, gpio_task));
|
||||
|
||||
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio, i & 0x01));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
// check the final level
|
||||
TEST_ASSERT_EQUAL(1, gpio_get_level(output_gpio));
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio, i & 0x01));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
// check the final level
|
||||
TEST_ASSERT_EQUAL(0, gpio_get_level(output_gpio));
|
||||
|
||||
// delete gpio etm task without remove all bounded GPIOs should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_etm_del_task(gpio_task));
|
||||
// remove unrelated GPIO from the task should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gpio_etm_task_rm_gpio(gpio_task, 10));
|
||||
|
||||
// delete etm primitives
|
||||
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio));
|
||||
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_del_task(gpio_task));
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event));
|
||||
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
|
||||
}
|
119
components/hal/esp32c6/include/hal/gpio_etm_ll.h
Normal file
119
components/hal/esp32c6/include/hal/gpio_etm_ll.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "hal/assert.h"
|
||||
#include "hal/misc.h"
|
||||
#include "soc/gpio_ext_struct.h"
|
||||
#include "soc/soc_etm_source.h"
|
||||
|
||||
#define GPIO_LL_ETM_EVENT_ID_POS_EDGE(ch) (GPIO_EVT_CH0_RISE_EDGE + (ch))
|
||||
#define GPIO_LL_ETM_EVENT_ID_NEG_EDGE(ch) (GPIO_EVT_CH0_FALL_EDGE + (ch))
|
||||
#define GPIO_LL_ETM_EVENT_ID_ANY_EDGE(ch) (GPIO_EVT_CH0_ANY_EDGE + (ch))
|
||||
|
||||
#define GPIO_LL_ETM_TASK_ID_SET(ch) (GPIO_TASK_CH0_SET + (ch))
|
||||
#define GPIO_LL_ETM_TASK_ID_CLR(ch) (GPIO_TASK_CH0_CLEAR + (ch))
|
||||
#define GPIO_LL_ETM_TASK_ID_TOG(ch) (GPIO_TASK_CH0_TOGGLE + (ch))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bounded to the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint32_t chan, uint32_t gpio_num)
|
||||
{
|
||||
dev->event_chn_cfg[chan].etm_ch0_event_sel = gpio_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param enable True to enable, false to disable
|
||||
*/
|
||||
static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_t chan, bool enable)
|
||||
{
|
||||
dev->event_chn_cfg[chan].etm_ch0_event_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bounded to the task channel
|
||||
*
|
||||
* @note One channel can be bounded to multiple different GPIOs
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num, uint32_t chan)
|
||||
{
|
||||
int g_p = gpio_num / 4;
|
||||
int g_idx = gpio_num % 4;
|
||||
uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val;
|
||||
reg_val &= ~(0x07 << (g_idx * 8 + 1));
|
||||
reg_val |= ((chan & 0x07) << (g_idx * 8 + 1));
|
||||
dev->etm_task_pn_cfg[g_p].val = reg_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the GPIO to be managed by the task channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
* @param enable True to enable, false to disable
|
||||
*/
|
||||
static inline void gpio_ll_etm_enable_task_gpio(gpio_etm_dev_t *dev, uint32_t gpio_num, bool enable)
|
||||
{
|
||||
int g_p = gpio_num / 4;
|
||||
int g_idx = gpio_num % 4;
|
||||
uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val;
|
||||
reg_val &= ~(0x01 << (g_idx * 8));
|
||||
reg_val |= ((enable & 0x01) << (g_idx * 8));
|
||||
dev->etm_task_pn_cfg[g_p].val = reg_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether a GPIO has been enabled and managed by a task channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
* @return True if enabled, false otherwise
|
||||
*/
|
||||
static inline bool gpio_ll_etm_is_task_gpio_enabled(gpio_etm_dev_t *dev, uint32_t gpio_num)
|
||||
{
|
||||
int g_p = gpio_num / 4;
|
||||
int g_idx = gpio_num % 4;
|
||||
return dev->etm_task_pn_cfg[g_p].val & (0x01 << (g_idx * 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the channel number that the GPIO is bounded to
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
* @return GPIO ETM Task channel number
|
||||
*/
|
||||
static inline uint32_t gpio_ll_etm_gpio_get_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num)
|
||||
{
|
||||
int g_p = gpio_num / 4;
|
||||
int g_idx = gpio_num % 4;
|
||||
return (dev->etm_task_pn_cfg[g_p].val >> (g_idx * 8 + 1)) & 0x07;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -263,6 +263,18 @@ config SOC_GPIO_PIN_COUNT
|
||||
int
|
||||
default 31
|
||||
|
||||
config SOC_GPIO_SUPPORT_ETM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_GPIO_ETM_EVENTS_PER_GROUP
|
||||
int
|
||||
default 8
|
||||
|
||||
config SOC_GPIO_ETM_TASKS_PER_GROUP
|
||||
int
|
||||
default 8
|
||||
|
||||
config SOC_GPIO_SUPPORT_RTC_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
@ -155,314 +155,7 @@ typedef union {
|
||||
uint32_t reserved_28:4;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p0_cfg_reg_t;
|
||||
|
||||
/** Type of etm_task_p1_cfg register
|
||||
* Etm Configure Register to decide which GPIO been chosen
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** etm_task_gpio4_en : R/W; bitpos: [0]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio4_en:1;
|
||||
/** etm_task_gpio4_sel : R/W; bitpos: [3:1]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio4_sel:3;
|
||||
uint32_t reserved_4:4;
|
||||
/** etm_task_gpio5_en : R/W; bitpos: [8]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio5_en:1;
|
||||
/** etm_task_gpio5_sel : R/W; bitpos: [11:9]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio5_sel:3;
|
||||
uint32_t reserved_12:4;
|
||||
/** etm_task_gpio6_en : R/W; bitpos: [16]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio6_en:1;
|
||||
/** etm_task_gpio6_sel : R/W; bitpos: [19:17]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio6_sel:3;
|
||||
uint32_t reserved_20:4;
|
||||
/** etm_task_gpio7_en : R/W; bitpos: [24]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio7_en:1;
|
||||
/** etm_task_gpio7_sel : R/W; bitpos: [27:25]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio7_sel:3;
|
||||
uint32_t reserved_28:4;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p1_cfg_reg_t;
|
||||
|
||||
/** Type of etm_task_p2_cfg register
|
||||
* Etm Configure Register to decide which GPIO been chosen
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** etm_task_gpio8_en : R/W; bitpos: [0]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio8_en:1;
|
||||
/** etm_task_gpio8_sel : R/W; bitpos: [3:1]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio8_sel:3;
|
||||
uint32_t reserved_4:4;
|
||||
/** etm_task_gpio9_en : R/W; bitpos: [8]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio9_en:1;
|
||||
/** etm_task_gpio9_sel : R/W; bitpos: [11:9]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio9_sel:3;
|
||||
uint32_t reserved_12:4;
|
||||
/** etm_task_gpio10_en : R/W; bitpos: [16]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio10_en:1;
|
||||
/** etm_task_gpio10_sel : R/W; bitpos: [19:17]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio10_sel:3;
|
||||
uint32_t reserved_20:4;
|
||||
/** etm_task_gpio11_en : R/W; bitpos: [24]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio11_en:1;
|
||||
/** etm_task_gpio11_sel : R/W; bitpos: [27:25]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio11_sel:3;
|
||||
uint32_t reserved_28:4;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p2_cfg_reg_t;
|
||||
|
||||
/** Type of etm_task_p3_cfg register
|
||||
* Etm Configure Register to decide which GPIO been chosen
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** etm_task_gpio12_en : R/W; bitpos: [0]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio12_en:1;
|
||||
/** etm_task_gpio12_sel : R/W; bitpos: [3:1]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio12_sel:3;
|
||||
uint32_t reserved_4:4;
|
||||
/** etm_task_gpio13_en : R/W; bitpos: [8]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio13_en:1;
|
||||
/** etm_task_gpio13_sel : R/W; bitpos: [11:9]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio13_sel:3;
|
||||
uint32_t reserved_12:4;
|
||||
/** etm_task_gpio14_en : R/W; bitpos: [16]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio14_en:1;
|
||||
/** etm_task_gpio14_sel : R/W; bitpos: [19:17]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio14_sel:3;
|
||||
uint32_t reserved_20:4;
|
||||
/** etm_task_gpio15_en : R/W; bitpos: [24]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio15_en:1;
|
||||
/** etm_task_gpio15_sel : R/W; bitpos: [27:25]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio15_sel:3;
|
||||
uint32_t reserved_28:4;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p3_cfg_reg_t;
|
||||
|
||||
/** Type of etm_task_p4_cfg register
|
||||
* Etm Configure Register to decide which GPIO been chosen
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** etm_task_gpio16_en : R/W; bitpos: [0]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio16_en:1;
|
||||
/** etm_task_gpio16_sel : R/W; bitpos: [3:1]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio16_sel:3;
|
||||
uint32_t reserved_4:4;
|
||||
/** etm_task_gpio17_en : R/W; bitpos: [8]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio17_en:1;
|
||||
/** etm_task_gpio17_sel : R/W; bitpos: [11:9]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio17_sel:3;
|
||||
uint32_t reserved_12:4;
|
||||
/** etm_task_gpio18_en : R/W; bitpos: [16]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio18_en:1;
|
||||
/** etm_task_gpio18_sel : R/W; bitpos: [19:17]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio18_sel:3;
|
||||
uint32_t reserved_20:4;
|
||||
/** etm_task_gpio19_en : R/W; bitpos: [24]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio19_en:1;
|
||||
/** etm_task_gpio19_sel : R/W; bitpos: [27:25]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio19_sel:3;
|
||||
uint32_t reserved_28:4;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p4_cfg_reg_t;
|
||||
|
||||
/** Type of etm_task_p5_cfg register
|
||||
* Etm Configure Register to decide which GPIO been chosen
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** etm_task_gpio20_en : R/W; bitpos: [0]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio20_en:1;
|
||||
/** etm_task_gpio20_sel : R/W; bitpos: [3:1]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio20_sel:3;
|
||||
uint32_t reserved_4:4;
|
||||
/** etm_task_gpio21_en : R/W; bitpos: [8]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio21_en:1;
|
||||
/** etm_task_gpio21_sel : R/W; bitpos: [11:9]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio21_sel:3;
|
||||
uint32_t reserved_12:4;
|
||||
/** etm_task_gpio22_en : R/W; bitpos: [16]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio22_en:1;
|
||||
/** etm_task_gpio22_sel : R/W; bitpos: [19:17]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio22_sel:3;
|
||||
uint32_t reserved_20:4;
|
||||
/** etm_task_gpio23_en : R/W; bitpos: [24]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio23_en:1;
|
||||
/** etm_task_gpio23_sel : R/W; bitpos: [27:25]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio23_sel:3;
|
||||
uint32_t reserved_28:4;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p5_cfg_reg_t;
|
||||
|
||||
/** Type of etm_task_p6_cfg register
|
||||
* Etm Configure Register to decide which GPIO been chosen
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** etm_task_gpio24_en : R/W; bitpos: [0]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio24_en:1;
|
||||
/** etm_task_gpio24_sel : R/W; bitpos: [3:1]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio24_sel:3;
|
||||
uint32_t reserved_4:4;
|
||||
/** etm_task_gpio25_en : R/W; bitpos: [8]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio25_en:1;
|
||||
/** etm_task_gpio25_sel : R/W; bitpos: [11:9]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio25_sel:3;
|
||||
uint32_t reserved_12:4;
|
||||
/** etm_task_gpio26_en : R/W; bitpos: [16]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio26_en:1;
|
||||
/** etm_task_gpio26_sel : R/W; bitpos: [19:17]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio26_sel:3;
|
||||
uint32_t reserved_20:4;
|
||||
/** etm_task_gpio27_en : R/W; bitpos: [24]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio27_en:1;
|
||||
/** etm_task_gpio27_sel : R/W; bitpos: [27:25]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio27_sel:3;
|
||||
uint32_t reserved_28:4;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p6_cfg_reg_t;
|
||||
|
||||
/** Type of etm_task_p7_cfg register
|
||||
* Etm Configure Register to decide which GPIO been chosen
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** etm_task_gpio28_en : R/W; bitpos: [0]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio28_en:1;
|
||||
/** etm_task_gpio28_sel : R/W; bitpos: [3:1]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio28_sel:3;
|
||||
uint32_t reserved_4:4;
|
||||
/** etm_task_gpio29_en : R/W; bitpos: [8]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio29_en:1;
|
||||
/** etm_task_gpio29_sel : R/W; bitpos: [11:9]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio29_sel:3;
|
||||
uint32_t reserved_12:4;
|
||||
/** etm_task_gpio30_en : R/W; bitpos: [16]; default: 0;
|
||||
* Enable bit of GPIO response etm task.
|
||||
*/
|
||||
uint32_t etm_task_gpio30_en:1;
|
||||
/** etm_task_gpio30_sel : R/W; bitpos: [19:17]; default: 0;
|
||||
* GPIO choose a etm task channel.
|
||||
*/
|
||||
uint32_t etm_task_gpio30_sel:3;
|
||||
uint32_t reserved_20:12;
|
||||
};
|
||||
uint32_t val;
|
||||
} gpio_etm_task_p7_cfg_reg_t;
|
||||
|
||||
} gpio_etm_task_pn_cfg_reg_t;
|
||||
|
||||
/** Group: Version Register */
|
||||
/** Type of version register
|
||||
@ -491,17 +184,10 @@ typedef struct {
|
||||
volatile gpio_glitch_filter_chn_reg_t glitch_filter_chn[8];
|
||||
} gpio_glitch_filter_dev_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct gpio_etm_dev_t {
|
||||
volatile gpio_etm_event_chn_cfg_reg_t event_chn_cfg[8];
|
||||
uint32_t reserved_080[8];
|
||||
volatile gpio_etm_task_p0_cfg_reg_t etm_task_p0_cfg;
|
||||
volatile gpio_etm_task_p1_cfg_reg_t etm_task_p1_cfg;
|
||||
volatile gpio_etm_task_p2_cfg_reg_t etm_task_p2_cfg;
|
||||
volatile gpio_etm_task_p3_cfg_reg_t etm_task_p3_cfg;
|
||||
volatile gpio_etm_task_p4_cfg_reg_t etm_task_p4_cfg;
|
||||
volatile gpio_etm_task_p5_cfg_reg_t etm_task_p5_cfg;
|
||||
volatile gpio_etm_task_p6_cfg_reg_t etm_task_p6_cfg;
|
||||
volatile gpio_etm_task_p7_cfg_reg_t etm_task_p7_cfg;
|
||||
volatile gpio_etm_task_pn_cfg_reg_t etm_task_pn_cfg[8];
|
||||
} gpio_etm_dev_t;
|
||||
|
||||
typedef struct gpio_ext_dev_t {
|
||||
@ -517,6 +203,7 @@ typedef struct gpio_ext_dev_t {
|
||||
extern gpio_sd_dev_t SDM;
|
||||
extern gpio_glitch_filter_dev_t GLITCH_FILTER;
|
||||
extern gpio_etm_dev_t GPIO_ETM;
|
||||
extern gpio_ext_dev_t GPIO_EXT;
|
||||
|
||||
#ifndef __cplusplus
|
||||
_Static_assert(sizeof(gpio_ext_dev_t) == 0x100, "Invalid size of gpio_ext_dev_t structure");
|
||||
|
@ -151,6 +151,11 @@
|
||||
#define SOC_GPIO_PORT (1U)
|
||||
#define SOC_GPIO_PIN_COUNT (31)
|
||||
|
||||
// GPIO peripheral has the ETM extension
|
||||
#define SOC_GPIO_SUPPORT_ETM 1
|
||||
#define SOC_GPIO_ETM_EVENTS_PER_GROUP 8
|
||||
#define SOC_GPIO_ETM_TASKS_PER_GROUP 8
|
||||
|
||||
// Target has the full LP IO subsystem
|
||||
// On ESP32-C6, Digital IOs have their own registers to control pullup/down capability, independent of LP registers.
|
||||
#define SOC_GPIO_SUPPORT_RTC_INDEPENDENT (1)
|
||||
|
@ -46,7 +46,7 @@ PROVIDE ( HMAC = 0x6008D000 );
|
||||
|
||||
PROVIDE ( IO_MUX = 0x60090000 );
|
||||
PROVIDE ( GPIO = 0x60091000 );
|
||||
PROVIDE ( GPIO_EXT = 0x60091f00 ); /*ESP32C6-TODO*/
|
||||
PROVIDE ( GPIO_EXT = 0x60091f00 );
|
||||
PROVIDE ( SDM = 0x60091f00 );
|
||||
PROVIDE ( GLITCH_FILTER = 0x60091f30 );
|
||||
PROVIDE ( GPIO_ETM = 0x60091f60 );
|
||||
|
Loading…
Reference in New Issue
Block a user