summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/cortex-m/task.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c
index e64063dc15..bf0eb5b397 100644
--- a/core/cortex-m/task.c
+++ b/core/cortex-m/task.c
@@ -415,6 +415,15 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched)
uint32_t evt;
int ret __attribute__((unused));
+ /*
+ * Scheduling task when interrupts are disabled will result in Forced
+ * Hard Fault because:
+ * - Disabling interrupt using 'cpsid i' also disables SVCall handler
+ * (because it has configurable priority)
+ * - Escalation to Hard Fault (also known as 'priority escalation')
+ * occurs when handler for that fault is not enabled
+ */
+ ASSERT(is_interrupt_enabled());
ASSERT(!in_interrupt_context());
if (timeout_us > 0) {
@@ -445,7 +454,7 @@ uint32_t task_set_event(task_id_t tskid, uint32_t event)
atomic_or(&receiver->events, event);
/* Re-schedule if priorities have changed */
- if (in_interrupt_context()) {
+ if (in_interrupt_context() || !is_interrupt_enabled()) {
/* The receiver might run again */
atomic_or(&tasks_ready, 1 << tskid);
#ifndef CONFIG_TASK_PROFILING
@@ -497,7 +506,8 @@ void task_enable_all_tasks(void)
/* Mark all tasks as ready and able to run. */
tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1;
/* Reschedule the highest priority task. */
- __schedule(0, 0);
+ if (is_interrupt_enabled())
+ __schedule(0, 0);
}
void task_enable_task(task_id_t tskid)
@@ -509,7 +519,8 @@ void task_disable_task(task_id_t tskid)
{
atomic_clear_bits(&tasks_enabled, BIT(tskid));
- if (!in_interrupt_context() && tskid == task_get_current())
+ if (!in_interrupt_context() && is_interrupt_enabled() &&
+ tskid == task_get_current())
__schedule(0, 0);
}