mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Revision:
592:a274ee790e56
Parent:
579:53297373a894
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c	Wed Jul 15 08:15:08 2015 +0100
+++ b/targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c	Fri Jul 17 09:15:10 2015 +0100
@@ -20,7 +20,12 @@
 #include "pinmap.h"
 #include "PeripheralPins.h"
 #include "usart.h"
-#include "samr21_xplained_pro.h"
+#include "pinmap_function.h"
+
+#define USART_TX_INDEX		0
+#define USART_RX_INDEX		1
+#define USART_RXFLOW_INDEX	2
+#define USART_TXFLOW_INDEX	3
 
 #if DEVICE_SERIAL_ASYNCH
 #define pUSART_S(obj)			obj->serial.usart
@@ -35,6 +40,13 @@
 
 uint8_t serial_get_index(serial_t *obj);
 IRQn_Type get_serial_irq_num (serial_t *obj);
+uint32_t get_serial_vector (serial_t *obj);
+void uart0_irq();
+void uart1_irq();
+void uart2_irq();
+void uart3_irq();
+void uart4_irq();
+void uart5_irq();
 
 static uint32_t serial_irq_ids[USART_NUM] = {0};
 static uart_irq_handler irq_handler;
@@ -90,9 +102,54 @@
     _USART(obj).CTRLA.reg = SERCOM_USART_CTRLA_SWRST;
 }
 
-static enum status_code usart_set_config_default( serial_t *obj)
+uint32_t serial_find_mux_settings (serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    uint32_t mux_setting = 0;
+    uint32_t pinpad[4] = {0};
+    uint8_t i = 0;
+    uint32_t sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[0], pSERIAL_S(obj)->pins[1]);
 
+    for (i = 0; i < 4 ; i++) {
+        pinpad[i] = pinmap_pad_sercom(pSERIAL_S(obj)->pins[i], sercom_index);
+    }
+
+    switch(pinpad[USART_RX_INDEX]) {
+        case 0:
+            mux_setting |= SERCOM_USART_CTRLA_RXPO(0);
+            break;
+        case 1:
+            mux_setting |= SERCOM_USART_CTRLA_RXPO(1);
+            break;
+        case 2:
+            mux_setting |= SERCOM_USART_CTRLA_RXPO(2);
+            break;
+        case 3:
+            mux_setting |= SERCOM_USART_CTRLA_RXPO(3);
+            break;
+    }
+
+    if ((pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] == NC) && (pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] == NC)) {
+        if (pinpad[USART_TX_INDEX] == 0) {
+            mux_setting |= SERCOM_USART_CTRLA_TXPO(0);
+        } else if(pinpad[USART_RX_INDEX] == 2) {
+            mux_setting |= SERCOM_USART_CTRLA_TXPO(1);
+        } else {
+            mux_setting = mux_setting;  // dummy condition
+        }
+    } else { // for hardware flow control and uart // expecting the tx in pad 0, rts in pad2 and cts in pad 3
+        if((pinpad[USART_TX_INDEX] == 0) && (pinpad[USART_RXFLOW_INDEX]/*rts pin*/ == 2) && (pinpad[USART_TXFLOW_INDEX] /*cts pin*/ == 3)) {
+            mux_setting |= SERCOM_USART_CTRLA_TXPO(2);
+        }
+    }
+    return mux_setting;
+}
+
+static enum status_code usart_set_config_default(serial_t *obj)
+{
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     /* Index for generic clock */
     uint32_t sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj));
     uint32_t gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
@@ -155,85 +212,60 @@
 
 void get_default_serial_values(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     /* Set default config to object */
     pSERIAL_S(obj)->parity = USART_PARITY_NONE;
     pSERIAL_S(obj)->stopbits = USART_STOPBITS_1;
     pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT;
     pSERIAL_S(obj)->baudrate = 9600;
     pSERIAL_S(obj)->mux_setting = USART_RX_1_TX_2_XCK_3;
-    pSERIAL_S(obj)->pinmux_pad0 = PINMUX_DEFAULT;
-    pSERIAL_S(obj)->pinmux_pad1 = PINMUX_DEFAULT;
-    pSERIAL_S(obj)->pinmux_pad2 = PINMUX_DEFAULT;
-    pSERIAL_S(obj)->pinmux_pad3 = PINMUX_DEFAULT;
 };
 
 void serial_init(serial_t *obj, PinName tx, PinName rx)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     if (g_sys_init == 0) {
         system_init();
         g_sys_init = 1;
     }
