1067 lines
28 KiB
C
1067 lines
28 KiB
C
|
|
/**
|
|||
|
|
* @file hguart_v2.c
|
|||
|
|
* @author bxd
|
|||
|
|
* @brief normal uart
|
|||
|
|
* @version
|
|||
|
|
* TXW80X; TXW81X
|
|||
|
|
* @date 2023-08-02
|
|||
|
|
*
|
|||
|
|
* @copyright Copyright (c) 2023
|
|||
|
|
*
|
|||
|
|
*/
|
|||
|
|
#include "typesdef.h"
|
|||
|
|
#include "list.h"
|
|||
|
|
#include "errno.h"
|
|||
|
|
#include "dev.h"
|
|||
|
|
#include "osal/irq.h"
|
|||
|
|
#include "osal/string.h"
|
|||
|
|
#include "osal/semaphore.h"
|
|||
|
|
#include "osal/mutex.h"
|
|||
|
|
#include "hal/uart.h"
|
|||
|
|
#include "dev/uart/hguart_v2.h"
|
|||
|
|
#include "hguart_v2_hw.h"
|
|||
|
|
#include "osal/sleep.h"
|
|||
|
|
|
|||
|
|
#define UART_FLAG_TDMA_BUSY (0x1)
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**********************************************************************************/
|
|||
|
|
/* LOW LAYER FUNCTION */
|
|||
|
|
/**********************************************************************************/
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_switch_hal_uart_parity(enum uart_parity param)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
switch (param) {
|
|||
|
|
case (UART_PARITY_NONE):
|
|||
|
|
return 0;
|
|||
|
|
break;
|
|||
|
|
case (UART_PARITY_ODD):
|
|||
|
|
return 1;
|
|||
|
|
break;
|
|||
|
|
case (UART_PARITY_EVEN):
|
|||
|
|
return 2;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
return -1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_switch_hal_uart_stop_bit(enum uart_stop_bit param)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
switch (param) {
|
|||
|
|
case (UART_STOP_BIT_1):
|
|||
|
|
return 0;
|
|||
|
|
break;
|
|||
|
|
case (UART_STOP_BIT_2):
|
|||
|
|
return 1;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
return -1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_switch_hal_uart_data_bit(enum uart_data_bit param)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
switch (param) {
|
|||
|
|
case (UART_DATA_BIT_8):
|
|||
|
|
return 0;
|
|||
|
|
break;
|
|||
|
|
case (UART_DATA_BIT_9):
|
|||
|
|
return 1;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
return -1;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_set_data_bit(struct hguart_v2_hw *p_uart, enum uart_data_bit data_bit)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
int32 data_bit_to_reg = 0;
|
|||
|
|
|
|||
|
|
data_bit_to_reg = hguart_v2_switch_hal_uart_data_bit(data_bit);
|
|||
|
|
|
|||
|
|
if (((-1) == data_bit_to_reg)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (data_bit_to_reg) {
|
|||
|
|
p_uart->CON |= LL_UART_CON_BIT9_EN;
|
|||
|
|
} else {
|
|||
|
|
p_uart->CON &= ~ LL_UART_CON_BIT9_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_set_parity(struct hguart_v2_hw *p_uart, enum uart_parity parity)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
int32 parity_to_reg = 0;
|
|||
|
|
|
|||
|
|
parity_to_reg = hguart_v2_switch_hal_uart_parity(parity);
|
|||
|
|
|
|||
|
|
if (((-1) == parity_to_reg)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch (parity_to_reg) {
|
|||
|
|
case (0):
|
|||
|
|
p_uart->CON &= ~(LL_UART_CON_PARITY_EN | LL_UART_CON_ODD_EN);
|
|||
|
|
break;
|
|||
|
|
case (1):
|
|||
|
|
p_uart->CON |= LL_UART_CON_PARITY_EN | LL_UART_CON_ODD_EN;
|
|||
|
|
break;
|
|||
|
|
case (2):
|
|||
|
|
p_uart->CON = (p_uart->CON & ~(LL_UART_CON_ODD_EN)) | LL_UART_CON_PARITY_EN;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_set_stop_bit(struct hguart_v2_hw *p_uart, enum uart_stop_bit stop_bit)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
int32 stop_bit_to_reg = 0;
|
|||
|
|
|
|||
|
|
stop_bit_to_reg = hguart_v2_switch_hal_uart_stop_bit(stop_bit);
|
|||
|
|
|
|||
|
|
if (((-1) == stop_bit_to_reg)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (stop_bit_to_reg) {
|
|||
|
|
p_uart->CON |= LL_UART_CON_STOP_BIT(1);
|
|||
|
|
} else {
|
|||
|
|
p_uart->CON &= ~ LL_UART_CON_STOP_BIT(1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_set_time_out(struct hguart_v2_hw *p_uart, uint32 time_bit, uint32 enable)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
if (enable) {
|
|||
|
|
p_uart->TOCON = (p_uart->TOCON & ~ LL_UART_TOCON_TO_BIT_LEN(0xFFFF)) | LL_UART_TOCON_TO_BIT_LEN(time_bit) | LL_UART_TOCON_TO_EN;
|
|||
|
|
} else {
|
|||
|
|
p_uart->TOCON = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_set_dma(struct hguart_v2 *dev, uint32 enable)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
if (enable) {
|
|||
|
|
dev->use_dma = 1;
|
|||
|
|
} else {
|
|||
|
|
dev->use_dma = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_set_baudrate(struct hguart_v2_hw *p_uart, uint32 baudrate)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
p_uart->BAUD = (peripheral_clock_get(HG_APB0_PT_UART0) / baudrate - 1);
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_set_mode(struct hguart_v2_hw *p_uart, uint32 mode)
|
|||
|
|
{
|
|||
|
|
switch (mode) {
|
|||
|
|
case UART_MODE_DUPLEX:
|
|||
|
|
p_uart->CON &= ~ LL_UART_CON_WORK_MODE(0x3);
|
|||
|
|
p_uart->CON |= LL_UART_CON_WORK_MODE(0);
|
|||
|
|
break;
|
|||
|
|
case UART_MODE_SIMPLEX_TX:
|
|||
|
|
p_uart->CON &= ~ LL_UART_CON_WORK_MODE(0x3);
|
|||
|
|
p_uart->CON |= LL_UART_CON_WORK_MODE(1);
|
|||
|
|
break;
|
|||
|
|
case UART_MODE_SIMPLEX_RX:
|
|||
|
|
p_uart->CON &= ~ LL_UART_CON_WORK_MODE(0x3);
|
|||
|
|
p_uart->CON |= LL_UART_CON_WORK_MODE(2);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
return -ENOTSUPP;
|
|||
|
|
}
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void hguart_v2_dma_tx_config(struct hguart_v2_hw *p_uart, uint8 status)
|
|||
|
|
{
|
|||
|
|
uint32 _dmacon = p_uart->DMACON;
|
|||
|
|
|
|||
|
|
if (status) {
|
|||
|
|
_dmacon |= LL_UART_DMACON_TX_DMA_EN;
|
|||
|
|
} else {
|
|||
|
|
_dmacon &= ~ BIT(0);
|
|||
|
|
_dmacon |= BIT(8);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
p_uart->DMACON = _dmacon;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_dma_rx_config(struct hguart_v2_hw *p_uart, uint8 status)
|
|||
|
|
{
|
|||
|
|
uint32 _dmacon = p_uart->DMACON;
|
|||
|
|
|
|||
|
|
if (status) {
|
|||
|
|
_dmacon |= LL_UART_DMACON_RX_DMA_EN;
|
|||
|
|
} else {
|
|||
|
|
_dmacon &= ~ BIT(1);
|
|||
|
|
_dmacon |= BIT(9);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
p_uart->DMACON = _dmacon;
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// static int32 hguart_v2_rs485_config(struct hguart_v2_hw *p_uart, uint8 enable,
|
|||
|
|
// uint8 re_sig_active_level, uint8 de_sig_active_level,
|
|||
|
|
// uint32 de_deassertion_time, uint32 de_assertion_time,
|
|||
|
|
// uint32 de2re_turnaround_time, uint32 re2de_turnaround_time)
|
|||
|
|
// {
|
|||
|
|
// struct hguart_v2 *dev = (struct hguart_v2 *)p_uart;
|
|||
|
|
// struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
// if (enable) {
|
|||
|
|
// hw->RS485_DET = LL_UART_RS485_DET_DE_AT(de_assertion_time) | LL_UART_RS485_DET_DE_DAT(de_deassertion_time);
|
|||
|
|
// hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(de2re_turnaround_time) | LL_UART_RS485_TAT_RE2DE_T(re2de_turnaround_time);
|
|||
|
|
|
|||
|
|
// hw->RS485_CON = LL_UART_RS485_CON_DE_EN | LL_UART_RS485_CON_RE_EN | \
|
|||
|
|
// LL_UART_RS485_CON_RS485_MODE(1) | \
|
|||
|
|
// LL_UART_RS485_CON_RE_POL(re_sig_active_level)| \
|
|||
|
|
// LL_UART_RS485_CON_DE_POL(de_sig_active_level)| \
|
|||
|
|
// LL_UART_RS485_CON_RS485_EN;
|
|||
|
|
|
|||
|
|
// } else {
|
|||
|
|
// hw->RS485_CON = 0;
|
|||
|
|
// hw->RS485_DET = 0;
|
|||
|
|
// hw->RS485_TAT = 0;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// // hw->RS485_DET = LL_UART_RS485_DET_DE_AT(200) | LL_UART_RS485_DET_DE_DAT(100);
|
|||
|
|
// // hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(400) | LL_UART_RS485_TAT_RE2DE_T(300);
|
|||
|
|
// //
|
|||
|
|
// // hw->RS485_CON = LL_UART_RS485_CON_DE_EN | LL_UART_RS485_CON_RE_EN | \
|
|||
|
|
// // LL_UART_RS485_CON_RS485_MODE(1) |\
|
|||
|
|
// // LL_UART_RS485_CON_RE_POL(1)|\
|
|||
|
|
// // LL_UART_RS485_CON_DE_POL(0)|\
|
|||
|
|
// // LL_UART_RS485_CON_RS485_EN;
|
|||
|
|
|
|||
|
|
// return RET_OK;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485det_set(struct hguart_v2_hw *p_uart, uint32 de_deassertion_time, uint32 de_assertion_time)
|
|||
|
|
{
|
|||
|
|
struct hguart_v2_hw *hw = p_uart;
|
|||
|
|
|
|||
|
|
hw->RS485_DET = LL_UART_RS485_DET_DE_AT(de_assertion_time) | LL_UART_RS485_DET_DE_DAT(de_deassertion_time);
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485tat_set(struct hguart_v2_hw *p_uart, uint32 de2re_turnaround_time, uint32 re2de_turnaround_time)
|
|||
|
|
{
|
|||
|
|
struct hguart_v2_hw *hw = p_uart;
|
|||
|
|
|
|||
|
|
hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(de2re_turnaround_time) | LL_UART_RS485_TAT_RE2DE_T(re2de_turnaround_time);
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485dre_pol_set(struct hguart_v2_hw *p_uart, uint8 re_sig_active_level, uint8 de_sig_active_level)
|
|||
|
|
{
|
|||
|
|
struct hguart_v2_hw *hw = p_uart;
|
|||
|
|
|
|||
|
|
hw->RS485_CON &= ~(LL_UART_RS485_CON_RE_POL(1)|LL_UART_RS485_CON_DE_POL(1));
|
|||
|
|
|
|||
|
|
hw->RS485_CON |= LL_UART_RS485_CON_RE_POL(re_sig_active_level)| \
|
|||
|
|
LL_UART_RS485_CON_DE_POL(de_sig_active_level);
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485_en(struct hguart_v2_hw *p_uart, uint8 enable)
|
|||
|
|
{
|
|||
|
|
struct hguart_v2_hw *hw = p_uart;
|
|||
|
|
|
|||
|
|
if (enable) {
|
|||
|
|
hw->RS485_DET = LL_UART_RS485_DET_DE_AT(200) | LL_UART_RS485_DET_DE_DAT(100);
|
|||
|
|
hw->RS485_TAT = LL_UART_RS485_TAT_DE2RE_T(400) | LL_UART_RS485_TAT_RE2DE_T(300);
|
|||
|
|
hw->RS485_CON = LL_UART_RS485_CON_DE_EN | LL_UART_RS485_CON_RE_EN | \
|
|||
|
|
LL_UART_RS485_CON_RS485_MODE(1) | \
|
|||
|
|
LL_UART_RS485_CON_RE_POL(1)| \
|
|||
|
|
LL_UART_RS485_CON_DE_POL(0)| \
|
|||
|
|
LL_UART_RS485_CON_RS485_EN;
|
|||
|
|
} else {
|
|||
|
|
hw->RS485_CON = 0;
|
|||
|
|
hw->RS485_DET = 0;
|
|||
|
|
hw->RS485_TAT = 0;
|
|||
|
|
}
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_hw_control_config(struct hguart_v2_hw *p_uart, uint8 enable)
|
|||
|
|
{
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)p_uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if (enable) {
|
|||
|
|
hw->CON |= LL_UART_CON_CTS_EN | LL_UART_CON_RTS_EN;
|
|||
|
|
hw->RS485_CON = 0;
|
|||
|
|
hw->RS485_DET = 0;
|
|||
|
|
hw->RS485_TAT = 0;
|
|||
|
|
} else {
|
|||
|
|
hw->CON &= ~(LL_UART_CON_CTS_EN | LL_UART_CON_RTS_EN);
|
|||
|
|
hw->RS485_CON = 0;
|
|||
|
|
hw->RS485_DET = 0;
|
|||
|
|
hw->RS485_TAT = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**********************************************************************************/
|
|||
|
|
/* ATTCH FUNCTION */
|
|||
|
|
/**********************************************************************************/
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_open(struct uart_device *uart, uint32 baudrate)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if (dev->opened) {
|
|||
|
|
if (!dev->dsleep) {
|
|||
|
|
return -EBUSY;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ((baudrate < 0) || ((peripheral_clock_get(HG_APB0_PT_UART0) / baudrate) > 0x0003ffff)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* pin config */
|
|||
|
|
if (pin_func(dev->dev.dev.dev_id, 1) != RET_OK) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* open UART clk
|
|||
|
|
*/
|
|||
|
|
if (UART0_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart0_clk_open();
|
|||
|
|
} else if (UART1_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart1_clk_open();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* clear reg */
|
|||
|
|
hw->CON = 0;
|
|||
|
|
hw->BAUD = 0;
|
|||
|
|
hw->STA = 0xFFFFFFFF;
|
|||
|
|
hw->DMACON = 0;
|
|||
|
|
hw->DMASTA = 0xFFFFFFFF;
|
|||
|
|
hw->RSTADR = 0;
|
|||
|
|
hw->TSTADR = 0;
|
|||
|
|
hw->RDMALEN = 0;
|
|||
|
|
hw->TDMALEN = 0;
|
|||
|
|
hw->TOCON = 0;
|
|||
|
|
hw->RS485_CON = 0;
|
|||
|
|
hw->RS485_DET = 0;
|
|||
|
|
hw->RS485_TAT = 0;
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* reg config */
|
|||
|
|
#ifndef FPGA_SUPPORT
|
|||
|
|
hw->BAUD = (peripheral_clock_get(HG_APB0_PT_UART0) / baudrate) - 1;
|
|||
|
|
#else
|
|||
|
|
hw->BAUD = (96000000 / baudrate) - 1;
|
|||
|
|
#endif
|
|||
|
|
hw->CON = 0x1; /* Default config: 8bit + 1 stop_bit + no parity + duplex mode */
|
|||
|
|
|
|||
|
|
dev->opened = 1;
|
|||
|
|
dev->dsleep = 0;
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_close(struct uart_device *uart)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if (!dev->opened) {
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* close UART clk
|
|||
|
|
*/
|
|||
|
|
if (UART0_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart0_clk_close();
|
|||
|
|
} else if (UART1_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart1_clk_close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
hw->CON &= ~0x1;
|
|||
|
|
irq_disable(dev->irq_num);
|
|||
|
|
pin_func(dev->dev.dev.dev_id, 0);
|
|||
|
|
|
|||
|
|
dev->opened = 0;
|
|||
|
|
dev->dsleep = 0;
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485_de_set(struct hguart_v2_hw *p_uart)
|
|||
|
|
{
|
|||
|
|
if(PIN_UART0_DE != 255) {
|
|||
|
|
ll_uart485_de_enable(p_uart);
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485_de_reset(struct hguart_v2_hw *p_uart)
|
|||
|
|
{
|
|||
|
|
if(PIN_UART0_DE != 255) {
|
|||
|
|
ll_uart485_de_disable(p_uart);
|
|||
|
|
return RET_OK;
|
|||
|
|
// p_uart->RS485_CON &= (~LL_UART_RS485_CON_DE_EN);
|
|||
|
|
}
|
|||
|
|
// os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485_re_set(struct hguart_v2_hw *p_uart)
|
|||
|
|
{
|
|||
|
|
if(PIN_UART4_RE != 255) {
|
|||
|
|
ll_uart485_re_enable(p_uart);
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_rs485_re_reset(struct hguart_v2_hw *p_uart)
|
|||
|
|
{
|
|||
|
|
if(PIN_UART4_RE != 255) {
|
|||
|
|
ll_uart485_re_disable(p_uart);
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_putc(struct uart_device *uart, int8 value)
|
|||
|
|
{
|
|||
|
|
uint8 rs485_en_flag = 0;
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if (dev->opened && (hw->CON & LL_UART_CON_UART_EN) && (!dev->dsleep)) {
|
|||
|
|
if (hw->RS485_CON & LL_UART_RS485_CON_RS485_EN) {
|
|||
|
|
hguart_v2_rs485_en(hw, 0);
|
|||
|
|
rs485_en_flag = 1;
|
|||
|
|
}
|
|||
|
|
while (!(hw->STA & LL_UART_STA_TX_BUF_EMPTY));
|
|||
|
|
hw->DATA = value;
|
|||
|
|
if(rs485_en_flag) {
|
|||
|
|
rs485_en_flag = 0;
|
|||
|
|
hguart_v2_rs485_en(hw, 1);
|
|||
|
|
}
|
|||
|
|
return RET_OK;
|
|||
|
|
} else {
|
|||
|
|
return -EIO;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static uint8 hguart_v2_getc(struct uart_device *uart)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if (dev->opened && (hw->CON & LL_UART_CON_UART_EN) && (!dev->dsleep)) {
|
|||
|
|
while (!(hw->STA & LL_UART_STA_RX_BUF_NOT_EMPTY));
|
|||
|
|
}
|
|||
|
|
return hw->DATA;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_puts(struct uart_device *uart, uint8 *buf, uint32 len)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
int32 i = 0;
|
|||
|
|
uint32_t irq_flag;
|
|||
|
|
|
|||
|
|
if ((!dev->opened) || (dev->dsleep)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(hw->RS485_CON & LL_UART_RS485_CON_RS485_EN) {
|
|||
|
|
hguart_v2_rs485_de_set(hw);
|
|||
|
|
hguart_v2_rs485_re_set(hw);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (((__PSRAM_ADDR_START <= (uint32)buf)) && (((uint32)buf) <= __PSRAM_ADDR_END)) {
|
|||
|
|
for (i = 0; i < len; i++) {
|
|||
|
|
hguart_v2_putc(uart, buf[i]);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
if (dev->use_dma) {
|
|||
|
|
irq_flag = disable_irq();
|
|||
|
|
/* Clear the former configuration */
|
|||
|
|
hguart_v2_dma_tx_config(hw, 0);
|
|||
|
|
|
|||
|
|
/* clear the tx dma done pending before tx kick */
|
|||
|
|
hw->DMASTA = BIT(0);
|
|||
|
|
|
|||
|
|
hw->TSTADR = (uint32)buf;
|
|||
|
|
hw->TDMALEN = len;
|
|||
|
|
|
|||
|
|
hguart_v2_dma_tx_config(hw, 1);
|
|||
|
|
dev->flag |= UART_FLAG_TDMA_BUSY;
|
|||
|
|
enable_irq(irq_flag);
|
|||
|
|
|
|||
|
|
|
|||
|
|
//TDMA_IE_EN会造成两种情况
|
|||
|
|
if ((hw->DMACON & LL_UART_DMACON_TX_DMA_IE_EN)
|
|||
|
|
&& (!irq_flag)) {
|
|||
|
|
while(dev->flag & UART_FLAG_TDMA_BUSY);
|
|||
|
|
} else {
|
|||
|
|
while (!(hw->DMASTA & LL_UART_DMASTA_TX_DMA_PEND)) {
|
|||
|
|
//休眠唤醒后pending位被清零了, 防卡死
|
|||
|
|
if(!hw->TDMALEN) {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
for (i = 0; i < len; i++) {
|
|||
|
|
hguart_v2_putc(uart, buf[i]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(hw->RS485_CON & LL_UART_RS485_CON_RS485_EN) {
|
|||
|
|
hguart_v2_rs485_de_reset(hw);
|
|||
|
|
hguart_v2_rs485_re_reset(hw);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
irq_flag = disable_irq();
|
|||
|
|
dev->flag &= ~UART_FLAG_TDMA_BUSY;
|
|||
|
|
enable_irq(irq_flag);
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_gets(struct uart_device *uart, uint8 *buf, uint32 len)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
int32 i = 0;
|
|||
|
|
|
|||
|
|
if ((!dev->opened) || (dev->dsleep)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (((__PSRAM_ADDR_START <= (uint32)buf)) && (((uint32)buf) <= __PSRAM_ADDR_END)) {
|
|||
|
|
for (i = 0; i < len; i++) {
|
|||
|
|
buf[i] = hguart_v2_getc(uart);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return i;
|
|||
|
|
} else {
|
|||
|
|
if (dev->use_dma) {
|
|||
|
|
/* Clear the former configuration */
|
|||
|
|
hguart_v2_dma_rx_config(hw, 0);
|
|||
|
|
|
|||
|
|
hw->STA = BIT(1);
|
|||
|
|
hw->RSTADR = (uint32)buf;
|
|||
|
|
hw->RDMALEN = len;
|
|||
|
|
|
|||
|
|
hguart_v2_dma_rx_config(hw, 1);
|
|||
|
|
return RET_OK;
|
|||
|
|
} else {
|
|||
|
|
for (i = 0; i < len; i++) {
|
|||
|
|
buf[i] = hguart_v2_getc(uart);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return i;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
struct uart_testS {
|
|||
|
|
struct uart_device *uart;
|
|||
|
|
uint8_t *buf;
|
|||
|
|
int len;
|
|||
|
|
int id;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
static int32 uart_test_irqhdl(uint32 irq_flag, uint32 irq_data, uint32 param1, uint32 param2)
|
|||
|
|
{
|
|||
|
|
struct uart_testS *tuart = (struct uart_testS *)irq_data;
|
|||
|
|
int32 ret = 0;
|
|||
|
|
switch (irq_flag) {
|
|||
|
|
case UART_IRQ_FLAG_DMA_RX_DONE: // maybe overbuff?
|
|||
|
|
case UART_IRQ_FLAG_TIME_OUT:
|
|||
|
|
if (tuart->id == 1) {
|
|||
|
|
if (memcmp(tuart->buf, "uart5 msg", 9) != 0) {
|
|||
|
|
os_printf("uart1 recv lp err\r\n");
|
|||
|
|
}
|
|||
|
|
} else if (tuart->id == 5) {
|
|||
|
|
if (memcmp(tuart->buf, "uart1 msg", 9) != 0) {
|
|||
|
|
os_printf("uart5 recv lp err\r\n");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
tuart->buf[param1] = 0;
|
|||
|
|
os_printf("id = %d, recv: %s\r\n", tuart->id, tuart->buf);
|
|||
|
|
uart_gets(tuart->uart, tuart->buf, tuart->len);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void uart_sleep_test()
|
|||
|
|
{
|
|||
|
|
uint8_t *uart1_buf = os_malloc(32);
|
|||
|
|
uint8_t *uart5_buf = os_malloc(32);
|
|||
|
|
struct uart_device *uart1 = (void *)dev_get(1+1);
|
|||
|
|
struct uart_device *uart5 = (void *)dev_get(1+5);
|
|||
|
|
|
|||
|
|
uint8_t uart1_msg[] = "uart1 msg\r\n";
|
|||
|
|
//uint8_t uart5_msg[] = "uart5 msg\r\n";
|
|||
|
|
struct uart_testS uart1ts = {
|
|||
|
|
.uart = uart1,
|
|||
|
|
.buf = uart1_buf,
|
|||
|
|
.len = 32,
|
|||
|
|
.id = 1,
|
|||
|
|
};
|
|||
|
|
struct uart_testS uart5ts = {
|
|||
|
|
.uart = uart5,
|
|||
|
|
.buf = uart5_buf,
|
|||
|
|
.len = 32,
|
|||
|
|
.id = 5,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
uart_open(uart1, 921600);
|
|||
|
|
uart_open(uart5, 921600);
|
|||
|
|
|
|||
|
|
uart_ioctl(uart1, UART_IOCTL_CMD_USE_DMA, 1, 0);
|
|||
|
|
uart_ioctl(uart5, UART_IOCTL_CMD_USE_DMA, 1, 0);
|
|||
|
|
uart_ioctl(uart1, UART_IOCTL_CMD_SET_TIME_OUT, 40, 1);
|
|||
|
|
uart_ioctl(uart5, UART_IOCTL_CMD_SET_TIME_OUT, 40, 1);
|
|||
|
|
|
|||
|
|
uart_request_irq(uart1, uart_test_irqhdl,
|
|||
|
|
UART_IRQ_FLAG_DMA_RX_DONE | UART_IRQ_FLAG_TIME_OUT, (uint32)&uart1ts);
|
|||
|
|
// uart_request_irq(uart1, uart_test_irqhdl,
|
|||
|
|
// UART_IRQ_FLAG_DMA_RX_DONE, (uint32)&uart1ts);
|
|||
|
|
uart_request_irq(uart5, uart_test_irqhdl,
|
|||
|
|
UART_IRQ_FLAG_DMA_RX_DONE | UART_IRQ_FLAG_TIME_OUT, (uint32)&uart5ts);
|
|||
|
|
uart_gets(uart1, uart1_buf, 32);
|
|||
|
|
uart_gets(uart5, uart5_buf, 32);
|
|||
|
|
while(1)
|
|||
|
|
{
|
|||
|
|
// uart_puts(uart5, uart5_msg, os_strlen((const char *)uart5_msg));
|
|||
|
|
|
|||
|
|
uart_puts(uart1, uart1_msg, os_strlen((const char *)uart1_msg));
|
|||
|
|
|
|||
|
|
os_sleep_ms(1000);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#ifdef CONFIG_SLEEP
|
|||
|
|
int32 hguart_v2_suspend(struct dev_obj *obj)
|
|||
|
|
{
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)obj;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if ((!dev->opened) || (dev->dsleep)) {
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uint32_t disable = disable_irq();
|
|||
|
|
enable_irq(disable);
|
|||
|
|
|
|||
|
|
while(dev->flag & UART_FLAG_TDMA_BUSY);
|
|||
|
|
hw->TDMALEN = 0;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* save the reglist
|
|||
|
|
*/
|
|||
|
|
dev->bp_regs.con = hw->CON;
|
|||
|
|
dev->bp_regs.baud = hw->BAUD;
|
|||
|
|
dev->bp_regs.tstadr = hw->TSTADR|0x20000000;
|
|||
|
|
dev->bp_regs.rstadr = hw->RSTADR|0x20000000;
|
|||
|
|
dev->bp_regs.tdmalen = hw->TDMALEN;
|
|||
|
|
dev->bp_regs.rdmalen = hw->RDMALEN;
|
|||
|
|
dev->bp_regs.dmacon = hw->DMACON;
|
|||
|
|
dev->bp_regs.rs485_con = hw->RS485_CON;
|
|||
|
|
dev->bp_regs.rs485_det = hw->RS485_DET;
|
|||
|
|
dev->bp_regs.rs485_tat = hw->RS485_TAT;
|
|||
|
|
dev->bp_regs.tocon = hw->TOCON;
|
|||
|
|
|
|||
|
|
/*!
|
|||
|
|
* Close the UART
|
|||
|
|
*/
|
|||
|
|
hw->DMACON = 0x300; //disable dma
|
|||
|
|
hw->CON &= ~ BIT(0);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// pin_func(dev->dev.dev.dev_id, 0);
|
|||
|
|
irq_disable(dev->irq_num);
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* clear pending
|
|||
|
|
*/
|
|||
|
|
hw->DMASTA = 0xFFFFFFFF;
|
|||
|
|
hw->STA = 0xFFFFFFFF;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* clear the data in the UART fifo
|
|||
|
|
*/
|
|||
|
|
do {
|
|||
|
|
hw->DATA;
|
|||
|
|
} while (hw->STA & LL_UART_STA_RX_CNT(0x7));
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (UART0_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart0_clk_close();
|
|||
|
|
} else if (UART1_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart1_clk_close();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dev->dsleep = 1;
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int32 hguart_v2_resume(struct dev_obj *obj)
|
|||
|
|
{
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)obj;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
if ((!dev->opened) || (!dev->dsleep)) {
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* pin config */
|
|||
|
|
if (pin_func(dev->dev.dev.dev_id, 1) != RET_OK) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (UART0_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart0_clk_open();
|
|||
|
|
} else if (UART1_BASE == (uint32)hw) {
|
|||
|
|
sysctrl_uart1_clk_open();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* clear pending
|
|||
|
|
*/
|
|||
|
|
hw->DMASTA = 0xFFFFFFFF;
|
|||
|
|
hw->STA = 0xFFFFFFFF;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* recovery the reglist from sram
|
|||
|
|
*/
|
|||
|
|
hw->CON = dev->bp_regs.con;
|
|||
|
|
hw->BAUD = dev->bp_regs.baud;
|
|||
|
|
hw->TSTADR = dev->bp_regs.tstadr;
|
|||
|
|
hw->RSTADR = dev->bp_regs.rstadr;
|
|||
|
|
hw->TDMALEN = dev->bp_regs.tdmalen;
|
|||
|
|
hw->RDMALEN = dev->bp_regs.rdmalen;
|
|||
|
|
hw->DMACON = dev->bp_regs.dmacon;
|
|||
|
|
hw->RS485_CON = dev->bp_regs.rs485_con;
|
|||
|
|
hw->RS485_DET = dev->bp_regs.rs485_det;
|
|||
|
|
hw->RS485_TAT = dev->bp_regs.rs485_tat;
|
|||
|
|
hw->TOCON = dev->bp_regs.tocon;
|
|||
|
|
|
|||
|
|
/*!
|
|||
|
|
* Open the UART
|
|||
|
|
*/
|
|||
|
|
hw->CON |= BIT(0);
|
|||
|
|
if (dev->bp_regs.dmacon & LL_UART_DMACON_RX_DMA_EN)
|
|||
|
|
hguart_v2_dma_rx_config(hw, 1);
|
|||
|
|
|
|||
|
|
irq_enable(dev->irq_num);
|
|||
|
|
|
|||
|
|
dev->dsleep = 0;
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
#else
|
|||
|
|
int32 hguart_v2_suspend(struct dev_obj *obj)
|
|||
|
|
{
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
int32 hguart_v2_resume(struct dev_obj *obj)
|
|||
|
|
{
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_ioctl(struct uart_device *uart, enum uart_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
int32 ret_val = RET_OK;
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if ((!dev->opened) || (dev->dsleep)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch (ioctl_cmd) {
|
|||
|
|
case (UART_IOCTL_CMD_SET_BAUDRATE):
|
|||
|
|
ret_val = hguart_v2_set_baudrate(hw, param1);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_DATA_BIT):
|
|||
|
|
ret_val = hguart_v2_set_data_bit(hw, param1);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_PARITY):
|
|||
|
|
ret_val = hguart_v2_set_parity(hw, param1);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_STOP_BIT):
|
|||
|
|
ret_val = hguart_v2_set_stop_bit(hw, param1);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_TIME_OUT):
|
|||
|
|
ret_val = hguart_v2_set_time_out(hw, param1, param2);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_USE_DMA):
|
|||
|
|
ret_val = hguart_v2_set_dma(dev, param1);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_WORK_MODE):
|
|||
|
|
ret_val = hguart_v2_set_mode(hw, param1);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_RS485_EN):
|
|||
|
|
ret_val = hguart_v2_rs485_en(hw, param1);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_RS485_DET):
|
|||
|
|
ret_val = hguart_v2_rs485det_set(hw, param1, param2);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_RS485_TAT):
|
|||
|
|
ret_val = hguart_v2_rs485tat_set(hw, param1, param2);
|
|||
|
|
break;
|
|||
|
|
case (UART_IOCTL_CMD_SET_RS485DRE_POL):
|
|||
|
|
ret_val = hguart_v2_rs485dre_pol_set(hw, param1, param2);
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
ret_val = -ENOTSUPP;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ret_val;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void hguart_v2_irq_handler(void *data)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)data;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
static uint8 rec_data_len[2] = {0};
|
|||
|
|
|
|||
|
|
/*------Time out interrupt-----*/
|
|||
|
|
if ((hw->TOCON & LL_UART_TOCON_TO_IE_EN) &&
|
|||
|
|
(hw->STA & LL_UART_STA_TO_PEND)) {
|
|||
|
|
hw->STA = LL_UART_STA_TO_PEND;
|
|||
|
|
|
|||
|
|
if (dev->irq_hdl) {
|
|||
|
|
rec_data_len[1] = hw->RDMACNT >> 8;
|
|||
|
|
rec_data_len[0] = hw->RDMACNT;
|
|||
|
|
dev->irq_hdl(UART_IRQ_FLAG_TIME_OUT, dev->irq_data, hw->RDMACNT, 0);
|
|||
|
|
if((PIN_UART0_DE != 255) && (PIN_UART0_RE != 255)) {
|
|||
|
|
uart_puts((struct uart_device *)dev, rec_data_len, sizeof(rec_data_len));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*------Frame erro interrupt-----*/
|
|||
|
|
if ((hw->CON & LL_UART_CON_FERR_IE_EN) &&
|
|||
|
|
(hw->STA & LL_UART_STA_FERR_PENDING)) {
|
|||
|
|
hw->STA = LL_UART_STA_FERR_PENDING;
|
|||
|
|
|
|||
|
|
if (dev->irq_hdl) {
|
|||
|
|
dev->irq_hdl(UART_IRQ_FLAG_FRAME_ERR, dev->irq_data, 0, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*------TX complete interrupt-----*/
|
|||
|
|
if ((hw->CON & LL_UART_CON_TCIE_EN) &&
|
|||
|
|
(hw->STA & LL_UART_STA_TC_PENDING)) {
|
|||
|
|
hw->STA = LL_UART_STA_TC_PENDING;
|
|||
|
|
|
|||
|
|
if (dev->irq_hdl) {
|
|||
|
|
dev->irq_hdl(UART_IRQ_FLAG_TX_BYTE, dev->irq_data, 0, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*------RX_DMA_INTERRUPT-----*/
|
|||
|
|
if ((hw->DMACON & LL_UART_DMACON_RX_DMA_IE_EN) &&
|
|||
|
|
(hw->DMASTA & LL_UART_DMASTA_RX_DMA_PEND)) {
|
|||
|
|
hw->DMASTA = LL_UART_DMASTA_RX_DMA_PEND;
|
|||
|
|
|
|||
|
|
if (dev->irq_hdl) {
|
|||
|
|
dev->irq_hdl(UART_IRQ_FLAG_DMA_RX_DONE, dev->irq_data, hw->RDMACNT, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*------TX_DMA_INTERRUPT-----*/
|
|||
|
|
if ((hw->DMACON & LL_UART_DMACON_TX_DMA_IE_EN) &&
|
|||
|
|
(hw->DMASTA & LL_UART_DMASTA_TX_DMA_PEND)) {
|
|||
|
|
hw->DMASTA = LL_UART_DMASTA_TX_DMA_PEND;
|
|||
|
|
dev->flag &= ~UART_FLAG_TDMA_BUSY;
|
|||
|
|
|
|||
|
|
if (dev->irq_hdl) {
|
|||
|
|
dev->irq_hdl(UART_IRQ_FLAG_DMA_TX_DONE, dev->irq_data, hw->TDMACNT, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*------RX buf not empty interrupt-----*/
|
|||
|
|
if ((hw->CON & LL_UART_CON_RXBUF_NEMPTY_IE_EN) &&
|
|||
|
|
(hw->STA & LL_UART_STA_RX_BUF_NOT_EMPTY)) {
|
|||
|
|
|
|||
|
|
if (dev->irq_hdl) {
|
|||
|
|
dev->irq_hdl(UART_IRQ_FLAG_RX_BYTE, dev->irq_data, hw->DATA, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_request_irq(struct uart_device *uart, uart_irq_hdl irq_hdl, uint32 irq_flag, uint32 irq_data)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if ((!dev->opened) || (dev->dsleep)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dev->irq_hdl = irq_hdl;
|
|||
|
|
dev->irq_data = irq_data;
|
|||
|
|
request_irq(dev->irq_num, hguart_v2_irq_handler, dev);
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_TX_BYTE) {
|
|||
|
|
hw->CON |= LL_UART_CON_TCIE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_TIME_OUT) {
|
|||
|
|
hw->TOCON |= LL_UART_TOCON_TO_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_DMA_TX_DONE) {
|
|||
|
|
hw->DMACON |= LL_UART_DMACON_TX_DMA_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_DMA_RX_DONE) {
|
|||
|
|
hw->DMACON |= LL_UART_DMACON_RX_DMA_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_FRAME_ERR) {
|
|||
|
|
hw->CON |= LL_UART_CON_FERR_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_RX_BYTE) {
|
|||
|
|
hw->CON |= LL_UART_CON_RXBUF_NEMPTY_IE_EN;
|
|||
|
|
}
|
|||
|
|
irq_enable(dev->irq_num);
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static int32 hguart_v2_release_irq(struct uart_device *uart, uint32 irq_flag)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
struct hguart_v2 *dev = (struct hguart_v2 *)uart;
|
|||
|
|
struct hguart_v2_hw *hw = (struct hguart_v2_hw *)dev->hw;
|
|||
|
|
|
|||
|
|
if ((!dev->opened) || (dev->dsleep)) {
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_TX_BYTE) {
|
|||
|
|
hw->CON &= ~ LL_UART_CON_TCIE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_TIME_OUT) {
|
|||
|
|
hw->TOCON &= ~ LL_UART_TOCON_TO_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_DMA_TX_DONE) {
|
|||
|
|
hw->DMACON &= ~ LL_UART_DMACON_TX_DMA_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_DMA_RX_DONE) {
|
|||
|
|
hw->DMACON &= ~ LL_UART_DMACON_RX_DMA_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_FRAME_ERR) {
|
|||
|
|
hw->CON &= ~ LL_UART_CON_FERR_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (irq_flag & UART_IRQ_FLAG_RX_BYTE) {
|
|||
|
|
hw->CON &= ~ LL_UART_CON_RXBUF_NEMPTY_IE_EN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
static const struct uart_hal_ops uart_v2_ops = {
|
|||
|
|
.open = hguart_v2_open,
|
|||
|
|
.close = hguart_v2_close,
|
|||
|
|
.putc = hguart_v2_putc,
|
|||
|
|
.getc = hguart_v2_getc,
|
|||
|
|
.puts = hguart_v2_puts,
|
|||
|
|
.gets = hguart_v2_gets,
|
|||
|
|
.ioctl = hguart_v2_ioctl,
|
|||
|
|
.request_irq = hguart_v2_request_irq,
|
|||
|
|
.release_irq = hguart_v2_release_irq,
|
|||
|
|
#ifdef CONFIG_SLEEP
|
|||
|
|
.ops.suspend = NULL,//hguart_v2_suspend,
|
|||
|
|
.ops.resume = NULL,//hguart_v2_resume,
|
|||
|
|
#endif
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
int32 hguart_v2_attach(uint32 dev_id, struct hguart_v2 *uart)
|
|||
|
|
{
|
|||
|
|
uart->opened = 0;
|
|||
|
|
uart->dsleep = 0;
|
|||
|
|
uart->use_dma = 0;
|
|||
|
|
uart->irq_hdl = NULL;
|
|||
|
|
uart->irq_data = 0;
|
|||
|
|
uart->flag = 0;
|
|||
|
|
uart->dev.dev.ops = (const struct devobj_ops *)&uart_v2_ops;
|
|||
|
|
#ifdef CONFIG_SLEEP
|
|||
|
|
|
|||
|
|
|
|||
|
|
#endif
|
|||
|
|
irq_disable(uart->irq_num);
|
|||
|
|
dev_register(dev_id, (struct dev_obj *)uart);
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|