Add disabling/enabling of shared interrupt, add testcase for interrupts
This commit is contained in:
parent
32fa94935d
commit
ae8c37e0b6
16 changed files with 348 additions and 102 deletions
|
@ -321,10 +321,10 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig)
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags)
|
||||
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle)
|
||||
{
|
||||
GPIO_CHECK(fn, "GPIO ISR null", ESP_ERR_INVALID_ARG);
|
||||
return esp_intr_alloc(ETS_GPIO_INTR_SOURCE, intr_alloc_flags, fn, arg, NULL);
|
||||
return esp_intr_alloc(ETS_GPIO_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
|
||||
}
|
||||
|
||||
/*only level interrupt can be used for wake-up function*/
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "soc/gpio_sig_map.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -203,6 +204,9 @@ typedef enum {
|
|||
GPIO_FLOATING, /*!< Pad floating */
|
||||
} gpio_pull_mode_t;
|
||||
|
||||
|
||||
|
||||
typedef intr_handle_t gpio_isr_handle_t;
|
||||
typedef void (*gpio_event_callback)(gpio_num_t gpio_intr_num);
|
||||
|
||||
/**
|
||||
|
@ -352,7 +356,7 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
|
|||
* - ESP_OK Success ;
|
||||
* - ESP_ERR_INVALID_ARG GPIO error
|
||||
*/
|
||||
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags);
|
||||
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "soc/ledc_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -100,6 +101,7 @@ typedef struct {
|
|||
uint32_t freq_hz; /*!< LEDC timer frequency(Hz)*/
|
||||
} ledc_timer_config_t;
|
||||
|
||||
typedef intr_handle_t ledc_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief LEDC channel configuration
|
||||
|
@ -268,7 +270,7 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty,
|
|||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags);
|
||||
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief configure LEDC settings
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "soc/pcnt_struct.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -76,6 +77,8 @@ typedef struct {
|
|||
pcnt_channel_t channel; /*!< the PCNT channel */
|
||||
} pcnt_config_t;
|
||||
|
||||
typedef intr_handle_t pcnt_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Configure Pulse Counter unit
|
||||
*
|
||||
|
@ -223,7 +226,7 @@ esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16
|
|||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t pcnt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags);
|
||||
esp_err_t pcnt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, pcnt_isr_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief Configure PCNT pulse signal input pin and control input pin
|
||||
|
|
|
@ -117,6 +117,8 @@ typedef struct {
|
|||
};
|
||||
} rmt_config_t;
|
||||
|
||||
typedef intr_handle_t rmt_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Set RMT clock divider, channel clock is divided from source clock.
|
||||
*
|
||||
|
@ -574,13 +576,25 @@ esp_err_t rmt_config(rmt_config_t* rmt_param);
|
|||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param If non-zero, a handle to later clean up the ISR gets stored here.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
* - ESP_FAIL System driver installed, can not register ISR handler for RMT
|
||||
*/
|
||||
esp_err_t rmt_isr_register(void (* fn)(void* ), void * arg, int intr_alloc_flags);
|
||||
esp_err_t rmt_isr_register(void (* fn)(void* ), void * arg, int intr_alloc_flags, rmt_isr_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief Deregister previously registered RMT interrupt handler
|
||||
*
|
||||
* @param handle Handle obtained from rmt_isr_register
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Handle invalid
|
||||
*/
|
||||
esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Fill memory data of channel with given RMT items.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "soc/soc.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/timer_group_struct.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -100,6 +101,13 @@ typedef struct {
|
|||
uint16_t divider; /*!< Counter clock divider*/
|
||||
} timer_config_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interrupt handle, used in order to free the isr after use.
|
||||
* Aliases to an int handle for now.
|
||||
*/
|
||||
typedef intr_handle_t timer_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Read the counter value of hardware timer.
|
||||
*
|
||||
|
@ -264,7 +272,7 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
|
|||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void*), void * arg, int intr_alloc_flags);
|
||||
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle);
|
||||
|
||||
/** @brief Initializes and configure the timer.
|
||||
*
|
||||
|
|
|
@ -371,8 +371,7 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh);
|
|||
* @param fn Interrupt handler function.
|
||||
* @param arg parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. Note that the UART
|
||||
* driver at the moment does not work with a shared interrupt.
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
|
|
|
@ -114,12 +114,12 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel,
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags)
|
||||
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle)
|
||||
{
|
||||
esp_err_t ret;
|
||||
LEDC_CHECK(fn, "ledc isr null", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
ret=esp_intr_alloc(ETS_LEDC_INTR_SOURCE, intr_alloc_flags, fn, arg, NULL);
|
||||
ret=esp_intr_alloc(ETS_LEDC_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -267,9 +267,9 @@ esp_err_t pcnt_filter_disable(pcnt_unit_t unit)
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_isr_register(void (*fun)(void*), void * arg, int intr_alloc_flags)
|
||||
esp_err_t pcnt_isr_register(void (*fun)(void*), void * arg, int intr_alloc_flags, pcnt_isr_handle_t *handle)
|
||||
{
|
||||
PCNT_CHECK(fun != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
return esp_intr_alloc(ETS_PCNT_INTR_SOURCE, intr_alloc_flags, fun, arg, NULL);
|
||||
return esp_intr_alloc(ETS_PCNT_INTR_SOURCE, intr_alloc_flags, fun, arg, handle);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
static const char* RMT_TAG = "RMT";
|
||||
static bool s_rmt_driver_installed = false;
|
||||
static rmt_isr_handle_t s_rmt_driver_intr_handle;
|
||||
|
||||
#define RMT_CHECK(a, str, ret) if (!(a)) { \
|
||||
ESP_LOGE(RMT_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
|
||||
|
@ -473,17 +474,23 @@ esp_err_t rmt_fill_tx_items(rmt_channel_t channel, rmt_item32_t* item, uint16_t
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rmt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags)
|
||||
esp_err_t rmt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, rmt_isr_handle_t *handle)
|
||||
{
|
||||
esp_err_t ret;
|
||||
RMT_CHECK((fn != NULL), RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
RMT_CHECK(s_rmt_driver_installed == false, "RMT DRIVER INSTALLED, CAN NOT REG ISR HANDLER", ESP_FAIL);
|
||||
portENTER_CRITICAL(&rmt_spinlock);
|
||||
ret=esp_intr_alloc(ETS_RMT_INTR_SOURCE, intr_alloc_flags, fn, arg, NULL);
|
||||
ret=esp_intr_alloc(ETS_RMT_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
|
||||
portEXIT_CRITICAL(&rmt_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle)
|
||||
{
|
||||
return esp_intr_free(handle);
|
||||
}
|
||||
|
||||
static int IRAM_ATTR rmt_get_mem_len(rmt_channel_t channel)
|
||||
{
|
||||
int block_num = RMT.conf_ch[channel].conf0.mem_size;
|
||||
|
@ -615,7 +622,7 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
|
|||
free(p_rmt_obj[channel]);
|
||||
p_rmt_obj[channel] = NULL;
|
||||
s_rmt_driver_installed = false;
|
||||
return ESP_OK;
|
||||
return rmt_isr_deregister(s_rmt_driver_intr_handle);
|
||||
}
|
||||
|
||||
esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr_alloc_flags)
|
||||
|
@ -650,7 +657,7 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr
|
|||
rmt_set_err_intr_en(channel, 1);
|
||||
}
|
||||
if(s_rmt_driver_installed == false) {
|
||||
rmt_isr_register(rmt_driver_isr_default, NULL, intr_alloc_flags);
|
||||
rmt_isr_register(rmt_driver_isr_default, NULL, intr_alloc_flags, &s_rmt_driver_intr_handle);
|
||||
s_rmt_driver_installed = true;
|
||||
}
|
||||
rmt_set_tx_intr_en(channel, 1);
|
||||
|
|
|
@ -169,13 +169,15 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
|
|||
}
|
||||
|
||||
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
|
||||
void (*fn)(void*), void * arg, int intr_alloc_flags)
|
||||
void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle)
|
||||
{
|
||||
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(fn != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
int intr_source = 0;
|
||||
uint32_t status_reg = 0;
|
||||
int mask = 0;
|
||||
switch(group_num) {
|
||||
case TIMER_GROUP_0:
|
||||
default:
|
||||
|
@ -184,6 +186,8 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
|
|||
} else {
|
||||
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
|
||||
}
|
||||
status_reg = TIMG_INT_ST_TIMERS_REG(0);
|
||||
mask = 1<<timer_num;
|
||||
break;
|
||||
case TIMER_GROUP_1:
|
||||
if((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
|
||||
|
@ -191,9 +195,11 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
|
|||
} else {
|
||||
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
|
||||
}
|
||||
status_reg = TIMG_INT_ST_TIMERS_REG(1);
|
||||
mask = 1<<timer_num;
|
||||
break;
|
||||
}
|
||||
return esp_intr_alloc(intr_source, intr_alloc_flags, fn, arg, NULL);
|
||||
return esp_intr_alloc_intrstatus(intr_source, intr_alloc_flags, status_reg, mask, fn, arg, handle);
|
||||
}
|
||||
|
||||
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)
|
||||
|
|
|
@ -55,7 +55,7 @@ typedef struct {
|
|||
uart_port_t uart_num; /*!< UART port number*/
|
||||
int queue_size; /*!< UART event queue size*/
|
||||
QueueHandle_t xQueueUart; /*!< UART queue handler*/
|
||||
int_handle_t intr_handle; /*!< UART interrupt handle*/
|
||||
intr_handle_t intr_handle; /*!< UART interrupt handle*/
|
||||
//rx parameters
|
||||
SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/
|
||||
int rx_buf_size; /*!< RX ring buffer size */
|
||||
|
@ -292,7 +292,6 @@ esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg,
|
|||
{
|
||||
int ret;
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||
UART_CHECK(((intr_alloc_flags & ESP_INTR_FLAG_SHARED)==0), "UART doesn't support shared interrupts", ESP_FAIL);
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
switch(uart_num) {
|
||||
case UART_NUM_1:
|
||||
|
|
|
@ -47,6 +47,7 @@ extern "C" {
|
|||
#define ESP_INTR_FLAG_SHARED (1<<8) ///< Interrupt can be shared between ISRs
|
||||
#define ESP_INTR_FLAG_EDGE (1<<9) ///< Edge-triggered interrupt
|
||||
#define ESP_INTR_FLAG_IRAM (1<<10) ///< ISR can be called if cache is disabled
|
||||
#define ESP_INTR_FLAG_INTRDISABLED (1<<11) ///< Return with this interrupt disabled
|
||||
|
||||
#define ESP_INTR_FLAG_LOWMED (ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3) ///< Low and medium prio interrupts. These can be handled in C.
|
||||
#define ESP_INTR_FLAG_HIGH (ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6|ESP_INTR_FLAG_NMI) ///< High level interrupts. Need to be handled in assembly.
|
||||
|
@ -79,8 +80,8 @@ extern "C" {
|
|||
typedef void (*intr_handler_t)(void *arg);
|
||||
|
||||
|
||||
typedef struct int_handle_data_t int_handle_data_t;
|
||||
typedef int_handle_data_t* int_handle_t ;
|
||||
typedef struct intr_handle_data_t intr_handle_data_t;
|
||||
typedef intr_handle_data_t* intr_handle_t ;
|
||||
|
||||
/**
|
||||
* @brief Mark an interrupt as a shared interrupt
|
||||
|
@ -134,7 +135,7 @@ esp_err_t esp_intr_reserve(int intno, int cpu);
|
|||
* @param handler The interrupt handler. Must be NULL when an interrupt of level >3
|
||||
* is requested, because these types of interrupts aren't C-callable.
|
||||
* @param arg Optional argument for passed to the interrupt handler
|
||||
* @param ret_handle Pointer to an int_handle_t to store a handle that can later be
|
||||
* @param ret_handle Pointer to an intr_handle_t to store a handle that can later be
|
||||
* used to request details or free the interrupt. Can be NULL if no handle
|
||||
* is required.
|
||||
*
|
||||
|
@ -142,7 +143,7 @@ esp_err_t esp_intr_reserve(int intno, int cpu);
|
|||
* ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
|
||||
* ESP_OK otherwise
|
||||
*/
|
||||
esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, int_handle_t *ret_handle);
|
||||
esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -171,7 +172,7 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar
|
|||
* @param handler The interrupt handler. Must be NULL when an interrupt of level >3
|
||||
* is requested, because these types of interrupts aren't C-callable.
|
||||
* @param arg Optional argument for passed to the interrupt handler
|
||||
* @param ret_handle Pointer to an int_handle_t to store a handle that can later be
|
||||
* @param ret_handle Pointer to an intr_handle_t to store a handle that can later be
|
||||
* used to request details or free the interrupt. Can be NULL if no handle
|
||||
* is required.
|
||||
*
|
||||
|
@ -179,7 +180,7 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar
|
|||
* ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
|
||||
* ESP_OK otherwise
|
||||
*/
|
||||
esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, void *arg, int_handle_t *ret_handle);
|
||||
esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, void *arg, intr_handle_t *ret_handle);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -194,7 +195,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
|
|||
* where the interrupt is allocated on.
|
||||
* ESP_OK otherwise
|
||||
*/
|
||||
esp_err_t esp_intr_free(int_handle_t handle);
|
||||
esp_err_t esp_intr_free(intr_handle_t handle);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -204,7 +205,7 @@ esp_err_t esp_intr_free(int_handle_t handle);
|
|||
*
|
||||
* @return The core number where the interrupt is allocated
|
||||
*/
|
||||
int esp_intr_get_cpu(int_handle_t handle);
|
||||
int esp_intr_get_cpu(intr_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Get the allocated interrupt for a certain handle
|
||||
|
@ -213,32 +214,36 @@ int esp_intr_get_cpu(int_handle_t handle);
|
|||
*
|
||||
* @return The interrupt number
|
||||
*/
|
||||
int esp_intr_get_intno(int_handle_t handle);
|
||||
int esp_intr_get_intno(intr_handle_t handle);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable the interrupt associated with the handle
|
||||
*
|
||||
* @note This function can only disable non-shared inteerupts allocated on the CPU that runs this function.
|
||||
* @warning Do not call this in a critical section; when the critical section ends the interrupt status
|
||||
* on critical section enter may be restored.
|
||||
*
|
||||
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
|
||||
*
|
||||
* @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
|
||||
* ESP_OK otherwise
|
||||
*/
|
||||
esp_err_t esp_intr_disable(int_handle_t handle);
|
||||
esp_err_t esp_intr_disable(intr_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Ensable the interrupt associated with the handle
|
||||
*
|
||||
* @note This function can only enable non-shared inteerupts allocated on the CPU that runs this function.
|
||||
* @warning Do not call this in a critical section; when the critical section ends the interrupt status
|
||||
* on critical section enter may be restored.
|
||||
*
|
||||
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
|
||||
*
|
||||
* @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
|
||||
* ESP_OK otherwise
|
||||
*/
|
||||
esp_err_t esp_intr_enable(int_handle_t handle);
|
||||
esp_err_t esp_intr_enable(intr_handle_t handle);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -131,28 +131,12 @@ const static int_desc_t int_desc[32]={
|
|||
{ 5, INTTP_LEVEL, {INTDESC_RESVD, INTDESC_RESVD } }, //31
|
||||
};
|
||||
|
||||
|
||||
//For memory usage and to get an unique ID for every int on every CPU core, the
|
||||
//intrs and cpus are stored in in one int. These functions handle that.
|
||||
inline static int to_intno_cpu(int intno, int cpu)
|
||||
{
|
||||
return intno+cpu*32;
|
||||
}
|
||||
|
||||
inline static int to_intno(int intno_cpu)
|
||||
{
|
||||
return (intno_cpu)&31;
|
||||
}
|
||||
|
||||
inline static int to_cpu(int intno_cpu)
|
||||
{
|
||||
return (intno_cpu)/32;
|
||||
}
|
||||
|
||||
typedef struct shared_vector_desc_t shared_vector_desc_t;
|
||||
typedef struct vector_desc_t vector_desc_t;
|
||||
|
||||
struct shared_vector_desc_t {
|
||||
int disabled: 1;
|
||||
int source: 8;
|
||||
volatile uint32_t *statusreg;
|
||||
uint32_t statusmask;
|
||||
intr_handler_t isr;
|
||||
|
@ -166,20 +150,23 @@ struct shared_vector_desc_t {
|
|||
#define VECDESC_FL_SHARED (1<<2)
|
||||
#define VECDESC_FL_NONSHARED (1<<3)
|
||||
|
||||
//Pack using bitfields for better memory use
|
||||
struct vector_desc_t {
|
||||
int intno_cpu; //intno+cpu*32
|
||||
int flags; //OR of VECDESC_FLAG_* defines
|
||||
int flags: 16; //OR of VECDESC_FLAG_* defines
|
||||
unsigned int cpu: 1;
|
||||
unsigned int intno: 5;
|
||||
int source: 8; //Interrupt mux flags, used when not shared
|
||||
shared_vector_desc_t *shared_vec_info; //used when VECDESC_FL_SHARED
|
||||
vector_desc_t *next;
|
||||
};
|
||||
|
||||
struct int_handle_data_t {
|
||||
struct intr_handle_data_t {
|
||||
vector_desc_t *vector_desc;
|
||||
shared_vector_desc_t *shared_vector_desc;
|
||||
};
|
||||
|
||||
|
||||
//Linked list of vector descriptions, sorted by intno_cpu value
|
||||
//Linked list of vector descriptions, sorted by cpu.intno value
|
||||
static vector_desc_t *vector_desc_head;
|
||||
|
||||
//This bitmask has an 1 if the int should be disabled when the flash is disabled.
|
||||
|
@ -192,13 +179,14 @@ static bool non_iram_int_disabled_flag[portNUM_PROCESSORS];
|
|||
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
//Inserts an item into vector_desc list so that the list is sorted
|
||||
//with an incrementing intno_cpu value.
|
||||
//with an incrementing cpu.intno value.
|
||||
static void insert_vector_desc(vector_desc_t *to_insert)
|
||||
{
|
||||
vector_desc_t *vd=vector_desc_head;
|
||||
vector_desc_t *prev=NULL;
|
||||
while(vd!=NULL) {
|
||||
if (vd->intno_cpu >= to_insert->intno_cpu) break;
|
||||
if (vd->cpu > to_insert->cpu) break;
|
||||
if (vd->cpu == to_insert->cpu && vd->intno >= to_insert->intno) break;
|
||||
prev=vd;
|
||||
vd=vd->next;
|
||||
}
|
||||
|
@ -217,7 +205,7 @@ static vector_desc_t *find_desc_for_int(int intno, int cpu)
|
|||
{
|
||||
vector_desc_t *vd=vector_desc_head;
|
||||
while(vd!=NULL) {
|
||||
if (vd->intno_cpu==to_intno_cpu(intno, cpu)) break;
|
||||
if (vd->cpu==cpu && vd->intno==intno) break;
|
||||
vd=vd->next;
|
||||
}
|
||||
return vd;
|
||||
|
@ -233,7 +221,8 @@ static vector_desc_t *get_desc_for_int(int intno, int cpu)
|
|||
vector_desc_t *newvd=malloc(sizeof(vector_desc_t));
|
||||
if (newvd==NULL) return NULL;
|
||||
memset(newvd, 0, sizeof(vector_desc_t));
|
||||
newvd->intno_cpu=to_intno_cpu(intno, cpu);
|
||||
newvd->intno=intno;
|
||||
newvd->cpu=cpu;
|
||||
insert_vector_desc(newvd);
|
||||
return newvd;
|
||||
} else {
|
||||
|
@ -296,6 +285,7 @@ static bool int_has_handler(int intr, int cpu)
|
|||
|
||||
//Locate a free interrupt compatible with the flags given.
|
||||
//The 'force' argument can be -1, or 0-31 to force checking a certain interrupt.
|
||||
//When a CPU is forced, the INTDESC_SPECIAL marked interrupts are also accepted.
|
||||
static int get_free_int(int flags, int cpu, int force)
|
||||
{
|
||||
int x;
|
||||
|
@ -323,10 +313,14 @@ static int get_free_int(int flags, int cpu, int force)
|
|||
x, int_desc[x].cpuflags[cpu]==INTDESC_RESVD, int_desc[x].level,
|
||||
int_desc[x].type==INTTP_LEVEL?"LEVEL":"EDGE", int_has_handler(x, cpu));
|
||||
//Check if interrupt is not reserved by design
|
||||
if (int_desc[x].cpuflags[cpu]==INTDESC_RESVD) { //ToDo: Check for SPECIAL and force!=-1
|
||||
if (int_desc[x].cpuflags[cpu]==INTDESC_RESVD) {
|
||||
ALCHLOG(TAG, "....Unusable: reserved");
|
||||
continue;
|
||||
}
|
||||
if (int_desc[x].cpuflags[cpu]==INTDESC_SPECIAL && force==-1) {
|
||||
ALCHLOG(TAG, "....Unusable: special-purpose int");
|
||||
continue;
|
||||
}
|
||||
//Check if the interrupt level is acceptable
|
||||
if (!(flags&(1<<int_desc[x].level))) {
|
||||
ALCHLOG(TAG, "....Unusable: incompatible level");
|
||||
|
@ -426,30 +420,31 @@ static void IRAM_ATTR shared_intr_isr(void *arg)
|
|||
shared_vector_desc_t *sh_vec=vd->shared_vec_info;
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
while(sh_vec) {
|
||||
if (!sh_vec->disabled) {
|
||||
if ((sh_vec->statusreg == NULL) || (*sh_vec->statusreg & sh_vec->statusmask)) {
|
||||
sh_vec->isr(sh_vec->arg);
|
||||
sh_vec=sh_vec->next;
|
||||
}
|
||||
}
|
||||
sh_vec=sh_vec->next;
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
}
|
||||
|
||||
|
||||
//We use ESP_EARLY_LOG* here because this can be called before the scheduler is running.
|
||||
esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler,
|
||||
void *arg, int_handle_t *ret_handle)
|
||||
void *arg, intr_handle_t *ret_handle)
|
||||
{
|
||||
int_handle_data_t *ret=NULL;
|
||||
intr_handle_data_t *ret=NULL;
|
||||
int force=-1;
|
||||
printf("Src %d reg/mask %x/%x\n", source, intrstatusreg, intrstatusmask);
|
||||
ESP_EARLY_LOGV(TAG, "esp_intr_alloc_intrstatus (cpu %d): checking args", xPortGetCoreID());
|
||||
//Shared interrupts should be level-triggered.
|
||||
if ((flags&ESP_INTR_FLAG_SHARED) && (flags&ESP_INTR_FLAG_EDGE)) return ESP_ERR_INVALID_ARG;
|
||||
//You can't set an handler / arg for a non-C-callable interrupt.
|
||||
if ((flags&ESP_INTR_FLAG_HIGH) && (handler)) return ESP_ERR_INVALID_ARG;
|
||||
//Shared ints should have handler
|
||||
if ((flags&ESP_INTR_FLAG_SHARED) && (!handler)) return ESP_ERR_INVALID_ARG;
|
||||
//Only shared interrupts can have status reg / mask
|
||||
if (intrstatusreg && (!(flags&ESP_INTR_FLAG_SHARED))) return ESP_ERR_INVALID_ARG;
|
||||
//Shared ints should have handler and non-processor-local source
|
||||
if ((flags&ESP_INTR_FLAG_SHARED) && (!handler || source<0)) return ESP_ERR_INVALID_ARG;
|
||||
//Statusreg should have a mask
|
||||
if (intrstatusreg && !intrstatusmask) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
|
@ -472,11 +467,9 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
|
|||
if (source==ETS_INTERNAL_SW1_INTR_SOURCE) force=ETS_INTERNAL_SW1_INTR_NO;
|
||||
if (source==ETS_INTERNAL_PROFILING_INTR_SOURCE) force=ETS_INTERNAL_PROFILING_INTR_NO;
|
||||
|
||||
//If we should return a handle, allocate it here.
|
||||
if (ret_handle!=NULL) {
|
||||
ret=malloc(sizeof(int_handle_data_t));
|
||||
//Allocate a return handle. If we end up not needing it, we'll free it later on.
|
||||
ret=malloc(sizeof(intr_handle_data_t));
|
||||
if (ret==NULL) return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
int cpu=xPortGetCoreID();
|
||||
|
@ -511,6 +504,8 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
|
|||
sh_vec->isr=handler;
|
||||
sh_vec->arg=arg;
|
||||
sh_vec->next=vd->shared_vec_info;
|
||||
sh_vec->source=source;
|
||||
sh_vec->disabled=0;
|
||||
vd->shared_vec_info=sh_vec;
|
||||
vd->flags|=VECDESC_FL_SHARED;
|
||||
//(Re-)set shared isr handler to new value.
|
||||
|
@ -522,6 +517,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
|
|||
xt_set_interrupt_handler(intr, handler, arg);
|
||||
}
|
||||
if (flags&ESP_INTR_FLAG_EDGE) xthal_set_intclear(1 << intr);
|
||||
vd->source=source;
|
||||
}
|
||||
if (flags&ESP_INTR_FLAG_IRAM) {
|
||||
vd->flags|=VECDESC_FL_INIRAM;
|
||||
|
@ -533,22 +529,34 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
|
|||
if (source>=0) {
|
||||
intr_matrix_set(cpu, source, intr);
|
||||
}
|
||||
//Fill return handle if needed
|
||||
if (ret_handle!=NULL) {
|
||||
|
||||
//Fill return handle data.
|
||||
ret->vector_desc=vd;
|
||||
ret->shared_vector_desc=vd->shared_vec_info;
|
||||
*ret_handle=ret;
|
||||
|
||||
//Enable int at CPU-level;
|
||||
ESP_INTR_ENABLE(intr);
|
||||
|
||||
//If interrupt has to be started disabled, do that now; ints won't be enabled for real until the end
|
||||
//of the critical section.
|
||||
if (flags&ESP_INTR_FLAG_INTRDISABLED) {
|
||||
esp_intr_disable(ret);
|
||||
}
|
||||
|
||||
//We enable the interrupt in any case. For shared interrupts, the interrupts are enabled as soon as we exit
|
||||
//the critical region anyway, so this is consistent.
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
|
||||
//Fill return handle if needed, otherwise free handle.
|
||||
if (ret_handle!=NULL) {
|
||||
*ret_handle=ret;
|
||||
} else {
|
||||
free(ret);
|
||||
}
|
||||
|
||||
ESP_EARLY_LOGD(TAG, "Connected src %d to int %d (cpu %d)", source, intr, cpu);
|
||||
ESP_INTR_ENABLE(intr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, int_handle_t *ret_handle)
|
||||
esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle)
|
||||
{
|
||||
/*
|
||||
As an optimization, we can create a table with the possible interrupt status registers and masks for every single
|
||||
|
@ -559,13 +567,14 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar
|
|||
}
|
||||
|
||||
|
||||
esp_err_t esp_intr_free(int_handle_t handle)
|
||||
esp_err_t esp_intr_free(intr_handle_t handle)
|
||||
{
|
||||
bool free_shared_vector=false;
|
||||
if (!handle) return ESP_ERR_INVALID_ARG;
|
||||
//This routine should be called from the interrupt the task is scheduled on.
|
||||
if (to_cpu(handle->vector_desc->intno_cpu)!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG;
|
||||
if (handle->vector_desc->cpu!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
esp_intr_disable(handle);
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
if (handle->vector_desc->flags&VECDESC_FL_SHARED) {
|
||||
//Find and kill the shared int
|
||||
|
@ -593,46 +602,87 @@ esp_err_t esp_intr_free(int_handle_t handle)
|
|||
|
||||
if ((handle->vector_desc->flags&VECDESC_FL_NONSHARED) || free_shared_vector) {
|
||||
ESP_LOGV(TAG, "esp_intr_free: Disabling int, killing handler");
|
||||
//Interrupt is not shared. Just disable it and revert to the default interrupt handler.
|
||||
ESP_INTR_DISABLE(to_intno(handle->vector_desc->intno_cpu));
|
||||
xt_set_interrupt_handler(to_intno(handle->vector_desc->intno_cpu), xt_unhandled_interrupt, NULL);
|
||||
//Reset to normal handler
|
||||
xt_set_interrupt_handler(handle->vector_desc->intno, xt_unhandled_interrupt, (void*)handle->vector_desc->intno);
|
||||
//Theoretically, we could free the vector_desc... not sure if that's worth the few bytes of memory
|
||||
//we save.(We can also not use the same exit path for empty shared ints anymore if we delete
|
||||
//the desc.) For now, just mark it as free.
|
||||
handle->vector_desc->flags&=!(VECDESC_FL_NONSHARED|VECDESC_FL_RESERVED);
|
||||
//Also kill non_iram mask bit.
|
||||
non_iram_int_mask[to_cpu(handle->vector_desc->intno_cpu)]&=~(1<<(to_intno(handle->vector_desc->intno_cpu)));
|
||||
non_iram_int_mask[handle->vector_desc->cpu]&=~(1<<(handle->vector_desc->intno));
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
free(handle);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int esp_intr_get_intno(int_handle_t handle)
|
||||
int esp_intr_get_intno(intr_handle_t handle)
|
||||
{
|
||||
return to_intno(handle->vector_desc->intno_cpu);
|
||||
return handle->vector_desc->intno;
|
||||
}
|
||||
|
||||
int esp_intr_get_cpu(int_handle_t handle)
|
||||
int esp_intr_get_cpu(intr_handle_t handle)
|
||||
{
|
||||
return to_cpu(handle->vector_desc->intno_cpu);
|
||||
return handle->vector_desc->cpu;
|
||||
}
|
||||
|
||||
esp_err_t esp_intr_enable(int_handle_t handle)
|
||||
/*
|
||||
Interrupt disabling strategy:
|
||||
If the source is >=0 (meaning a muxed interrupt), we disable it by muxing the interrupt to a non-connected
|
||||
interrupt. If the source is <0 (meaning an internal, per-cpu interrupt), we disable it using ESP_INTR_DISABLE.
|
||||
This allows us to, for the muxed CPUs, disable an int from the other core. It also allows disabling shared
|
||||
interrupts.
|
||||
*/
|
||||
|
||||
//Muxing an interrupt source to interrupt 6, 7, 11, 15, 16 or 29 cause the interrupt to effectively be disabled.
|
||||
#define INT_MUX_DISABLED_INTNO 6
|
||||
|
||||
esp_err_t esp_intr_enable(intr_handle_t handle)
|
||||
{
|
||||
if (!handle) return ESP_ERR_INVALID_ARG;
|
||||
if (handle->shared_vector_desc) return ESP_ERR_INVALID_ARG; //Shared ints can't be enabled using this function.
|
||||
if (to_cpu(handle->vector_desc->intno_cpu)!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG; //Can only enable ints on this cpu
|
||||
ESP_INTR_ENABLE(to_intno(handle->vector_desc->intno_cpu));
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
int source;
|
||||
if (handle->shared_vector_desc) {
|
||||
handle->shared_vector_desc->disabled=0;
|
||||
source=handle->shared_vector_desc->source;
|
||||
} else {
|
||||
source=handle->vector_desc->source;
|
||||
}
|
||||
if (source >= 0) {
|
||||
//Disabled using int matrix; re-connect to enable
|
||||
intr_matrix_set(handle->vector_desc->cpu, source, handle->vector_desc->intno);
|
||||
} else {
|
||||
//Re-enable using cpu int ena reg
|
||||
if (handle->vector_desc->cpu!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG; //Can only enable these ints on this cpu
|
||||
ESP_INTR_ENABLE(handle->vector_desc->intno);
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_intr_disable(int_handle_t handle)
|
||||
esp_err_t esp_intr_disable(intr_handle_t handle)
|
||||
{
|
||||
if (!handle) return ESP_ERR_INVALID_ARG;
|
||||
if (handle->shared_vector_desc) return ESP_ERR_INVALID_ARG; //Shared ints can't be disabled using this function.
|
||||
if (to_cpu(handle->vector_desc->intno_cpu)!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG; //Can only disable ints on this cpu
|
||||
ESP_INTR_DISABLE(to_intno(handle->vector_desc->intno_cpu));
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
int source;
|
||||
if (handle->shared_vector_desc) {
|
||||
handle->shared_vector_desc->disabled=1;
|
||||
source=handle->shared_vector_desc->source;
|
||||
} else {
|
||||
source=handle->vector_desc->source;
|
||||
}
|
||||
if (source >= 0) {
|
||||
//Disable using int matrix
|
||||
intr_matrix_set(handle->vector_desc->cpu, source, INT_MUX_DISABLED_INTNO);
|
||||
} else {
|
||||
//Disable using per-cpu regs
|
||||
if (handle->vector_desc->cpu!=xPortGetCoreID()) {
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
return ESP_ERR_INVALID_ARG; //Can only enable these ints on this cpu
|
||||
}
|
||||
ESP_INTR_DISABLE(handle->vector_desc->intno);
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
|
150
components/esp32/test/test_intr_alloc.c
Normal file
150
components/esp32/test/test_intr_alloc.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
Test for multicore FreeRTOS. This test spins up threads, fiddles with queues etc.
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "rom/ets_sys.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "unity.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/timer.h"
|
||||
|
||||
|
||||
#define TIMER_DIVIDER 16 /*!< Hardware timer clock divider */
|
||||
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */
|
||||
#define TIMER_INTERVAL0_SEC (3.4179) /*!< test interval for timer 0 */
|
||||
#define TIMER_INTERVAL1_SEC (5.78) /*!< test interval for timer 1 */
|
||||
|
||||
|
||||
/*
|
||||
* @brief timer group0 hardware timer1 init
|
||||
*/
|
||||
static void my_timer_init(int timer_group, int timer_idx, int ival)
|
||||
{
|
||||
timer_config_t config;
|
||||
config.alarm_en = 1;
|
||||
config.auto_reload = 1;
|
||||
config.counter_dir = TIMER_COUNT_UP;
|
||||
config.divider = TIMER_DIVIDER;
|
||||
config.intr_type = TIMER_INTR_LEVEL;
|
||||
config.counter_en = TIMER_PAUSE;
|
||||
/*Configure timer*/
|
||||
timer_init(timer_group, timer_idx, &config);
|
||||
/*Stop timer counter*/
|
||||
timer_pause(timer_group, timer_idx);
|
||||
/*Load counter value */
|
||||
timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL);
|
||||
/*Set alarm value*/
|
||||
timer_set_alarm_value(timer_group, timer_idx, ival);
|
||||
/*Enable timer interrupt*/
|
||||
timer_enable_intr(timer_group, timer_idx);
|
||||
}
|
||||
|
||||
static volatile int count[4]={0,0,0,0};
|
||||
|
||||
|
||||
static void timer_isr(void *arg)
|
||||
{
|
||||
int timer_idx = (int)arg;
|
||||
count[timer_idx]++;
|
||||
if (timer_idx==0) {
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
TIMERG0.hw_timer[0].update=1;
|
||||
TIMERG0.hw_timer[0].config.alarm_en = 1;
|
||||
}
|
||||
if (timer_idx==1) {
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
TIMERG0.hw_timer[1].update=1;
|
||||
TIMERG0.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
if (timer_idx==2) {
|
||||
TIMERG1.int_clr_timers.t0 = 1;
|
||||
TIMERG1.hw_timer[0].update=1;
|
||||
TIMERG1.hw_timer[0].config.alarm_en = 1;
|
||||
}
|
||||
if (timer_idx==3) {
|
||||
TIMERG1.int_clr_timers.t1 = 1;
|
||||
TIMERG1.hw_timer[1].update=1;
|
||||
TIMERG1.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
// ets_printf("int %d\n", timer_idx);
|
||||
}
|
||||
|
||||
|
||||
static void timer_test(int flags) {
|
||||
int x;
|
||||
timer_isr_handle_t inth[4];
|
||||
my_timer_init(TIMER_GROUP_0, TIMER_0, 110000);
|
||||
my_timer_init(TIMER_GROUP_0, TIMER_1, 120000);
|
||||
my_timer_init(TIMER_GROUP_1, TIMER_0, 130000);
|
||||
my_timer_init(TIMER_GROUP_1, TIMER_1, 140000);
|
||||
timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_isr, (void*)0, flags|ESP_INTR_FLAG_INTRDISABLED, &inth[0]);
|
||||
timer_isr_register(TIMER_GROUP_0, TIMER_1, timer_isr, (void*)1, flags, &inth[1]);
|
||||
timer_isr_register(TIMER_GROUP_1, TIMER_0, timer_isr, (void*)2, flags, &inth[2]);
|
||||
timer_isr_register(TIMER_GROUP_1, TIMER_1, timer_isr, (void*)3, flags, &inth[3]);
|
||||
timer_start(TIMER_GROUP_0, TIMER_0);
|
||||
timer_start(TIMER_GROUP_0, TIMER_1);
|
||||
timer_start(TIMER_GROUP_1, TIMER_0);
|
||||
timer_start(TIMER_GROUP_1, TIMER_1);
|
||||
|
||||
for (x=0; x<4; x++) count[x]=0;
|
||||
printf("Interrupts allocated: %d (dis) %d %d %d\n",
|
||||
esp_intr_get_intno(inth[0]), esp_intr_get_intno(inth[1]),
|
||||
esp_intr_get_intno(inth[2]), esp_intr_get_intno(inth[3]));
|
||||
printf("Timer values on start: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
printf("Timer values after 1 sec: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
|
||||
TEST_ASSERT(count[0]==0);
|
||||
TEST_ASSERT(count[1]!=0);
|
||||
TEST_ASSERT(count[2]!=0);
|
||||
TEST_ASSERT(count[3]!=0);
|
||||
|
||||
printf("Disabling timers 1 and 2...\n");
|
||||
esp_intr_enable(inth[0]);
|
||||
esp_intr_disable(inth[1]);
|
||||
esp_intr_disable(inth[2]);
|
||||
for (x=0; x<4; x++) count[x]=0;
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
printf("Timer values after 1 sec: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
|
||||
TEST_ASSERT(count[0]!=0);
|
||||
TEST_ASSERT(count[1]==0);
|
||||
TEST_ASSERT(count[2]==0);
|
||||
TEST_ASSERT(count[3]!=0);
|
||||
printf("Disabling other half...\n");
|
||||
esp_intr_enable(inth[1]);
|
||||
esp_intr_enable(inth[2]);
|
||||
esp_intr_disable(inth[0]);
|
||||
esp_intr_disable(inth[3]);
|
||||
for (x=0; x<4; x++) count[x]=0;
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
printf("Timer values after 1 sec: %d %d %d %d\n", count[0], count[1], count[2], count[3]);
|
||||
TEST_ASSERT(count[0]==0);
|
||||
TEST_ASSERT(count[1]!=0);
|
||||
TEST_ASSERT(count[2]!=0);
|
||||
TEST_ASSERT(count[3]==0);
|
||||
printf("Done.\n");
|
||||
esp_intr_free(inth[0]);
|
||||
esp_intr_free(inth[1]);
|
||||
esp_intr_free(inth[2]);
|
||||
esp_intr_free(inth[3]);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Intr_alloc test, private ints", "[esp32]")
|
||||
{
|
||||
timer_test(0);
|
||||
}
|
||||
|
||||
TEST_CASE("Intr_alloc test, shared ints", "[esp32]")
|
||||
{
|
||||
timer_test(ESP_INTR_FLAG_SHARED);
|
||||
}
|
|
@ -74,6 +74,7 @@ CONFIG_OPTIMIZATION_LEVEL_DEBUG=y
|
|||
#
|
||||
# Component config
|
||||
#
|
||||
CONFIG_BTC_TASK_STACK_SIZE=2048
|
||||
CONFIG_BT_RESERVE_DRAM=0
|
||||
|
||||
#
|
||||
|
@ -85,7 +86,6 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
|||
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||
# CONFIG_ESP32_ENABLE_STACK_WIFI is not set
|
||||
# CONFIG_ESP32_ENABLE_STACK_BT is not set
|
||||
CONFIG_ESP32_ENABLE_STACK_NONE=y
|
||||
CONFIG_MEMMAP_SMP=y
|
||||
# CONFIG_MEMMAP_TRACEMEM is not set
|
||||
CONFIG_TRACEMEM_RESERVE_DRAM=0x0
|
||||
|
@ -165,7 +165,6 @@ CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384
|
|||
CONFIG_MBEDTLS_HARDWARE_AES=y
|
||||
CONFIG_MBEDTLS_HARDWARE_MPI=y
|
||||
CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y
|
||||
CONFIG_MBEDTLS_MPI_INTERRUPT_NUM=18
|
||||
CONFIG_MBEDTLS_HARDWARE_SHA=y
|
||||
|
||||
#
|
||||
|
|
Loading…
Reference in a new issue