-
     struct system_gclk_chan_config gclk_chan_conf;
     UARTName uart;
     uint32_t gclk_index;
     uint32_t pm_index;
     uint32_t sercom_index = 0;
     uint32_t muxsetting = 0;
-    uint32_t padsetting[4] = {0};
 
     /* Disable USART module */
     disable_usart(obj);
 
     get_default_serial_values(obj);
 
-    find_pin_settings(tx, rx, NC, NC, &padsetting[0]);  // tx, rx, clk(rts), chipsel(cts) pad array  // getting pads from pins
-    muxsetting = find_mux_setting(tx, rx, NC, NC);  // getting mux setting from pins
-    sercom_index = pinmap_sercom_peripheral(tx, rx);  // same variable sercom_index reused for optimization
-    switch (sercom_index) {
-        case 0:
-            uart = UART_0;
-            pUSART_S(obj) = SERCOM0;
-            break;
-        case 1:
-            uart = UART_1;
-            pUSART_S(obj) = SERCOM1;
-            break;
-        case 2:
-            uart = UART_2;
-            pUSART_S(obj) = SERCOM2;
-            break;
-        case 3:
-            uart = UART_3;
-            pUSART_S(obj) = SERCOM3;
-            break;
-        case 4:
-            uart = UART_4;
-            pUSART_S(obj) = SERCOM4;
-            break;
-        case 5:
-            uart = UART_5;
-            pUSART_S(obj) = SERCOM5;
-            break;
+    pSERIAL_S(obj)->pins[USART_TX_INDEX] = tx;
+    pSERIAL_S(obj)->pins[USART_RX_INDEX] = rx;
+    pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] = NC;
+    pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] = NC;
+
+    muxsetting = serial_find_mux_settings(obj);  // getting mux setting from pins
+    sercom_index = pinmap_merge_sercom(tx, rx);  // same variable sercom_index reused for optimization
+    if (sercom_index == (uint32_t)NC) {
+        /*expecting a valid value for sercom index*/
+        return;
     }
-
-    pSERIAL_S(obj)->txpin = tx;
-    pSERIAL_S(obj)->rxpin = rx;
-    pSERIAL_S(obj)->mux_setting = muxsetting;//EDBG_CDC_SERCOM_MUX_SETTING;
-    pSERIAL_S(obj)->pinmux_pad0 = padsetting[0];//EDBG_CDC_SERCOM_PINMUX_PAD0;
-    pSERIAL_S(obj)->pinmux_pad1 = padsetting[1];//EDBG_CDC_SERCOM_PINMUX_PAD1;
-    pSERIAL_S(obj)->pinmux_pad2 = padsetting[2];//EDBG_CDC_SERCOM_PINMUX_PAD2;
-    pSERIAL_S(obj)->pinmux_pad3 = padsetting[3];//EDBG_CDC_SERCOM_PINMUX_PAD3;
+    sercom_index &= 0x0F;
+    uart = pinmap_peripheral_sercom(NC, sercom_index);
+    pUSART_S(obj) = (Sercom *)uart;
 
     pm_index     = sercom_index + PM_APBCMASK_SERCOM0_Pos;
     gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
 
     if (_USART(obj).CTRLA.reg & SERCOM_USART_CTRLA_SWRST) {
-        /* The module is busy resetting itself */
+        return;  /* The module is busy resetting itself */
     }
 
     if (_USART(obj).CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) {
-        /* Check the module is enabled */
+        return;    /* Check the module is enabled */
     }
 
     /* Turn on module in PM */
@@ -245,29 +277,23 @@
     system_gclk_chan_enable(gclk_index);
     sercom_set_gclk_generator(GCLK_GENERATOR_0, false);
 
