summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorTom Hughes <tomhughes@chromium.org>2020-10-09 14:17:19 -0700
committerCommit Bot <commit-bot@chromium.org>2020-10-12 19:12:06 +0000
commit9dfd286309e0b43a905bf77a56923d29027f505b (patch)
tree15ecfd97f3ea9255d369af811419f1b2dc517873 /docs
parent5ec7c4f83a868c788da4ccbc3944c75ef3f7b739 (diff)
downloadchrome-ec-9dfd286309e0b43a905bf77a56923d29027f505b.tar.gz
docs: Fix typos
BRANCH=none BUG=none TEST=view in gitiles Signed-off-by: Tom Hughes <tomhughes@chromium.org> Change-Id: I5ca6773dfdfe41fc99780e6f3f532fa27b25424b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2464007 Commit-Queue: Diana Z <dzigterman@chromium.org> Reviewed-by: Diana Z <dzigterman@chromium.org>
Diffstat (limited to 'docs')
-rw-r--r--docs/core_runtime.md84
1 files changed, 42 insertions, 42 deletions
diff --git a/docs/core_runtime.md b/docs/core_runtime.md
index b2c819a545..f2eb17f069 100644
--- a/docs/core_runtime.md
+++ b/docs/core_runtime.md
@@ -1,6 +1,6 @@
-# Chromium OS Embedded Controller runtime
+# Chromium OS Embedded Controller Runtime
-## Design principles
+## Design Principles
1. Never do at runtime what you can do at compile time The goal is saving flash
space and computations. Compile-time configuration until you really need to
@@ -13,7 +13,7 @@
32-bit single core CPU for small systems : 4kB to 64kB data RAM, possibly
execute-in-place from flash.
-## Execution contexts
+## Execution Contexts
This is a pre-emptible runtime with static tasks. It has only 2 possible
execution contexts:
@@ -22,9 +22,9 @@ execution contexts:
- the [interrupt handlers](#interrupts)
The initial startup is an exception as described in the
-[dedicated paragraph](#Startup).
+[dedicated paragraph](#startup).
-### tasks
+### Tasks
The tasks are statically defined at compile-time. They are described for each
*board* in the [board/$board/ec.tasklist](../board/host/ec.tasklist) file.
@@ -42,11 +42,11 @@ priority tasks, see the [preemption section](#scheduling-and-preemption) for
details and the [locking section](#locking-and-atomicity) for the few cases
where you need to avoid it.
-### interrupts
+### Interrupts
The hardware interrupt requests are connected to the interruption handling *C*
routines declared by the `DECLARE_IRQ` macros, through some chip/core specific
-mechanisms (e.g. depending whether we have a vectored interrupt controller,
+mechanisms (e.g. depending on whether we have a vectored interrupt controller,
slave interrupt controllers...)
The interrupts can be nested (ie interrupted by a higher priority interrupt).
@@ -54,7 +54,7 @@ All the interrupt vectors are assigned a priority as defined in their
`DECLARE_IRQ` macro. The number of available priority level is
architecture-specific (e.g. 4 on Cortex-M0, 8 on Cortex-M3/M4) and several
interrupt handlers can have the same priority. An interrupt handler can only be
-interrupted by an handler having a priority **strictly** **greater** than its
+interrupted by a handler having a priority **strictly** **greater** than its
own.
In most cases, the exceptions (e.g data/prefetch aborts, software interrupt) can
@@ -67,7 +67,7 @@ exceptions should ultimately lead to a reboot.
Each task has a *pending* events bitmap[1] implemented as a 32-bit word. Several
events are pre-defined for all tasks, the most significant bits on the 32-bit
bitmap are reserved for them : the timer pending event on bit 31
-([see the corresponding section](#Timers)), the requested task wake (bit 29),
+([see the corresponding section](#time)), the requested task wake (bit 29),
the event to kick the waiters on a mutex (bit 30), along with a few hardware
specific events. The 19 least significant bits are available for task-specific
meanings.
@@ -84,17 +84,17 @@ The two typical use-cases are:
- a task sends a message to another task (simply use some common memory
structures [see explanation](#single-address-space) and want it to process
it now.
-- an hardware IRQ occurred and we need to do some long processing to respond
+- a hardware IRQ occurred, and we need to do some long processing to respond
to it (e.g. an I2C transaction). The associated interrupt handler cannot do
it (for latency reason), so it will raise an event to ask a task to do it.
The task code chooses to consume them (or a subset of them) when it's running
through the `task_wait_event()` and `task_wait_event_mask()` primitives.
-### Scheduling and preemption
+### Scheduling and Preemption
The system has a global bitmap[1] called `tasks_ready` containing one bit per
-task and indicating whether or not it is *ready* *to* *run* (ie want/need to be
+task and indicating whether it is *ready* *to* *run* (ie want/need to be
scheduled). The task ready bit can only be cleared when it's calling itself one
of the functions explicitly triggering a re-scheduling (e.g. `task_wait_event()`
or `task_set_event()`) **and** it has no pending event. The task ready bit is
@@ -123,7 +123,7 @@ can happen:
returning to the interrupt task.
- a task sets an event on another task. The runtime will trigger a software
interrupt to force a re-scheduling at its exit.
-- the running task voluntarily relinguish its current execution rights by
+- the running task voluntarily relinquish its current execution rights by
calling `task_wait_event()` or a similar function. This will call the
software interrupt similarly to the previous case.
@@ -133,7 +133,7 @@ processor registers on the current task stack, switch the stack pointer to the
newly scheduled task, and restore the registers from the previously saved
context from there.
-### hooks and deferred function
+### Hooks and Deferred Functions
The lowest priority task (ie Task 1, aka TASK_ID_HOOKS) is reserved to execute
repetitive actions and future actions deferred in time without blocking the
@@ -144,7 +144,7 @@ The HOOKS task has a list of deferred functions and their next deadline. Every
time it is waken up, it runs through the list and calls the ones whose deadline
is expired. Before going back to sleep, it arms a timer to the closest deadline.
The deferred functions can be created using the `DECLARED_DEFERRED()` macro.
-Similarly the HOOK_SECOND and HOOK_TICK hooks are called periodically by the
+Similarly, the HOOK_SECOND and HOOK_TICK hooks are called periodically by the
HOOKS task loop (the *tick* duration is platform-defined and shorter than the
second).
@@ -152,13 +152,13 @@ Note: be specially careful about priority inversions when accessing resources
protected by a mutex (e.g. a shared I2C controller) in a deferred function.
Indeed being the lowest priority task, it might be de-scheduled for long time
and starve higher priority tasks trying to access the resource given there is no
-priority boosting implemented for this case. Also be careful about long delays
+priority boosting implemented for this case. Also, be careful about long delays
(> x 100us) in hook or deferred function handlers, since those will starve other
hooks of execution time. It is better to implement a state machine where you set
up a subsequent call to a deferred function than have a long delay in your
handler.
-### watchdog
+### Watchdog
The system is always protected against misbehaving tasks and interrupt handlers
by a hardware watchdog rebooting the CPU when it is not attended.
@@ -170,12 +170,12 @@ guarantees that all tasks are getting some run time during the watchdog period.
Note: that's also why one should not sprinkle its code with `watchdog_reload()`
to paper over long-running routine issues.
-To help debugging bad sequences triggering watchdog reboots, most platforms
+To help debug bad sequences triggering watchdog reboots, most platforms
implement a warning mechanism defined under `CONFIG_WATCHDOG_HELP`. It's a timer
firing at the middle of the watchdog period if it hasn't been petted by then,
and dumping on the console the current state of the execution mainly to help
-finding a stuck task or handler. The normal execution is resumed though after
-this alert.
+find a stuck task or handler. The normal execution is resumed though after this
+alert.
### Startup
@@ -190,7 +190,7 @@ The startup sequence goes through the following steps:
protection if any, gpios in their default state, prepare the interrupt
controller, set the clocks, then timers, enable interrupts, init the debug
UART and the watchdog.
-- finally start tasks.
+- finally, start tasks.
For the tasks startup, initially only the HOOKS task is marked as ready, so it
is the first to start and can call all the HOOK_INIT handlers performing
@@ -198,15 +198,15 @@ initializations before actually executing any real task code. Then all tasks are
marked as ready, and the highest priority one is given the control.
During all the startup sequence until the control is given the first task, we
-are using a speciak stack called 'system stack' which will be later re-used as
+are using a special stack called 'system stack' which will be later re-used as
the interrupts and exception stack.
To prepare the first context switch, the code in `task_pre_init()` is stuffing
-all the tasks stacks with a *fake* saved context whose program counter is
-containing the task start address and the stack pointer is pointing to its
-reserved stack space.
+all the tasks stacks with a *fake* saved context whose program counter contains
+the task start address, and the stack pointer is pointing to its reserved stack
+space.
-### locking and atomicity
+### Locking and Atomicity
The two main concurrency primitives are lightweight atomic variables and heavier
mutexes.
@@ -215,31 +215,31 @@ The atomic variables are 32-bit integers (which can usually be loaded/stored
atomically on the architecture we are supporting). The `atomic.h` headers
include primitives to do atomically various bit and arithmetic operations using
either load-linked/load-exclusive, store-conditional/store-exclusive or simple
-depending what is available.
+depending on what is available.
The mutexes are actually statically allocated binary semaphores. In case of
contention, they will make the waiting task sleep (removing its ready bit) and
-use the [event mechanism](#Events) to wake-up the other waiters on unlocking.
+use the [event mechanism](#events) to wake-up the other waiters on unlocking.
Note: the mutexes are NOT triggering any priority boosting to avoid the priority
inversion phenomenon.
Given the runtime is running on single core CPU, spinlocks would be equivalent
to masking interrupts with `interrupt_disable()` spinlocks, but it's strongly
-discouraged to avoid harming the real-time characterics of the runtime.
+discouraged to avoid harming the real-time characteristics of the runtime.
## Time
-### time keeping
+### Time Keeping
In the runtime, the time is accounted everywhere using a **64-bit**
**microsecond** count since the microcontroller **cold** **boot**.
-Note: The runtime has no notion of wall-time/date, even though a few platform
+Note: The runtime has no notion of wall-time/date, even though a few platforms
have an RTC inside the microcontroller.
These microsecond timestamps are implemented in the code using the `timestamp_t`
-type and the current timestamp is returned by the `get_time()` function.
+type, and the current timestamp is returned by the `get_time()` function.
The time-keeping is preferably implemented using a 32-bit hardware free running
counter at 1Mhz plus a 32-bit word in memory keeping track of the high word of
@@ -247,10 +247,10 @@ the 64-bit absolute time. This word is incremented by the 32-bit timer rollback
interrupt.
Note: as a consequence of this implementation, when the 64-bit timestamp is read
-in interrupt context in an handler having a higher priority than the timer IRQ
+in interrupt context in a handler having a higher priority than the timer IRQ
(which is somewhat rare), the high 32-bit word might be incoherent (off by one).
-### timer event
+### Timer Event
The runtime offers *one* (and only one) timer per task. All the task timers are
multiplexed on a single hardware timer. (can be just a *match* *interrupt* on
@@ -268,7 +268,7 @@ will fail due to the lack of available timer.
## Memory
-### Single address space
+### Single Address Space
There is no memory isolation between tasks (ie they all live in the same address
space). Some architectures implement memory protection mechanism albeit only to
@@ -276,12 +276,12 @@ differentiate executable area (eg `.code`) from writable area (eg `.bss` or
`.data`) as there is a **single** **privilege** level for all execution
contexts.
-As all the memory is implicitely shared between the task, the inter-task
+As all the memory is implicitly shared between the task, the inter-task
communication can be done by simply writing the data structures in memory and
using events to wake the other task (given we properly thought the concurrent
-accesses on thoses structures).
+accesses on those structures).
-### heap
+### Heap
The data structure should be statically allocated at compile time.
@@ -293,7 +293,7 @@ long-tail of failures.
- TODO: talk about shared memory
- TODO: where/how we store *panic* *memory* and *sysjump* *parameters*.
-### stacks
+### Stacks
Each task has its own stack, in addition there is a system stack used for
startup and interrupts/exceptions.
@@ -306,17 +306,17 @@ the total RAM consumption, so their sizes need to be carefully tuned. (please
refer to the [debugging paragraph](#debugging) for additional input on this
topic.
-## Firmware code organization and multiple copies
+## Firmware Code Organization and Multiple Copies
- TODO: Details the classical RO / RW partitions and how we sysjump.
-## power management
+## Power Management
- TODO: talk about the idle task + WFI (note: interrupts are disabled!)
- TODO: more about low power idle and the sleep-disable bitmap
- TODO: adjusting the microsecond timer at wake-up
-## debugging
+## Debugging
- TODO: our main tool: serial console ... (but non-blocking / discard
overflow, cflush DO/DONT)