Add uart software lib.
This commit is contained in:
parent
393499537d
commit
d2942fe094
|
@ -0,0 +1,115 @@
|
|||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define UART_BASE 0x40004000
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define DECL_REG(addr, name) \
|
||||
volatile uint32_t *const(name) = (volatile uint32_t *)(addr)
|
||||
|
||||
#define __time_critical __attribute__((section(".time_critical")))
|
||||
|
||||
typedef volatile uint32_t io_rw_32;
|
||||
|
||||
#endif
|
||||
|
||||
// #include "addressmap.h"
|
||||
#include "uart_regs.h"
|
||||
|
||||
DECL_REG(UART_BASE + UART_CSR_OFFS, UART_CSR);
|
||||
DECL_REG(UART_BASE + UART_DIV_OFFS, UART_DIV);
|
||||
DECL_REG(UART_BASE + UART_FSTAT_OFFS, UART_FSTAT);
|
||||
DECL_REG(UART_BASE + UART_TX_OFFS, UART_TX);
|
||||
DECL_REG(UART_BASE + UART_RX_OFFS, UART_RX);
|
||||
|
||||
static inline void uart_enable(bool en) {
|
||||
*UART_CSR = *UART_CSR & ~UART_CSR_EN_MASK | (!!en << UART_CSR_EN_LSB);
|
||||
}
|
||||
|
||||
// 10.4 fixed point format.
|
||||
// Encodes number of clock cycles per clock enable.
|
||||
// Each baud period is 16 clock enables (default modparam)
|
||||
static inline void uart_clkdiv(uint32_t div) { *UART_DIV = div; }
|
||||
|
||||
// Use constant arguments:
|
||||
#define uart_clkdiv_baud(clk_mhz, baud) \
|
||||
uart_clkdiv((uint32_t)((clk_mhz) * 1e6 * (16.0 / 8.0) / (float)(baud)))
|
||||
|
||||
static inline bool uart_tx_full() {
|
||||
return !!(*UART_FSTAT & UART_FSTAT_TXFULL_MASK);
|
||||
}
|
||||
|
||||
static inline bool uart_tx_empty() {
|
||||
return !!(*UART_FSTAT & UART_FSTAT_TXEMPTY_MASK);
|
||||
}
|
||||
|
||||
static inline size_t uart_tx_level() {
|
||||
return (*UART_FSTAT & UART_FSTAT_TXLEVEL_MASK) >> UART_FSTAT_TXLEVEL_LSB;
|
||||
}
|
||||
|
||||
static inline bool uart_rx_full() {
|
||||
return !!(*UART_FSTAT & UART_FSTAT_RXFULL_MASK);
|
||||
}
|
||||
|
||||
static inline bool uart_rx_empty() {
|
||||
return !!(*UART_FSTAT & UART_FSTAT_RXEMPTY_MASK);
|
||||
}
|
||||
|
||||
static inline size_t uart_rx_level() {
|
||||
return (*UART_FSTAT & UART_FSTAT_RXLEVEL_MASK) >> UART_FSTAT_RXLEVEL_LSB;
|
||||
}
|
||||
|
||||
static inline void uart_put(uint8_t x) {
|
||||
while (uart_tx_full());
|
||||
*(volatile uint8_t *const)UART_TX = x;
|
||||
}
|
||||
|
||||
static inline uint8_t uart_get() {
|
||||
while (uart_rx_empty());
|
||||
return *(volatile uint8_t *const)UART_RX;
|
||||
}
|
||||
|
||||
static inline void uart_puts(const char *s) {
|
||||
while (*s) {
|
||||
if (*s == '\n') uart_put('\r');
|
||||
uart_put((uint8_t)(*s++));
|
||||
}
|
||||
}
|
||||
|
||||
// Have you seen how big printf is?
|
||||
static const char hextable[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
static inline void uart_putint(uint32_t x) {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
uart_put((uint8_t)(hextable[x >> 28]));
|
||||
x <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart_putbyte(uint8_t x) {
|
||||
uart_put((uint8_t)(hextable[x >> 4]));
|
||||
uart_put((uint8_t)(hextable[x & 0xf]));
|
||||
}
|
||||
|
||||
static inline void uart_wait_done() { while (*UART_CSR & UART_CSR_BUSY_MASK); }
|
||||
|
||||
static inline void uart_init() {
|
||||
*UART_CSR = 0;
|
||||
while (*UART_CSR & UART_CSR_BUSY_MASK);
|
||||
while (!uart_rx_empty()) (void)uart_get();
|
||||
uart_enable(true);
|
||||
}
|
||||
|
||||
static inline void uart_enable_cts(bool en) {
|
||||
*UART_CSR = *UART_CSR & ~UART_CSR_CTSEN_MASK | (!!en << UART_CSR_CTSEN_LSB);
|
||||
}
|
||||
|
||||
#endif // _UART_H_
|
|
@ -0,0 +1,142 @@
|
|||
/*******************************************************************************
|
||||
* AUTOGENERATED BY REGBLOCK *
|
||||
* Do not edit manually. *
|
||||
* Edit the source file (or regblock utility) and regenerate. *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _UART_REGS_H_
|
||||
#define _UART_REGS_H_
|
||||
|
||||
// Block name : uart
|
||||
// Bus type : apb
|
||||
// Bus data width : 32
|
||||
// Bus address width : 16
|
||||
|
||||
#define UART_CSR_OFFS 0
|
||||
#define UART_DIV_OFFS 4
|
||||
#define UART_FSTAT_OFFS 8
|
||||
#define UART_TX_OFFS 12
|
||||
#define UART_RX_OFFS 16
|
||||
|
||||
/*******************************************************************************
|
||||
* CSR *
|
||||
*******************************************************************************/
|
||||
|
||||
// Control and status register
|
||||
|
||||
// Field: CSR_EN Access: RW
|
||||
// UART runs when en is high. Synchronous reset (excluding FIFOs) when low.
|
||||
#define UART_CSR_EN_LSB 0
|
||||
#define UART_CSR_EN_BITS 1
|
||||
#define UART_CSR_EN_MASK 0x1
|
||||
// Field: CSR_BUSY Access: ROV
|
||||
// UART TX is still sending data
|
||||
#define UART_CSR_BUSY_LSB 1
|
||||
#define UART_CSR_BUSY_BITS 1
|
||||
#define UART_CSR_BUSY_MASK 0x2
|
||||
// Field: CSR_TXIE Access: RW
|
||||
// Enable TX FIFO interrupt
|
||||
#define UART_CSR_TXIE_LSB 2
|
||||
#define UART_CSR_TXIE_BITS 1
|
||||
#define UART_CSR_TXIE_MASK 0x4
|
||||
// Field: CSR_RXIE Access: RW
|
||||
// Enable RX FIFO interrupt
|
||||
#define UART_CSR_RXIE_LSB 3
|
||||
#define UART_CSR_RXIE_BITS 1
|
||||
#define UART_CSR_RXIE_MASK 0x8
|
||||
// Field: CSR_CTSEN Access: RW
|
||||
// Enable pausing of TX while CTS is not asserted
|
||||
#define UART_CSR_CTSEN_LSB 4
|
||||
#define UART_CSR_CTSEN_BITS 1
|
||||
#define UART_CSR_CTSEN_MASK 0x10
|
||||
// Field: CSR_LOOPBACK Access: RW
|
||||
// Connect TX -> RX and RTS -> CTS internally (for testing).
|
||||
#define UART_CSR_LOOPBACK_LSB 8
|
||||
#define UART_CSR_LOOPBACK_BITS 1
|
||||
#define UART_CSR_LOOPBACK_MASK 0x100
|
||||
|
||||
/*******************************************************************************
|
||||
* DIV *
|
||||
*******************************************************************************/
|
||||
|
||||
// Clock divider control fields
|
||||
|
||||
// Field: DIV_INT Access: WO
|
||||
#define UART_DIV_INT_LSB 4
|
||||
#define UART_DIV_INT_BITS 10
|
||||
#define UART_DIV_INT_MASK 0x3ff0
|
||||
// Field: DIV_FRAC Access: WO
|
||||
#define UART_DIV_FRAC_LSB 0
|
||||
#define UART_DIV_FRAC_BITS 4
|
||||
#define UART_DIV_FRAC_MASK 0xf
|
||||
|
||||
/*******************************************************************************
|
||||
* FSTAT *
|
||||
*******************************************************************************/
|
||||
|
||||
// FIFO status register
|
||||
|
||||
// Field: FSTAT_TXLEVEL Access: ROV
|
||||
#define UART_FSTAT_TXLEVEL_LSB 0
|
||||
#define UART_FSTAT_TXLEVEL_BITS 8
|
||||
#define UART_FSTAT_TXLEVEL_MASK 0xff
|
||||
// Field: FSTAT_TXFULL Access: ROV
|
||||
#define UART_FSTAT_TXFULL_LSB 8
|
||||
#define UART_FSTAT_TXFULL_BITS 1
|
||||
#define UART_FSTAT_TXFULL_MASK 0x100
|
||||
// Field: FSTAT_TXEMPTY Access: ROV
|
||||
#define UART_FSTAT_TXEMPTY_LSB 9
|
||||
#define UART_FSTAT_TXEMPTY_BITS 1
|
||||
#define UART_FSTAT_TXEMPTY_MASK 0x200
|
||||
// Field: FSTAT_TXOVER Access: W1C
|
||||
#define UART_FSTAT_TXOVER_LSB 10
|
||||
#define UART_FSTAT_TXOVER_BITS 1
|
||||
#define UART_FSTAT_TXOVER_MASK 0x400
|
||||
// Field: FSTAT_TXUNDER Access: W1C
|
||||
#define UART_FSTAT_TXUNDER_LSB 11
|
||||
#define UART_FSTAT_TXUNDER_BITS 1
|
||||
#define UART_FSTAT_TXUNDER_MASK 0x800
|
||||
// Field: FSTAT_RXLEVEL Access: ROV
|
||||
#define UART_FSTAT_RXLEVEL_LSB 16
|
||||
#define UART_FSTAT_RXLEVEL_BITS 8
|
||||
#define UART_FSTAT_RXLEVEL_MASK 0xff0000
|
||||
// Field: FSTAT_RXFULL Access: ROV
|
||||
#define UART_FSTAT_RXFULL_LSB 24
|
||||
#define UART_FSTAT_RXFULL_BITS 1
|
||||
#define UART_FSTAT_RXFULL_MASK 0x1000000
|
||||
// Field: FSTAT_RXEMPTY Access: ROV
|
||||
#define UART_FSTAT_RXEMPTY_LSB 25
|
||||
#define UART_FSTAT_RXEMPTY_BITS 1
|
||||
#define UART_FSTAT_RXEMPTY_MASK 0x2000000
|
||||
// Field: FSTAT_RXOVER Access: W1C
|
||||
#define UART_FSTAT_RXOVER_LSB 26
|
||||
#define UART_FSTAT_RXOVER_BITS 1
|
||||
#define UART_FSTAT_RXOVER_MASK 0x4000000
|
||||
// Field: FSTAT_RXUNDER Access: W1C
|
||||
#define UART_FSTAT_RXUNDER_LSB 27
|
||||
#define UART_FSTAT_RXUNDER_BITS 1
|
||||
#define UART_FSTAT_RXUNDER_MASK 0x8000000
|
||||
|
||||
/*******************************************************************************
|
||||
* TX *
|
||||
*******************************************************************************/
|
||||
|
||||
// TX data FIFO
|
||||
|
||||
// Field: TX Access: WF
|
||||
#define UART_TX_LSB 0
|
||||
#define UART_TX_BITS 8
|
||||
#define UART_TX_MASK 0xff
|
||||
|
||||
/*******************************************************************************
|
||||
* RX *
|
||||
*******************************************************************************/
|
||||
|
||||
// RX data FIFO
|
||||
|
||||
// Field: RX Access: RF
|
||||
#define UART_RX_LSB 0
|
||||
#define UART_RX_BITS 8
|
||||
#define UART_RX_MASK 0xff
|
||||
|
||||
#endif // _UART_REGS_H_
|
Loading…
Reference in New Issue