+    pSERIAL_S(obj)->mux_setting = muxsetting;
     /* Set configuration according to the config struct */
     usart_set_config_default(obj);
+
     struct system_pinmux_config pin_conf;
-    system_pinmux_get_config_defaults(&pin_conf);
     pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
     pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
-
-    uint32_t pad_pinmuxes[] = {
-        pSERIAL_S(obj)->pinmux_pad0, pSERIAL_S(obj)->pinmux_pad1,
-        pSERIAL_S(obj)->pinmux_pad2, pSERIAL_S(obj)->pinmux_pad3
-    };
+    pin_conf.powersave    = false;
 
     /* Configure the SERCOM pins according to the user configuration */
     for (uint8_t pad = 0; pad < 4; pad++) {
-        uint32_t current_pinmux = pad_pinmuxes[pad];
-
-        if (current_pinmux == PINMUX_DEFAULT) {
-            current_pinmux = _sercom_get_default_pad(pUSART_S(obj), pad);
-        }
-
-        if (current_pinmux != PINMUX_UNUSED) {
-            pin_conf.mux_position = current_pinmux & 0xFFFF;
-            system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
+        uint32_t current_pin = pSERIAL_S(obj)->pins[pad];
+        if (current_pin != (uint32_t)NC) {
+            pin_conf.mux_position = pinmap_function_sercom(current_pin, sercom_index);
+            if ((uint8_t)NC != pin_conf.mux_position) {
+                system_pinmux_pin_set_config(current_pin, &pin_conf);
+            }
         }
     }
 
@@ -275,23 +301,25 @@
         stdio_uart_inited = 1;
         memcpy(&stdio_uart, obj, sizeof(serial_t));
     }
-
     /* Wait until synchronization is complete */
     usart_syncing(obj);
 
     /* Enable USART module */
     enable_usart(obj);
-
 }
 
 void serial_free(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     serial_irq_ids[serial_get_index(obj)] = 0;
     disable_usart(obj);
 }
 
 void serial_baud(serial_t *obj, int baudrate)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     MBED_ASSERT((baudrate == 110) || (baudrate == 150) || (baudrate == 300) || (baudrate == 1200) ||
                 (baudrate == 2400) || (baudrate == 4800) || (baudrate == 9600) || (baudrate == 19200) || (baudrate == 38400) ||
                 (baudrate == 57600) || (baudrate == 115200) || (baudrate == 230400) || (baudrate == 460800) || (baudrate == 921600) );
@@ -330,6 +358,8 @@
 
 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     MBED_ASSERT((stop_bits == 1) || (stop_bits == 2));
     MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven));
     MBED_ASSERT((data_bits == 5) || (data_bits == 6) || (data_bits == 7) || (data_bits == 8) /*|| (data_bits == 9)*/);
@@ -418,117 +448,114 @@
 }
 
 #ifdef DEVICE_SERIAL_FC
-void uart0_irq();
-void uart1_irq();
-void uart2_irq();
-void uart3_irq();
-void uart4_irq();
-void uart5_irq();
 
 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     uint32_t muxsetting = 0;
     uint32_t sercom_index = 0;
-    uint32_t padsetting[4] = {0};
-
     IRQn_Type irq_n = (IRQn_Type)0;
     uint32_t vector = 0;
 
-    switch ((int)pUSART_S(obj)) {
-        case UART_0:
-            vector = (uint32_t)uart0_irq;
-            break;
-        case UART_1:
-            vector = (uint32_t)uart1_irq;
-            break;
-        case UART_2:
-            vector = (uint32_t)uart2_irq;
-            break;
-        case UART_3:
-            vector = (uint32_t)uart3_irq;
-            break;
-        case UART_4:
-            vector = (uint32_t)uart4_irq;
-            break;
-        case UART_5:
-            vector = (uint32_t)uart5_irq;
-            break;
+    pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] = rxflow;
+    pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] = txflow;
+    muxsetting = serial_find_mux_settings(obj);  // getting mux setting from pins
+    sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], pSERIAL_S(obj)->pins[USART_RX_INDEX]);  // same variable sercom_index reused for optimization
+    if (sercom_index == (uint32_t)NC) {
+        /*expecting a valid value for sercom index*/
+        return;
     }
