add SERCOM HAL Async library

Change-Id: I530a5bc5ee7e89149eb251bda0adf7963733d2ee
This commit is contained in:
Kevin Redon 2019-01-24 18:30:26 +01:00
parent e676557550
commit ccbed0b1df
12 changed files with 1207 additions and 30 deletions

View File

@ -42,7 +42,7 @@
<description>Atmel Start Framework</description>
<RTE_Components_h>#define ATMEL_START</RTE_Components_h>
<files>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usart_sync.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usart_async.rst"/>
<file category="doc" condition="ARMCC, GCC, IAR" name="hal/documentation/usb_device_async.rst"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_atomic.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_cache.h"/>
@ -94,9 +94,11 @@
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_increment_macro.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_list.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_repeat_macro.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/utils_ringbuffer.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_assert.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_event.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_list.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/utils/src/utils_ringbuffer.c"/>
<file category="source" condition="GCC" name="hal/utils/src/utils_syscalls.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hri/hri_ac_e54.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hri/hri_adc_e54.h"/>
@ -165,12 +167,12 @@
<file category="header" condition="ARMCC, GCC, IAR" name="atmel_start_pins.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="examples/driver_examples.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="examples/driver_examples.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_usart_sync.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hal_usart_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_missing_features.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_reset.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_async.h"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/include/hpl_usart_sync.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_usart_sync.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hal/src/hal_usart_async.c"/>
<file category="header" condition="ARMCC, GCC, IAR" name="hal/utils/include/parts.h"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/cmcc/hpl_cmcc.c"/>
<file category="source" condition="ARMCC, GCC, IAR" name="hpl/core/hpl_core_m4.c"/>

View File

@ -959,9 +959,9 @@ drivers:
domain_group: null
UART_debug:
user_label: UART_debug
definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM2::driver_config_definition::UART::HAL:Driver:USART.Sync
definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM2::driver_config_definition::UART::HAL:Driver:USART.Async
functionality: USART
api: HAL:Driver:USART_Sync
api: HAL:Driver:USART_Async
configuration:
usart_advanced: false
usart_arch_clock_mode: USART with internal clock

View File

@ -11,9 +11,33 @@
#include <utils.h>
#include <hal_init.h>
struct usart_sync_descriptor UART_debug;
/*! The buffer size for USART */
#define UART_DEBUG_BUFFER_SIZE 16
void UART_debug_PORT_init(void)
struct usart_async_descriptor UART_debug;
static uint8_t UART_debug_buffer[UART_DEBUG_BUFFER_SIZE];
/**
* \brief USART Clock initialization function
*
* Enables register interface and peripheral clock
*/
void UART_debug_CLOCK_init()
{
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_CORE, CONF_GCLK_SERCOM2_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_SLOW, CONF_GCLK_SERCOM2_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_mclk_set_APBBMASK_SERCOM2_bit(MCLK);
}
/**
* \brief USART pinmux initialization function
*
* Set each required pin to USART functionality
*/
void UART_debug_PORT_init()
{
gpio_set_pin_function(PB25, PINMUX_PB25D_SERCOM2_PAD0);
@ -21,18 +45,15 @@ void UART_debug_PORT_init(void)
gpio_set_pin_function(PB24, PINMUX_PB24D_SERCOM2_PAD1);
}
void UART_debug_CLOCK_init(void)
{
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_CORE, CONF_GCLK_SERCOM2_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_SLOW, CONF_GCLK_SERCOM2_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
hri_mclk_set_APBBMASK_SERCOM2_bit(MCLK);
}
/**
* \brief USART initialization function
*
* Enables USART peripheral, clocks and initializes USART driver
*/
void UART_debug_init(void)
{
UART_debug_CLOCK_init();
usart_sync_init(&UART_debug, SERCOM2, (void *)NULL);
usart_async_init(&UART_debug, SERCOM2, UART_debug_buffer, UART_DEBUG_BUFFER_SIZE, (void *)NULL);
UART_debug_PORT_init();
}

View File

