mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-28 03:23:14 +00:00
8509ec1958
Route PCNT unit interrupts through private shared groups bound by module name so units in the same PCNT instance share one CPU line without allowing other peripherals to join. Remove redundant PCNT-side priority conflict checks and rely on the interrupt allocator for conflict validation. Switch the PCNT test app to unity leak utilities and clean newlib reent state during teardown so leak checks are more stable with lazy allocations.
PCNT Driver Design
Concurrency
The count value and the overflow state of the count value are located in different registers, resulting in the software being unable to obtain information from both of them in the same read instruction.
The race condition case is as follow:
sequenceDiagram
participant HW as PCNT Hardware
participant CPU0_ISR as CPU0_ISR
participant CPU1_Task as CPU1_Task (pcnt_unit_get_count)
participant REG as Reg and Soft accum counter State
CPU1_Task->>CPU1_Task: Call pcnt_unit_get_count()
Note over REG: intr_status = 0<br/>cnt_reg = cnt_value<br/>accum_value = old_value
CPU1_Task->>CPU1_Task: portENTER_CRITICAL_SAFE()
CPU1_Task->>REG: Read intr_status
Note over CPU1_Task: intr_status=0, no need to do compensation
HW->>REG: Overflow interrupt triggered
Note over REG: intr_status = 1<br/>cnt_reg = 0<br/>accum_value = old_value
REG->>CPU0_ISR: ISR is called
CPU0_ISR->>CPU0_ISR: try portENTER_CRITICAL_SAFE() but spin
CPU1_Task->>REG: Read cnt_reg(0) + accum_value(old)
CPU1_Task->>CPU1_Task: portEXIT_CRITICAL_SAFE()
CPU0_ISR->>CPU0_ISR: portENTER_CRITICAL_SAFE()
CPU0_ISR->>REG: Clear interrupt status and update accum_value
Note over REG: intr_status = 0<br/>accum_value = new_value
CPU0_ISR->>CPU0_ISR: portEXIT_CRITICAL_SAFE()
Note over CPU0_ISR: Process events
Note over CPU1_Task: Return incorrect count ❌
In the software, we determine whether to perform compensation by checking whether the count value exceeds half of the limit. This can prevent counting errors when the overflow frequency is not high.