+
+    vector = get_serial_vector(obj);
     irq_n = get_serial_irq_num(obj);
 
     disable_usart(obj);
-    //TODO : assert for rxflow and txflow pis to be added
-    find_pin_settings(pSERIAL_S(obj)->txpin, pSERIAL_S(obj)->rxpin, rxflow, txflow, &padsetting[0]);  // tx, rx, clk(rts), chipsel(cts) pad array  // getting pads from pins
-    muxsetting = find_mux_setting(pSERIAL_S(obj)->txpin, pSERIAL_S(obj)->rxpin, rxflow, txflow);  // getting mux setting from pins
-
-    pSERIAL_S(obj)->mux_setting = muxsetting;//EDBG_CDC_SERCOM_MUX_SETTING;
-    pSERIAL_S(obj)->pinmux_pad0 = padsetting[0];//EDBG_CDC_SERCOM_PINMUX_PAD0;
-    pSERIAL_S(obj)->pinmux_pad1 = padsetting[1];//EDBG_CDC_SERCOM_PINMUX_PAD1;
-    pSERIAL_S(obj)->pinmux_pad2 = padsetting[2];//EDBG_CDC_SERCOM_PINMUX_PAD2;
-    pSERIAL_S(obj)->pinmux_pad3 = padsetting[3];//EDBG_CDC_SERCOM_PINMUX_PAD3;
 
     /* Set configuration according to the config struct */
+    pSERIAL_S(obj)->mux_setting = muxsetting;  // mux setting to be changed for configuring hardware control
     usart_set_config_default(obj);
 
     struct system_pinmux_config pin_conf;
-    system_pinmux_get_config_defaults(&pin_conf);
     pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
     pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
-
-    uint32_t pad_pinmuxes[] = {
-        pSERIAL_S(obj)->pinmux_pad0, pSERIAL_S(obj)->pinmux_pad1,
-        pSERIAL_S(obj)->pinmux_pad2, pSERIAL_S(obj)->pinmux_pad3
-    };
+    pin_conf.powersave    = false;
 
-    /* Configure the SERCOM pins according to the user configuration */
-    for (uint8_t pad = 0; pad < 3; pad++) {
-        uint32_t current_pinmux = pad_pinmuxes[pad];
-
-        if (current_pinmux == PINMUX_DEFAULT) {
-            current_pinmux = _sercom_get_default_pad(pUSART_S(obj), pad);
-        }
-
-        if (current_pinmux != PINMUX_UNUSED) {
-            pin_conf.mux_position = current_pinmux & 0xFFFF;
-            system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
+    for (uint8_t pad = 0; pad < 2; pad++) {  // setting for rx and tx
+        uint32_t current_pin = pSERIAL_S(obj)->pins[pad];
+        if (current_pin != (uint32_t)NC) {
+            pin_conf.mux_position = pinmap_function_sercom(current_pin, sercom_index);
+            if ((uint8_t)NC != pin_conf.mux_position) {
+                system_pinmux_pin_set_config(current_pin, &pin_conf);
+            }
         }
     }
-    if (pSERIAL_S(obj)->pinmux_pad3 != PINMUX_UNUSED) {
-        pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
-        pin_conf.mux_position = pSERIAL_S(obj)->pinmux_pad3 & 0xFFFF;
-        system_pinmux_pin_set_config(pSERIAL_S(obj)->pinmux_pad3 >> 16, &pin_conf);
+    if((FlowControlRTS == type) || (FlowControlRTSCTS== type))  {
+        if (pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] != NC) {
+            pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT; // setting for rxflow
+            pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
+            pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] , sercom_index);
+            if ((uint8_t)NC != pin_conf.mux_position) {
+                system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX], &pin_conf);
+            }
+        }
     }
