294 lines
7.7 KiB
C
294 lines
7.7 KiB
C
/* Copyright 2018 Canaan Inc.
|
||
*
|
||
* 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.
|
||
*/
|
||
|
||
/**
|
||
* @file
|
||
* @brief Universal Asynchronous Receiver/Transmitter (UART)
|
||
*
|
||
* The UART peripheral supports the following features:
|
||
*
|
||
* - 8-N-1 and 8-N-2 formats: 8 data bits, no parity bit, 1 start
|
||
* bit, 1 or 2 stop bits
|
||
*
|
||
* - 8-entry transmit and receive FIFO buffers with programmable
|
||
* watermark interrupts
|
||
*
|
||
* - 16× Rx oversampling with 2/3 majority voting per bit
|
||
*
|
||
* The UART peripheral does not support hardware flow control or
|
||
* other modem control signals, or synchronous serial data
|
||
* tranfesrs.
|
||
*
|
||
* @note UART RAM Layout
|
||
*
|
||
* | Address | Name | Description |
|
||
* |-----------|----------|---------------------------------|
|
||
* | 0x000 | txdata | Transmit data register |
|
||
* | 0x004 | rxdata | Receive data register |
|
||
* | 0x008 | txctrl | Transmit control register |
|
||
* | 0x00C | rxctrl | Receive control register |
|
||
* | 0x010 | ie | UART interrupt enable |
|
||
* | 0x014 | ip | UART Interrupt pending |
|
||
* | 0x018 | div | Baud rate divisor |
|
||
*
|
||
*/
|
||
|
||
#ifndef _DRIVER_UARTHS_H
|
||
#define _DRIVER_UARTHS_H
|
||
|
||
#include <stddef.h>
|
||
#include <stdint.h>
|
||
#include "platform.h"
|
||
#include "plic.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* clang-format off */
|
||
/* Register address offsets */
|
||
#define UARTHS_REG_TXFIFO (0x00)
|
||
#define UARTHS_REG_RXFIFO (0x04)
|
||
#define UARTHS_REG_TXCTRL (0x08)
|
||
#define UARTHS_REG_RXCTRL (0x0c)
|
||
#define UARTHS_REG_IE (0x10)
|
||
#define UARTHS_REG_IP (0x14)
|
||
#define UARTHS_REG_DIV (0x18)
|
||
|
||
/* TXCTRL register */
|
||
#define UARTHS_TXEN (0x01)
|
||
#define UARTHS_TXWM(x) (((x) & 0xffff) << 16)
|
||
|
||
/* RXCTRL register */
|
||
#define UARTHS_RXEN (0x01)
|
||
#define UARTHS_RXWM(x) (((x) & 0xffff) << 16)
|
||
|
||
/* IP register */
|
||
#define UARTHS_IP_TXWM (0x01)
|
||
#define UARTHS_IP_RXWM (0x02)
|
||
/* clang-format on */
|
||
|
||
typedef struct _uarths_txdata
|
||
{
|
||
/* Bits [7:0] is data */
|
||
uint32_t data : 8;
|
||
/* Bits [30:8] is 0 */
|
||
uint32_t zero : 23;
|
||
/* Bit 31 is full status */
|
||
uint32_t full : 1;
|
||
} __attribute__((packed, aligned(4))) uarths_txdata_t;
|
||
|
||
typedef struct _uarths_rxdata
|
||
{
|
||
/* Bits [7:0] is data */
|
||
uint32_t data : 8;
|
||
/* Bits [30:8] is 0 */
|
||
uint32_t zero : 23;
|
||
/* Bit 31 is empty status */
|
||
uint32_t empty : 1;
|
||
} __attribute__((packed, aligned(4))) uarths_rxdata_t;
|
||
|
||
typedef struct _uarths_txctrl
|
||
{
|
||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||
uint32_t txen : 1;
|
||
/* Bit 1 is nstop, 0 for one stop bit and 1 for two stop bits */
|
||
uint32_t nstop : 1;
|
||
/* Bits [15:2] is reserved */
|
||
uint32_t resv0 : 14;
|
||
/* Bits [18:16] is threshold of interrupt triggers */
|
||
uint32_t txcnt : 3;
|
||
/* Bits [31:19] is reserved */
|
||
uint32_t resv1 : 13;
|
||
} __attribute__((packed, aligned(4))) uarths_txctrl_t;
|
||
|
||
typedef struct _uarths_rxctrl
|
||
{
|
||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||
uint32_t rxen : 1;
|
||
/* Bits [15:1] is reserved */
|
||
uint32_t resv0 : 15;
|
||
/* Bits [18:16] is threshold of interrupt triggers */
|
||
uint32_t rxcnt : 3;
|
||
/* Bits [31:19] is reserved */
|
||
uint32_t resv1 : 13;
|
||
} __attribute__((packed, aligned(4))) uarths_rxctrl_t;
|
||
|
||
typedef struct _uarths_ip
|
||
{
|
||
/* Bit 0 is txwm, raised less than txcnt */
|
||
uint32_t txwm : 1;
|
||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||
uint32_t rxwm : 1;
|
||
/* Bits [31:2] is 0 */
|
||
uint32_t zero : 30;
|
||
} __attribute__((packed, aligned(4))) uarths_ip_t;
|
||
|
||
typedef struct _uarths_ie
|
||
{
|
||
/* Bit 0 is txwm, raised less than txcnt */
|
||
uint32_t txwm : 1;
|
||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||
uint32_t rxwm : 1;
|
||
/* Bits [31:2] is 0 */
|
||
uint32_t zero : 30;
|
||
} __attribute__((packed, aligned(4))) uarths_ie_t;
|
||
|
||
typedef struct _uarths_div
|
||
{
|
||
/* Bits [31:2] is baud rate divisor register */
|
||
uint32_t div : 16;
|
||
/* Bits [31:16] is 0 */
|
||
uint32_t zero : 16;
|
||
} __attribute__((packed, aligned(4))) uarths_div_t;
|
||
|
||
typedef struct _uarths
|
||
{
|
||
/* Address offset 0x00 */
|
||
uarths_txdata_t txdata;
|
||
/* Address offset 0x04 */
|
||
uarths_rxdata_t rxdata;
|
||
/* Address offset 0x08 */
|
||
uarths_txctrl_t txctrl;
|
||
/* Address offset 0x0c */
|
||
uarths_rxctrl_t rxctrl;
|
||
/* Address offset 0x10 */
|
||
uarths_ie_t ie;
|
||
/* Address offset 0x14 */
|
||
uarths_ip_t ip;
|
||
/* Address offset 0x18 */
|
||
uarths_div_t div;
|
||
} __attribute__((packed, aligned(4))) uarths_t;
|
||
|
||
typedef enum _uarths_interrupt_mode
|
||
{
|
||
UARTHS_SEND = 1,
|
||
UARTHS_RECEIVE = 2,
|
||
UARTHS_SEND_RECEIVE = 3,
|
||
} uarths_interrupt_mode_t;
|
||
|
||
typedef enum _uarths_stopbit
|
||
{
|
||
UARTHS_STOP_1,
|
||
UARTHS_STOP_2
|
||
} uarths_stopbit_t;
|
||
|
||
extern volatile uarths_t *const uarths;
|
||
|
||
/**
|
||
* @brief Initialization Core UART
|
||
*
|
||
* @return result
|
||
* - 0 Success
|
||
* - Other Fail
|
||
*/
|
||
void uarths_init(void);
|
||
|
||
/**
|
||
* @brief Put a char to UART
|
||
*
|
||
* @param[in] c The char to put
|
||
*
|
||
* @note If c is '\n', a '\r' will be appended automatically
|
||
*
|
||
* @return result
|
||
* - 0 Success
|
||
* - Other Fail
|
||
*/
|
||
int uarths_putchar(char c);
|
||
|
||
/**
|
||
* @brief Send a string to UART
|
||
*
|
||
* @param[in] s The string to send
|
||
*
|
||
* @note The string must ending with '\0'
|
||
*
|
||
* @return result
|
||
* - 0 Success
|
||
* - Other Fail
|
||
*/
|
||
int uarths_puts(const char *s);
|
||
|
||
|
||
/**
|
||
* @brief Get a byte from UART
|
||
*
|
||
* @return byte as int type from UART
|
||
*/
|
||
int uarths_getc(void);
|
||
|
||
/**
|
||
* @brief Set uarths interrupt callback
|
||
*
|
||
* @param[in] interrupt_mode Interrupt mode recevice or send
|
||
* @param[in] uarths_callback Interrupt callback
|
||
* @param[in] ctx Param of callback
|
||
* @param[in] priority Interrupt priority
|
||
*
|
||
*/
|
||
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority);
|
||
|
||
/**
|
||
* @brief Uarths receive data
|
||
*
|
||
* @param[in] buf The data received
|
||
* @param[in] buf_len The length of data
|
||
*
|
||
* @return Number of received data
|
||
*/
|
||
size_t uarths_receive_data(uint8_t *buf, size_t buf_len);
|
||
|
||
/**
|
||
* @brief Uarths receive data
|
||
*
|
||
* @param[in] buf The data sended
|
||
* @param[in] buf_len The length of data
|
||
*
|
||
* @return Number of sended data
|
||
*/
|
||
size_t uarths_send_data(const uint8_t *buf, size_t buf_len);
|
||
|
||
/**
|
||
* @brief Get interrupt mode
|
||
*
|
||
* @return Mode of interrupt
|
||
*/
|
||
uarths_interrupt_mode_t uarths_get_interrupt_mode(void);
|
||
|
||
/**
|
||
* @brief Set uarths baud rate and stopbit
|
||
*
|
||
* @param[in] baud_rate The baud rate
|
||
* @param[in] stopbit The stopbit of data
|
||
*
|
||
*/
|
||
void uarths_config(uint32_t baud_rate, uarths_stopbit_t stopbit);
|
||
|
||
/**
|
||
* @brief Set uart interrupt condition
|
||
*
|
||
* @param[in] interrupt_mode The interrupt mode
|
||
* @param[in] cnt The count of tigger
|
||
*
|
||
*/
|
||
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* _DRIVER_UARTHS_H */
|