feat(rmt): specify interrupt priority

This commit is contained in:
Planck (Lu Zeyu)
2023-08-29 17:56:03 +08:00
parent e0f5d3c527
commit 80fa5da9e8
10 changed files with 199 additions and 10 deletions

View File

@@ -53,6 +53,8 @@ rmt_group_t *rmt_acquire_group_handle(int group_id)
// enable APB access RMT registers
periph_module_enable(rmt_periph_signals.groups[group_id].module);
periph_module_reset(rmt_periph_signals.groups[group_id].module);
// "uninitialize" group intr_priority, read comments in `rmt_new_tx_channel()` for detail
group->intr_priority = RMT_GROUP_INTR_PRIORITY_UNINITALIZED;
// hal layer initialize
rmt_hal_init(&group->hal);
}
@@ -204,3 +206,48 @@ esp_err_t rmt_disable(rmt_channel_handle_t channel)
ESP_RETURN_ON_FALSE(channel->fsm == RMT_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "channel not in enable state");
return channel->disable(channel);
}
bool rmt_set_intr_priority_to_group(rmt_group_t *group, int intr_priority)
{
bool priority_conflict = false;
portENTER_CRITICAL(&group->spinlock);
if (group->intr_priority == RMT_GROUP_INTR_PRIORITY_UNINITALIZED) {
// intr_priority never allocated, accept user's value unconditionally
// intr_priority could only be set once here
group->intr_priority = intr_priority;
} else {
// group intr_priority already specified
// If interrupt priority specified before, it CANNOT BE CHANGED until `rmt_release_group_handle()` called
// So we have to check if the new priority specified conflicts with the old one
if (intr_priority) {
// User specified intr_priority, check if conflict or not
// Even though the `group->intr_priority` is 0, an intr_priority must have been specified automatically too,
// although we do not know it exactly now, so specifying the intr_priority again might also cause conflict.
// So no matter if `group->intr_priority` is 0 or not, we have to check.
// Value `0` of `group->intr_priority` means "unknown", NOT "unspecified"!
if (intr_priority != (group->intr_priority)) {
// intr_priority conflicts!
priority_conflict = true;
}
}
// else do nothing
// user did not specify intr_priority, then keep the old priority
// We'll use the `RMT_INTR_ALLOC_FLAG | RMT_ALLOW_INTR_PRIORITY_MASK`, which should always success
}
// The `group->intr_priority` will not change any longer, even though another task tries to modify it.
// So we could exit critical here safely.
portEXIT_CRITICAL(&group->spinlock);
return priority_conflict;
}
int rmt_get_isr_flags(rmt_group_t *group) {
int isr_flags = RMT_INTR_ALLOC_FLAG;
if (group->intr_priority) {
// Use user-specified priority bit
isr_flags |= (1 << (group->intr_priority));
} else {
// Allow all LOWMED priority bits
isr_flags |= RMT_ALLOW_INTR_PRIORITY_MASK;
}
return isr_flags;
}