+    if((FlowControlCTS == type) || (FlowControlRTSCTS== type)) {
+        if (pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] != NC) {
+            pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; // setting for txflow
+            pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
+            pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] , sercom_index);
+            if ((uint8_t)NC != pin_conf.mux_position) {
+                system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX], &pin_conf);
+            }
+        }
+    }
+    enable_usart(obj);
+}
 
-    NVIC_SetVector(irq_n, vector);
-    NVIC_EnableIRQ(irq_n);
-
-    enable_usart(obj);
-    _USART(obj).INTENSET.reg = SERCOM_USART_INTENCLR_CTSIC;
-}
+#endif  //DEVICE_SERIAL_FC
 
 void serial_break_set(serial_t *obj)
 {
-    disable_usart(obj);
-    _USART(obj).CTRLB.reg &= ~SERCOM_SPI_CTRLB_RXEN;
-    usart_syncing(obj);
-    enable_usart(obj);
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    struct system_pinmux_config pin_conf;
+    pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT;
+    pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
+    pin_conf.mux_position = SYSTEM_PINMUX_GPIO;
+    pin_conf.powersave    = false;
+
+    if (pSERIAL_S(obj)->pins[USART_TX_INDEX] != NC) {
+        system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TX_INDEX], &pin_conf);
+    }
 }
 
 void serial_break_clear(serial_t *obj)
 {
-    disable_usart(obj);
-    _USART(obj).CTRLB.reg |= SERCOM_SPI_CTRLB_RXEN;
-    usart_syncing(obj);
-    enable_usart(obj);
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    uint32_t sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], pSERIAL_S(obj)->pins[USART_RX_INDEX]);
+
+    struct system_pinmux_config pin_conf;
+    pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
+    pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
+    pin_conf.powersave    = false;
+
+    if (pSERIAL_S(obj)->pins[USART_TX_INDEX] != NC) {
+        pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], sercom_index);
+        if ((uint8_t)NC != pin_conf.mux_position) {
+            system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TX_INDEX], &pin_conf);
+        }
+    }
 }
 
-#endif  //DEVICE_SERIAL_FC
-
 /******************************************************************************
  * INTERRUPTS HANDLING
  ******************************************************************************/
 inline uint8_t serial_get_index(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     switch ((int)pUSART_S(obj)) {
         case UART_0:
             return 0;
@@ -545,8 +572,10 @@
     }
     return 0;
 }
+
 static inline void uart_irq(SercomUsart *const usart, uint32_t index)
 {
+    MBED_ASSERT(usart != (void*)0);
     uint16_t interrupt_status;
     interrupt_status = usart->INTFLAG.reg;
     interrupt_status &= usart->INTENSET.reg;
@@ -560,10 +589,6 @@
             usart->INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
             irq_handler(serial_irq_ids[index], RxIrq);
         }
-        if (interrupt_status & SERCOM_USART_INTFLAG_CTSIC) { // hardware flow control
-            usart->INTENCLR.reg = SERCOM_USART_INTENCLR_CTSIC;
-            usart->INTFLAG.reg = SERCOM_USART_INTENCLR_CTSIC;
-        }
     }
 }
 
@@ -597,37 +622,11 @@
     uart_irq((SercomUsart *)UART_5, 5);
 }
 
