diff options
author | Alec Berg <alecaberg@chromium.org> | 2014-05-01 14:00:03 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-05-02 19:03:31 +0000 |
commit | e68cfa73ca8db094cbf5f3cc683e44a8e653112e (patch) | |
tree | 4cfc9951f715fa7ac5900ee3464dc1553b6a9960 | |
parent | 0f01a40c86faaba64ddc1f49fda705f10800b7f4 (diff) | |
download | chrome-ec-e68cfa73ca8db094cbf5f3cc683e44a8e653112e.tar.gz |
cortex-m0: fix hard-faults during software interrupt calls part 2
This is another patch to fix the bug which causes a HardFault exception
at the "svc" instruction in __wait_evt().
The HardFault is due to a priority escalation problem in which "svc"
is called when the PRIMASK is high, meaning interrupts are disabled.
The issue was that an interrupt can occur just before the "svc"
instruction, and when an interrupt fires that performs a context switch,
the IRQ handler disables interrupts setting the PRIMASK reg high.
The arm v6 reference manual specifies that "PRIMASK unchanged on
exception exit". So, therefore, we must clear PRIMASK by running "cpsie"
before exiting IRQ handler.
BRANCH=none
BUG=chrome-os-partner:28296
TEST=
Reproduce the problem on a fruitpie by inserting dummy for loop in
__wait_evt() before "svc" call:
asm volatile("isb");
for (i = 0; i < 250; i++) ;
__schedule(1, resched);
Then, when running pd dev, the system gets the HardFault exception
within a few minutes because there is more time for an interrupt
to occur and disable interrupts right before call to "svc".
After applying this patch, the code has run for > 3 hours without
a HardFault.
Change-Id: Ic50252b09c40c7d76975ff7f16d799c9eae2bde6
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/197839
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | core/cortex-m0/irq_handler.h | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/core/cortex-m0/irq_handler.h b/core/cortex-m0/irq_handler.h index 4383f3c7ca..77816949d0 100644 --- a/core/cortex-m0/irq_handler.h +++ b/core/cortex-m0/irq_handler.h @@ -55,7 +55,8 @@ extern int need_resched_or_profiling; "cpsid i\n isb\n" \ /* re-schedule the highest priority task */ \ "bl svc_handler\n" \ - /* return from exception */ \ + /* enable interrupts and return from exception */ \ + "cpsie i\n" \ "pop {r0,pc}\n" \ : : "r"(&need_resched_or_profiling)); \ } \ |