mcpwm capture module doesn't work after running for a while.
Posted: Fri Mar 31, 2023 4:23 am
Hello everyone, I'm using a ESP32 board and developed a firmware to capture frequency input by mcpwm module from 2 sensor inputs channel.
It's usually working fine, but almost every time when I increase the input frequency from one of input channel, the mcpwm capture module just seems stopping working any more, at this moment I have to reboot to fix it.
here's the detail:
1. I use MCPWM_UNIT_0 module to capture two frequency input channel which are two GPIO pins, let's say FE1 and FE2. The initialization code looks like:
2. Inside the isr_getfreq_handler() code, I handle and measure the frequency each time it triggered.
Push the data into queue, just as:
3. I use another loop code to receive those data from queue in main task, just as:
I think above are all related codes, and I have several problems:
a. Normally, the frequency input from two GPIO input are the same, in this case, it works fine.
However, if I manually increase one of frequency making it much different than the others', let's say one input is set to 200 Hz and the other's increased to 500 - 1000 Hz, it will finally cause the isr_getfreq_handler() function does not work anymore. From that moment on, I have to reboot the device, otherwise, it will not recover even I decrease two input frequency to the same value.
The reason I think the isr_getfreq_handler() function has stopped working is that from the main while loop, it can't receive anything from queue.
b. When I try to add some log message within isr_getfreq_handler(), such as ESP_LOG() or printf(), it just cause a run-time crash which I have no idea why.
c. As you can see, in my main while loop, I use xQueueReceive(capv_queue, &evt, 500) function to get data from queue, however, I intentionally expect this function return in 500ms even there is no data from queue by passing 500 instead of max_delay. But seems that it blocks forever if the queue is empty, any idea?
Could some one kindly provide any idea or suggestion ? Thank you very much!
It's usually working fine, but almost every time when I increase the input frequency from one of input channel, the mcpwm capture module just seems stopping working any more, at this moment I have to reboot to fix it.
here's the detail:
1. I use MCPWM_UNIT_0 module to capture two frequency input channel which are two GPIO pins, let's say FE1 and FE2. The initialization code looks like:
Code: Select all
mcpwm_pin_config_t FE12_config = {
.mcpwm_cap0_in_num = FE1,
.mcpwm_cap1_in_num = FE2,
};
mcpwm_set_pin(MCPWM_UNIT_0, &FE12_config);
mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, MCPWM_POS_EDGE, 0); // 0.5s
mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_SELECT_CAP1, MCPWM_POS_EDGE, 0);
MCPWM[MCPWM_UNIT_0]->int_ena.val = CAP0_INT_EN | CAP1_INT_EN;
mcpwm_isr_register(MCPWM_UNIT_0, isr_getfreq_handler, NULL, ESP_INTR_FLAG_EDGE, NULL); // Set ISR Handler
Push the data into queue, just as:
Code: Select all
static void IRAM_ATTR isr_getfreq_handler()
{
uint32_t mcpwm_intr_status;
capture evt;
mcpwm_intr_status = MCPWM[MCPWM_UNIT_0]->int_st.val; // Read interrupt status
if (mcpwm_intr_status & CAP0_INT_EN) { // Check for interrupt on rising edge on CAP0 signal
current_cap_value[0] = mcpwm_capture_signal_get_value(MCPWM_UNIT_0, MCPWM_SELECT_CAP0); // get capture signal counter value
evt.capture_signal = (current_cap_value[0] - previous_cap_value[0]) * 0.0125;
previous_cap_value[0] = current_cap_value[0];
evt.sel_cap_signal = MCPWM_SELECT_CAP0;
xQueueSendFromISR(capv_queue, &evt, NULL);
}
if (mcpwm_intr_status & CAP1_INT_EN) { // Check for interrupt on rising edge on CAP1 signal
current_cap_value[1] = mcpwm_capture_signal_get_value(MCPWM_UNIT_0, MCPWM_SELECT_CAP1); // get capture signal counter value
evt.capture_signal = (current_cap_value[1] - previous_cap_value[1]) * 0.0125;
previous_cap_value[1] = current_cap_value[1];
evt.sel_cap_signal = MCPWM_SELECT_CAP1;
xQueueSendFromISR(capv_queue, &evt, NULL);
}
MCPWM[MCPWM_UNIT_0]->int_clr.val = mcpwm_intr_status;
}
Code: Select all
while (1) {
// for test jje
static uint32_t _count = 0;
bool _log = false;
if (++_count % 200 == 0) {
_log = true;
}
if (_log) {
ESP_LOGI(TAG, "[DEBUG] : GetFreq() called. wiht count cycle : %d", _count);
}
esp_task_wdt_reset(); // Comment this line to trigger a TWDT timeout
// 双路测频
if (xQueueReceive(capv_queue, &evt, 500)) {
if (evt.sel_cap_signal == MCPWM_SELECT_CAP0) {
ProcessValue.freq1 = 1.0 / (float)evt.capture_signal * 1000000;
getFreq1 = 1;
// for test jje
if (_log) {
ESP_LOGI(TAG, "[DEBUG] : MCPWM_SELECT_CAP0 in GetFreq() called. wiht count cycle : %d", _count);
}
}
if (evt.sel_cap_signal == MCPWM_SELECT_CAP1) {
ProcessValue.freq2 = 1.0 / (float)evt.capture_signal * 1000000;
getFreq2 = 1;
// for test jje
if (_log) {
ESP_LOGI(TAG, "[DEBUG] : MCPWM_SELECT_CAP1 in GetFreq() called. wiht count cycle : %d", _count);
}
}
}
}
a. Normally, the frequency input from two GPIO input are the same, in this case, it works fine.
However, if I manually increase one of frequency making it much different than the others', let's say one input is set to 200 Hz and the other's increased to 500 - 1000 Hz, it will finally cause the isr_getfreq_handler() function does not work anymore. From that moment on, I have to reboot the device, otherwise, it will not recover even I decrease two input frequency to the same value.
The reason I think the isr_getfreq_handler() function has stopped working is that from the main while loop, it can't receive anything from queue.
b. When I try to add some log message within isr_getfreq_handler(), such as ESP_LOG() or printf(), it just cause a run-time crash which I have no idea why.
c. As you can see, in my main while loop, I use xQueueReceive(capv_queue, &evt, 500) function to get data from queue, however, I intentionally expect this function return in 500ms even there is no data from queue by passing 500 instead of max_delay. But seems that it blocks forever if the queue is empty, any idea?
Could some one kindly provide any idea or suggestion ? Thank you very much!