Skip to content

Commit bc25754

Browse files
duda-patrykCommit Bot
authored andcommitted
cortex-m0/task: Check if interrupts are enabled before switching task
Switching task with disabled interrupts leads to Hard Fault on Cortex-M0 because: - SVCall exception have configurable priority (full list can be found at 2.3.2 Exception types PM0215 p.23) - We are using 'cpsid i' to disable interrupts. This instruction sets PRIMASK bit (3.7.2 CPSID CPSIE PM0215 p.62) - When PRIMASK bit is set, all exceptions with configurable priority are disabled (PM0215 p.16), so SVCall is masked too If Hard Fault is inevitable, it will be a good idea to catch this earlier. It will save time spent debugging why Forced Hard Fault happens. In functions responsible for enabling, disabling or making task ready we postpone task switch when interrupts are disabled BUG=b:190597666 BRANCH=none TEST=Compile and flash EC on boards with Cortex-M0 and make sure that it works properly. Signed-off-by: Patryk Duda <[email protected]> Change-Id: Id3be74e977ae5d5eed79aad78ee378fa413ed4ee Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2953229 Commit-Queue: Marcin Wojtas <[email protected]> Tested-by: Patryk Duda <[email protected]> Reviewed-by: Aseda Aboagye <[email protected]>
1 parent 51625cb commit bc25754

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

core/cortex-m0/task.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ static uint32_t __wait_evt(int timeout_us, task_id_t resched)
336336
uint32_t evt;
337337
int ret __attribute__((unused));
338338

339+
/*
340+
* Scheduling task when interrupts are disabled will result in Forced
341+
* Hard Fault because disabling interrupt using 'cpsid i' also disables
342+
* SVCall handler (because it has configurable priority)
343+
*/
344+
ASSERT(is_interrupt_enabled());
339345
ASSERT(!in_interrupt_context());
340346

341347
if (timeout_us > 0) {
@@ -373,7 +379,7 @@ uint32_t task_set_event(task_id_t tskid, uint32_t event)
373379
atomic_or(&receiver->events, event);
374380

375381
/* Re-schedule if priorities have changed */
376-
if (in_interrupt_context()) {
382+
if (in_interrupt_context() || !is_interrupt_enabled()) {
377383
/* The receiver might run again */
378384
atomic_or(&tasks_ready, 1 << tskid);
379385
if (start_called) {
@@ -436,7 +442,8 @@ void task_enable_all_tasks(void)
436442
/* Mark all tasks as ready and able to run. */
437443
tasks_ready = tasks_enabled = BIT(TASK_ID_COUNT) - 1;
438444
/* Reschedule the highest priority task. */
439-
__schedule(0, 0);
445+
if (is_interrupt_enabled())
446+
__schedule(0, 0);
440447
}
441448

442449
void task_enable_task(task_id_t tskid)
@@ -448,7 +455,8 @@ void task_disable_task(task_id_t tskid)
448455
{
449456
atomic_clear_bits(&tasks_enabled, BIT(tskid));
450457

451-
if (!in_interrupt_context() && tskid == task_get_current())
458+
if (!in_interrupt_context() && is_interrupt_enabled() &&
459+
tskid == task_get_current())
452460
__schedule(0, 0);
453461
}
454462

0 commit comments

Comments
 (0)