summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-12-17 20:58:36 -0800
committerKeith Packard <keithp@keithp.com>2016-12-17 21:04:33 -0800
commit89ecc32b90565ace078c4a84d4406a4d1f86821a (patch)
tree3b32f1d922380b3dfd25db75552a30dc84c24d41 /src/kernel
parentf650211f9e99e1d3d0ae13ae559dd1c082f71545 (diff)
altos/arm: Align data so that gcc 5.4 doesn't do byte-accesses. Add -Wcast-align
Gcc 5.4.1 tracks alignment of data through assignments, so that a uint32_t pointer which comes from byte-aligned uint8_t data: extern uint8_t foo[]; uint32_t *q = (void *) foo; Fetches and stores through this pointer are done bytewise. This is slow (meh), but if q references a device register, things to bad very quickly. This patch works around this bug in the compiler by adding __attribute__((aligned(4))) tags to some variables, or changing them from uint8_t to uint32_t. Places doing this will now be caught as I've added -Wcast-align to the compiler flags. That required adding (void *) casts, after the relevant code was checked to make sure the compiler could tell that the addresses were aligned. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/ao_list.h2
-rw-r--r--src/kernel/ao_pyro.c4
-rw-r--r--src/kernel/ao_task.h13
3 files changed, 15 insertions, 4 deletions
diff --git a/src/kernel/ao_list.h b/src/kernel/ao_list.h
index e2df6885..45a3df5b 100644
--- a/src/kernel/ao_list.h
+++ b/src/kernel/ao_list.h
@@ -138,7 +138,7 @@ ao_list_is_empty(struct ao_list *head)
* @return A pointer to the data struct containing the list head.
*/
#define ao_container_of(ptr, type, member) \
- ((type *)((char *)(ptr) - offsetof(type, member)))
+ ((type *)((void *) ((char *)(ptr) - offsetof(type, member))))
/**
* Alias of ao_container_of
diff --git a/src/kernel/ao_pyro.c b/src/kernel/ao_pyro.c
index b11d1080..a0881f9e 100644
--- a/src/kernel/ao_pyro.c
+++ b/src/kernel/ao_pyro.c
@@ -438,7 +438,7 @@ ao_pyro_show(void)
if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE)
value = *((uint8_t *) ((char *) pyro + ao_pyro_values[v].offset));
else
- value = *((int16_t *) ((char *) pyro + ao_pyro_values[v].offset));
+ value = *((int16_t *) (void *) ((char *) pyro + ao_pyro_values[v].offset));
printf ("%6d ", value);
} else {
printf (" ");
@@ -517,7 +517,7 @@ ao_pyro_set(void)
} else {
if (negative)
ao_cmd_lex_i = -ao_cmd_lex_i;
- *((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
+ *((int16_t *) (void *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i;
}
}
}
diff --git a/src/kernel/ao_task.h b/src/kernel/ao_task.h
index f1dbd654..30b018ff 100644
--- a/src/kernel/ao_task.h
+++ b/src/kernel/ao_task.h
@@ -26,6 +26,17 @@
#define HAS_TASK_INFO 1
#endif
+/* arm stacks must be 32-bit aligned */
+#ifdef __arm__
+#define AO_STACK_ALIGNMENT __attribute__ ((aligned(4)))
+#endif
+#ifdef SDCC
+#define AO_STACK_ALIGNMENT
+#endif
+#ifdef __AVR__
+#define AO_STACK_ALIGNMENT
+#endif
+
/* An AltOS task */
struct ao_task {
__xdata void *wchan; /* current wait channel (NULL if running) */
@@ -37,7 +48,7 @@ struct ao_task {
struct ao_list queue;
struct ao_list alarm_queue;
#endif
- uint8_t stack[AO_STACK_SIZE]; /* saved stack */
+ uint8_t stack[AO_STACK_SIZE] AO_STACK_ALIGNMENT; /* saved stack */
#if HAS_SAMPLE_PROFILE
uint32_t ticks;
uint32_t yields;