-void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
-{
-    irq_handler = handler;
-    serial_irq_ids[serial_get_index(obj)] = id;
-}
-
-IRQn_Type get_serial_irq_num (serial_t *obj)
+uint32_t get_serial_vector (serial_t *obj)
 {
-    switch ((int)pUSART_S(obj)) {
-        case UART_0:
-            return SERCOM0_IRQn;
-        case UART_1:
-            return SERCOM1_IRQn;
-        case UART_2:
-            return SERCOM2_IRQn;
-        case UART_3:
-            return SERCOM3_IRQn;
-        case UART_4:
-            return SERCOM4_IRQn;
-        case UART_5:
-            return SERCOM5_IRQn;
-        default:
-            MBED_ASSERT(0);
-    }
-}
-
-void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
-{
-    IRQn_Type irq_n = (IRQn_Type)0;
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     uint32_t vector = 0;
-
     switch ((int)pUSART_S(obj)) {
         case UART_0:
             vector = (uint32_t)uart0_irq;
@@ -648,6 +647,48 @@
             vector = (uint32_t)uart5_irq;
             break;
     }
+    return vector;
+}
+
+void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
+{
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    irq_handler = handler;
+    serial_irq_ids[serial_get_index(obj)] = id;
+}
+
+IRQn_Type get_serial_irq_num (serial_t *obj)
+{
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    switch ((int)pUSART_S(obj)) {
+        case UART_0:
+            return SERCOM0_IRQn;
+        case UART_1:
+            return SERCOM1_IRQn;
+        case UART_2:
+            return SERCOM2_IRQn;
+        case UART_3:
+            return SERCOM3_IRQn;
+        case UART_4:
+            return SERCOM4_IRQn;
+        case UART_5:
+            return SERCOM5_IRQn;
+        default:
+            MBED_ASSERT(0);
+    }
+    return SERCOM0_IRQn; // to avoid warning
+}
+
+void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
+{
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    IRQn_Type irq_n = (IRQn_Type)0;
+    uint32_t vector = 0;
+
+    vector = get_serial_vector(obj);
     irq_n = get_serial_irq_num(obj);
 
     if (enable) {
@@ -680,12 +721,16 @@
  ******************************************************************************/
 int serial_getc(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     while (!serial_readable(obj));
     return _USART(obj).DATA.reg ;
 }
 
 void serial_putc(serial_t *obj, int c)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     uint16_t q = (c & SERCOM_USART_DATA_MASK);
     while (!serial_writable(obj));
     _USART(obj).DATA.reg = q;
@@ -694,6 +739,8 @@
 
 int serial_readable(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     uint32_t status = 1;
     if (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_RXC)) {
         status = 0;
@@ -705,6 +752,8 @@
 
 int serial_writable(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     uint32_t status = 1;
     if (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)) {
         status = 0;
@@ -725,6 +774,8 @@
  ***********************************/
 void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     if(enable) {
         pSERIAL_S(obj)->events |= event;
     } else {
@@ -734,6 +785,8 @@
 
 void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     if(enable) {
         pSERIAL_S(obj)->events |= event;
     } else {
@@ -743,6 +796,9 @@
 
 void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    MBED_ASSERT(tx != (void*)0);
     // We only support byte buffers for now
     MBED_ASSERT(width == 8);
 
@@ -757,6 +813,9 @@
 
 void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    MBED_ASSERT(rx != (void*)0);
     // We only support byte buffers for now
     MBED_ASSERT(width == 8);
 
@@ -771,6 +830,8 @@
 
 void serial_set_char_match(serial_t *obj, uint8_t char_match)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     if (char_match != SERIAL_RESERVED_CHAR_MATCH) {
         obj->char_match = char_match;
     }
@@ -781,6 +842,8 @@
  ***********************************/
 int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     MBED_ASSERT(tx != (void*)0);
     if(tx_length == 0) return 0;
 
@@ -790,7 +853,6 @@
 //    if( hint == DMA_USAGE_NEVER) {  //TODO: DMA to be implemented later
     NVIC_ClearPendingIRQ(get_serial_irq_num(obj));
     NVIC_DisableIRQ(get_serial_irq_num(obj));
-    NVIC_SetPriority(get_serial_irq_num(obj), 1);
     NVIC_SetVector(get_serial_irq_num(obj), (uint32_t)handler);
     NVIC_EnableIRQ(get_serial_irq_num(obj));
 
@@ -799,20 +861,23 @@
         _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_DRE;
     }
 //	}
+    return 0;
 }
 
 void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     MBED_ASSERT(rx != (void*)0);
 
     serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
     serial_rx_enable_event(obj, event, true);
     serial_set_char_match(obj, char_match);
-
     serial_rx_buffer_set(obj, rx, rx_length, rx_width);
 
 //    if( hint == DMA_USAGE_NEVER) {  //TODO: DMA to be implemented later
     NVIC_ClearPendingIRQ(get_serial_irq_num(obj));
+    NVIC_DisableIRQ(get_serial_irq_num(obj));
     NVIC_SetVector(get_serial_irq_num(obj), (uint32_t)handler);
     NVIC_EnableIRQ(get_serial_irq_num(obj));
 
@@ -820,35 +885,43 @@
         _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
     }
 //	}
+    return;
 }
 
 uint8_t serial_tx_active(serial_t *obj)
 {
-    return ((_USART(obj).INTENSET.reg & SERCOM_USART_INTFLAG_DRE) ? true : false);
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    return ((obj->tx_buff.length > 0) ? true : false);
 }
 
 uint8_t serial_rx_active(serial_t *obj)
 {
-    return ((_USART(obj).INTENSET.reg & SERCOM_USART_INTFLAG_RXC) ? true : false);
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    return ((obj->rx_buff.length > 0) ? true : false);
 }
 
 int serial_tx_irq_handler_asynch(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
+    serial_tx_abort_asynch(obj);
     return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
 }
 
 int serial_rx_irq_handler_asynch(serial_t *obj)
 {
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     int event = 0;
     /* This interrupt handler is called from USART irq */
     uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
     uint8_t error_code = 0;
     uint16_t received_data = 0;
 
-
     error_code = (uint8_t)(_USART(obj).STATUS.reg & SERCOM_USART_STATUS_MASK);
-
     /* Check if an error has occurred during the receiving */
     if (error_code) {
         /* Check which error occurred */
@@ -882,6 +955,7 @@
         if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
             event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
         }
+        _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
         serial_rx_abort_asynch(obj);
         return event & obj->serial.events;
     }
@@ -891,20 +965,19 @@
         event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
     }
 
-    /* check for final char event */
-    if((obj->rx_buff.length) == 0) {
-        event |= SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
-    }
-
+    /* Return to the call back if character match occured */
     if(event != 0) {
         serial_rx_abort_asynch(obj);
         return event & obj->serial.events;
     }
+    return 0;
 }
 
 int serial_irq_handler_asynch(serial_t *obj)
 {
 //TODO: DMA to be implemented
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
     uint16_t interrupt_status;
     uint8_t *buf = obj->tx_buff.buffer;
 
@@ -915,12 +988,9 @@
         if (interrupt_status & SERCOM_USART_INTFLAG_DRE) {
             /* Interrupt has another TX source */
             if(obj->tx_buff.pos >= obj->tx_buff.length) {
-
                 /* Transfer complete. Switch off interrupt and return event. */
                 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
-                serial_tx_abort_asynch(obj);
-
-                return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
+                _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_TXC;
             } else {
                 while((serial_writable(obj)) && (obj->tx_buff.pos <= (obj->tx_buff.length - 1))) {
                     _USART(obj).DATA.reg = buf[obj->tx_buff.pos];
@@ -929,29 +999,34 @@
             }
         }
         if (interrupt_status & SERCOM_USART_INTFLAG_TXC) {
-            serial_tx_irq_handler_asynch(obj);
+            return serial_tx_irq_handler_asynch(obj);
         }
         if (interrupt_status & SERCOM_USART_INTFLAG_RXC) {
-            serial_rx_irq_handler_asynch(obj);
+            return serial_rx_irq_handler_asynch(obj);
         }
     }
-
+    return 0;
 }
 
 void serial_tx_abort_asynch(serial_t *obj)
 {
 //TODO: DMA to be implemented
-    _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_TXC;
-    obj->tx_buff.pos = 0;
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_TXC;
     obj->tx_buff.length = 0;
+    obj->rx_buff.pos = 0;
+
 }
 
 void serial_rx_abort_asynch(serial_t *obj)
 {
 //TODO: DMA to be implemented
-    _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
+    /* Sanity check arguments */
+    MBED_ASSERT(obj);
+    _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
+    obj->rx_buff.length = 0;
     obj->rx_buff.pos = 0;
-    obj->rx_buff.length = 0;
 }
 
 #endif
\ No newline at end of file