@ -21,11 +21,11 @@ extern "C" {
#include <hal_io.h>
#include <hal_sleep.h>
#include <hal_usart_sync.h>
#include <hal_usart_async.h>
#include "hal_usb_device.h"
extern struct usart_sync_descriptor UART_debug;
extern struct usart_async_descriptor UART_debug;
void UART_debug_PORT_init(void);
void UART_debug_CLOCK_init(void);

View File

@ -12,12 +12,29 @@
/**
* Example of using UART_debug to write "Hello World" using the IO abstraction.
*
* Since the driver is asynchronous we need to use statically allocated memory for string
* because driver initiates transfer and then returns before the transmission is completed.
*
* Once transfer has been completed the tx_cb function will be called.
*/
static uint8_t example_UART_debug[12] = "Hello World!";
static void tx_cb_UART_debug(const struct usart_async_descriptor *const io_descr)
{
/* Transfer completed */
}
void UART_debug_example(void)
{
struct io_descriptor *io;
usart_sync_get_io_descriptor(&UART_debug, &io);
usart_sync_enable(&UART_debug);
io_write(io, (uint8_t *)"Hello World!", 12);
usart_async_register_callback(&UART_debug, USART_ASYNC_TXC_CB, tx_cb_UART_debug);
/*usart_async_register_callback(&UART_debug, USART_ASYNC_RXC_CB, rx_cb);
usart_async_register_callback(&UART_debug, USART_ASYNC_ERROR_CB, err_cb);*/
usart_async_get_io_descriptor(&UART_debug, &io);
usart_async_enable(&UART_debug);
io_write(io, example_UART_debug, 12);
}

View File

@ -52,7 +52,7 @@ hal/src/hal_io.o \
hpl/core/hpl_core_m4.o \
usb/class/cdc/device/cdcdf_acm.o \
hal/utils/src/utils_syscalls.o \
hpl/dmac/hpl_dmac.o \
usb_start.o \
gcc/system_same54.o \
hpl/usb/hpl_usb.o \
hal/src/hal_delay.o \
@ -61,9 +61,8 @@ hpl/core/hpl_init.o \
hpl/gclk/hpl_gclk.o \
hal/utils/src/utils_list.o \
hal/utils/src/utils_assert.o \
usb_start.o \
hpl/dmac/hpl_dmac.o \
hpl/oscctrl/hpl_oscctrl.o \
hal/src/hal_usart_sync.o \
hpl/mclk/hpl_mclk.o \
hpl/ramecc/hpl_ramecc.o \
usb/usb_protocol.o \
@ -73,7 +72,9 @@ hal/src/hal_usb_device.o \
hpl/osc32kctrl/hpl_osc32kctrl.o \
examples/driver_examples.o \
driver_init.o \
hal/src/hal_usart_async.o \
hpl/sercom/hpl_sercom.o \
hal/utils/src/utils_ringbuffer.o \
hal/src/hal_gpio.o \
hal/utils/src/utils_event.o \
hal/src/hal_sleep.o \
@ -89,7 +90,7 @@ OBJS_AS_ARGS += \
"hpl/core/hpl_core_m4.o" \
"usb/class/cdc/device/cdcdf_acm.o" \
"hal/utils/src/utils_syscalls.o" \
"hpl/dmac/hpl_dmac.o" \
"usb_start.o" \
"gcc/system_same54.o" \
"hpl/usb/hpl_usb.o" \
"hal/src/hal_delay.o" \
@ -98,9 +99,8 @@ OBJS_AS_ARGS += \
"hpl/gclk/hpl_gclk.o" \
"hal/utils/src/utils_list.o" \
"hal/utils/src/utils_assert.o" \
"usb_start.o" \
"hpl/dmac/hpl_dmac.o" \
"hpl/oscctrl/hpl_oscctrl.o" \
"hal/src/hal_usart_sync.o" \
"hpl/mclk/hpl_mclk.o" \
"hpl/ramecc/hpl_ramecc.o" \
"usb/usb_protocol.o" \
@ -110,7 +110,9 @@ OBJS_AS_ARGS += \
"hpl/osc32kctrl/hpl_osc32kctrl.o" \
"examples/driver_examples.o" \
"driver_init.o" \
"hal/src/hal_usart_async.o" \
"hpl/sercom/hpl_sercom.o" \
"hal/utils/src/utils_ringbuffer.o" \
"hal/src/hal_gpio.o" \
"hal/utils/src/utils_event.o" \
"hal/src/hal_sleep.o" \
@ -135,7 +137,7 @@ DEPS_AS_ARGS += \
"hpl/usb/hpl_usb.d" \
"hal/utils/src/utils_list.d" \
"hpl/cmcc/hpl_cmcc.d" \
"usb_start.d" \
"hpl/dmac/hpl_dmac.d" \
"hal/utils/src/utils_assert.d" \
"hal/src/hal_delay.d" \
"hpl/core/hpl_init.d" \
@ -143,16 +145,17 @@ DEPS_AS_ARGS += \
"usb/usb_protocol.d" \
"hpl/gclk/hpl_gclk.d" \
"hal/src/hal_usb_device.d" \
"hpl/dmac/hpl_dmac.d" \
"usb_start.d" \
"hal/src/hal_init.d" \
"hal/src/hal_usart_sync.d" \
"main.d" \
"hpl/mclk/hpl_mclk.d" \
"driver_init.d" \
"hal/src/hal_usart_async.d" \
"hpl/osc32kctrl/hpl_osc32kctrl.d" \
"examples/driver_examples.d" \
"hal/src/hal_cache.d" \
"hal/src/hal_sleep.d" \
"hal/utils/src/utils_ringbuffer.d" \
"hpl/sercom/hpl_sercom.d" \
"hal/src/hal_gpio.d" \
"hal/src/hal_atomic.d" \

View File

@ -0,0 +1,72 @@
The USART Asynchronous Driver
=============================
The universal synchronous and asynchronous receiver and transmitter
(USART) is usually used to transfer data from one device to the other.
The USART driver use a ring buffer to store received data. When the USART
raise the data received interrupt, this data will be stored in the ring buffer
at the next free location. When the ring buffer is full, the next reception
will overwrite the oldest data stored in the ring buffer. There is one
USART_BUFFER_SIZE macro per used hardware instance, e.g. for SERCOM0 the macro
is called SERCOM0_USART_BUFFER_SIZE.
On the other hand, when sending data over USART, the data is not copied to an
internal buffer, but the data buffer supplied by the user is used. The callback
will only be generated at the end of the buffer and not for each byte.
User can set action for flow control pins by function usart_set_flow_control,
if the flow control is enabled. All the available states are defined in union
usart_flow_control_state.
Note that user can set state of flow control pins only if automatic support of
the flow control is not supported by the hardware.
Features
--------
* Initialization/de-initialization
* Enabling/disabling
* Control of the following settings:
* Baudrate
* UART or USRT communication mode
* Character size
* Data order
* Flow control
* Data transfer: transmission, reception
* Notifications about transfer done or error case via callbacks
* Status information with busy state and transfer count
Applications
------------
They are commonly used in a terminal application or low-speed communication
between devices.
Dependencies
------------
USART capable hardware, with interrupt on each character is sent or
received.
Concurrency
-----------
Write buffer should not be changed while data is being sent.
Limitations
-----------
* The driver does not support 9-bit character size.
* The "USART with ISO7816" mode can be only used in ISO7816 capable devices.
And the SCK pin can't be set directly. Application can use a GCLK output PIN
to generate SCK. For example to communicate with a SMARTCARD with ISO7816
(F = 372 ; D = 1), and baudrate=9600, the SCK pin output frequency should be
config as 372*9600=3571200Hz. More information can be refer to ISO7816 Specification.
Known issues and workarounds
----------------------------
N/A

View File

@ -0,0 +1,339 @@
/**
* \file
*
* \brief USART related functionality declaration.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _HAL_USART_ASYNC_H_INCLUDED
#define _HAL_USART_ASYNC_H_INCLUDED
#include "hal_io.h"
#include <hpl_usart_async.h>
#include <utils_ringbuffer.h>
/**
* \addtogroup doc_driver_hal_usart_async
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief USART descriptor
*
* The USART descriptor forward declaration.
*/
struct usart_async_descriptor;
/**
* \brief USART callback type
*/
typedef void (*usart_cb_t)(const struct usart_async_descriptor *const descr);
/**
* \brief USART callback types
*/
enum usart_async_callback_type { USART_ASYNC_RXC_CB, USART_ASYNC_TXC_CB, USART_ASYNC_ERROR_CB };
/**
* \brief USART callbacks
*/
struct usart_async_callbacks {
usart_cb_t tx_done;
usart_cb_t rx_done;
usart_cb_t error;
};
/** \brief USART status
* Status descriptor holds the current status of transfer.
*/
struct usart_async_status {
/** Status flags */
uint32_t flags;
/** Number of characters transmitted */
uint16_t txcnt;
/** Number of characters receviced */
uint16_t rxcnt;
};
/**
* \brief Asynchronous USART descriptor structure
*/
struct usart_async_descriptor {
struct io_descriptor io;
struct _usart_async_device device;
struct usart_async_callbacks usart_cb;
uint32_t stat;
struct ringbuffer rx;
uint16_t tx_por;
uint8_t * tx_buffer;
uint16_t tx_buffer_length;
};
/** USART write busy */
#define USART_ASYNC_STATUS_BUSY 0x0001
/**
* \brief Initialize USART interface
*
* This function initializes the given I/O descriptor to be used as USART
* interface descriptor.
* It checks if the given hardware is not initialized and if the given hardware
* is permitted to be initialized.
*
* \param[out] descr A USART descriptor which is used to communicate via the USART
* \param[in] hw The pointer to the hardware instance
* \param[in] rx_buffer An RX buffer
* \param[in] rx_buffer_length The length of the buffer above
* \param[in] func The pointer to a set of function pointers
*
* \return Initialization status.
* \retval -1 Passed parameters were invalid or the interface is already
* initialized
* \retval 0 The initialization is completed successfully
*/
int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *const rx_buffer,
const uint16_t rx_buffer_length, void *const func);
/**
* \brief Deinitialize USART interface
*
* This function deinitializes the given I/O descriptor.
* It checks if the given hardware is initialized and if the given hardware
* is permitted to be deinitialized.
*
* \param[in] descr A USART descriptor which is used to communicate via USART
*
* \return De-initialization status.
*/
int32_t usart_async_deinit(struct usart_async_descriptor *const descr);
/**
* \brief Enable USART interface
*
* Enables the USART interface
*
* \param[in] descr A USART descriptor which is used to communicate via USART
*
* \return Enabling status.
*/
int32_t usart_async_enable(struct usart_async_descriptor *const descr);
/**
* \brief Disable USART interface
*
* Disables the USART interface
*
* \param[in] descr A USART descriptor which is used to communicate via USART
*
* \return Disabling status.
*/
int32_t usart_async_disable(struct usart_async_descriptor *const descr);
/**
* \brief Retrieve I/O descriptor
*
* This function retrieves the I/O descriptor of the given USART descriptor.
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[out] io An I/O descriptor to retrieve
*
* \return The status of I/O descriptor retrieving.
*/
int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io);
/**
* \brief Register USART callback
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] type Callback type
* \param[in] cb A callback function
*
* \return The status of callback assignment.
* \retval -1 Passed parameters were invalid or the interface is not initialized
* \retval 0 A callback is registered successfully
*/
int32_t usart_async_register_callback(struct usart_async_descriptor *const descr,
const enum usart_async_callback_type type, usart_cb_t cb);
/**
* \brief Specify action for flow control pins
*
* This function sets action (or state) for flow control pins if
* the flow control is enabled.
* It sets state of flow control pins only if automatic support of
* the flow control is not supported by the hardware.
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] state A state to set the flow control pins
*
* \return The status of flow control action setup.
*/
int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr,
const union usart_flow_control_state state);
/**
* \brief Set USART baud rate
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] baud_rate A baud rate to set
*
* \return The status of baud rate setting.
*/
int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate);
/**
* \brief Set USART data order
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] data_order A data order to set
*
* \return The status of data order setting.
*/
int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order);
/**
* \brief Set USART mode
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] mode A mode to set
*
* \return The status of mode setting.
*/
int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode);
/**
* \brief Set USART parity
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] parity A parity to set
*
* \return The status of parity setting.
*/
int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity);
/**
* \brief Set USART stop bits
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] stop_bits Stop bits to set
*
* \return The status of stop bits setting.
*/
int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits);
/**
* \brief Set USART character size
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[in] size A character size to set
*
* \return The status of character size setting.
*/
int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr,
const enum usart_character_size size);
/**
* \brief Retrieve the state of flow control pins
*
* This function retrieves the flow control pins
* if the flow control is enabled.
*
* The function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case
* if the flow control is done by the hardware
* and the pins state cannot be read out.
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[out] state The state of flow control pins
*
* \return The status of flow control state reading.
*/
int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr,
union usart_flow_control_state *const state);
/**
* \brief Check if the USART transmitter is empty
*
* \param[in] descr A USART descriptor which is used to communicate via USART
*
* \return The status of USART TX empty checking.
* \retval 0 The USART transmitter is not empty
* \retval 1 The USART transmitter is empty
*/
int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr);
/**
* \brief Check if the USART receiver is not empty
*
* \param[in] descr A USART descriptor which is used to communicate via USART
*
* \return The status of the USART RX empty checking.
* \retval 1 The USART receiver is not empty
* \retval 0 The USART receiver is empty
*/
int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr);
/**
* \brief Retrieve the current interface status
*
* \param[in] descr A USART descriptor which is used to communicate via USART
* \param[out] status The state of USART
*
* \return The status of USART status retrieving.
*/
int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status);
/**
* \brief flush USART ringbuf
*
* This function flush USART RX ringbuf.
*
* \param[in] descr The pointer to USART descriptor
*
* \return ERR_NONE
*/
int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr);
/**
* \brief Retrieve the current driver version
*
* \return Current driver version.
*/
uint32_t usart_async_get_version(void);
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _HAL_USART_ASYNC_H_INCLUDED */

View File

@ -0,0 +1,420 @@
/**
* \file
*
* \brief I/O USART related functionality implementation.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include "hal_usart_async.h"
#include <utils_assert.h>
#include <hal_atomic.h>
#include <utils.h>
/**
* \brief Driver version
*/
#define DRIVER_VERSION 0x00000001u
static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length);
static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length);
static void usart_process_byte_sent(struct _usart_async_device *device);
static void usart_transmission_complete(struct _usart_async_device *device);
static void usart_error(struct _usart_async_device *device);
static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data);
/**
* \brief Initialize usart interface
*/
int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *rx_buffer,
uint16_t rx_buffer_length, void *const func)
{
int32_t init_status;
ASSERT(descr && hw && rx_buffer && rx_buffer_length);
if (ERR_NONE != ringbuffer_init(&descr->rx, rx_buffer, rx_buffer_length)) {
return ERR_INVALID_ARG;
}
init_status = _usart_async_init(&descr->device, hw);
if (init_status) {
return init_status;
}
descr->io.read = usart_async_read;
descr->io.write = usart_async_write;
descr->device.usart_cb.tx_byte_sent = usart_process_byte_sent;
descr->device.usart_cb.rx_done_cb = usart_fill_rx_buffer;
descr->device.usart_cb.tx_done_cb = usart_transmission_complete;
descr->device.usart_cb.error_cb = usart_error;
return ERR_NONE;
}
/**
* \brief Deinitialize usart interface
*/
int32_t usart_async_deinit(struct usart_async_descriptor *const descr)
{
ASSERT(descr);
_usart_async_deinit(&descr->device);
descr->io.read = NULL;
descr->io.write = NULL;
return ERR_NONE;
}
/**
* \brief Enable usart interface
*/
int32_t usart_async_enable(struct usart_async_descriptor *const descr)
{
ASSERT(descr);
_usart_async_enable(&descr->device);
return ERR_NONE;
}
/**
* \brief Disable usart interface
*/
int32_t usart_async_disable(struct usart_async_descriptor *const descr)
{
ASSERT(descr);
_usart_async_disable(&descr->device);
return ERR_NONE;
}
/**
* \brief Retrieve I/O descriptor
*/
int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io)
{
ASSERT(descr && io);
*io = &descr->io;
return ERR_NONE;
}
/**
* \brief Register usart callback
*/
int32_t usart_async_register_callback(struct usart_async_descriptor *const descr,
const enum usart_async_callback_type type, usart_cb_t cb)
{
ASSERT(descr);
switch (type) {
case USART_ASYNC_RXC_CB:
descr->usart_cb.rx_done = cb;
_usart_async_set_irq_state(&descr->device, USART_ASYNC_RX_DONE, NULL != cb);
break;
case USART_ASYNC_TXC_CB:
descr->usart_cb.tx_done = cb;
_usart_async_set_irq_state(&descr->device, USART_ASYNC_TX_DONE, NULL != cb);
break;
case USART_ASYNC_ERROR_CB:
descr->usart_cb.error = cb;
_usart_async_set_irq_state(&descr->device, USART_ASYNC_ERROR, NULL != cb);
break;
default:
return ERR_INVALID_ARG;
}
return ERR_NONE;
}
/**
* \brief Specify action for flow control pins
*/
int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr,
const union usart_flow_control_state state)
{
ASSERT(descr);
_usart_async_set_flow_control_state(&descr->device, state);
return ERR_NONE;
}
/**
* \brief Set usart baud rate
*/
int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate)
{
ASSERT(descr);
_usart_async_set_baud_rate(&descr->device, baud_rate);
return ERR_NONE;
}
/**
* \brief Set usart data order
*/
int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order)
{
ASSERT(descr);
_usart_async_set_data_order(&descr->device, data_order);
return ERR_NONE;
}
/**
* \brief Set usart mode
*/
int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode)
{
ASSERT(descr);
_usart_async_set_mode(&descr->device, mode);
return ERR_NONE;
}
/**
* \brief Set usart parity
*/
int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity)
{
ASSERT(descr);
_usart_async_set_parity(&descr->device, parity);
return ERR_NONE;
}
/**
* \brief Set usart stop bits
*/
int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits)
{
ASSERT(descr);
_usart_async_set_stop_bits(&descr->device, stop_bits);
return ERR_NONE;
}
/**
* \brief Set usart character size
*/
int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr, const enum usart_character_size size)
{
ASSERT(descr);
_usart_async_set_character_size(&descr->device, size);
return ERR_NONE;
}
/**
* \brief Retrieve the state of flow control pins
*/
int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr,
union usart_flow_control_state *const state)
{
ASSERT(descr && state);
*state = _usart_async_get_flow_control_state(&descr->device);
return ERR_NONE;
}
/**
* \brief Check if the usart transmitter is empty
*/
int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr)
{
ASSERT(descr);
return _usart_async_is_byte_sent(&descr->device);
}
/**
* \brief Check if the usart receiver is not empty
*/
int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr)
{
ASSERT(descr);
return ringbuffer_num(&descr->rx) > 0;
}
/**
* \brief Retrieve the current interface status
*/
int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status)
{
ASSERT(descr);
volatile uint32_t *tmp_stat = &(descr->stat);
volatile uint16_t *tmp_txcnt = &(descr->tx_por);
if (status) {
status->flags = *tmp_stat;
status->txcnt = *tmp_txcnt;
status->rxcnt = ringbuffer_num(&descr->rx);
}
if (*tmp_stat & USART_ASYNC_STATUS_BUSY) {
return ERR_BUSY;
}
return ERR_NONE;
}
/**
* \brief flush usart rx ringbuf
*/
int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr)
{
ASSERT(descr);
return ringbuffer_flush(&descr->rx);
}
/**
* \brief Retrieve the current driver version
*/
uint32_t usart_async_get_version(void)
{
return DRIVER_VERSION;
}
/*
* \internal Write the given data to usart interface
*
* \param[in] descr The pointer to an io descriptor
* \param[in] buf Data to write to usart
* \param[in] length The number of bytes to write
*
* \return The number of bytes written.
*/
static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length)
{
struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io);
ASSERT(descr && buf && length);
if (descr->tx_por != descr->tx_buffer_length) {
return ERR_NO_RESOURCE;
}
descr->tx_buffer = (uint8_t *)buf;
descr->tx_buffer_length = length;
descr->tx_por = 0;
descr->stat = USART_ASYNC_STATUS_BUSY;
_usart_async_enable_byte_sent_irq(&descr->device);
return (int32_t)length;
}
/*
* \internal Read data from usart interface
*
* \param[in] descr The pointer to an io descriptor
* \param[in] buf A buffer to read data to
* \param[in] length The size of a buffer
*
* \return The number of bytes read.
*/
static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length)
{
uint16_t was_read = 0;
uint32_t num;
struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io);
ASSERT(descr && buf && length);
CRITICAL_SECTION_ENTER()
num = ringbuffer_num(&descr->rx);
CRITICAL_SECTION_LEAVE()
while ((was_read < num) && (was_read < length)) {
ringbuffer_get(&descr->rx, &buf[was_read++]);
}
return (int32_t)was_read;
}
/**
* \brief Process "byte is sent" interrupt
*
* \param[in] device The pointer to device structure
*/
static void usart_process_byte_sent(struct _usart_async_device *device)
{
struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device);
if (descr->tx_por != descr->tx_buffer_length) {
_usart_async_write_byte(&descr->device, descr->tx_buffer[descr->tx_por++]);
_usart_async_enable_byte_sent_irq(&descr->device);
} else {
_usart_async_enable_tx_done_irq(&descr->device);
}
}
/**
* \brief Process completion of data sending
*
* \param[in] device The pointer to device structure
*/
static void usart_transmission_complete(struct _usart_async_device *device)
{
struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device);
descr->stat = 0;
if (descr->usart_cb.tx_done) {
descr->usart_cb.tx_done(descr);
}
}
/**
* \brief Process byte reception
*
* \param[in] device The pointer to device structure
* \param[in] data Data read
*/
static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data)
{
struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device);
ringbuffer_put(&descr->rx, data);
if (descr->usart_cb.rx_done) {
descr->usart_cb.rx_done(descr);
}
}
/**
* \brief Process error interrupt
*
* \param[in] device The pointer to device structure
*/
static void usart_error(struct _usart_async_device *device)
{
struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device);
descr->stat = 0;
if (descr->usart_cb.error) {
descr->usart_cb.error(descr);
}
}
//@}

