Add uarths driver
This commit is contained in:
parent
9ed07e6918
commit
6271fd8af7
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue