mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-01 19:54:32 +02:00
Merge branch 'feature/optimized_gpio_intr_service' into 'master'
driver: Add optimization by speed in ISR functions for gpio, rmt, pcnt Closes IDF-328 See merge request idf/esp-idf!4241
This commit is contained in:
@@ -327,37 +327,37 @@ esp_err_t gpio_reset_pin(gpio_num_t gpio_num)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR gpio_intr_service(void* arg)
|
static inline void IRAM_ATTR gpio_isr_loop(uint32_t status, const uint32_t gpio_num_start) {
|
||||||
|
while (status) {
|
||||||
|
int nbit = __builtin_ffs(status) - 1;
|
||||||
|
status &= ~(1 << nbit);
|
||||||
|
int gpio_num = gpio_num_start + nbit;
|
||||||
|
if (gpio_isr_func[gpio_num].fn != NULL) {
|
||||||
|
gpio_isr_func[gpio_num].fn(gpio_isr_func[gpio_num].args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void IRAM_ATTR gpio_intr_service(void* arg)
|
||||||
{
|
{
|
||||||
//GPIO intr process
|
//GPIO intr process
|
||||||
uint32_t gpio_num = 0;
|
|
||||||
//read status to get interrupt status for GPIO0-31
|
|
||||||
uint32_t gpio_intr_status;
|
|
||||||
gpio_intr_status = GPIO.status;
|
|
||||||
//read status1 to get interrupt status for GPIO32-39
|
|
||||||
uint32_t gpio_intr_status_h;
|
|
||||||
gpio_intr_status_h = GPIO.status1.intr_st;
|
|
||||||
|
|
||||||
if (gpio_isr_func == NULL) {
|
if (gpio_isr_func == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
do {
|
|
||||||
if (gpio_num < 32) {
|
//read status to get interrupt status for GPIO0-31
|
||||||
if (gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
|
const uint32_t gpio_intr_status = GPIO.status;
|
||||||
if (gpio_isr_func[gpio_num].fn != NULL) {
|
if (gpio_intr_status) {
|
||||||
gpio_isr_func[gpio_num].fn(gpio_isr_func[gpio_num].args);
|
gpio_isr_loop(gpio_intr_status, 0);
|
||||||
}
|
GPIO.status_w1tc = gpio_intr_status;
|
||||||
GPIO.status_w1tc = BIT(gpio_num);
|
}
|
||||||
}
|
|
||||||
} else {
|
//read status1 to get interrupt status for GPIO32-39
|
||||||
if (gpio_intr_status_h & BIT(gpio_num - 32)) {
|
const uint32_t gpio_intr_status_h = GPIO.status1.intr_st;
|
||||||
if (gpio_isr_func[gpio_num].fn != NULL) {
|
if (gpio_intr_status_h) {
|
||||||
gpio_isr_func[gpio_num].fn(gpio_isr_func[gpio_num].args);
|
gpio_isr_loop(gpio_intr_status_h, 32);
|
||||||
}
|
GPIO.status1_w1tc.intr_st = gpio_intr_status_h;
|
||||||
GPIO.status1_w1tc.intr_st = BIT(gpio_num - 32);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (++gpio_num < GPIO_PIN_COUNT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args)
|
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args)
|
||||||
|
@@ -296,15 +296,16 @@ esp_err_t pcnt_isr_register(void (*fun)(void*), void * arg, int intr_alloc_flags
|
|||||||
// pcnt interrupt service
|
// pcnt interrupt service
|
||||||
static void IRAM_ATTR pcnt_intr_service(void* arg)
|
static void IRAM_ATTR pcnt_intr_service(void* arg)
|
||||||
{
|
{
|
||||||
uint32_t intr_status = PCNT.int_st.val;
|
const uint32_t intr_status = PCNT.int_st.val;
|
||||||
for (int unit = 0; unit < PCNT_UNIT_MAX; unit++) {
|
uint32_t status = intr_status;
|
||||||
if (intr_status & (BIT(unit))) {
|
while (status) {
|
||||||
if (pcnt_isr_func[unit].fn != NULL) {
|
int unit = __builtin_ffs(status) - 1;
|
||||||
(pcnt_isr_func[unit].fn)(pcnt_isr_func[unit].args);
|
status &= ~(1 << unit);
|
||||||
}
|
if (pcnt_isr_func[unit].fn != NULL) {
|
||||||
PCNT.int_clr.val = BIT(unit);
|
(pcnt_isr_func[unit].fn)(pcnt_isr_func[unit].args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PCNT.int_clr.val = intr_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t pcnt_isr_handler_add(pcnt_unit_t unit, void(*isr_handler)(void *), void *args)
|
esp_err_t pcnt_isr_handler_add(pcnt_unit_t unit, void(*isr_handler)(void *), void *args)
|
||||||
|
@@ -555,116 +555,112 @@ static int IRAM_ATTR rmt_get_mem_len(rmt_channel_t channel)
|
|||||||
|
|
||||||
static void IRAM_ATTR rmt_driver_isr_default(void* arg)
|
static void IRAM_ATTR rmt_driver_isr_default(void* arg)
|
||||||
{
|
{
|
||||||
uint32_t intr_st = RMT.int_st.val;
|
const uint32_t intr_st = RMT.int_st.val;
|
||||||
uint32_t i = 0;
|
uint32_t status = intr_st;
|
||||||
uint8_t channel;
|
uint8_t channel;
|
||||||
portBASE_TYPE HPTaskAwoken = 0;
|
portBASE_TYPE HPTaskAwoken = 0;
|
||||||
for(i = 0; i < 32; i++) {
|
while (status) {
|
||||||
|
int i = __builtin_ffs(status) - 1;
|
||||||
|
status &= ~(1 << i);
|
||||||
if(i < 24) {
|
if(i < 24) {
|
||||||
if(intr_st & BIT(i)) {
|
channel = i / 3;
|
||||||
channel = i / 3;
|
rmt_obj_t* p_rmt = p_rmt_obj[channel];
|
||||||
rmt_obj_t* p_rmt = p_rmt_obj[channel];
|
if(NULL == p_rmt) {
|
||||||
if(NULL == p_rmt) {
|
continue;
|
||||||
RMT.int_clr.val = BIT(i);
|
}
|
||||||
continue;
|
switch(i % 3) {
|
||||||
}
|
//TX END
|
||||||
switch(i % 3) {
|
case 0:
|
||||||
//TX END
|
xSemaphoreGiveFromISR(p_rmt->tx_sem, &HPTaskAwoken);
|
||||||
case 0:
|
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
|
||||||
xSemaphoreGiveFromISR(p_rmt->tx_sem, &HPTaskAwoken);
|
RMT.conf_ch[channel].conf1.mem_rd_rst = 0;
|
||||||
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
|
p_rmt->tx_data = NULL;
|
||||||
RMT.conf_ch[channel].conf1.mem_rd_rst = 0;
|
p_rmt->tx_len_rem = 0;
|
||||||
p_rmt->tx_data = NULL;
|
p_rmt->tx_offset = 0;
|
||||||
p_rmt->tx_len_rem = 0;
|
p_rmt->tx_sub_len = 0;
|
||||||
p_rmt->tx_offset = 0;
|
p_rmt->sample_cur = NULL;
|
||||||
p_rmt->tx_sub_len = 0;
|
p_rmt->translator = false;
|
||||||
p_rmt->sample_cur = NULL;
|
if(rmt_tx_end_callback.function != NULL) {
|
||||||
p_rmt->translator = false;
|
rmt_tx_end_callback.function(channel, rmt_tx_end_callback.arg);
|
||||||
if(rmt_tx_end_callback.function != NULL) {
|
}
|
||||||
rmt_tx_end_callback.function(channel, rmt_tx_end_callback.arg);
|
break;
|
||||||
}
|
//RX_END
|
||||||
break;
|
case 1:
|
||||||
//RX_END
|
RMT.conf_ch[channel].conf1.rx_en = 0;
|
||||||
case 1:
|
int item_len = rmt_get_mem_len(channel);
|
||||||
RMT.conf_ch[channel].conf1.rx_en = 0;
|
//change memory owner to protect data.
|
||||||
int item_len = rmt_get_mem_len(channel);
|
RMT.conf_ch[channel].conf1.mem_owner = RMT_MEM_OWNER_TX;
|
||||||
//change memory owner to protect data.
|
if(p_rmt->rx_buf) {
|
||||||
RMT.conf_ch[channel].conf1.mem_owner = RMT_MEM_OWNER_TX;
|
BaseType_t res = xRingbufferSendFromISR(p_rmt->rx_buf, (void*) RMTMEM.chan[channel].data32, item_len * 4, &HPTaskAwoken);
|
||||||
if(p_rmt->rx_buf) {
|
if(res == pdFALSE) {
|
||||||
BaseType_t res = xRingbufferSendFromISR(p_rmt->rx_buf, (void*) RMTMEM.chan[channel].data32, item_len * 4, &HPTaskAwoken);
|
ESP_EARLY_LOGE(RMT_TAG, "RMT RX BUFFER FULL");
|
||||||
if(res == pdFALSE) {
|
|
||||||
ESP_EARLY_LOGE(RMT_TAG, "RMT RX BUFFER FULL");
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ESP_EARLY_LOGE(RMT_TAG, "RMT RX BUFFER ERROR\n");
|
|
||||||
}
|
}
|
||||||
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
} else {
|
||||||
RMT.conf_ch[channel].conf1.mem_owner = RMT_MEM_OWNER_RX;
|
ESP_EARLY_LOGE(RMT_TAG, "RMT RX BUFFER ERROR\n");
|
||||||
RMT.conf_ch[channel].conf1.rx_en = 1;
|
}
|
||||||
break;
|
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
|
||||||
//ERR
|
RMT.conf_ch[channel].conf1.mem_owner = RMT_MEM_OWNER_RX;
|
||||||
case 2:
|
RMT.conf_ch[channel].conf1.rx_en = 1;
|
||||||
ESP_EARLY_LOGE(RMT_TAG, "RMT[%d] ERR", channel);
|
break;
|
||||||
ESP_EARLY_LOGE(RMT_TAG, "status: 0x%08x", RMT.status_ch[channel]);
|
//ERR
|
||||||
RMT.int_ena.val &= (~(BIT(i)));
|
case 2:
|
||||||
break;
|
ESP_EARLY_LOGE(RMT_TAG, "RMT[%d] ERR", channel);
|
||||||
default:
|
ESP_EARLY_LOGE(RMT_TAG, "status: 0x%08x", RMT.status_ch[channel]);
|
||||||
break;
|
RMT.int_ena.val &= (~(BIT(i)));
|
||||||
}
|
break;
|
||||||
RMT.int_clr.val = BIT(i);
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(intr_st & (BIT(i))) {
|
channel = i - 24;
|
||||||
channel = i - 24;
|
rmt_obj_t* p_rmt = p_rmt_obj[channel];
|
||||||
rmt_obj_t* p_rmt = p_rmt_obj[channel];
|
|
||||||
RMT.int_clr.val = BIT(i);
|
|
||||||
|
|
||||||
if(p_rmt->tx_data == NULL) {
|
if(p_rmt->tx_data == NULL) {
|
||||||
//skip
|
//skip
|
||||||
|
} else {
|
||||||
|
if(p_rmt->translator) {
|
||||||
|
if(p_rmt->sample_size_remain > 0) {
|
||||||
|
size_t translated_size = 0;
|
||||||
|
p_rmt->sample_to_rmt((void *) p_rmt->sample_cur,
|
||||||
|
p_rmt->tx_buf,
|
||||||
|
p_rmt->sample_size_remain,
|
||||||
|
p_rmt->tx_sub_len,
|
||||||
|
&translated_size,
|
||||||
|
&p_rmt->tx_len_rem
|
||||||
|
);
|
||||||
|
p_rmt->sample_size_remain -= translated_size;
|
||||||
|
p_rmt->sample_cur += translated_size;
|
||||||
|
p_rmt->tx_data = p_rmt->tx_buf;
|
||||||
|
} else {
|
||||||
|
p_rmt->sample_cur = NULL;
|
||||||
|
p_rmt->translator = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const rmt_item32_t* pdata = p_rmt->tx_data;
|
||||||
|
int len_rem = p_rmt->tx_len_rem;
|
||||||
|
if(len_rem >= p_rmt->tx_sub_len) {
|
||||||
|
rmt_fill_memory(channel, pdata, p_rmt->tx_sub_len, p_rmt->tx_offset);
|
||||||
|
p_rmt->tx_data += p_rmt->tx_sub_len;
|
||||||
|
p_rmt->tx_len_rem -= p_rmt->tx_sub_len;
|
||||||
|
} else if(len_rem == 0) {
|
||||||
|
RMTMEM.chan[channel].data32[p_rmt->tx_offset].val = 0;
|
||||||
} else {
|
} else {
|
||||||
if(p_rmt->translator) {
|
rmt_fill_memory(channel, pdata, len_rem, p_rmt->tx_offset);
|
||||||
if(p_rmt->sample_size_remain > 0) {
|
RMTMEM.chan[channel].data32[p_rmt->tx_offset + len_rem].val = 0;
|
||||||
size_t translated_size = 0;
|
p_rmt->tx_data += len_rem;
|
||||||
p_rmt->sample_to_rmt((void *) p_rmt->sample_cur,
|
p_rmt->tx_len_rem -= len_rem;
|
||||||
p_rmt->tx_buf,
|
}
|
||||||
p_rmt->sample_size_remain,
|
if(p_rmt->tx_offset == 0) {
|
||||||
p_rmt->tx_sub_len,
|
p_rmt->tx_offset = p_rmt->tx_sub_len;
|
||||||
&translated_size,
|
} else {
|
||||||
&p_rmt->tx_len_rem
|
p_rmt->tx_offset = 0;
|
||||||
);
|
|
||||||
p_rmt->sample_size_remain -= translated_size;
|
|
||||||
p_rmt->sample_cur += translated_size;
|
|
||||||
p_rmt->tx_data = p_rmt->tx_buf;
|
|
||||||
} else {
|
|
||||||
p_rmt->sample_cur = NULL;
|
|
||||||
p_rmt->translator = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const rmt_item32_t* pdata = p_rmt->tx_data;
|
|
||||||
int len_rem = p_rmt->tx_len_rem;
|
|
||||||
if(len_rem >= p_rmt->tx_sub_len) {
|
|
||||||
rmt_fill_memory(channel, pdata, p_rmt->tx_sub_len, p_rmt->tx_offset);
|
|
||||||
p_rmt->tx_data += p_rmt->tx_sub_len;
|
|
||||||
p_rmt->tx_len_rem -= p_rmt->tx_sub_len;
|
|
||||||
} else if(len_rem == 0) {
|
|
||||||
RMTMEM.chan[channel].data32[p_rmt->tx_offset].val = 0;
|
|
||||||
} else {
|
|
||||||
rmt_fill_memory(channel, pdata, len_rem, p_rmt->tx_offset);
|
|
||||||
RMTMEM.chan[channel].data32[p_rmt->tx_offset + len_rem].val = 0;
|
|
||||||
p_rmt->tx_data += len_rem;
|
|
||||||
p_rmt->tx_len_rem -= len_rem;
|
|
||||||
}
|
|
||||||
if(p_rmt->tx_offset == 0) {
|
|
||||||
p_rmt->tx_offset = p_rmt->tx_sub_len;
|
|
||||||
} else {
|
|
||||||
p_rmt->tx_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RMT.int_clr.val = intr_st;
|
||||||
if(HPTaskAwoken == pdTRUE) {
|
if(HPTaskAwoken == pdTRUE) {
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
@@ -959,4 +955,4 @@ esp_err_t rmt_get_channel_status(rmt_channel_status_result_t *channel_status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user