add SERCOM HAL Async library
Change-Id: I530a5bc5ee7e89149eb251bda0adf7963733d2ee
This commit is contained in:
parent
e676557550
commit
ccbed0b1df
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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" \
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue