summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-05-20 19:47:34 -0700
committerVincent Palatin <vpalatin@chromium.org>2012-05-25 16:11:41 +0000
commitc7fcad29242e8576add5b9a3640149bb1d22dd34 (patch)
tree1ad7eb4488b576cad515cee9fa7d1a8852e1c703
parent61902efd16095af85764bd4b2df51415df49ea55 (diff)
downloadchrome-ec-c7fcad29242e8576add5b9a3640149bb1d22dd34.tar.gz
Init task contexts/stacks at runtime
Instead of storing task contexts in .data and wasting several kB of flash with mostly 0s, move them to .bss and fill the initial context at EC startup. The runtime overhead is small enough. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BUG=chrome-os-partner:9839 TEST=run on Link and check verified boot and chromeOS startup are OK. Change-Id: Iaef23d46a4e3e80e49886dfbf7ab1f537c587362
-rw-r--r--core/cortex-m/ec.lds.S29
-rw-r--r--core/cortex-m/task.c42
2 files changed, 42 insertions, 29 deletions
diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S
index 18d8fe6dc8..4eee36f763 100644
--- a/core/cortex-m/ec.lds.S
+++ b/core/cortex-m/ec.lds.S
@@ -96,11 +96,21 @@ SECTIONS
#endif
#ifdef COMPILE_FOR_RAM
} > IRAM
- __ro_end = . ;
- .data : {
#else
} > FLASH
+#endif
__ro_end = . ;
+ .bss : {
+ . = ALIGN(4);
+ __bss_start = .;
+ *(.bss.tasks)
+ *(.bss)
+ . = ALIGN(4);
+ __bss_end = .;
+ } > IRAM
+#ifdef COMPILE_FOR_RAM
+ .data : {
+#else
.data : AT(ADDR(.rodata) + SIZEOF(.rodata)) {
#endif
. = ALIGN(4);
@@ -111,6 +121,10 @@ SECTIONS
*(.iram.text)
. = ALIGN(4);
__data_end = .;
+
+ /* Shared memory buffer must be at the end of preallocated RAM, so it
+ * can expand to use all the remaining RAM. */
+ __shared_mem_buf = .;
} > IRAM
/* The linker won't notice if the .data section is too big to fit,
* apparently because we're sending it into IRAM, not FLASH. The following
@@ -127,17 +141,6 @@ SECTIONS
*(.google)
}
#endif
- .bss : {
- . = ALIGN(4);
- __bss_start = .;
- *(.bss)
- . = ALIGN(4);
- __bss_end = .;
-
- /* Shared memory buffer must be at the end of preallocated RAM, so it
- * can expand to use all the remaining RAM. */
- __shared_mem_buf = .;
- } > IRAM
/DISCARD/ : { *(.ARM.*) }
}
diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c
index 3041f431c8..4bd194bd78 100644
--- a/core/cortex-m/task.c
+++ b/core/cortex-m/task.c
@@ -33,9 +33,6 @@ typedef union {
uint32_t context[TASK_SIZE/4];
} task_;
-#define CONTEXT_SP (__builtin_offsetof(task_, sp) / sizeof(uint32_t))
-#define CONTEXT_GUARD (__builtin_offsetof(task_, guard) / sizeof(uint32_t))
-
/* declare task routine prototypes */
#define TASK(n, r, d) int r(void *);
#include TASK_LIST
@@ -94,24 +91,23 @@ static void task_exit_trap(void)
#define GUARD_VALUE 0x12345678
-/* Declare and fill the contexts for all tasks. Note that while it would be
- * more readable to use the struct fields (.sp, .guard) where applicable, gcc
- * can't mix initializing some fields on one side of the union and some fields
- * on the other, so we have to use .context for all initialization. */
-#define TASK(n, r, d) { \
- .context[CONTEXT_SP] = (uint32_t)(tasks + TASK_ID_##n + 1) - 64,\
- .context[CONTEXT_GUARD] = GUARD_VALUE, \
- .context[TASK_SIZE/4 - 8/*r0*/] = (uint32_t)d, \
- .context[TASK_SIZE/4 - 3/*lr*/] = (uint32_t)task_exit_trap, \
- .context[TASK_SIZE/4 - 2/*pc*/] = (uint32_t)r, \
- .context[TASK_SIZE/4 - 1/*psr*/] = 0x01000000 },
+/* Startup parameters for all tasks. */
+#define TASK(n, r, d) { \
+ .r0 = (uint32_t)d, \
+ .pc = (uint32_t)r, \
+},
#include TASK_LIST
-static task_ tasks[] __attribute__((section(".data.tasks")))
- __attribute__((aligned(TASK_SIZE))) = {
+static const struct {
+ uint32_t r0;
+ uint32_t pc;
+} const tasks_init[] = {
TASK(IDLE, __idle, 0)
CONFIG_TASK_LIST
};
#undef TASK
+/* Contexts and stacks for all tasks. */
+static task_ tasks[TASK_ID_COUNT] __attribute__((section(".bss.tasks")))
+ __attribute__((aligned(TASK_SIZE)));
/* Reserve space to discard context on first context switch. */
uint32_t scratchpad[17] __attribute__((section(".data.tasks")));
@@ -561,6 +557,20 @@ DECLARE_CONSOLE_COMMAND(taskready, command_task_ready);
int task_pre_init(void)
{
+ int i;
+
+ /* fill the task memory with initial values */
+ for (i = 0; i < TASK_ID_COUNT; i++) {
+ tasks[i].sp = (uint32_t)(tasks + i + 1) - 64;
+ tasks[i].guard = GUARD_VALUE;
+ /* initial context on stack */
+ tasks[i].context[TASK_SIZE/4 - 8/*r0*/] = tasks_init[i].r0;
+ tasks[i].context[TASK_SIZE/4 - 3/*lr*/] =
+ (uint32_t)task_exit_trap;
+ tasks[i].context[TASK_SIZE/4 - 2/*pc*/] = tasks_init[i].pc;
+ tasks[i].context[TASK_SIZE/4 - 1/*psr*/] = 0x01000000;
+ }
+
/* Fill in guard value in scratchpad to prevent stack overflow
* detection failure on the first context switch. */
((task_ *)scratchpad)->guard = GUARD_VALUE;