mbed library sources
Fork of mbed-src by
Diff: targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c
- Revision:
- 613:bc40b8d2aec4
- Parent:
- 612:fba1c7dc54c0
- Child:
- 614:9d86c2ae5de0
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c Tue Aug 18 15:00:09 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1032 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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 <string.h> -#include "mbed_assert.h" -#include "cmsis.h" -#include "serial_api.h" -#include "pinmap.h" -#include "PeripheralPins.h" -#include "usart.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 -#define pSERIAL_S(obj) ((struct serial_s*)&(obj->serial)) -#else -#define pUSART_S(obj) obj->serial -#define pSERIAL_S(obj) ((struct serial_s*)obj) -#endif -#define _USART(obj) pUSART_S(obj)->USART -#define USART_NUM 6 - - -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; - -int stdio_uart_inited = 0; -serial_t stdio_uart; - -extern uint8_t g_sys_init; - -static inline bool usart_syncing(serial_t *obj) -{ - /* Sanity check arguments */ - MBED_ASSERT(obj); - - return (_USART(obj).SYNCBUSY.reg); -} - -static inline void enable_usart(serial_t *obj) -{ - /* Sanity check arguments */ - MBED_ASSERT(obj); - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /* Enable USART module */ - _USART(obj).CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; -} - -static inline void disable_usart(serial_t *obj) -{ - /* Sanity check arguments */ - MBED_ASSERT(obj); - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /* Disable USART module */ - _USART(obj).CTRLA.reg &= ~SERCOM_USART_CTRLA_ENABLE; -} - -static inline void reset_usart(serial_t *obj) -{ - /* Sanity check arguments */ - MBED_ASSERT(obj); - - disable_usart(obj); - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /* Reset module */ - _USART(obj).CTRLA.reg = SERCOM_USART_CTRLA_SWRST; -} - -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; - - /* Cache new register values to minimize the number of register writes */ - uint32_t ctrla = 0; - uint32_t ctrlb = 0; - uint16_t baud = 0; - - enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC; - enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16; - - /* Set data order, internal muxing, and clock polarity */ - ctrla = (uint32_t)USART_DATAORDER_LSB | // data order - (uint32_t)pSERIAL_S(obj)->mux_setting; // mux setting // clock polarity is not used - - - /* Get baud value from mode and clock */ - _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate,system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num); // for asynchronous transfer mode - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /*Set baud val */ - _USART(obj).BAUD.reg = baud; - - /* Set sample mode */ - ctrla |= USART_TRANSFER_ASYNCHRONOUSLY; - - /* for disabled external clock source */ - ctrla |= SERCOM_USART_CTRLA_MODE(0x1); - - /* Set stopbits, character size and enable transceivers */ - ctrlb = (uint32_t)pSERIAL_S(obj)->stopbits | (uint32_t)pSERIAL_S(obj)->character_size | - (0x1ul << SERCOM_USART_CTRLB_RXEN_Pos) | // receiver enable - (0x1ul << SERCOM_USART_CTRLB_TXEN_Pos); // transmitter enable - - /* Check parity mode bits */ - if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) { - ctrla |= SERCOM_USART_CTRLA_FORM(1); - ctrlb |= pSERIAL_S(obj)->parity; - } else { - ctrla |= SERCOM_USART_CTRLA_FORM(0); - } - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /* Write configuration to CTRLB */ - _USART(obj).CTRLB.reg = ctrlb; - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /* Write configuration to CTRLA */ - _USART(obj).CTRLA.reg = ctrla; - - return STATUS_OK; -} - -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; -}; - -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; - - /* Disable USART module */ - disable_usart(obj); - - get_default_serial_values(obj); - - 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; - } - 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) { - return; /* The module is busy resetting itself */ - } - - if (_USART(obj).CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) { - return; /* Check the module is enabled */ - } - - /* Turn on module in PM */ - system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index); - - /* Set up the GCLK for the module */ - gclk_chan_conf.source_generator = GCLK_GENERATOR_0; - system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); - 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; - pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; - pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE; - pin_conf.powersave = false; - - /* Configure the SERCOM pins according to the user configuration */ - for (uint8_t pad = 0; pad < 4; pad++) { - 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 (uart == STDIO_UART) { - 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) ); - - struct system_gclk_chan_config gclk_chan_conf; - uint32_t gclk_index; - uint16_t baud = 0; - uint32_t sercom_index = 0; - enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC; - enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16; - - pSERIAL_S(obj)->baudrate = baudrate; - disable_usart(obj); - - sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj)); - gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE; - - gclk_chan_conf.source_generator = GCLK_GENERATOR_0; - system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); - system_gclk_chan_enable(gclk_index); - sercom_set_gclk_generator(GCLK_GENERATOR_0, false); - - /* Get baud value from mode and clock */ - _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate, system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num); - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /*Set baud val */ - _USART(obj).BAUD.reg = baud; - /* Wait until synchronization is complete */ - usart_syncing(obj); - - enable_usart(obj); -} - -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)*/); - - /* Cache new register values to minimize the number of register writes */ - uint32_t ctrla = 0; - uint32_t ctrlb = 0; - - disable_usart(obj); - - ctrla = _USART(obj).CTRLA.reg; - ctrlb = _USART(obj).CTRLB.reg; - - ctrla &= ~(SERCOM_USART_CTRLA_FORM_Msk); - ctrlb &= ~(SERCOM_USART_CTRLB_CHSIZE_Msk); - ctrlb &= ~(SERCOM_USART_CTRLB_SBMODE); - ctrlb &= ~(SERCOM_USART_CTRLB_PMODE); - - switch (stop_bits) { - case 1: - pSERIAL_S(obj)->stopbits = USART_STOPBITS_1; - break; - case 2: - pSERIAL_S(obj)->stopbits = USART_STOPBITS_2; - break; - default: - pSERIAL_S(obj)->stopbits = USART_STOPBITS_1; - } - - switch (parity) { - case ParityNone: - pSERIAL_S(obj)->parity = USART_PARITY_NONE; - break; - case ParityOdd: - pSERIAL_S(obj)->parity = USART_PARITY_ODD; - break; - case ParityEven: - pSERIAL_S(obj)->parity = USART_PARITY_EVEN; - break; - default: - pSERIAL_S(obj)->parity = USART_PARITY_NONE; - } - - switch (data_bits) { - case 5: - pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_5BIT; - break; - case 6: - pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_6BIT; - break; - case 7: - pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_7BIT; - break; - case 8: - pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT; - break; // 9 bit transfer not required in mbed - default: - pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT; - } - - - /* Set stopbits, character size and enable transceivers */ - ctrlb = (uint32_t)pSERIAL_S(obj)->stopbits | (uint32_t)pSERIAL_S(obj)->character_size; - - /* Check parity mode bits */ - if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) { - ctrla |= SERCOM_USART_CTRLA_FORM(1); - ctrlb |= pSERIAL_S(obj)->parity; - } else { - ctrla |= SERCOM_USART_CTRLA_FORM(0); - } - - /* Write configuration to CTRLB */ - _USART(obj).CTRLB.reg = ctrlb; - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - /* Write configuration to CTRLA */ - _USART(obj).CTRLA.reg = ctrla; - - /* Wait until synchronization is complete */ - usart_syncing(obj); - - enable_usart(obj); -} - -#ifdef DEVICE_SERIAL_FC - -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; - IRQn_Type irq_n = (IRQn_Type)0; - uint32_t vector = 0; - - 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); - - /* 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; - pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; - pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE; - pin_conf.powersave = false; - - 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((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); -} - -#endif //DEVICE_SERIAL_FC - -void serial_break_set(serial_t *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) -{ - /* 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); - } - } -} - -/****************************************************************************** - * 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; - case UART_1: - return 1; - case UART_2: - return 2; - case UART_3: - return 3; - case UART_4: - return 4; - case UART_5: - return 5; - } - 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; - - if (serial_irq_ids[index] != 0) { - if (interrupt_status & SERCOM_USART_INTFLAG_TXC) { // for transmit complete - usart->INTFLAG.reg = SERCOM_USART_INTFLAG_TXC; - irq_handler(serial_irq_ids[index], TxIrq); - } - if (interrupt_status & SERCOM_USART_INTFLAG_RXC) { // for receive complete - usart->INTFLAG.reg = SERCOM_USART_INTFLAG_RXC; - irq_handler(serial_irq_ids[index], RxIrq); - } - } -} - -void uart0_irq() -{ - uart_irq((SercomUsart *)UART_0, 0); -} - -void uart1_irq() -{ - uart_irq((SercomUsart *)UART_1, 1); -} - -void uart2_irq() -{ - uart_irq((SercomUsart *)UART_2, 2); -} - -void uart3_irq() -{ - uart_irq((SercomUsart *)UART_3, 3); -} - -void uart4_irq() -{ - uart_irq((SercomUsart *)UART_4, 4); -} - -void uart5_irq() -{ - uart_irq((SercomUsart *)UART_5, 5); -} - -uint32_t get_serial_vector (serial_t *obj) -{ - /* Sanity check arguments */ - MBED_ASSERT(obj); - 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; - } - 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) { - switch (irq) { - case RxIrq: - _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_RXC; - break; - case TxIrq: - _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_TXC; - break; - } - NVIC_SetVector(irq_n, vector); - NVIC_EnableIRQ(irq_n); - - } else { - switch (irq) { - case RxIrq: - _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_RXC; - break; - case TxIrq: - _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_TXC; - break; - } - NVIC_DisableIRQ(irq_n); - } -} - -/****************************************************************************** - * READ/WRITE - ******************************************************************************/ -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; - while (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)); // wait till data is sent -} - -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; - } else { - status = 1; - } - return status; -} - -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; - } else { - status = 1; - } - return status; -} - -/************************************************************************************ - * ASYNCHRONOUS HAL * - ************************************************************************************/ - -#if DEVICE_SERIAL_ASYNCH - -/************************************ - * HELPER FUNCTIONS * - ***********************************/ -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 { - pSERIAL_S(obj)->events &= ~ event; - } -} - -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 { - pSERIAL_S(obj)->events &= ~ event; - } -} - -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); - - if(serial_tx_active(obj)) return; - - obj->tx_buff.buffer = tx; - obj->tx_buff.length = tx_length; - obj->tx_buff.pos = 0; - - return; -} - -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); - - if(serial_rx_active(obj)) return; - - obj->rx_buff.buffer = rx; - obj->rx_buff.length = rx_length; - obj->rx_buff.pos = 0; - - return; -} - -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; - } -} - -/************************************ - * TRANSFER FUNCTIONS * - ***********************************/ -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; - - serial_tx_buffer_set(obj, (void *)tx, tx_length, tx_width); - serial_tx_enable_event(obj, event, true); - -// 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)); - - if (pUSART_S(obj)) { - _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_TXC; - _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)); - - if (pUSART_S(obj)) { - _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_RXC; - } -// } - return; -} - -uint8_t serial_tx_active(serial_t *obj) -{ - /* Sanity check arguments */ - MBED_ASSERT(obj); - return ((obj->tx_buff.length > 0) ? true : false); -} - -uint8_t serial_rx_active(serial_t *obj) -{ - /* 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 */ - if (error_code & SERCOM_USART_STATUS_FERR) { - /* Store the error code and clear flag by writing 1 to it */ - _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_FERR; - return SERIAL_EVENT_RX_FRAMING_ERROR; - } else if (error_code & SERCOM_USART_STATUS_BUFOVF) { - /* Store the error code and clear flag by writing 1 to it */ - _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_BUFOVF; - return SERIAL_EVENT_RX_OVERFLOW; - } else if (error_code & SERCOM_USART_STATUS_PERR) { - /* Store the error code and clear flag by writing 1 to it */ - _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_PERR; - return SERIAL_EVENT_RX_PARITY_ERROR; - } - } - - /* Read current packet from DATA register, - * increment buffer pointer and decrement buffer length */ - received_data = (_USART(obj).DATA.reg & SERCOM_USART_DATA_MASK); - - /* Read value will be at least 8-bits long */ - buf[obj->rx_buff.pos] = received_data; - /* Increment 8-bit pointer */ - obj->rx_buff.pos++; - - /* Check if the last character have been received */ - if(--(obj->rx_buff.length) == 0) { - event |= SERIAL_EVENT_RX_COMPLETE; - 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; - } - - /* Check for character match event */ - if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) { - event |= SERIAL_EVENT_RX_CHARACTER_MATCH; - } - - /* 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; - - interrupt_status = _USART(obj).INTFLAG.reg; - interrupt_status &= _USART(obj).INTENSET.reg; - - if (pUSART_S(obj)) { - 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; - _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]; - obj->tx_buff.pos++; - } - } - } - if (interrupt_status & SERCOM_USART_INTFLAG_TXC) { - return serial_tx_irq_handler_asynch(obj); - } - if (interrupt_status & SERCOM_USART_INTFLAG_RXC) { - return serial_rx_irq_handler_asynch(obj); - } - } - return 0; -} - -void serial_tx_abort_asynch(serial_t *obj) -{ -//TODO: DMA to be implemented - /* 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 - /* Sanity check arguments */ - MBED_ASSERT(obj); - _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_RXC; - obj->rx_buff.length = 0; - obj->rx_buff.pos = 0; -} - -#endif \ No newline at end of file