altos/arm: Align data so that gcc 5.4 doesn't do byte-accesses. Add -Wcast-align
authorKeith Packard <keithp@keithp.com>
Sun, 18 Dec 2016 04:58:36 +0000 (20:58 -0800)
committerKeith Packard <keithp@keithp.com>
Sun, 18 Dec 2016 05:04:33 +0000 (21:04 -0800)
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>
16 files changed:
src/aes/ao_aes.c
src/drivers/ao_gps_ublox.c
src/drivers/ao_trng_send.c
src/kernel/ao_list.h
src/kernel/ao_pyro.c
src/kernel/ao_task.h
src/stm/Makefile.defs
src/stm/ao_arch_funcs.h
src/stm/ao_eeprom_stm.c
src/stm/ao_usb_stm.c
src/stm/stm32l.h
src/stmf0/Makefile-stmf0.defs
src/stmf0/ao_adc_fast.h
src/stmf0/ao_arch_funcs.h
src/stmf0/ao_usb_stm.c
src/stmf0/stm32f0.h

index a04174c6ec12b1bf9eec44b796bc6e57112dcdab..fd90c5bf3ee03fa0c3435db43e5a4d3fea043b31 100644 (file)
@@ -359,10 +359,10 @@ void xrijndaelDecrypt(word32 block[], roundkey *rkk)
 #endif
 
 uint8_t ao_aes_mutex;
-static uint8_t key[16];
+static word32 key[16/4];
 static roundkey        rkk;
 
-static uint8_t iv[16];
+static word32 iv[16/4];
 
 void
 ao_aes_set_mode(enum ao_aes_mode mode)
@@ -389,10 +389,11 @@ ao_aes_run(__xdata uint8_t *in,
           __xdata uint8_t *out)
 {
        uint8_t i;
+       uint8_t *_iv = (uint8_t *) iv;
 
        for (i = 0; i < 16; i++)
-               iv[i] ^= in[i];
-       xrijndaelEncrypt((word32 *) iv, &rkk);
+               _iv[i] ^= in[i];
+       xrijndaelEncrypt(iv, &rkk);
        if (out)
                memcpy(out, iv, 16);
 }
index 22af413a0098008f2ed7dd1e1fa44834ef0c54f9..c720f802acd2e9a73476d6a95dce6dca0bf0dde9 100644 (file)
@@ -156,7 +156,7 @@ static char __xdata *ublox_target;
 
 static void ublox_u16(uint8_t offset)
 {
-       uint16_t __xdata *ptr = (uint16_t __xdata *) (ublox_target + offset);
+       uint16_t __xdata *ptr = (uint16_t __xdata *) (void __xdata *) (ublox_target + offset);
        uint16_t val;
 
        val = data_byte();
@@ -175,7 +175,7 @@ static void ublox_u8(uint8_t offset)
 
 static void ublox_u32(uint8_t offset) __reentrant
 {
-       uint32_t __xdata *ptr = (uint32_t __xdata *) (ublox_target + offset);
+       uint32_t __xdata *ptr = (uint32_t __xdata *) (void __xdata *) (ublox_target + offset);
        uint32_t val;
 
        val = ((uint32_t) data_byte ());
index 85034efd767f7337ebbabbff75a428fccd6b8e73..b1227aaab8dba5a0213e50c4fd9b30ac7d1cdef9 100644 (file)
@@ -104,7 +104,7 @@ ao_trng_get_cooked(uint16_t *buf)
 {
        uint16_t        i;
        uint16_t        t;
-       uint32_t        *rnd = (uint32_t *) ao_adc_ring;
+       uint32_t        *rnd = (uint32_t *) (void *) ao_adc_ring;
        uint8_t         mismatch = 0;
 
        t = ao_adc_get(AO_USB_IN_SIZE) >> 1;            /* one 16-bit value per output byte */
index e2df6885d72fd98ae2c8599b38e132ae6f0ae7f1..45a3df5b0a9172d3870e78d8c5ef5363f88cc400 100644 (file)
@@ -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
index b11d1080a54fbc1a7c25f5cb23a8eae492a7cf23..a0881f9e3a8262fce6ec2b925363c5fcbb75ac32 100644 (file)
@@ -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;
                        }
                }
        }
index f1dbd65426ae709353c0f226eda63a42c76ecaef..30b018ffe36aff064afb91b0a8fe1c41e1a20483 100644 (file)
 #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;
index c3d2707faf76dae341d4b86943c58ce0e0b52242..0ba86f5abef6352ed365e99f8ab505de4f8e8ff6 100644 (file)
@@ -27,7 +27,7 @@ LIBS=$(PDCLIB_LIBS_M3) -lgcc
 WARN_FLAGS=-Wall -Wextra -Werror
 
 AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../math -I.. $(PDCLIB_INCLUDES)
-STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb \
+STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -Wcast-align \
        -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
 
 LDFLAGS=-L../stm -Wl,-Taltos.ld
index 18ca20dab69b2b2dec06a643a01372a92a141215..a9d0fa34f02fed0ab58159eb6f7293f059a00a16 100644 (file)
@@ -375,7 +375,7 @@ ao_arch_irq_check(void) {
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
-       uint32_t        *sp = (uint32_t *) (task->stack + AO_STACK_SIZE);
+       uint32_t        *sp = (uint32_t *) ((void*) task->stack + AO_STACK_SIZE);
        uint32_t        a = (uint32_t) start;
        int             i;
 
@@ -413,16 +413,11 @@ static inline void ao_arch_save_stack(void) {
        uint32_t        *sp;
        asm("mov %0,sp" : "=&r" (sp) );
        ao_cur_task->sp = (sp);
-       if ((uint8_t *) sp < &ao_cur_task->stack[0])
-               ao_panic (AO_PANIC_STACK);
 }
 
 static inline void ao_arch_restore_stack(void) {
-       uint32_t        sp;
-       sp = (uint32_t) ao_cur_task->sp;
-
        /* Switch stacks */
-       asm("mov sp, %0" : : "r" (sp) );
+       asm("mov sp, %0" : : "r" (ao_cur_task->sp) );
 
        /* Restore PRIMASK */
        asm("pop {r0}");
index 05f880b851d351fa24c33e388e55a0f93923b3d2..4f477122784975f78db3eda27e2ac021c342ccda 100644 (file)
@@ -83,7 +83,7 @@ ao_intflash_write32(uint16_t pos, uint32_t w)
 {
        volatile uint32_t       *addr;
 
-       addr = (uint32_t *) (stm_eeprom + pos);
+       addr = (uint32_t *) (void *) (stm_eeprom + pos);
 
        /* Write a word to a valid address in the data EEPROM */
        *addr = w;
@@ -96,7 +96,7 @@ ao_intflash_write8(uint16_t pos, uint8_t d)
        uint32_t        w, *addr, mask;
        uint8_t         shift;
        
-       addr = (uint32_t *) (stm_eeprom + (pos & ~3));
+       addr = (uint32_t *) (void *) (stm_eeprom + (pos & ~3));
 
        /* Compute word to be written */
        shift = (pos & 3) << 3;
index f2b8ea94cfe0aa4fb10ee23c420f4c12f581c52c..9d72844e0c1a6710c06700f9725c13aae9d622a7 100644 (file)
@@ -139,7 +139,7 @@ static inline uint32_t set_toggle(uint32_t  current_value,
 
 static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr)
 {
-       return (uint32_t *) (stm_usb_sram + 2 * sram_addr);
+       return (uint32_t *) (((void *) ((uint8_t *) stm_usb_sram + 2 * sram_addr)));
 }
 
 static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) {
index 463125e25f19ebea5472adbd1c0cab57eaa407ff..be1e1d65112c6c47f7b65ee1b3be7bc9934c2472 100644 (file)
@@ -1961,7 +1961,7 @@ union stm_usb_bdt {
 
 #define STM_USB_BDT_SIZE       8
 
-extern uint8_t stm_usb_sram[];
+extern uint8_t stm_usb_sram[] __attribute__ ((aligned(4)));
 
 struct stm_exti {
        vuint32_t       imr;
index 4862f46efbe62b74ae75fe1a604e5afb8f9bcafe..f3296b6959628d14951c0e28b28338af4b720b86 100644 (file)
@@ -25,7 +25,7 @@ endif
 ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
 CC=$(ARM_CC)
 
-WARN_FLAGS=-Wall -Wextra -Werror
+WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align
 
 AO_CFLAGS=-I. -I$(TOPDIR)/stmf0 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math $(PDCLIB_INCLUDES) 
 STMF0_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\
index b8b5e003bd775b7ee50e77dc29fa70bd0b216386..3f0b0547dec790c244a20b6006ca3c2e18e0d32a 100644 (file)
@@ -28,7 +28,7 @@ ao_adc_init(void);
 /* Total ring size in samples */
 #define AO_ADC_RING_SIZE       256
 
-extern uint16_t        ao_adc_ring[AO_ADC_RING_SIZE];
+extern uint16_t        ao_adc_ring[AO_ADC_RING_SIZE] __attribute__((aligned(4)));
 
 #define ao_adc_ring_step(pos,inc)      (((pos) + (inc)) & (AO_ADC_RING_SIZE - 1))
 
index d35bafbde1dbb87b76ddaa0d0d67dac657343697..c38ce41afbad0545f32be50ffcc55085d33a5d73 100644 (file)
@@ -366,7 +366,7 @@ ao_arch_memory_barrier() {
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
-       uint32_t        *sp = (uint32_t *) (task->stack + AO_STACK_SIZE);
+       uint32_t        *sp = (uint32_t *) ((void *) task->stack + AO_STACK_SIZE);
        uint32_t        a = (uint32_t) start;
        int             i;
 
index cbedb9962231fa972256c33f0ee18bedef92aba2..652b3b6ca9facebaa742a57392f542f62e4958fa 100644 (file)
@@ -185,7 +185,7 @@ static inline uint32_t set_toggle(uint32_t  current_value,
 
 static inline uint16_t *ao_usb_packet_buffer_addr(uint16_t sram_addr)
 {
-       return (uint16_t *) (stm_usb_sram + sram_addr);
+       return (uint16_t *) (void *) (stm_usb_sram + sram_addr);
 }
 
 static inline uint16_t ao_usb_packet_buffer_offset(uint16_t *addr)
index 182cd9639df0af69ede15503542f88be7dec15bb..1c33f020b8af55ed380911de87d2e089c323e552 100644 (file)
@@ -1996,7 +1996,7 @@ union stm_usb_bdt {
 
 #define STM_USB_BDT_SIZE       8
 
-extern uint8_t stm_usb_sram[];
+extern uint8_t stm_usb_sram[] __attribute__((aligned(4)));
 
 struct stm_exti {
        vuint32_t       imr;