pac55xx: add usart definitions and basic support code.
This commit is contained in:
parent
253a091936
commit
df55d45cc1
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
* @brief USART definitions for the Qorvo PAC55xx series of microcontrollers
|
||||
*
|
||||
* @addtogroup PAC55xx_usart USART
|
||||
* @ingroup PAC55xx_defines
|
||||
* @author Kevin Stefanik <kevin@allocor.tech>
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @date 25 Feb 2020
|
||||
*
|
||||
* Definitions in this file come from the PAC55XX Family User Guide Rev 1.23
|
||||
* by Active-Semi dated November 19, 2019. TX and RX hardware buffer sizes
|
||||
* are both 16 bytes.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LIBOPENCM3_PAC55XX_USART_H_
|
||||
#define LIBOPENCM3_PAC55XX_USART_H_
|
||||
|
||||
#include <libopencm3/pac55xx/memorymap.h>
|
||||
#include <libopencm3/cm3/common.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** @defgroup usart_registers Registers
|
||||
@{*/
|
||||
/** Receive Buffer Register RO, only bits 7:0 used */
|
||||
#define USART_RBR(usart_base) MMIO32((usart_base) + 0x0000)
|
||||
/** Transmit Holding Register WO, only bits 7:0 used */
|
||||
#define USART_THR(usart_base) MMIO32((usart_base) + 0x0004)
|
||||
/** Divisor Latch Register RW, default 0000 0001h, only bits 15:0 used.*/
|
||||
#define USART_DLR(usart_base) MMIO32((usart_base) + 0x0008)
|
||||
/** Interrupt Enable Register RW, default 0000 0000h */
|
||||
#define USART_IER(usart_base) MMIO32((usart_base) + 0x000C)
|
||||
/** Interrupt Identification Register RO, default 0000 0001h */
|
||||
#define USART_IIR(usart_base) MMIO32((usart_base) + 0x0010)
|
||||
/** FIFO Control Register RW, default 0000 0000h */
|
||||
#define USART_FCR(usart_base) MMIO32((usart_base) + 0x0014)
|
||||
/** Line control Register RW, default 0000 0000h */
|
||||
#define USART_LCR(usart_base) MMIO32((usart_base) + 0x0018)
|
||||
/** Line Status Register RO, default 0000 0060h */
|
||||
#define USART_LSR(usart_base) MMIO32((usart_base) + 0x0020)
|
||||
/** Scratch Pad Register RW, only bits 7:0 used */
|
||||
#define USART_SCR(usart_base) MMIO32((usart_base) + 0x0028)
|
||||
/** Enhanced Mode Register RW, default 0000 000h */
|
||||
#define USART_EFR(usart_base) MMIO32((usart_base) + 0x002C)
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup usart_ier_bits Interrupt Enable Register bits
|
||||
@{*/
|
||||
/** Enable RX line status interrupt */
|
||||
#define USART_IER_RLSIE BIT2
|
||||
/** Enable the TX Holding Empty interrupt */
|
||||
#define USART_IER_THRIE BIT1
|
||||
/** Enable the RX Buffer Register Interrupt */
|
||||
#define USART_IER_RBRIE BIT0
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup usart_iir_bits Interrupt ID Register bits
|
||||
@{*/
|
||||
/** This bit is active low to indicate an interrupt is pending */
|
||||
#define USART_IIR_INTSTATUS BIT0
|
||||
/** TX Holding Register Empty */
|
||||
#define USART_IIR_TXEMPTY (0x02)
|
||||
/** Receive Data Available */
|
||||
#define USART_IIR_RXAVAIL (0x04)
|
||||
/** Receive Line Status */
|
||||
#define USART_IIR_RXLINESTAT (0x06)
|
||||
/** Receive FIFO Character Time-out */
|
||||
#define USART_IIR_RXTIMEOUT (0x0C)
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup usart_fcr_bits FIFO Control Register bits
|
||||
@{*/
|
||||
/** Enable both UART RX and TX FIFOs, must be set before writing rest of FCR */
|
||||
#define USART_FCR_FIFOEN BIT0
|
||||
/** RX FIFO Reset. Write 1 to clear. This bit is self-clearing. */
|
||||
#define USART_FCR_RXFIFORST BIT1
|
||||
/** TX FIFO Reset. Write 1 to clear. This bit is self-clearing. */
|
||||
#define USART_FCR_TXFIFORST BIT2
|
||||
#define USART_FCR_TXTL_MASK (3)
|
||||
#define USART_FCR_TXTL_SHIFT 4
|
||||
/** TX Trigger Level */
|
||||
#define USART_FCR_TXTL(txtl) (((txtl) & USART_FCR_TXTL_MASK) << USART_FCR_TXTL_SHIFT)
|
||||
#define USART_FCR_RXTL_MASK (3)
|
||||
#define USART_FCR_RXTL_SHIFT 6
|
||||
/** RX Trigger Level */
|
||||
#define USART_FCR_RXTL(rxtl) (((rxtl) & USART_FCR_RXTL_MASK) << USART_FCR_RXTL_SHIFT)
|
||||
#define USART_FIFO_TRIG_1CHAR (0)
|
||||
#define USART_FIFO_TRIG_4CHAR (1)
|
||||
#define USART_FIFO_TRIG_8CHAR (2)
|
||||
#define USART_FIFO_TRIG_14CHAR (3)
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup usart_lcr_bits Line Control Register bits
|
||||
@{*/
|
||||
/** LCR:WLS 5-bit character length */
|
||||
#define USART_DATABITS_5 (0)
|
||||
/** LCR:WLS 6-bit character length */
|
||||
#define USART_DATABITS_6 (0x01)
|
||||
/** LCR:WLS 7-bit character length */
|
||||
#define USART_DATABITS_7 (0x02)
|
||||
/** LCR:WLS 8-bit character length */
|
||||
#define USART_DATABITS_8 (0x03)
|
||||
/** LCR:PSEL & LCR:PEN Odd parity */
|
||||
#define USART_PSELPEN_ODD (0x01)
|
||||
/** LCR:PSEL & LCR:PEN Even parity */
|
||||
#define USART_PSELPEN_EVEN (0x03)
|
||||
/** LCR:PSEL & LCR:PEN Force 1 stick parity */
|
||||
#define USART_PSELPEN_FORCE1 (0x05)
|
||||
/** LCR:PSEL & LCR:PEN Force 0 stick parity */
|
||||
#define USART_PSELPEN_FORCE0 (0x07)
|
||||
/** LCR:PSEL & LCR:PEN Disable parity */
|
||||
#define USART_PARITY_DISABLE (0)
|
||||
/** LCR:PSEL & LCR:PEN Odd parity */
|
||||
#define USART_PARITY_ODD USART_PSELPEN_ODD
|
||||
/** LCR:PSEL & LCR:PEN Even parity */
|
||||
#define USART_PARITY_EVEN USART_PSELPEN_EVEN
|
||||
/** LCR:PSEL & LCR:PEN Force 1 stick parity */
|
||||
#define USART_PARITY_FORCE1 USART_PSELPEN_FORCE1
|
||||
/** LCR:PSEL & LCR:PEN Force 0 stick parity */
|
||||
#define USART_PARITY_FORCE0 USART_PSELPEN_FORCE0
|
||||
/** LCR:SBS Use 1 stop bit */
|
||||
#define USART_STOPBITS_1 (0)
|
||||
/** LCR:SBS Use 1.5 stop bit when databits is 5 */
|
||||
#define USART_STOPBITS_1P5 USART_LCR_SBS
|
||||
/** LCR:SBS Use 2 stop bits */
|
||||
#define USART_STOPBITS_2 USART_LCR_SBS
|
||||
#define USART_LCR_WLS_MASK (3)
|
||||
/** Word length select: 5-8 databits */
|
||||
#define USART_LCR_WLS(wls) ((wls) & USART_LCR_WLS_MASK)
|
||||
/** Set LCR:SBS for 1.5 or 2 stop bits, Clear for 1 stop bit */
|
||||
#define USART_LCR_SBS BIT2
|
||||
/** Enable parity checking */
|
||||
#define USART_LCR_PEN BIT3
|
||||
#define USART_LCR_PSELPEN_MASK (7)
|
||||
#define USART_LCR_PSELPEN_SHIFT 3
|
||||
/** LCR:PSEL and LCR:PEN control parity */
|
||||
#define USART_LCR_PSELPEN(psel) (((psel) & USART_LCR_PSELPEN_MASK) << USART_LCR_PSELPEN_SHIFT)
|
||||
/** Break Control: Enabling this bit forces TX to logic 0 */
|
||||
#define USART_LCR_BCON BIT6
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup usart_lsr_bits Line Status Register bits
|
||||
@{*/
|
||||
/** Receiver Data Ready */
|
||||
#define USART_LSR_RDR BIT0
|
||||
/** Overrun Error */
|
||||
#define USART_LSR_OE BIT1
|
||||
/** Parity Error */
|
||||
#define USART_LSR_PE BIT2
|
||||
/** Framing Error */
|
||||
#define USART_LSR_FE BIT3
|
||||
/** Break Interrupt */
|
||||
#define USART_LSR_BI BIT4
|
||||
/** Transmitter Holding Register Empty */
|
||||
#define USART_LSR_THRE BIT5
|
||||
/** Transmitter Empty */
|
||||
#define USART_LSR_TEMT BIT6
|
||||
/** Error in RX FIFO */
|
||||
#define USART_LSR_RXFE BIT7
|
||||
/**@}*/
|
||||
|
||||
/** TX FIFO depth */
|
||||
#define USART_TX_FIFO_DEPTH (16)
|
||||
/** RX FIFO depth */
|
||||
#define USART_RX_FIFO_DETPH (16)
|
||||
|
||||
/** Enable Enhanced Mode to use TX and RX FIFO trigger level interrupts */
|
||||
#define USART_EFR_ENMODE BIT4
|
||||
|
||||
/**@}*/
|
||||
|
||||
BEGIN_DECLS
|
||||
|
||||
uint32_t usart_set_baudrate(uint32_t usart, uint32_t baud);
|
||||
void usart_configure_lcr(uint32_t usart, uint8_t data_bits, uint8_t stop_bits,
|
||||
uint8_t parity);
|
||||
void usart_break_enable(uint32_t usart);
|
||||
void usart_break_disable(uint32_t usart);
|
||||
void usart_enhanced_enable(uint32_t usart);
|
||||
void usart_enhanced_disable(uint32_t usart);
|
||||
void usart_set_fifo_depth(uint32_t usart, uint8_t tx_depth, uint8_t rx_depth);
|
||||
void usart_send(uint32_t usart, uint8_t data);
|
||||
uint8_t usart_recv(uint32_t usart);
|
||||
void usart_enable_rx_interrupt(uint32_t usart);
|
||||
void usart_disable_rx_interrupt(uint32_t usart);
|
||||
void usart_enable_tx_interrupt(uint32_t usart);
|
||||
void usart_disable_tx_interrupt(uint32_t usart);
|
||||
void usart_enable_rls_interrupt(uint32_t usart);
|
||||
void usart_disable_rls_interrupt(uint32_t usart);
|
||||
void usart_fifo_enable(uint32_t usart);
|
||||
void usart_fifo_disable(uint32_t usart);
|
||||
void usart_clear_tx_fifo(uint32_t usart);
|
||||
void usart_clear_rx_fifo(uint32_t usart);
|
||||
|
||||
END_DECLS
|
||||
|
||||
#endif /* LIBOPENCM3_PAC55XX_USART_H_ */
|
|
@ -39,6 +39,7 @@ OBJS += can.o
|
|||
OBJS += ccs.o
|
||||
OBJS += gpio.o
|
||||
OBJS += memctl.o
|
||||
OBJS += usart.o
|
||||
|
||||
VPATH += ../cm3
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
/**
|
||||
* @defgroup usart_api USART peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief <b>PAC55xxxx USART Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date February 25, 2020
|
||||
*
|
||||
* This library supports the USART module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/usart.h>
|
||||
#include <libopencm3/cm3/common.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** @brief USART Set Baudrate
|
||||
The baud rate is computed assuming a peripheral clock of 150MHz.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] baud unsigned 32 bit. Baud rate specified in Hz.
|
||||
@return Actual baud rate.
|
||||
*/
|
||||
uint32_t usart_set_baudrate(uint32_t usart, uint32_t baud) {
|
||||
/* TODO Assumes 150MHz PCLK. Update this to ccs_get_peripheral_freq() like on other platforms */
|
||||
const uint32_t pclk = 150000000;
|
||||
uint32_t denom = (baud << 4); /* denominator is baud * 16. */
|
||||
uint32_t dlr = 0xFFFFu & ((pclk + denom / 2) / denom);
|
||||
USART_DLR(usart) = dlr;
|
||||
return pclk / (dlr << 4); /* Baud Rate = PCLK / (16 * UARTADLR) */
|
||||
}
|
||||
|
||||
/** @brief USART Configure Line Control Register
|
||||
This register sets the data bits, stop bits, and parity
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] data_bits unsigned 8 bit. One of USART_DATABITS_5/6/7/8.
|
||||
@param[in] stop_bits unsigned 8 bit. One of USART_STOPBITS_1/1P5/2.
|
||||
@param[in] parity unsigned 8 bit. One of USART_PARITY_DISABLE/ODD/EVEN/FORCE1/FORCE0
|
||||
*/
|
||||
void usart_configure_lcr(uint32_t usart, uint8_t data_bits, uint8_t stop_bits,
|
||||
uint8_t parity) {
|
||||
USART_LCR(usart) = USART_LCR_WLS(data_bits)
|
||||
| ((stop_bits==USART_STOPBITS_2) ? USART_LCR_SBS : 0)
|
||||
| USART_LCR_PSELPEN(parity);
|
||||
}
|
||||
|
||||
/** @brief Enable Break Control
|
||||
Enables break control bit that forces TX pin to logic low.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_break_enable(uint32_t usart) {
|
||||
USART_LCR(usart) |= USART_LCR_BCON;
|
||||
}
|
||||
|
||||
/** @brief Disable Break Control
|
||||
Disables break control bit that forces TX pin to logic low.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_break_disable(uint32_t usart) {
|
||||
USART_LCR(usart) &= ~USART_LCR_BCON;
|
||||
}
|
||||
|
||||
/** @brief Enable Enhanced Mode
|
||||
Enable enhanced mode to generate interrupts when FIFO thresholds in FCR are reached.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enhanced_enable(uint32_t usart) {
|
||||
USART_EFR(usart) = USART_EFR_ENMODE;
|
||||
}
|
||||
|
||||
/** @brief Disable Enhanced Mode
|
||||
Disable enhanced mode to generate interrupts when FIFO thresholds in FCR are reached.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enhanced_disable(uint32_t usart) {
|
||||
USART_EFR(usart) &= ~USART_EFR_ENMODE;
|
||||
}
|
||||
|
||||
/** @brief Enable FIFOs
|
||||
Enable both TX and RX FIFOs. This must be set before setting the trigger levels.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_fifo_enable(uint32_t usart) {
|
||||
USART_FCR(usart) |= USART_FCR_FIFOEN;
|
||||
}
|
||||
|
||||
/** @brief Disable FIFOs
|
||||
Disable both TX and RX FIFOs.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_fifo_disable(uint32_t usart) {
|
||||
USART_FCR(usart) &= ~USART_FCR_FIFOEN;
|
||||
}
|
||||
|
||||
/** Set the TX and RX FIFO depth. This function also enables the FIFOs if not already.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] tx_depth unsigned 8 bit. One of USART_FIFO_TRIG_1/2/4/14CHAR.
|
||||
@param[in] rx_depth unsigned 8 bit. One of USART_FIFO_TRIG_1/2/4/14CHAR.
|
||||
*/
|
||||
void usart_set_fifo_depth(uint32_t usart, uint8_t tx_depth, uint8_t rx_depth) {
|
||||
USART_FCR(usart) |= USART_FCR_FIFOEN;
|
||||
USART_FCR(usart) = USART_FCR_TXTL(tx_depth) | USART_FCR_RXTL(rx_depth) | USART_FCR_FIFOEN;
|
||||
}
|
||||
|
||||
/** @brief Write byte to TX FIFO
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] data unsigned 8 bit. Data to write to the TX FIFO.
|
||||
*/
|
||||
void usart_send(uint32_t usart, uint8_t data) {
|
||||
USART_THR(usart) = (uint32_t)data;
|
||||
}
|
||||
|
||||
/** @brief Read byte from the RX FIFO
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@return Data read from the RX FIFO.
|
||||
*/
|
||||
uint8_t usart_recv(uint32_t usart) {
|
||||
return (uint8_t)USART_RBR(usart);
|
||||
}
|
||||
|
||||
/** @brief Enable RX Interrupts
|
||||
Enable both the Receive Data Available and Character Timeout interrupts.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enable_rx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) |= USART_IER_RBRIE;
|
||||
}
|
||||
|
||||
/** @brief Disable RX Interrupts
|
||||
Disable both the Receive Data Available and Character Timeout interrupts.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_disable_rx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) &= ~USART_IER_RBRIE;
|
||||
}
|
||||
|
||||
/** @brief Enable TX Interrupt
|
||||
Enable the TX Holding Register Empty interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enable_tx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) |= USART_IER_THRIE;
|
||||
}
|
||||
|
||||
/** @brief Disable TX Interrupt
|
||||
Disable the TX Holding Register Empty interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_disable_tx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) &= ~USART_IER_THRIE;
|
||||
}
|
||||
|
||||
/** @brief Enable RX Line Status Interrupt
|
||||
Enable the RX Line Status interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enable_rls_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) |= USART_IER_RLSIE;
|
||||
}
|
||||
|
||||
/** @brief Disable RX Line Status Interrupt
|
||||
Disable the RX Line Status interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_disable_rls_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) &= ~USART_IER_RLSIE;
|
||||
}
|
||||
|
||||
/** @brief Clear the TX FIFO
|
||||
Clears the TX FIFO. The bit is self-clearing.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_clear_tx_fifo(uint32_t usart) {
|
||||
USART_FCR(usart) |= USART_FCR_TXFIFORST;
|
||||
}
|
||||
|
||||
/** @brief Clear the RX FIFO
|
||||
Clears the RX FIFO. The bit is self-clearing.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_clear_rx_fifo(uint32_t usart) {
|
||||
USART_FCR(usart) |= USART_FCR_RXFIFORST;
|
||||
}
|
||||
|
||||
/**@}*/
|
Loading…
Reference in New Issue