mbed-os/hal/serial_api.h

467 lines
16 KiB
C

/** \addtogroup hal */
/** @{*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#ifndef MBED_SERIAL_API_H
#define MBED_SERIAL_API_H
#include "device.h"
#include "pinmap.h"
#include "hal/buffer.h"
#include "hal/dma_api.h"
#if DEVICE_SERIAL
#define SERIAL_EVENT_TX_SHIFT (2)
#define SERIAL_EVENT_RX_SHIFT (8)
#define SERIAL_EVENT_TX_MASK (0x00FC)
#define SERIAL_EVENT_RX_MASK (0x3F00)
#define SERIAL_EVENT_ERROR (1 << 1)
/**
* @defgroup SerialTXEvents Serial TX Events Macros
*
* @{
*/
#define SERIAL_EVENT_TX_COMPLETE (1 << (SERIAL_EVENT_TX_SHIFT + 0))
#define SERIAL_EVENT_TX_ALL (SERIAL_EVENT_TX_COMPLETE)
/**@}*/
/**
* @defgroup SerialRXEvents Serial RX Events Macros
*
* @{
*/
#define SERIAL_EVENT_RX_COMPLETE (1 << (SERIAL_EVENT_RX_SHIFT + 0))
#define SERIAL_EVENT_RX_OVERRUN_ERROR (1 << (SERIAL_EVENT_RX_SHIFT + 1))
#define SERIAL_EVENT_RX_FRAMING_ERROR (1 << (SERIAL_EVENT_RX_SHIFT + 2))
#define SERIAL_EVENT_RX_PARITY_ERROR (1 << (SERIAL_EVENT_RX_SHIFT + 3))
#define SERIAL_EVENT_RX_OVERFLOW (1 << (SERIAL_EVENT_RX_SHIFT + 4))
#define SERIAL_EVENT_RX_CHARACTER_MATCH (1 << (SERIAL_EVENT_RX_SHIFT + 5))
#define SERIAL_EVENT_RX_ALL (SERIAL_EVENT_RX_OVERFLOW | SERIAL_EVENT_RX_PARITY_ERROR | \
SERIAL_EVENT_RX_FRAMING_ERROR | SERIAL_EVENT_RX_OVERRUN_ERROR | \
SERIAL_EVENT_RX_COMPLETE | SERIAL_EVENT_RX_CHARACTER_MATCH)
/**@}*/
#define SERIAL_RESERVED_CHAR_MATCH (255)
typedef enum {
ParityNone = 0,
ParityOdd = 1,
ParityEven = 2,
ParityForced1 = 3,
ParityForced0 = 4
} SerialParity;
/** Serial interrupt sources
*/
typedef enum {
RxIrq, /**< Receive Data Register Full */
TxIrq /**< Transmit Data Register Empty */
} SerialIrq;
typedef enum {
FlowControlNone,
FlowControlRTS,
FlowControlCTS,
FlowControlRTSCTS
} FlowControl;
typedef void (*uart_irq_handler)(uint32_t id, SerialIrq event);
#if DEVICE_SERIAL_ASYNCH
/** Asynch serial HAL structure
*/
typedef struct {
struct serial_s serial; /**< Target specific serial structure */
struct buffer_s tx_buff; /**< TX buffer */
struct buffer_s rx_buff; /**< RX buffer */
uint8_t char_match; /**< Character to be matched */
uint8_t char_found; /**< State of the matched character */
} serial_t;
#else
/** Non-asynch serial HAL structure
*/
typedef struct serial_s serial_t;
#endif
typedef struct {
int peripheral;
PinName tx_pin;
int tx_function;
PinName rx_pin;
int rx_function;
bool stdio_config;
} serial_pinmap_t;
typedef struct {
int peripheral;
PinName tx_flow_pin;
int tx_flow_function;
PinName rx_flow_pin;
int rx_flow_function;
} serial_fc_pinmap_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup hal_GeneralSerial Serial Configuration Functions
*
* # Defined behavior
* * ::serial_init initializes the ::serial_t
* * ::serial_init sets the default parameters for serial peripheral (9600 bps, 8N1 format)
* * ::serial_init configures the specified pins
* * ::serial_free releases the serial peripheral
* * ::serial_baud configures the baud rate
* * at least 9600 bps the baud rate must be supported
* * ::serial_format configures the transmission format (number of bits, parity and the number of stop bits)
* * at least 8N1 format must be supported
* * ::serial_irq_handler registers the interrupt handler which will be invoked when the interrupt fires.
* * ::serial_irq_set enables or disables the serial RX or TX IRQ.
* * If `RxIrq` is enabled by ::serial_irq_set, ::serial_irq_handler will be invoked whenever
* Receive Data Register Full IRQ is generated.
* * If `TxIrq` is enabled by ::serial_irq_set, ::serial_irq_handler will be invoked whenever
* Transmit Data Register Empty IRQ is generated.
* * If the interrupt condition holds true, when the interrupt is enabled with ::serial_irq_set,
* the ::serial_irq_handler is called instantly.
* * ::serial_getc returns the character from serial buffer.
* * ::serial_getc is a blocking call (waits for the character).
* * ::serial_putc sends a character.
* * ::serial_putc is a blocking call (waits for a peripheral to be available).
* * ::serial_readable returns non-zero value if a character can be read, 0 otherwise.
* * ::serial_writable returns non-zero value if a character can be written, 0 otherwise.
* * ::serial_clear clears the ::serial_t RX/TX buffers
* * ::serial_break_set sets the break signal.
* * ::serial_break_clear clears the break signal.
* * ::serial_pinout_tx configures the TX pin as an output (to be used in half-duplex mode).
* * ::serial_set_flow_control configures serial flow control.
* * ::serial_set_flow_control sets flow control in the hardware if a serial peripheral supports it,
* otherwise software emulation is used.
* * ::serial_tx_asynch starts the serial asynchronous transfer.
* * ::serial_tx_asynch writes `tx_length` bytes from the `tx` to the bus.
* * ::serial_tx_asynch must support 8 data bits
* * The callback given to ::serial_tx_asynch is invoked when the transfer completes.
* * ::serial_tx_asynch specifies the logical OR of events to be registered.
* * The ::serial_tx_asynch function may use the `DMAUsage` hint to select the appropriate async algorithm.
* * ::serial_rx_asynch starts the serial asynchronous transfer.
* * ::serial_rx_asynch reads `rx_length` bytes to the `rx` buffer.
* * ::serial_rx_asynch must support 8 data bits
* * The callback given to ::serial_rx_asynch is invoked when the transfer completes.
* * ::serial_rx_asynch specifies the logical OR of events to be registered.
* * The ::serial_rx_asynch function may use the `DMAUsage` hint to select the appropriate async algorithm.
* * ::serial_rx_asynch specifies a character in range 0-254 to be matched, 255 is a reserved value.
* * If SERIAL_EVENT_RX_CHARACTER_MATCH event is not registered, the `char_match` is ignored.
* * The SERIAL_EVENT_RX_CHARACTER_MATCH event is set in the callback when SERIAL_EVENT_RX_CHARACTER_MATCH event is
* registered AND `char_match` is present in the received data.
* * ::serial_tx_active returns non-zero if the TX transaction is ongoing, 0 otherwise.
* * ::serial_rx_active returns non-zero if the RX transaction is ongoing, 0 otherwise.
* * ::serial_irq_handler_asynch returns event flags if a transfer termination condition was met, otherwise returns 0.
* * ::serial_irq_handler_asynch takes no longer than one packet transfer time (packet_bits / baudrate) to execute.
* * ::serial_tx_abort_asynch aborts the ongoing TX transaction.
* * ::serial_tx_abort_asynch disables the enabled interupt for TX.
* * ::serial_tx_abort_asynch flushes the TX hardware buffer if TX FIFO is used.
* * ::serial_rx_abort_asynch aborts the ongoing RX transaction.
* * ::serial_rx_abort_asynch disables the enabled interupt for RX.
* * ::serial_rx_abort_asynch flushes the TX hardware buffer if RX FIFO is used.
* * Correct operation guaranteed when interrupt latency is shorter than one packet transfer time (packet_bits / baudrate)
* if the flow control is not used.
* * Correct operation guaranteed regardless of interrupt latency if the flow control is used.
*
* # Undefined behavior
* * Calling ::serial_init multiple times on the same `serial_t` without ::serial_free.
* * Passing invalid pin to ::serial_init, ::serial_pinout_tx.
* * Calling any function other than ::serial_init on am uninitialized or freed `serial_t`.
* * Passing an invalid pointer as `obj` to any function.
* * Passing an invalid pointer as `handler` to ::serial_irq_handler, ::serial_tx_asynch, ::serial_rx_asynch.
* * Calling ::serial_tx_abort while no async TX transfer is being processed.
* * Calling ::serial_rx_abort while no async RX transfer is being processed.
* * Devices behavior is undefined when the interrupt latency is longer than one packet transfer time
* (packet_bits / baudrate) if the flow control is not used.
* @{
*/
/**
* \defgroup hal_GeneralSerial_tests Serial hal tests
* The Serial HAL tests ensure driver conformance to defined behavior.
*
* To run the Serial hal tests use the command:
*
* mbed test -t <toolchain> -m <target> -n tests-mbed_hal_fpga_ci_test_shield-uart
*
*/
/** Initialize the serial peripheral. It sets the default parameters for serial
* peripheral, and configures its specifieds pins.
*
* @param obj The serial object
* @param tx The TX pin name
* @param rx The RX pin name
*/
void serial_init(serial_t *obj, PinName tx, PinName rx);
/** Initialize the serial peripheral. It sets the default parameters for serial
* peripheral, and configures its specifieds pins.
*
* @param obj The serial object
* @param pinmap pointer to structure which holds static pinmap
*/
void serial_init_direct(serial_t *obj, const serial_pinmap_t *pinmap);
/** Release the serial peripheral, not currently invoked. It requires further
* resource management.
*
* @param obj The serial object
*/
void serial_free(serial_t *obj);
/** Configure the baud rate
*
* @param obj The serial object
* @param baudrate The baud rate to be configured
*/
void serial_baud(serial_t *obj, int baudrate);
/** Configure the format. Set the number of bits, parity and the number of stop bits
*
* @param obj The serial object
* @param data_bits The number of data bits
* @param parity The parity
* @param stop_bits The number of stop bits
*/
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits);
/** The serial interrupt handler registration
*
* @param obj The serial object
* @param handler The interrupt handler which will be invoked when the interrupt fires
* @param id The SerialBase object
*/
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id);
/** Configure serial interrupt. This function is used for word-approach
*
* @param obj The serial object
* @param irq The serial IRQ type (RX or TX)
* @param enable Set to non-zero to enable events, or zero to disable them
*/
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable);
/** Get character. This is a blocking call, waiting for a character
*
* @param obj The serial object
*/
int serial_getc(serial_t *obj);
/** Send a character. This is a blocking call, waiting for a peripheral to be available
* for writing
*
* @param obj The serial object
* @param c The character to be sent
*/
void serial_putc(serial_t *obj, int c);
/** Check if the serial peripheral is readable
*
* @param obj The serial object
* @return Non-zero value if a character can be read, 0 if nothing to read
*/
int serial_readable(serial_t *obj);
/** Check if the serial peripheral is writable
*
* @param obj The serial object
* @return Non-zero value if a character can be written, 0 otherwise.
*/
int serial_writable(serial_t *obj);
/** Clear the serial peripheral
*
* @param obj The serial object
*/
void serial_clear(serial_t *obj);
/** Set the break
*
* @param obj The serial object
*/
void serial_break_set(serial_t *obj);
/** Clear the break
*
* @param obj The serial object
*/
void serial_break_clear(serial_t *obj);
/** Configure the TX pin for UART function.
*
* @param tx The pin name used for TX
*/
void serial_pinout_tx(PinName tx);
#if DEVICE_SERIAL_FC
/** Configure the serial for the flow control. It sets flow control in the hardware
* if a serial peripheral supports it, otherwise software emulation is used.
*
* @param obj The serial object
* @param type The type of the flow control. Look at the available FlowControl types.
* @param rxflow The TX pin name
* @param txflow The RX pin name
*/
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow);
/** Configure the serial for the flow control. It sets flow control in the hardware
* if a serial peripheral supports it, otherwise software emulation is used.
*
* @param obj The serial object
* @param type The type of the flow control. Look at the available FlowControl types.
* @param pinmap Pointer to structure which holds static pinmap
*/
void serial_set_flow_control_direct(serial_t *obj, FlowControl type, const serial_fc_pinmap_t *pinmap);
#endif
/** Get the pins that support Serial TX
*
* Return a PinMap array of pins that support Serial TX. The
* array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *serial_tx_pinmap(void);
/** Get the pins that support Serial RX
*
* Return a PinMap array of pins that support Serial RX. The
* array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *serial_rx_pinmap(void);
#if DEVICE_SERIAL_FC
/** Get the pins that support Serial CTS
*
* Return a PinMap array of pins that support Serial CTS. The
* array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *serial_cts_pinmap(void);
/** Get the pins that support Serial RTS
*
* Return a PinMap array of pins that support Serial RTS. The
* array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *serial_rts_pinmap(void);
#endif
#if DEVICE_SERIAL_ASYNCH
/**@}*/
/**
* \defgroup hal_AsynchSerial Asynchronous Serial Hardware Abstraction Layer
* @{
*/
/** Begin asynchronous TX transfer. The used buffer is specified in the serial object,
* tx_buff
*
* @param obj The serial object
* @param tx The transmit buffer
* @param tx_length The number of bytes to transmit
* @param tx_width Deprecated argument
* @param handler The serial handler
* @param event The logical OR of events to be registered
* @param hint A suggestion for how to use DMA with this transfer
* @return Returns number of data transfered, otherwise returns 0
*/
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);
/** Begin asynchronous RX transfer (enable interrupt for data collecting)
* The used buffer is specified in the serial object - rx_buff
*
* @param obj The serial object
* @param rx The receive buffer
* @param rx_length The number of bytes to receive
* @param rx_width Deprecated argument
* @param handler The serial handler
* @param event The logical OR of events to be registered
* @param char_match A character in range 0-254 to be matched
* @param hint A suggestion for how to use DMA with this transfer
*/
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);
/** Attempts to determine if the serial peripheral is already in use for TX
*
* @param obj The serial object
* @return Non-zero if the RX transaction is ongoing, 0 otherwise
*/
uint8_t serial_tx_active(serial_t *obj);
/** Attempts to determine if the serial peripheral is already in use for RX
*
* @param obj The serial object
* @return Non-zero if the RX transaction is ongoing, 0 otherwise
*/
uint8_t serial_rx_active(serial_t *obj);
/** The asynchronous TX and RX handler.
*
* @param obj The serial object
* @return Returns event flags if an RX transfer termination condition was met; otherwise returns 0
*/
int serial_irq_handler_asynch(serial_t *obj);
/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
* flushes the TX hardware buffer if TX FIFO is used
*
* @param obj The serial object
*/
void serial_tx_abort_asynch(serial_t *obj);
/** Abort the ongoing RX transaction. It disables the enabled interrupt for RX and
* flushes the RX hardware buffer if RX FIFO is used
*
* @param obj The serial object
*/
void serial_rx_abort_asynch(serial_t *obj);
/**@}*/
#endif
#ifdef __cplusplus
}
#endif
#endif
#endif
/** @}*/