diff options
| author | Marti Bolivar <mbolivar@leaflabs.com> | 2012-06-21 15:15:34 -0400 | 
|---|---|---|
| committer | Marti Bolivar <mbolivar@leaflabs.com> | 2012-06-22 14:06:10 -0400 | 
| commit | 3ba9c0ecd6fd881d21292a369f8b7e45be5d2cb4 (patch) | |
| tree | 1273e82e5cf30abd868daf58c4a1a0664f0bd998 /libmaple | |
| parent | 11d7ba62fb30bdcc26cd5e281eaf8b267782a561 (diff) | |
| download | librambutan-3ba9c0ecd6fd881d21292a369f8b7e45be5d2cb4.tar.gz librambutan-3ba9c0ecd6fd881d21292a369f8b7e45be5d2cb4.zip | |
libmaple/i2c.c: Cosmetics.
Move private API to bottom of file.
Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com>
Diffstat (limited to 'libmaple')
| -rw-r--r-- | libmaple/i2c.c | 378 | 
1 files changed, 190 insertions, 188 deletions
| diff --git a/libmaple/i2c.c b/libmaple/i2c.c index 15bcbe0..2e11f54 100644 --- a/libmaple/i2c.c +++ b/libmaple/i2c.c @@ -102,194 +102,6 @@ enum {  };  /** - * @brief IRQ handler for I2C master. Handles transmission/reception. - * @param dev I2C device - */ -void _i2c_irq_handler(i2c_dev *dev) { -    /* WTFs: -     * - Where is I2C_MSG_10BIT_ADDR handled? -     */ -    i2c_msg *msg = dev->msg; - -    uint8 read = msg->flags & I2C_MSG_READ; - -    uint32 sr1 = dev->regs->SR1; -    uint32 sr2 = dev->regs->SR2; -    I2C_CRUMB(IRQ_ENTRY, sr1, sr2); - -    /* -     * Reset timeout counter -     */ -    dev->timestamp = systick_uptime(); - -    /* -     * EV5: Start condition sent -     */ -    if (sr1 & I2C_SR1_SB) { -        msg->xferred = 0; -        i2c_enable_irq(dev, I2C_IRQ_BUFFER); - -        /* -         * Master receiver -         */ -        if (read) { -            i2c_enable_ack(dev); -        } - -        i2c_send_slave_addr(dev, msg->addr, read); -        sr1 = sr2 = 0; -    } - -    /* -     * EV6: Slave address sent -     */ -    if (sr1 & I2C_SR1_ADDR) { -        /* -         * Special case event EV6_1 for master receiver. -         * Generate NACK and restart/stop condition after ADDR -         * is cleared. -         */ -        if (read) { -            if (msg->length == 1) { -                i2c_disable_ack(dev); -                if (dev->msgs_left > 1) { -                    i2c_start_condition(dev); -                    I2C_CRUMB(RX_ADDR_START, 0, 0); -                } else { -                    i2c_stop_condition(dev); -                    I2C_CRUMB(RX_ADDR_STOP, 0, 0); -                } -            } -        } else { -            /* -             * Master transmitter: write first byte to fill shift -             * register.  We should get another TXE interrupt -             * immediately to fill DR again. -             */ -            if (msg->length != 1) { -                i2c_write(dev, msg->data[msg->xferred++]); -            } -        } -        sr1 = sr2 = 0; -    } - -    /* -     * EV8: Master transmitter -     * Transmit buffer empty, but we haven't finished transmitting the last -     * byte written. -     */ -    if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) { -        I2C_CRUMB(TXE_ONLY, 0, 0); -        if (dev->msgs_left) { -            i2c_write(dev, msg->data[msg->xferred++]); -            if (msg->xferred == msg->length) { -                /* -                 * End of this message. Turn off TXE/RXNE and wait for -                 * BTF to send repeated start or stop condition. -                 */ -                i2c_disable_irq(dev, I2C_IRQ_BUFFER); -                dev->msgs_left--; -            } -        } else { -            /* -             * This should be impossible... -             */ -            ASSERT(0); -        } -        sr1 = sr2 = 0; -    } - -    /* -     * EV8_2: Master transmitter -     * Last byte sent, program repeated start/stop -     */ -    if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) { -        I2C_CRUMB(TXE_BTF, 0, 0); -        if (dev->msgs_left) { -            I2C_CRUMB(TEST, 0, 0); -            /* -             * Repeated start insanity: We can't disable ITEVTEN or else SB -             * won't interrupt, but if we don't disable ITEVTEN, BTF will -             * continually interrupt us. What the fuck ST? -             */ -            i2c_start_condition(dev); -            while (!(dev->regs->SR1 & I2C_SR1_SB)) -                ; -            dev->msg++; -        } else { -            i2c_stop_condition(dev); - -            /* -             * Turn off event interrupts to keep BTF from firing until -             * the end of the stop condition. Why on earth they didn't -             * have a start/stop condition request clear BTF is beyond -             * me. -             */ -            i2c_disable_irq(dev, I2C_IRQ_EVENT); -            I2C_CRUMB(STOP_SENT, 0, 0); -            dev->state = I2C_STATE_XFER_DONE; -        } -        sr1 = sr2 = 0; -    } - -    /* -     * EV7: Master Receiver -     */ -    if (sr1 & I2C_SR1_RXNE) { -        I2C_CRUMB(RXNE_ONLY, 0, 0); -        msg->data[msg->xferred++] = dev->regs->DR; - -        /* -         * EV7_1: Second to last byte in the reception? Set NACK and generate -         * stop/restart condition in time for the last byte. We'll get one more -         * RXNE interrupt before shutting things down. -         */ -        if (msg->xferred == (msg->length - 1)) { -            i2c_disable_ack(dev); -            if (dev->msgs_left > 2) { -                i2c_start_condition(dev); -                I2C_CRUMB(RXNE_START_SENT, 0, 0); -            } else { -                i2c_stop_condition(dev); -                I2C_CRUMB(RXNE_STOP_SENT, 0, 0); -            } -        } else if (msg->xferred == msg->length) { -            dev->msgs_left--; -            if (dev->msgs_left == 0) { -                /* -                 * We're done. -                 */ -                I2C_CRUMB(RXNE_DONE, 0, 0); -                dev->state = I2C_STATE_XFER_DONE; -            } else { -                dev->msg++; -            } -        } -    } -} - -/** - * @brief Interrupt handler for I2C error conditions - * @param dev I2C device - * @sideeffect Aborts any pending I2C transactions - */ -void _i2c_irq_error_handler(i2c_dev *dev) { -    I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2); - -    dev->error_flags = dev->regs->SR2 & (I2C_SR1_BERR | -                                         I2C_SR1_ARLO | -                                         I2C_SR1_AF | -                                         I2C_SR1_OVR); -    /* Clear flags */ -    dev->regs->SR1 = 0; -    dev->regs->SR2 = 0; - -    i2c_stop_condition(dev); -    i2c_disable_irq(dev, I2C_IRQ_BUFFER | I2C_IRQ_EVENT | I2C_IRQ_ERROR); -    dev->state = I2C_STATE_ERROR; -} - -/**   * @brief Reset an I2C bus.   *   * Reset is accomplished by clocking out pulses until any hung slaves @@ -521,3 +333,193 @@ static inline int32 wait_for_state_change(i2c_dev *dev,          }      }  } + +/* + * Private API + */ + +/* + * IRQ handler for I2C master. Handles transmission/reception. + */ +void _i2c_irq_handler(i2c_dev *dev) { +    /* WTFs: +     * - Where is I2C_MSG_10BIT_ADDR handled? +     */ +    i2c_msg *msg = dev->msg; + +    uint8 read = msg->flags & I2C_MSG_READ; + +    uint32 sr1 = dev->regs->SR1; +    uint32 sr2 = dev->regs->SR2; +    I2C_CRUMB(IRQ_ENTRY, sr1, sr2); + +    /* +     * Reset timeout counter +     */ +    dev->timestamp = systick_uptime(); + +    /* +     * EV5: Start condition sent +     */ +    if (sr1 & I2C_SR1_SB) { +        msg->xferred = 0; +        i2c_enable_irq(dev, I2C_IRQ_BUFFER); + +        /* +         * Master receiver +         */ +        if (read) { +            i2c_enable_ack(dev); +        } + +        i2c_send_slave_addr(dev, msg->addr, read); +        sr1 = sr2 = 0; +    } + +    /* +     * EV6: Slave address sent +     */ +    if (sr1 & I2C_SR1_ADDR) { +        /* +         * Special case event EV6_1 for master receiver. +         * Generate NACK and restart/stop condition after ADDR +         * is cleared. +         */ +        if (read) { +            if (msg->length == 1) { +                i2c_disable_ack(dev); +                if (dev->msgs_left > 1) { +                    i2c_start_condition(dev); +                    I2C_CRUMB(RX_ADDR_START, 0, 0); +                } else { +                    i2c_stop_condition(dev); +                    I2C_CRUMB(RX_ADDR_STOP, 0, 0); +                } +            } +        } else { +            /* +             * Master transmitter: write first byte to fill shift +             * register.  We should get another TXE interrupt +             * immediately to fill DR again. +             */ +            if (msg->length != 1) { +                i2c_write(dev, msg->data[msg->xferred++]); +            } +        } +        sr1 = sr2 = 0; +    } + +    /* +     * EV8: Master transmitter +     * Transmit buffer empty, but we haven't finished transmitting the last +     * byte written. +     */ +    if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) { +        I2C_CRUMB(TXE_ONLY, 0, 0); +        if (dev->msgs_left) { +            i2c_write(dev, msg->data[msg->xferred++]); +            if (msg->xferred == msg->length) { +                /* +                 * End of this message. Turn off TXE/RXNE and wait for +                 * BTF to send repeated start or stop condition. +                 */ +                i2c_disable_irq(dev, I2C_IRQ_BUFFER); +                dev->msgs_left--; +            } +        } else { +            /* +             * This should be impossible... +             */ +            ASSERT(0); +        } +        sr1 = sr2 = 0; +    } + +    /* +     * EV8_2: Master transmitter +     * Last byte sent, program repeated start/stop +     */ +    if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) { +        I2C_CRUMB(TXE_BTF, 0, 0); +        if (dev->msgs_left) { +            I2C_CRUMB(TEST, 0, 0); +            /* +             * Repeated start insanity: We can't disable ITEVTEN or else SB +             * won't interrupt, but if we don't disable ITEVTEN, BTF will +             * continually interrupt us. What the fuck ST? +             */ +            i2c_start_condition(dev); +            while (!(dev->regs->SR1 & I2C_SR1_SB)) +                ; +            dev->msg++; +        } else { +            i2c_stop_condition(dev); + +            /* +             * Turn off event interrupts to keep BTF from firing until +             * the end of the stop condition. Why on earth they didn't +             * have a start/stop condition request clear BTF is beyond +             * me. +             */ +            i2c_disable_irq(dev, I2C_IRQ_EVENT); +            I2C_CRUMB(STOP_SENT, 0, 0); +            dev->state = I2C_STATE_XFER_DONE; +        } +        sr1 = sr2 = 0; +    } + +    /* +     * EV7: Master Receiver +     */ +    if (sr1 & I2C_SR1_RXNE) { +        I2C_CRUMB(RXNE_ONLY, 0, 0); +        msg->data[msg->xferred++] = dev->regs->DR; + +        /* +         * EV7_1: Second to last byte in the reception? Set NACK and generate +         * stop/restart condition in time for the last byte. We'll get one more +         * RXNE interrupt before shutting things down. +         */ +        if (msg->xferred == (msg->length - 1)) { +            i2c_disable_ack(dev); +            if (dev->msgs_left > 2) { +                i2c_start_condition(dev); +                I2C_CRUMB(RXNE_START_SENT, 0, 0); +            } else { +                i2c_stop_condition(dev); +                I2C_CRUMB(RXNE_STOP_SENT, 0, 0); +            } +        } else if (msg->xferred == msg->length) { +            dev->msgs_left--; +            if (dev->msgs_left == 0) { +                /* +                 * We're done. +                 */ +                I2C_CRUMB(RXNE_DONE, 0, 0); +                dev->state = I2C_STATE_XFER_DONE; +            } else { +                dev->msg++; +            } +        } +    } +} + +/* + * Interrupt handler for I2C error conditions. Aborts any pending I2C + * transactions. + */ +void _i2c_irq_error_handler(i2c_dev *dev) { +    I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2); + +    dev->error_flags = dev->regs->SR2 & (I2C_SR1_BERR | +                                         I2C_SR1_ARLO | +                                         I2C_SR1_AF | +                                         I2C_SR1_OVR); +    /* Clear flags */ +    dev->regs->SR1 = 0; +    dev->regs->SR2 = 0; + +    i2c_stop_condition(dev); +    i2c_disable_irq(dev, I2C_IRQ_BUFFER | I2C_IRQ_EVENT | I2C_IRQ_ERROR); +    dev->state = I2C_STATE_ERROR; +} | 