View File

@ -0,0 +1,116 @@
/**
* \file
*
* \brief Ringbuffer declaration.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#ifndef _UTILS_RINGBUFFER_H_INCLUDED
#define _UTILS_RINGBUFFER_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup doc_driver_hal_utils_ringbuffer
*
* @{
*/
#include "compiler.h"
#include "utils_assert.h"
/**
* \brief Ring buffer element type
*/
struct ringbuffer {
uint8_t *buf; /** Buffer base address */
uint32_t size; /** Buffer size */
uint32_t read_index; /** Buffer read index */
uint32_t write_index; /** Buffer write index */
};
/**
* \brief Ring buffer init
*
* \param[in] rb The pointer to a ring buffer structure instance
* \param[in] buf Space to store the data
* \param[in] size The buffer length, must be aligned with power of 2
*
* \return ERR_NONE on success, or an error code on failure.
*/
int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size);
/**
* \brief Get one byte from ring buffer, the user needs to handle the concurrent
* access on buffer via put/get/flush
*
* \param[in] rb The pointer to a ring buffer structure instance
* \param[in] data One byte space to store the read data
*
* \return ERR_NONE on success, or an error code on failure.
*/
int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data);
/**
* \brief Put one byte to ring buffer, the user needs to handle the concurrent access
* on buffer via put/get/flush
*
* \param[in] rb The pointer to a ring buffer structure instance
* \param[in] data One byte data to be put into ring buffer
*
* \return ERR_NONE on success, or an error code on failure.
*/
int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data);
/**
* \brief Return the element number of ring buffer
*
* \param[in] rb The pointer to a ring buffer structure instance
*
* \return The number of elements in ring buffer [0, rb->size]
*/
uint32_t ringbuffer_num(const struct ringbuffer *const rb);
/**
* \brief Flush ring buffer, the user needs to handle the concurrent access on buffer
* via put/get/flush
*
* \param[in] rb The pointer to a ring buffer structure instance
*
* \return ERR_NONE on success, or an error code on failure.
*/
uint32_t ringbuffer_flush(struct ringbuffer *const rb);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* _UTILS_RINGBUFFER_H_INCLUDED */

