Add uarths driver

This commit is contained in:
zhaozhongxiang 2018-10-18 15:19:40 +08:00
parent 9ed07e6918
commit 6271fd8af7
2 changed files with 163 additions and 0 deletions

View File

@ -50,6 +50,7 @@
#include <stdint.h>
#include "platform.h"
#include "plic.h"
#ifdef __cplusplus
extern "C" {
@ -170,6 +171,19 @@ typedef struct _uarths
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
{
UART_STOP_1,
UART_STOP_2
} uarths_stopbit_t;
extern volatile uarths_t *const uarths;
/**
@ -215,6 +229,61 @@ int uarths_puts(const char *s);
*/
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
}

View File

@ -21,6 +21,66 @@
volatile uarths_t *const uarths = (volatile uarths_t *)UARTHS_BASE_ADDR;
typedef struct _uarths_context
{
plic_irq_callback_t callback;
void *ctx;
uarths_interrupt_mode_t uarths_interrupt_mode;
} uarths_context_t;
uarths_context_t g_uarths_context;
uarths_interrupt_mode_t uarths_get_interrupt_mode(void)
{
uint32_t v_rx_interrupt = uarths->ip.rxwm;
uint32_t v_tx_interrupt = uarths->ip.txwm;
return (v_rx_interrupt << 1) | v_tx_interrupt;
}
int uarths_irq_callback(void *ctx)
{
uarths_context_t *uart_context = (uarths_context_t *)ctx;
if(uart_context->callback)
uart_context->callback(uart_context->ctx);
return 0;
}
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8_t cnt)
{
if(interrupt_mode == UARTHS_SEND)
uarths->txctrl.txcnt = cnt;
else
uarths->rxctrl.rxcnt = cnt;
}
void uarths_set_irq(uarths_interrupt_mode_t interrupt_mode, plic_irq_callback_t uarths_callback, void *ctx, uint32_t priority)
{
g_uarths_context.callback = uarths_callback;
g_uarths_context.ctx = ctx;
switch(interrupt_mode)
{
case UARTHS_SEND:
uarths->ie.txwm = 1;
uarths->ie.rxwm = 0;
break;
case UARTHS_RECEIVE:
uarths->ie.txwm = 0;
uarths->ie.rxwm = 1;
break;
default:
uarths->ie.txwm = 1;
uarths->ie.rxwm = 1;
break;
}
g_uarths_context.uarths_interrupt_mode = interrupt_mode;
plic_set_priority(IRQN_UARTHS_INTERRUPT, priority);
plic_irq_register(IRQN_UARTHS_INTERRUPT, uarths_irq_callback, &g_uarths_context);
plic_irq_enable(IRQN_UARTHS_INTERRUPT);
}
static inline int uarths_putc(char c)
{
while (uarths->txdata.full)
@ -30,6 +90,31 @@ static inline int uarths_putc(char c)
return 0;
}
size_t uarths_receive_data(uint8_t *buf, size_t buf_len)
{
size_t i;
for(i = 0; i < buf_len; i++)
{
uarths_rxdata_t recv = uarths->rxdata;
if(recv.empty)
break;
else
buf[i] = (recv.data & 0xFF);
}
return i;
}
size_t uarths_send_data(const uint8_t *buf, size_t buf_len)
{
size_t write = 0;
while (write < buf_len)
{
uarths_putc(*buf++);
write++;
}
return write;
}
int uarths_getc(void)
{
/* while not empty */
@ -70,3 +155,12 @@ void uarths_init(void)
uarths->ie.txwm = 0;
uarths->ie.rxwm = 1;
}
void uarths_config(uint32_t baud_rate, uarths_stopbit_t stopbit)
{
uint32_t freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
uint16_t div = freq / baud_rate - 1;
uarths->div.div = div;
uarths->txctrl.nstop = stopbit;
}