mbed library sources
Fork of mbed-src by
Diff: targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c
- 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