View File

@ -0,0 +1,118 @@
/**
* \file
*
* \brief Ringbuffer functionality implementation.
*
* Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*/
#include "utils_ringbuffer.h"
/**
* \brief Ringbuffer init
*/
int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size)
{
ASSERT(rb && buf && size);
/*
* buf size must be aligned to power of 2
*/
if ((size & (size - 1)) != 0) {
return ERR_INVALID_ARG;
}
/* size - 1 is faster in calculation */
rb->size = size - 1;
rb->read_index = 0;
rb->write_index = rb->read_index;
rb->buf = (uint8_t *)buf;
return ERR_NONE;
}
/**
* \brief Get one byte from ringbuffer
*
*/
int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data)
{
ASSERT(rb && data);
if (rb->write_index != rb->read_index) {
*data = rb->buf[rb->read_index & rb->size];
rb->read_index++;
return ERR_NONE;
}
return ERR_NOT_FOUND;
}
/**
* \brief Put one byte to ringbuffer
*
*/
int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data)
{
ASSERT(rb);
rb->buf[rb->write_index & rb->size] = data;
/*
* buffer full strategy: new data will overwrite the oldest data in
* the buffer
*/
if ((rb->write_index - rb->read_index) > rb->size) {
rb->read_index = rb->write_index - rb->size;
}
rb->write_index++;
return ERR_NONE;
}
/**
* \brief Return the element number of ringbuffer
*/
uint32_t ringbuffer_num(const struct ringbuffer *const rb)
{
ASSERT(rb);
return rb->write_index - rb->read_index;
}
/**
* \brief Flush ringbuffer
*/
uint32_t ringbuffer_flush(struct ringbuffer *const rb)
{
ASSERT(rb);
rb->read_index = rb->write_index;
return ERR_NONE;
}

