From a94521a4841cf17a22c8737bdd87f872318afe3f Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 18 Jan 2010 02:17:12 +0100 Subject: pressure_control: Fix IRQ memory barriers Signed-off-by: Michael Buesch --- pressure_control/firmware/main.c | 4 ++-- pressure_control/firmware/remote.c | 20 ++++++++++---------- pressure_control/firmware/util.c | 2 +- pressure_control/firmware/util.h | 35 +++++++++++++++++++++++------------ 4 files changed, 36 insertions(+), 25 deletions(-) (limited to 'pressure_control/firmware') diff --git a/pressure_control/firmware/main.c b/pressure_control/firmware/main.c index f0671b4..d947228 100644 --- a/pressure_control/firmware/main.c +++ b/pressure_control/firmware/main.c @@ -298,7 +298,7 @@ int main(void) { uint8_t mcucsr; - cli(); + irq_disable(); mcucsr = MCUCSR; MCUCSR = 0; wdt_disable(); @@ -328,7 +328,7 @@ int main(void) eeprom_load_config(); system_timer_init(); - sei(); + irq_enable(); print("Monitoring...\n"); remote_work(); diff --git a/pressure_control/firmware/remote.c b/pressure_control/firmware/remote.c index dac8d30..f54d4f5 100644 --- a/pressure_control/firmware/remote.c +++ b/pressure_control/firmware/remote.c @@ -108,9 +108,9 @@ static void queue_tx_message(struct remote_message *msg) /* IRQs were enabled before we were called. * Be nice to other interrupts and re-enable them * for a microsecond. */ - sei(); + irq_enable(); udelay(1); - cli(); + irq_disable(); mb(); } } while (tx_queue_used >= ARRAY_SIZE(tx_queue)); @@ -225,34 +225,34 @@ static void handle_received_message(void) case MSG_SET_DESIRED_PRESSURE: { struct pressure_config xy, z; - cli(); + irq_disable(); get_pressure_config(&xy, &z); if (rx_msg.setpressure.island == 0) xy.desired = rx_msg.setpressure.mbar; else if (rx_msg.setpressure.island == 1) z.desired = rx_msg.setpressure.mbar; set_pressure_config(&xy, &z); - sei(); + irq_enable(); break; } case MSG_SET_HYSTERESIS: { struct pressure_config xy, z; - cli(); + irq_disable(); get_pressure_config(&xy, &z); if (rx_msg.setpressure.island == 0) xy.hysteresis = rx_msg.setpressure.mbar; else if (rx_msg.setpressure.island == 1) z.hysteresis = rx_msg.setpressure.mbar; set_pressure_config(&xy, &z); - sei(); + irq_enable(); break; } case MSG_SET_CONFIG_FLAGS: { struct pressure_config xy, z; bool flag; - cli(); + irq_disable(); get_pressure_config(&xy, &z); flag = !!(rx_msg.setconfig.flags & (1 << CFG_FLAG_AUTOADJUST_ENABLE)); if (rx_msg.setconfig.island == 0) { @@ -269,7 +269,7 @@ static void handle_received_message(void) } } set_pressure_config(&xy, &z); - sei(); + irq_enable(); break; } case MSG_SET_VALVE: { @@ -464,7 +464,7 @@ void remote_work(void) mb(); rx_msg_valid = 0; } - cli(); + irq_disable(); if (rx_softirq) { rx_softirq = 0; usart_handle_rx_irq(); @@ -473,7 +473,7 @@ void remote_work(void) last_timeout_check = now; usart_rx_timeout_check(); } - sei(); + irq_enable(); } void remote_pressure_change_notification(uint16_t xy_mbar, uint16_t z_mbar) diff --git a/pressure_control/firmware/util.c b/pressure_control/firmware/util.c index 7497740..3ed33f3 100644 --- a/pressure_control/firmware/util.c +++ b/pressure_control/firmware/util.c @@ -81,7 +81,7 @@ void panic(const prog_char *msg) void infinite_sleep(void) { - cli(); + irq_disable(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); while (1) sleep_mode(); diff --git a/pressure_control/firmware/util.h b/pressure_control/firmware/util.h index fbfaa76..0e79e58 100644 --- a/pressure_control/firmware/util.h +++ b/pressure_control/firmware/util.h @@ -62,15 +62,29 @@ uint8_t hexdigit_to_ascii(uint8_t digit); * buf must be at least (NUM16_NR_DIGITS + 1) long */ void num16_to_ascii(uint8_t *buf, uint16_t v); -/* IRQ handling. - * We use a macro for irq_disable_save(), because stupid gcc is not - * able to properly optimize an inline function that returns a value. - */ -#define irq_disable_save() ({ \ - uint8_t sreg_flags = SREG; \ - cli(); \ - sreg_flags; \ - }) + +#define __irqs_disabled(sreg) (!(sreg & (1 << SREG_I))) +#define irqs_disabled() __irqs_disabled(SREG) + +static inline void irq_disable(void) +{ + cli(); + mb(); +} + +static inline void irq_enable(void) +{ + mb(); + sei(); +} + +static inline uint8_t irq_disable_save(void) +{ + uint8_t sreg = SREG; + cli(); + mb(); + return sreg; +} static inline void irq_restore(uint8_t sreg_flags) { @@ -78,9 +92,6 @@ static inline void irq_restore(uint8_t sreg_flags) SREG = sreg_flags; } -#define __irqs_disabled(sreg) (!(sreg & (1 << SREG_I))) -#define irqs_disabled() __irqs_disabled(SREG) - uint8_t crc8_block_update(uint8_t crc, const void *data, uint8_t size); -- cgit v1.2.3