You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
7.9 KiB
325 lines
7.9 KiB
#ifndef _USART_H |
|
#define _USART_H |
|
|
|
#include <hal_types.h> |
|
#include "ring_buffer.h" |
|
|
|
/* |
|
* Devices |
|
*/ |
|
|
|
#ifndef USART_RX_BUF_SIZE |
|
#define USART_RX_BUF_SIZE 512 |
|
#endif |
|
|
|
#ifndef USART_TX_BUF_SIZE |
|
#define USART_TX_BUF_SIZE 1024 |
|
#endif |
|
|
|
typedef void (* usart_cb)(); |
|
|
|
typedef struct usart_state { |
|
Handler callback; |
|
|
|
uint8_t txbusy; |
|
|
|
uint8_t rx_buf[USART_RX_BUF_SIZE]; |
|
uint8_t tx_buf[USART_TX_BUF_SIZE]; |
|
|
|
uint8_t is_used; // flag that USART is used |
|
|
|
} usart_state; |
|
|
|
/** USART device type */ |
|
typedef struct usart_dev { |
|
USART_TypeDef* USARTx; /**< Register map */ |
|
uint32_t clk; |
|
IRQn_Type irq; |
|
uint8_t rx_pin; |
|
uint8_t tx_pin; |
|
uint8_t gpio_af; |
|
usart_state *state; |
|
ring_buffer *rxrb; /**< RX ring buffer */ |
|
ring_buffer *txrb; /**< TX ring buffer */ |
|
} usart_dev; |
|
|
|
|
|
extern const usart_dev * const UARTS[]; |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
extern const usart_dev * const _USART1; |
|
extern const usart_dev * const _USART2; |
|
extern const usart_dev * const _USART3; |
|
extern const usart_dev * const _UART4; |
|
extern const usart_dev * const _UART5; |
|
extern const usart_dev * const _USART6; |
|
|
|
#define USART_F_RXNE 0x20 |
|
#define USART_F_TXE 0x80 |
|
#define USART_F_ORE 0x8 |
|
|
|
#define USART_MASK_IDLEIE 0x10 |
|
#define USART_MASK_RXNEIE 0x20 |
|
#define USART_MASK_TCEIE 0x40 |
|
#define USART_MASK_TXEIE 0x80 |
|
#define USART_MASK_PEIE 0x100 |
|
|
|
#define USART_MASK2_LBDIE 0x40 |
|
|
|
#define USART_MASK3_CTSIE 0x400 |
|
#define USART_MASK3_EIE 0x1 |
|
|
|
#define UART_Mode_Rx (0x0004) |
|
#define UART_Mode_Tx (0x0008) |
|
|
|
#define UART_HardwareFlowControl_None (0x0000) |
|
#define UART_HardwareFlowControl_RTS (0x0100) |
|
#define UART_HardwareFlowControl_CTS (0x0200) |
|
#define UART_HardwareFlowControl_RTS_CTS (0x0300) |
|
|
|
#define UART_Word_8b ((uint16_t)0x0000) |
|
#define UART_Word_9b ((uint16_t)0x1000) |
|
|
|
/** |
|
* @brief Initialize a serial port. |
|
* @param dev Serial port to be initialized |
|
*/ |
|
void usart_init(const usart_dev *dev); |
|
|
|
|
|
/* |
|
USART_Word_Length |
|
----------------- |
|
USART_WordLength_8b |
|
USART_WordLength_9b |
|
|
|
USART_Stop_Bits |
|
--------------- |
|
USART_StopBits_1 |
|
USART_StopBits_0_5 |
|
USART_StopBits_2 |
|
USART_StopBits_1_5 |
|
|
|
USART_Parity |
|
------------ |
|
USART_Parity_No |
|
USART_Parity_Even |
|
USART_Parity_Odd |
|
|
|
USART_Mode |
|
---------- |
|
USART_Mode_Rx |
|
USART_Mode_Tx |
|
|
|
USART_Hardware_Flow_Control |
|
--------------------------- |
|
USART_HardwareFlowControl_None |
|
USART_HardwareFlowControl_RTS |
|
USART_HardwareFlowControl_CTS |
|
USART_HardwareFlowControl_RTS_CTS |
|
*/ |
|
|
|
/** |
|
* @brief Configure a serial port's baud rate. |
|
* |
|
* @param dev Serial port to be configured |
|
* @param baudRate Baud rate for transmit/receive. |
|
* @param wordLength Specifies the number of data bits transmitted or received in a frame. This parameter can be a value of USART_Word_Length |
|
* @param stopBits Specifies the number of stop bits transmitted. This parameter can be a value of USART_Stop_Bits |
|
* @param parity Specifies the parity mode. This parameter can be a value of USART_Parity |
|
* @param mode Specifies wether the Receive or Transmit mode is enabled or disabled. This parameter can be a value of USART_Mode |
|
* @param hardwareFlowControl Specifies wether the hardware flow control mode is enabled or disabled. This parameter can be a value of USART_Hardware_Flow_Control |
|
*/ |
|
void usart_setup(const usart_dev *dev, |
|
uint32_t baudRate, |
|
uint16_t wordLength, |
|
uint16_t stopBits, |
|
uint16_t parity, |
|
uint16_t mode, |
|
uint16_t hardwareFlowControl); |
|
|
|
/** |
|
* @brief Enable a serial port. |
|
* |
|
* USART is enabled in single buffer transmission mode, multibuffer |
|
* receiver mode, 8n1. |
|
* |
|
* Serial port must have a baud rate configured to work properly. |
|
* |
|
* @param dev Serial port to enable. |
|
* @see usart_set_baud_rate() |
|
*/ |
|
static inline void usart_enable(const usart_dev *dev) |
|
{ |
|
dev->state->is_used=true; |
|
|
|
/* Check the parameters */ |
|
assert_param(IS_USART_ALL_PERIPH(dev->USARTx)); |
|
|
|
/* Enable USART */ |
|
// USART_Cmd(dev->USARTx, ENABLE); |
|
|
|
dev->USARTx->CR1 |= USART_CR1_UE; /* Enable the selected USART by setting the UE bit in the CR1 register */ |
|
|
|
} |
|
|
|
|
|
static inline uint8_t usart_is_used(const usart_dev *dev) |
|
{ |
|
return dev->state->is_used; |
|
} |
|
|
|
|
|
/** |
|
* @brief Turn off a serial port. |
|
* @param dev Serial port to be disabled |
|
*/ |
|
static inline void usart_disable(const usart_dev *dev){ |
|
/* Disable the selected USART by clearing the UE bit in the CR1 register */ |
|
dev->USARTx->CR1 &= (uint16_t)~((uint16_t)USART_CR1_UE); |
|
|
|
/* Clean up buffer */ |
|
dev->state->is_used=false; |
|
} |
|
|
|
/** |
|
* @brief Call a function on each USART. |
|
* @param fn Function to call. |
|
*/ |
|
void usart_foreach(void (*fn)(const usart_dev*)); |
|
|
|
|
|
static inline uint32_t usart_txfifo_nbytes(const usart_dev *dev) { |
|
return rb_full_count(dev->txrb); |
|
} |
|
static inline uint32_t usart_txfifo_freebytes(const usart_dev *dev) { |
|
uint32_t used = rb_full_count(dev->txrb); |
|
if(used >= USART_TX_BUF_SIZE/2) return 0; // leave half for dirty writes without check - thanks s_s |
|
return (USART_TX_BUF_SIZE/2-used); |
|
} |
|
/** |
|
* @brief Disable all serial ports. |
|
*/ |
|
static inline void usart_disable_all(void) { |
|
usart_foreach(usart_disable); |
|
} |
|
|
|
/** |
|
* @brief Nonblocking USART transmit |
|
* @param dev Serial port to transmit over |
|
* @param buf Buffer to transmit |
|
* @param len Maximum number of bytes to transmit |
|
* @return Number of bytes transmitted |
|
*/ |
|
uint32_t usart_tx(const usart_dev *dev, const uint8_t *buf, uint32_t len); |
|
|
|
/** |
|
* @brief Transmit an unsigned integer to the specified serial port in |
|
* decimal format. |
|
* |
|
* This function blocks until the integer's digits have been |
|
* completely transmitted. |
|
* |
|
* @param dev Serial port to send on |
|
* @param val Number to print |
|
*/ |
|
void usart_putudec(const usart_dev *dev, uint32_t val); |
|
|
|
/** |
|
* @brief Transmit one character on a serial port. |
|
* |
|
* This function blocks until the character has been successfully |
|
* transmitted. |
|
* |
|
* @param dev Serial port to send on. |
|
* @param byte Byte to transmit. |
|
*/ |
|
static inline uint32_t usart_putc(const usart_dev* dev, uint8_t bt) { |
|
//uint32_t ret=0; |
|
//uint32_t cnt=0; |
|
//if (!usart_tx(dev, &byte, 1)) |
|
//; |
|
return usart_tx(dev, &bt, 1); |
|
} |
|
|
|
/** |
|
* @brief Transmit a character string on a serial port. |
|
* |
|
* This function blocks until str is completely transmitted. |
|
* |
|
* @param dev Serial port to send on |
|
* @param str String to send |
|
used to inform about exception |
|
|
|
*/ |
|
|
|
|
|
static inline void usart_putstr(const usart_dev *dev, const char* str) { |
|
uint32_t i = 0; |
|
uint8_t c; |
|
while ( (c=str[i++]) ) usart_putc(dev, c); |
|
|
|
} |
|
|
|
/** |
|
* @brief Read one character from a serial port. |
|
* |
|
* It's not safe to call this function if the serial port has no data |
|
* available. |
|
* |
|
* @param dev Serial port to read from |
|
* @return byte read |
|
* @see usart_data_available() |
|
*/ |
|
static inline uint8_t usart_getc(const usart_dev *dev) { |
|
return rb_remove(dev->rxrb); |
|
} |
|
|
|
/** |
|
* @brief Return the amount of data available in a serial port's RX buffer. |
|
* @param dev Serial port to check |
|
* @return Number of bytes in dev's RX buffer. |
|
*/ |
|
static inline uint32_t usart_data_available(const usart_dev *dev) { |
|
return rb_full_count(dev->rxrb); |
|
} |
|
|
|
|
|
/** |
|
* @brief Discard the contents of a serial port's RX buffer. |
|
* @param dev Serial port whose buffer to empty. |
|
*/ |
|
static inline void usart_reset_rx(const usart_dev *dev) { |
|
rb_reset(dev->rxrb); |
|
} |
|
|
|
static inline void usart_reset_tx(const usart_dev *dev) { |
|
rb_reset(dev->txrb); |
|
dev->state->txbusy = 0; |
|
} |
|
|
|
static inline void usart_set_callback(const usart_dev *dev, Handler cb) |
|
{ |
|
dev->state->callback = cb; |
|
} |
|
|
|
|
|
void USART1_IRQHandler(void); |
|
void USART2_IRQHandler(void); |
|
void USART3_IRQHandler(void); |
|
void USART4_IRQHandler(void); |
|
void USART5_IRQHandler(void); |
|
void USART6_IRQHandler(void); |
|
|
|
void UART4_IRQHandler(void); |
|
void UART5_IRQHandler(void); |
|
|
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
#endif
|
|
|