View File

@ -163,6 +163,8 @@ static struct usart_configuration _usarts[] = {
};
#endif
static struct _usart_async_device *_sercom2_dev = NULL;
static uint8_t _get_sercom_index(const void *const hw);
static uint8_t _sercom_get_irq_num(const void *const hw);
static void _sercom_init_irq_param(const void *const hw, void *dev);
@ -562,6 +564,40 @@ void _usart_async_set_irq_state(struct _usart_async_device *const device, const
}
}
/**
* \internal Sercom interrupt handler
*
* \param[in] p The pointer to interrupt parameter
*/
static void _sercom_usart_interrupt_handler(struct _usart_async_device *device)
{
void *hw = device->hw;
if (hri_sercomusart_get_interrupt_DRE_bit(hw) && hri_sercomusart_get_INTEN_DRE_bit(hw)) {
hri_sercomusart_clear_INTEN_DRE_bit(hw);
device->usart_cb.tx_byte_sent(device);
} else if (hri_sercomusart_get_interrupt_TXC_bit(hw) && hri_sercomusart_get_INTEN_TXC_bit(hw)) {
hri_sercomusart_clear_INTEN_TXC_bit(hw);
device->usart_cb.tx_done_cb(device);
} else if (hri_sercomusart_get_interrupt_RXC_bit(hw)) {
if (hri_sercomusart_read_STATUS_reg(hw)
& (SERCOM_USART_STATUS_PERR | SERCOM_USART_STATUS_FERR | SERCOM_USART_STATUS_BUFOVF
| SERCOM_USART_STATUS_ISF | SERCOM_USART_STATUS_COLL)) {
hri_sercomusart_clear_STATUS_reg(hw, SERCOM_USART_STATUS_MASK);
return;
}
device->usart_cb.rx_done_cb(device, hri_sercomusart_read_DATA_reg(hw));
} else if (hri_sercomusart_get_interrupt_ERROR_bit(hw)) {
uint32_t status;
hri_sercomusart_clear_interrupt_ERROR_bit(hw);
device->usart_cb.error_cb(device);
status = hri_sercomusart_read_STATUS_reg(hw);
hri_sercomusart_clear_STATUS_reg(hw, status);
}
}
/**
* \internal Retrieve ordinal number of the given sercom hardware instance
*
@ -589,6 +625,10 @@ static uint8_t _get_sercom_index(const void *const hw)
*/
static void _sercom_init_irq_param(const void *const hw, void *dev)
{
if (hw == SERCOM2) {
_sercom2_dev = (struct _usart_async_device *)dev;
}
}
/**
@ -2349,6 +2389,35 @@ static inline const struct sercomspi_regs_cfg *_spi_get_regs(const uint32_t hw_a
return NULL;
}
/**
* \internal Sercom interrupt handler
*/
void SERCOM2_0_Handler(void)
{
_sercom_usart_interrupt_handler(_sercom2_dev);
}
/**
* \internal Sercom interrupt handler
*/
void SERCOM2_1_Handler(void)
{
_sercom_usart_interrupt_handler(_sercom2_dev);
}
/**
* \internal Sercom interrupt handler
*/
void SERCOM2_2_Handler(void)
{
_sercom_usart_interrupt_handler(_sercom2_dev);
}
/**
* \internal Sercom interrupt handler
*/
void SERCOM2_3_Handler(void)
{
_sercom_usart_interrupt_handler(_sercom2_dev);
}
int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw)
{
const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw);