added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Revision:
107:414e9c822e99
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_Atmel/TARGET_SAM_CortexM4/i2c_api.c	Tue Apr 05 18:15:12 2016 +0100
@@ -0,0 +1,715 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "device.h"
+#include "buffer.h"
+#include "dma_api.h"
+#include "i2c_api.h"
+#include "PeripheralPins.h"
+#include "twi.h"
+#include "pdc.h"
+#include "mbed_assert.h"
+#include "ioport.h"
+
+/**
+ * \defgroup GeneralI2C I2C Configuration Functions
+ * @{
+ */
+
+/** TWI Bus Clock 400kHz */
+extern uint8_t g_sys_init;
+
+#define TWI_CLK    (400000u)
+
+#define ADDR_LENGTH  0
+
+#define MAX_I2C		8
+
+extern uint32_t twi_mk_addr(const uint8_t *addr, int len);
+
+void pinmap_find_i2c_info(Twi *sercombase, i2c_t *obj)
+{
+    if(sercombase==TWI0) {
+        obj->i2c.flexcom=FLEXCOM0;
+        obj->i2c.module_number=0;
+        obj->i2c.pdc =PDC_TWI0;
+        obj->i2c.irq_type=FLEXCOM0_IRQn;
+    } else if(sercombase==TWI1) {
+        obj->i2c.flexcom=FLEXCOM1;
+        obj->i2c.module_number=1;
+        obj->i2c.pdc =PDC_TWI1;
+        obj->i2c.irq_type=FLEXCOM1_IRQn;
+    } else if(sercombase==TWI2) {
+        obj->i2c.flexcom=FLEXCOM2;
+        obj->i2c.module_number=2;
+        obj->i2c.pdc =PDC_TWI2;
+        obj->i2c.irq_type=FLEXCOM2_IRQn;
+    } else if(sercombase==TWI3) {
+        obj->i2c.flexcom=FLEXCOM3;
+        obj->i2c.module_number=3;
+        obj->i2c.pdc =PDC_TWI3;
+        obj->i2c.irq_type=FLEXCOM3_IRQn;
+    } else if(sercombase==TWI4) {
+        obj->i2c.flexcom=FLEXCOM4;
+        obj->i2c.module_number=4;
+        obj->i2c.pdc =PDC_TWI4;
+        obj->i2c.irq_type=FLEXCOM4_IRQn;
+    } else if(sercombase==TWI5) {
+        obj->i2c.flexcom=FLEXCOM5;
+        obj->i2c.module_number=5;
+        obj->i2c.pdc =PDC_TWI5;
+        obj->i2c.irq_type=FLEXCOM5_IRQn;
+    } else if(sercombase==TWI6) {
+        obj->i2c.flexcom=FLEXCOM6;
+        obj->i2c.module_number=6;
+        obj->i2c.pdc =PDC_TWI6;
+        obj->i2c.irq_type=FLEXCOM6_IRQn;
+    } else if(sercombase==TWI7) {
+        obj->i2c.flexcom=FLEXCOM7;
+        obj->i2c.module_number=7;
+        obj->i2c.pdc =PDC_TWI7;
+        obj->i2c.irq_type=FLEXCOM7_IRQn;
+    } else {
+        obj->i2c.flexcom=(Flexcom *)NC;
+        obj->i2c.module_number=0;
+        obj->i2c.pdc =(Pdc *) NC;
+    }
+}
+
+
+/** Initialize the I2C peripheral. It sets the default parameters for I2C
+ *  peripheral, and configure its specifieds pins.
+ *  @param obj  The i2c object
+ *  @param sda  The sda pin
+ *  @param scl  The scl pin
+ */
+void i2c_init(i2c_t *obj, PinName sda, PinName scl)
+{
+    MBED_ASSERT(obj);
+    MBED_ASSERT(sda !=NC && scl!=NC );
+
+    if (g_sys_init == 0) {
+        sysclk_init();
+        board_init();
+        g_sys_init = 1;
+    }
+
+
+    Twi* sda_base = (Twi*)pinmap_peripheral(sda, PinMap_I2C_SDA);
+    Twi* scl_base = (Twi*)pinmap_peripheral(scl, PinMap_I2C_SCL);
+    Twi* I2cBase = (Twi*)pinmap_merge((uint32_t)sda_base, (uint32_t)scl_base);
+
+    MBED_ASSERT(I2cBase !=NC );
+
+    obj->i2c.i2c_base=I2cBase;
+    pinmap_find_i2c_info(I2cBase,obj);
+
+    /* Configure I2C pins */
+    pin_function(sda, pinmap_find_function(sda, PinMap_I2C_SDA));
+    ioport_disable_pin(sda);
+
+    pin_function(scl, pinmap_find_function(scl, PinMap_I2C_SCL));
+    ioport_disable_pin(scl);
+
+#if (SAMG55)
+    /* Enable the peripheral and set TWI mode. */
+    MBED_ASSERT((int)obj->i2c.flexcom!=NC);
+    flexcom_enable(obj->i2c.flexcom);
+    flexcom_set_opmode(obj->i2c.flexcom, FLEXCOM_TWI);
+#else
+    /* Enable the peripheral clock for TWI */
+    pmc_enable_periph_clk(obj->i2c.i2c_base);
+#endif
+
+    twi_options_t twi_options;
+    twi_options.master_clk=sysclk_get_cpu_hz();
+    twi_options.speed=TWI_CLK;
+    twi_options.smbus = 0;
+
+    twi_master_init(obj->i2c.i2c_base,&twi_options);
+
+    obj->i2c.is_slave=false;
+    obj->i2c.speed=TWI_CLK;
+    obj->i2c.master_clk=twi_options.master_clk;
+}
+
+/** Configure the I2C frequency.
+ *  @param obj The i2c object
+ *  @param hz  Frequency in Hz
+ */
+void i2c_frequency(i2c_t *obj, int hz)
+{
+    MBED_ASSERT(obj);
+    if(obj->i2c.is_slave)
+        twi_disable_slave_mode(obj->i2c.i2c_base);
+    else
+        twi_disable_master_mode(obj->i2c.i2c_base);
+
+    twi_set_speed(obj->i2c.i2c_base,hz,obj->i2c.master_clk);
+
+    if(obj->i2c.is_slave)
+        twi_enable_slave_mode(obj->i2c.i2c_base);
+    else
+        twi_enable_master_mode(obj->i2c.i2c_base);
+}
+
+/** Send START command.
+ *  @param obj The i2c object
+ */
+int  i2c_start(i2c_t *obj)
+{
+    MBED_ASSERT(obj);
+    obj->i2c.i2c_base->TWI_CR = TWI_CR_START;
+    return 0;
+}
+
+/** Send STOP command.
+ *  @param obj The i2c object
+ */
+int  i2c_stop(i2c_t *obj)
+{
+    MBED_ASSERT(obj);
+    obj->i2c.i2c_base->TWI_CR = TWI_CR_STOP;
+    return 0;
+}
+
+
+uint32_t twi_master_read_no_stop(Twi *p_twi, twi_packet_t *p_packet, uint8_t stopena)
+{
+    uint32_t status;
+    uint32_t cnt = p_packet->length;
+    uint8_t *buffer = p_packet->buffer;
+    uint8_t stop_sent = 0;
+    uint32_t timeout = TWI_TIMEOUT;;
+
+    /* Check argument */
+    if (cnt == 0) {
+        return TWI_INVALID_ARGUMENT;
+    }
+
+    /* Set read mode, slave address and 3 internal address byte lengths */
+    p_twi->TWI_MMR = 0;
+    p_twi->TWI_MMR = TWI_MMR_MREAD | TWI_MMR_DADR(p_packet->chip) |
+                     ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) &
+                      TWI_MMR_IADRSZ_Msk);
+
+    /* Send a START condition */
+    if ((cnt == 1) && (stopena == 1)) {
+        p_twi->TWI_CR = TWI_CR_START | TWI_CR_STOP;
+        stop_sent = 1;
+    } else {
+        p_twi->TWI_CR = TWI_CR_START;
+        stop_sent = 0;
+    }
+
+    while (cnt > 0) {
+        status = p_twi->TWI_SR;
+        if (status & TWI_SR_NACK) {
+            return TWI_RECEIVE_NACK;
+        }
+
+        if (!timeout--) {
+            return TWI_ERROR_TIMEOUT;
+        }
+
+        /* Last byte ? */
+        if ((cnt == 1)  && (!stop_sent) && (stopena == 1)) {
+            p_twi->TWI_CR = TWI_CR_STOP;
+            stop_sent = 1;
+        }
+
+        if (!(status & TWI_SR_RXRDY)) {
+            continue;
+        }
+        *buffer++ = p_twi->TWI_RHR;
+
+        cnt--;
+        timeout = TWI_TIMEOUT;
+    }
+    if(stopena) {
+        while (!(p_twi->TWI_SR & TWI_SR_TXCOMP)) {
+        }
+    }
+
+    p_twi->TWI_SR;
+
+    return TWI_SUCCESS;
+
+}
+
+
+
+
+
+/** Blocking reading data.
+ *  @param obj     The i2c object
+ *  @param address 7-bit address (last bit is 1)
+ *  @param data    The buffer for receiving
+ *  @param length  Number of bytes to read
+ *  @param stop    Stop to be generated after the transfer is done
+ *  @return Number of read bytes
+ */
+int  i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
+{
+    MBED_ASSERT(obj);
+
+    twi_packet_t packet;
+    packet.chip= (address>>1) & 0x7F;
+    packet.addr_length=ADDR_LENGTH;
+    packet.buffer=data;
+    packet.length=length;
+
+    uint8_t status;
+    status= twi_master_read_no_stop(obj->i2c.i2c_base, &packet, stop);
+
+    if(TWI_SUCCESS==status)
+        return length;
+
+    return 0;
+}
+
+
+uint32_t twi_master_write_no_stop(Twi *p_twi, twi_packet_t *p_packet, uint8_t stopena)
+{
+    uint32_t status;
+    uint32_t cnt = p_packet->length;
+    uint8_t *buffer = p_packet->buffer;
+
+    /* Check argument */
+    if (cnt == 0) {
+        return TWI_INVALID_ARGUMENT;
+    }
+
+    /* Set write mode, slave address and 3 internal address byte lengths */
+    p_twi->TWI_MMR = 0;
+    p_twi->TWI_MMR = TWI_MMR_DADR(p_packet->chip) |
+                     ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) &
+                      TWI_MMR_IADRSZ_Msk);
+
+    /* Send a START condition */
+    if ((cnt == 1) && (stopena == 1)) {
+        p_twi->TWI_CR = TWI_CR_START | TWI_CR_STOP;
+    } else {
+        p_twi->TWI_CR = TWI_CR_START;
+    }
+
+    /* Send all bytes */
+    while (cnt > 0) {
+        status = p_twi->TWI_SR;
+        if (status & TWI_SR_NACK) {
+            return TWI_RECEIVE_NACK;
+        }
+
+        if (!(status & TWI_SR_TXRDY)) {
+            continue;
+        }
+        p_twi->TWI_THR = *buffer++;
+
+        cnt--;
+    }
+
+    while (1) {
+        status = p_twi->TWI_SR;
+        if (status & TWI_SR_NACK) {
+            return TWI_RECEIVE_NACK;
+        }
+
+        if (status & TWI_SR_TXRDY) {
+            break;
+        }
+    }
+
+    if (stopena) {
+        p_twi->TWI_CR = TWI_CR_STOP;
+        while (!(p_twi->TWI_SR & TWI_SR_TXCOMP));
+    }
+
+    return TWI_SUCCESS;
+}
+
+
+
+/** Blocking sending data.
+ *  @param obj     The i2c object
+ *  @param address 7-bit address (last bit is 0)
+ *  @param data    The buffer for sending
+ *  @param length  Number of bytes to wrte
+ *  @param stop    Stop to be generated after the transfer is done
+ *  @return Number of written bytes
+ */
+int  i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
+{
+    MBED_ASSERT(obj);
+
+    twi_packet_t packet;
+    packet.chip= (address>>1) & 0x7F;
+    packet.addr_length=ADDR_LENGTH;
+    packet.buffer= (void *)data;
+    packet.length=length;
+
+    uint8_t status;
+    status= twi_master_write_no_stop(obj->i2c.i2c_base,&packet, stop);
+
+    if(TWI_SUCCESS==status)
+        return length;
+
+    return 0;
+}
+
+/** Reset I2C peripheral. TODO: The action here. Most of the implementation sends stop().
+ *  @param obj The i2c object
+ */
+void i2c_reset(i2c_t *obj)
+{
+    MBED_ASSERT(obj);
+    twi_reset(obj->i2c.i2c_base);
+}
+
+/** Read one byte.
+ *  @param obj The i2c object
+ *  @param last Acknoledge
+ *  @return The read byte
+ */
+int  i2c_byte_read(i2c_t *obj, int last)
+{
+    MBED_ASSERT(obj);
+    if(!last)
+        twi_enable_slave_nack(obj->i2c.i2c_base);
+
+    return twi_read_byte(obj->i2c.i2c_base);
+}
+
+/** Write one byte.
+ *  @param obj The i2c object
+ *  @param data Byte to be written
+ *  @return 1 if NAK was received, 0 if ACK was received, 2 for timeout.
+ */
+#define ACK 0
+#define NAK	1
+#define TIMEOUT	2
+
+int  i2c_byte_write(i2c_t *obj, int data)
+{
+    MBED_ASSERT(obj);
+    twi_write_byte(obj->i2c.i2c_base,data);
+
+    uint32_t timeout = TWI_TIMEOUT;
+    while (timeout--) {
+        uint32_t status = obj->i2c.i2c_base->TWI_SR;
+        if (status & TWI_SR_NACK) {
+            return NAK;
+        }
+
+        if (status & TWI_SR_TXRDY) {
+            return ACK;
+        }
+
+        if (timeout<1) {
+            return TIMEOUT;
+        }
+    }
+
+    return ACK;
+}
+
+/**@}*/
+
+#if DEVICE_I2CSLAVE
+
+/**
+ * \defgroup SynchI2C Synchronous I2C Hardware Abstraction Layer for slave
+ * @{
+ */
+
+/** Configure I2C as slave or master.
+ *  @param obj The I2C object
+ *  @return non-zero if a value is available
+ */
+void i2c_slave_mode(i2c_t *obj, int enable_slave)
+{
+    MBED_ASSERT(obj);
+    /* Disable TWI interrupts */
+    obj->i2c.i2c_base->TWI_IDR = ~0UL;
+    obj->i2c.i2c_base->TWI_SR;
+
+    /* Reset TWI */
+    twi_reset(obj->i2c.i2c_base);
+
+    MBED_ASSERT(obj);
+    if(enable_slave)
+        twi_enable_slave_mode(obj->i2c.i2c_base);
+    else
+        twi_enable_master_mode(obj->i2c.i2c_base);
+}
+
+/** Check to see if the I2C slave has been addressed.
+ *  @param obj The I2C object
+ *  @return The status - 1 - read addresses, 2 - write to all slaves,
+ *         3 write addressed, 0 - the slave has not been addressed
+ */
+int  i2c_slave_receive(i2c_t *obj)
+{
+    uint32_t status = obj->i2c.i2c_base->TWI_SR;
+    if((status & TWI_SR_SVACC)) {
+        if(status & TWI_SR_SVREAD)
+            return 1;
+        else
+            return 3;
+    }
+    return 0;
+}
+
+
+uint32_t twi_slave_read_n(Twi *p_twi, uint8_t *p_data, int length)
+{
+    uint32_t status, cnt = 0;
+
+    do {
+        status = p_twi->TWI_SR;
+        if (status & TWI_SR_SVACC) {
+            if (!(status & (TWI_SR_GACC| TWI_SR_SVREAD )) &&
+                    (status & TWI_SR_RXRDY)
+               ) {
+                *p_data++ = (uint8_t) p_twi->TWI_RHR;
+                cnt++;
+                if(cnt>=length) break;
+            }
+        } else if ((status & (TWI_SR_EOSACC | TWI_SR_TXCOMP))
+                   == (TWI_SR_EOSACC | TWI_SR_TXCOMP)) {
+            break;
+        }
+    } while (1);
+
+    return cnt;
+}
+
+/** Read I2C slave.
+ *  @param obj The I2C object
+ *  @return non-zero if a value is available
+ */
+int  i2c_slave_read(i2c_t *obj, char *data, int length)
+{
+    MBED_ASSERT(obj);
+    int read= twi_slave_read_n(obj->i2c.i2c_base,(uint8_t *)  data,length);
+    return read;
+}
+
+
+uint32_t twi_slave_write_n(Twi *p_twi, uint8_t *p_data, int length)
+{
+    uint32_t status, cnt = 0;
+
+    do {
+        status = p_twi->TWI_SR;
+        if (status & TWI_SR_SVACC) {
+            if ((status & TWI_SR_SVREAD) && !(status & TWI_SR_GACC) &&
+                    (status & TWI_SR_TXRDY)) {
+                p_twi->TWI_THR = *p_data++;
+                cnt++;
+                if(cnt>=length) break;
+            }
+        } else if ((status & (TWI_SR_EOSACC | TWI_SR_TXCOMP))
+                   == (TWI_SR_EOSACC | TWI_SR_TXCOMP)) {
+            break;
+        }
+    } while (1);
+
+    return cnt;
+}
+
+
+/** Write I2C as slave.
+ *  @param obj The I2C object
+ *  @return non-zero if a value is available
+ */
+int  i2c_slave_write(i2c_t *obj, const char *data, int length)
+{
+    MBED_ASSERT(obj);
+    int write= twi_slave_write_n(obj->i2c.i2c_base, (uint8_t *) data,length);
+    return write;
+}
+
+/** Configure I2C address.
+ *  @param obj     The I2C object
+ *  @param idx     Currently not used
+ *  @param address The address to be set
+ *  @param mask    Currently not used
+ */
+void i2c_slave_address(i2c_t *obj, int idx/*not used*/, uint32_t address, uint32_t mask)
+{
+    MBED_ASSERT(obj);
+    twi_set_slave_addr(obj->i2c.i2c_base, (address>>1));
+}
+
+#endif
+
+/**@}*/
+
+#if DEVICE_I2C_ASYNCH
+
+/**
+ * \defgroup AsynchI2C Asynchronous I2C Hardware Abstraction Layer
+ * @{
+ */
+
+/** Start i2c asynchronous transfer.
+ *  @param obj       The I2C object
+ *  @param tx        The buffer to send
+ *  @param tx_length The number of words to transmit
+ *  @param rx        The buffer to receive
+ *  @param rx_length The number of words to receive
+ *  @param address   The address to be set - 7bit or 9 bit
+ *  @param stop      If true, stop will be generated after the transfer is done
+ *  @param handler   The I2C IRQ handler to be set
+ *  @param hint      DMA hint usage
+ */
+#warning "Only DMA async supported by I2C master transfer"
+
+void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint /*Not Used*/)
+{
+    uint32_t pdcenable=0;
+
+    if(address) {
+        twi_packet_t pdc_packet;
+        pdc_packet.chip=(address>>1) & 0x7F;
+        pdc_packet.addr_length=ADDR_LENGTH;
+
+        /* Set write mode, slave address and 3 internal address byte lengths */
+        obj->i2c.i2c_base->TWI_MMR = 0;
+        obj->i2c.i2c_base->TWI_MMR = TWI_MMR_DADR(pdc_packet.chip) |
+                                     ((pdc_packet.addr_length << TWI_MMR_IADRSZ_Pos) &
+                                      TWI_MMR_IADRSZ_Msk);
+    }
+
+    if(tx) {
+        pdc_packet_t pdc_packet_tx;
+        pdc_packet_tx.ul_addr=(uint32_t)tx;
+        pdc_packet_tx.ul_size=tx_length;
+
+        pdcenable|=PERIPH_PTCR_TXTEN;
+        /* Configure PDC for data send */
+        pdc_tx_init(obj->i2c.pdc, &pdc_packet_tx, NULL);
+    }
+
+    if(rx) {
+        obj->i2c.i2c_base->TWI_MMR |= TWI_MMR_MREAD;
+        pdc_rx_clear_cnt(obj->i2c.pdc);
+        pdc_packet_t pdc_packet_rx;
+        pdc_packet_rx.ul_addr=(uint32_t)rx;
+        pdc_packet_rx.ul_size=rx_length;
+        pdcenable|=PERIPH_PTCR_RXTEN;
+
+        /* Configure PDC for data receive */
+        pdc_rx_init(obj->i2c.pdc, &pdc_packet_rx, NULL);
+    }
+
+    obj->i2c.dma_usage=hint;
+    obj->i2c.event=event;
+    obj->i2c.stop=stop;
+    obj->i2c.address=address;
+
+    NVIC_ClearPendingIRQ(obj->i2c.irq_type);
+    NVIC_DisableIRQ(obj->i2c.irq_type);
+    NVIC_SetVector(obj->i2c.irq_type,handler);
+    NVIC_EnableIRQ(obj->i2c.irq_type);
+
+    /* Enable TWI IRQ */
+    twi_enable_interrupt(obj->i2c.i2c_base, TWI_IER_RXBUFF| TWI_IER_TXBUFE | TWI_IER_UNRE | TWI_IER_OVRE | TWI_IER_PECERR);
+
+    /* Enable PDC transfers */
+    pdc_enable_transfer(obj->i2c.pdc, pdcenable );
+
+}
+
+/** The asynchronous IRQ handler
+ *  @param obj The I2C object which holds the transfer information
+ *  @return event flags if a transfer termination condition was met or 0 otherwise.
+ */
+uint32_t i2c_irq_handler_asynch(i2c_t *obj)
+{
+    uint32_t event=0;
+
+    if(obj->i2c.stop) {
+        i2c_stop(obj);
+    }
+
+    // Data transferred via DMA
+    if((obj->i2c.i2c_base->TWI_SR & TWI_IER_TXBUFE)) {
+	    twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_TXBUFE | TWI_IDR_UNRE | TWI_IDR_OVRE | TWI_IDR_PECERR);		
+        if(obj->i2c.event | I2C_EVENT_TRANSFER_COMPLETE)
+            event |=I2C_EVENT_TRANSFER_COMPLETE;
+    }
+	
+    if((obj->i2c.i2c_base->TWI_SR & TWI_IER_RXBUFF)) {
+	    twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_RXBUFF | TWI_IDR_UNRE | TWI_IDR_OVRE | TWI_IDR_PECERR);
+	    if(obj->i2c.event | I2C_EVENT_TRANSFER_COMPLETE)
+	    event |=I2C_EVENT_TRANSFER_COMPLETE;
+    }
+    
+    if(obj->i2c.i2c_base->TWI_SR & TWI_IER_NACK) {
+        if(obj->i2c.event | I2C_EVENT_TRANSFER_EARLY_NACK)
+            event |=I2C_EVENT_TRANSFER_EARLY_NACK;
+    }
+
+
+    if((obj->i2c.i2c_base->TWI_SR & TWI_IER_UNRE) || (obj->i2c.i2c_base->TWI_SR & TWI_IER_OVRE) || (obj->i2c.i2c_base->TWI_SR & TWI_IER_PECERR) || (obj->i2c.i2c_base->TWI_SR & TWI_SR_TOUT) ) {
+        if((obj->i2c.event | I2C_EVENT_ERROR))
+            event |=I2C_EVENT_ERROR;
+
+        if(obj->i2c.address) {
+            uint8_t status= twi_probe(obj->i2c.i2c_base,obj->i2c.address);
+            if((obj->i2c.event | I2C_EVENT_ERROR_NO_SLAVE) && (status!=TWI_SUCCESS) )
+                event |=I2C_EVENT_ERROR_NO_SLAVE;
+        }
+    }
+
+    return event;
+}
+
+/** Attempts to determine if I2C peripheral is already in use.
+ *  @param obj The I2C object
+ *  @return non-zero if the I2C module is active or zero if it is not
+ */
+uint8_t i2c_active(i2c_t *obj)
+{
+
+    if(obj->i2c.i2c_base->TWI_SR & TWI_SR_ENDTX && obj->i2c.i2c_base->TWI_SR & TWI_SR_ENDRX)
+        return 0;
+
+    return 1;
+
+}
+
+/** Abort ongoing asynchronous transaction.
+ *  @param obj The I2C object
+ */
+void i2c_abort_asynch(i2c_t *obj)
+{
+    /* Disable PDC transfers */
+    pdc_disable_transfer(obj->i2c.pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
+
+    /* Clear PDC buffer receive counter */
+    pdc_rx_clear_cnt(obj->i2c.pdc);
+
+    /* Disable I2C IRQ */
+    twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_TXBUFE);
+    twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_RXBUFF);
+
+    /* Disable I2C interrupt */
+    NVIC_DisableIRQ(obj->i2c.irq_type);
+}
+
+#endif
\ No newline at end of file