1751 lines
43 KiB
C
1751 lines
43 KiB
C
// Copyright 2020-2021 Beken
|
|
//
|
|
// 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.
|
|
|
|
#include <common/bk_include.h>
|
|
#include <common/bk_compiler.h>
|
|
#include <os/mem.h>
|
|
#include "uart_driver.h"
|
|
#include "uart_hal.h"
|
|
#include <driver/uart.h>
|
|
#include "bk_uart.h"
|
|
#include "gpio_driver.h"
|
|
#include <driver/gpio.h>
|
|
#include "bk_fifo.h"
|
|
#include <os/os.h>
|
|
#include "uart_statis.h"
|
|
#include <driver/int.h>
|
|
#include "icu_driver.h"
|
|
#include "power_driver.h"
|
|
#include "clock_driver.h"
|
|
#include <os/os.h>
|
|
#include "bk_arch.h"
|
|
#include <components/system.h>
|
|
#if (CONFIG_SYSTEM_CTRL)
|
|
#include "sys_driver.h"
|
|
#include <modules/pm.h>
|
|
#endif
|
|
#if (CONFIG_UART_RX_DMA || CONFIG_UART_TX_DMA)
|
|
#include <driver/dma.h>
|
|
#endif
|
|
#if CONFIG_SPE
|
|
#include "security.h"
|
|
#endif
|
|
|
|
static void uart_isr_common(uart_id_t id) __BK_SECTION(".itcm");
|
|
static uint32_t uart_id_read_fifo_frame(uart_id_t id, const kfifo_ptr_t rx_ptr) __BK_SECTION(".itcm");
|
|
|
|
typedef struct {
|
|
uart_hal_t hal;
|
|
uint8_t id_init_bits;
|
|
uint8_t id_sw_fifo_enable_bits;
|
|
#if CONFIG_UART_PM_CB_SUPPORT
|
|
uint32_t pm_backup[UART_PM_BACKUP_REG_NUM];
|
|
uint8_t pm_bakeup_is_valid;
|
|
#endif
|
|
/*
|
|
* !!! WARNING !!! !!! WARNING !!!
|
|
* If APP wants to set rx_dma_en, please enable macro of CONFIG_UART_RX_DMA.
|
|
*
|
|
* Struct forces enable this elem(not controlled by CONFIG_UART_RX_DMA).
|
|
* When build libs(the lib function calls this struct) it does not enable the macro of CONFIG_UART_RX_DMA,
|
|
* but build UART Driver codes, it enables the macro of CONFIG_UART_RX_DMA.
|
|
* Then the lib function call UART DRIVER hasn't set param of rx_dma_en, but UART driver API
|
|
* init function will check this item and maybe set RX dma enable.
|
|
* If defined these elems, the value will be 0 if APP not set it.
|
|
*/
|
|
#if 1
|
|
bool rx_dma_enable;
|
|
dma_id_t rx_dma_id;
|
|
bool tx_dma_enable;
|
|
dma_id_t tx_dma_id;
|
|
#endif
|
|
} uart_driver_t;
|
|
|
|
typedef struct {
|
|
bool rx_blocked;
|
|
beken_semaphore_t rx_int_sema;
|
|
} uart_sema_t;
|
|
|
|
typedef struct
|
|
{
|
|
uart_isr_t callback;
|
|
void *param;
|
|
} uart_callback_t;
|
|
|
|
#define CONFIG_UART_MIN_BAUD_RATE (UART_CLOCK / (0x1fff + 1))
|
|
#define CONFIG_UART_MAX_BAUD_RATE (UART_CLOCK / (4 + 1))
|
|
#ifndef CONFIG_PRINTF_BUF_SIZE
|
|
#define CONFIG_PRINTF_BUF_SIZE (128)
|
|
#endif
|
|
|
|
static uart_driver_t s_uart[SOC_UART_ID_NUM_PER_UNIT] = {
|
|
{
|
|
.hal.hw = (uart_hw_t *)SOC_UART0_REG_BASE,
|
|
},
|
|
{
|
|
.hal.hw = (uart_hw_t *)SOC_UART1_REG_BASE,
|
|
},
|
|
#if (SOC_UART_ID_NUM_PER_UNIT > 2)
|
|
{
|
|
.hal.hw = (uart_hw_t *)SOC_UART2_REG_BASE,
|
|
},
|
|
#endif
|
|
};
|
|
static bool s_uart_driver_is_init = false;
|
|
static uart_callback_t s_uart_rx_isr[SOC_UART_ID_NUM_PER_UNIT] = {NULL};
|
|
static uart_callback_t s_uart_tx_isr[SOC_UART_ID_NUM_PER_UNIT] = {NULL};
|
|
static kfifo_ptr_t s_uart_rx_kfifo[SOC_UART_ID_NUM_PER_UNIT] = {NULL};
|
|
static uart_sema_t s_uart_sema[SOC_UART_ID_NUM_PER_UNIT] = {0};
|
|
|
|
#define UART_RETURN_ON_NOT_INIT() do {\
|
|
if (!s_uart_driver_is_init) {\
|
|
return BK_ERR_UART_NOT_INIT;\
|
|
}\
|
|
} while(0)
|
|
|
|
#define UART_RETURN_ON_INVALID_ID(id) do {\
|
|
if ((id) >= SOC_UART_ID_NUM_PER_UNIT) {\
|
|
return BK_ERR_UART_INVALID_ID;\
|
|
}\
|
|
} while(0)
|
|
|
|
#define UART_RETURN_ON_ID_NOT_INIT(id) do {\
|
|
if (!(s_uart[id].id_init_bits & BIT((id)))) {\
|
|
return BK_ERR_UART_ID_NOT_INIT;\
|
|
}\
|
|
} while(0)
|
|
|
|
#define UART_RETURN_ON_BAUD_RATE_NOT_SUPPORT(baud_rate) do {\
|
|
if ((baud_rate) < CONFIG_UART_MIN_BAUD_RATE ||\
|
|
(baud_rate) > CONFIG_UART_MAX_BAUD_RATE) {\
|
|
return BK_ERR_UART_BAUD_RATE_NOT_SUPPORT;\
|
|
}\
|
|
} while(0)
|
|
|
|
#if CONFIG_UART_PM_CB_SUPPORT
|
|
#define UART_PM_CHECK_RESTORE(id) do {\
|
|
GLOBAL_INT_DECLARATION();\
|
|
GLOBAL_INT_DISABLE();\
|
|
switch (id) {\
|
|
case UART_ID_0:\
|
|
break;\
|
|
case UART_ID_1:\
|
|
if (bk_pm_module_lv_sleep_state_get(PM_DEV_ID_UART2)) {\
|
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_UART1, PM_POWER_MODULE_STATE_ON);\
|
|
uart_pm_restore(0, (void *)id);\
|
|
bk_pm_module_lv_sleep_state_clear(PM_DEV_ID_UART2);\
|
|
}\
|
|
break;\
|
|
case UART_ID_2:\
|
|
if (bk_pm_module_lv_sleep_state_get(PM_DEV_ID_UART3)) {\
|
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_UART2, PM_POWER_MODULE_STATE_ON);\
|
|
uart_pm_restore(0, (void *)id);\
|
|
bk_pm_module_lv_sleep_state_clear(PM_DEV_ID_UART3);\
|
|
}\
|
|
break;\
|
|
default:\
|
|
break;\
|
|
}\
|
|
GLOBAL_INT_RESTORE();\
|
|
} while(0)
|
|
#else
|
|
#define UART_PM_CHECK_RESTORE(id)
|
|
#endif
|
|
|
|
#if CONFIG_SPE
|
|
#define UART_CHECK_SECURE(id) do {\
|
|
switch (id) {\
|
|
case UART_ID_0:\
|
|
BK_ASSERT(DEV_IS_SECURE(UART0) == 1);\
|
|
break;\
|
|
case UART_ID_1:\
|
|
BK_ASSERT(DEV_IS_SECURE(UART1) == 1);\
|
|
break;\
|
|
case UART_ID_2:\
|
|
BK_ASSERT(DEV_IS_SECURE(UART2) == 1);\
|
|
break;\
|
|
default:\
|
|
break;\
|
|
}\
|
|
} while(0)
|
|
#else
|
|
#define UART_CHECK_SECURE(id)
|
|
#endif
|
|
|
|
#if (CONFIG_DEBUG_FIRMWARE)
|
|
#define DEAD_WHILE() do{\
|
|
while(1);\
|
|
} while(0)
|
|
#else
|
|
#define DEAD_WHILE() do{\
|
|
os_printf("dead\r\n");\
|
|
} while(0)
|
|
#endif
|
|
|
|
#if (CONFIG_SYSTEM_CTRL)
|
|
void uart_clock_enable(uart_id_t id)
|
|
{
|
|
switch(id)
|
|
{
|
|
case UART_ID_0:
|
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_UART1, CLK_PWR_CTRL_PWR_UP);
|
|
break;
|
|
case UART_ID_1:
|
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_UART2, CLK_PWR_CTRL_PWR_UP);
|
|
break;
|
|
case UART_ID_2:
|
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_UART3, CLK_PWR_CTRL_PWR_UP);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void uart_clock_disable(uart_id_t id)
|
|
{
|
|
switch(id)
|
|
{
|
|
case UART_ID_0:
|
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_UART1, CLK_PWR_CTRL_PWR_DOWN);
|
|
break;
|
|
case UART_ID_1:
|
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_UART2, CLK_PWR_CTRL_PWR_DOWN);
|
|
break;
|
|
case UART_ID_2:
|
|
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_UART3, CLK_PWR_CTRL_PWR_DOWN);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void uart_interrupt_enable(uart_id_t id)
|
|
{
|
|
switch(id)
|
|
{
|
|
case UART_ID_0:
|
|
sys_drv_int_enable(UART0_INTERRUPT_CTRL_BIT);
|
|
break;
|
|
case UART_ID_1:
|
|
sys_drv_int_enable(UART1_INTERRUPT_CTRL_BIT);
|
|
break;
|
|
case UART_ID_2:
|
|
sys_drv_int_enable(UART2_INTERRUPT_CTRL_BIT);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void uart_interrupt_disable(uart_id_t id)
|
|
{
|
|
switch(id)
|
|
{
|
|
case UART_ID_0:
|
|
sys_drv_int_disable(UART0_INTERRUPT_CTRL_BIT);
|
|
break;
|
|
case UART_ID_1:
|
|
sys_drv_int_disable(UART1_INTERRUPT_CTRL_BIT);
|
|
break;
|
|
case UART_ID_2:
|
|
sys_drv_int_disable(UART2_INTERRUPT_CTRL_BIT);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void uart_init_gpio(uart_id_t id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case UART_ID_0:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_tx_pin(id));
|
|
gpio_dev_unmap(uart_hal_get_rx_pin(id));
|
|
gpio_dev_map(uart_hal_get_tx_pin(id), GPIO_DEV_UART1_TXD);
|
|
gpio_dev_map(uart_hal_get_rx_pin(id), GPIO_DEV_UART1_RXD);
|
|
bk_gpio_pull_up(uart_hal_get_tx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_rx_pin(id));
|
|
#if CONFIG_UART1_FLOW_CTRL
|
|
//NOTICE:BEKEN ASIC CTS PIN really function is RTS.
|
|
gpio_dev_map(uart_hal_get_cts_pin(id), GPIO_DEV_UART1_CTS);
|
|
bk_gpio_enable_output(uart_hal_get_cts_pin(id));
|
|
bk_gpio_pull_down(uart_hal_get_cts_pin(id));
|
|
|
|
gpio_dev_map(uart_hal_get_rts_pin(id), GPIO_DEV_UART1_RTS);
|
|
bk_gpio_enable_input(uart_hal_get_rts_pin(id));
|
|
bk_gpio_pull_down(uart_hal_get_rts_pin(id));
|
|
bk_uart_set_hw_flow_ctrl(id, UART1_FLOW_CTRL_CNT);
|
|
#endif
|
|
break;
|
|
}
|
|
case UART_ID_1:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_tx_pin(id));
|
|
gpio_dev_unmap(uart_hal_get_rx_pin(id));
|
|
gpio_dev_map(uart_hal_get_tx_pin(id), GPIO_DEV_UART2_TXD);
|
|
gpio_dev_map(uart_hal_get_rx_pin(id), GPIO_DEV_UART2_RXD);
|
|
bk_gpio_pull_up(uart_hal_get_tx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_rx_pin(id));
|
|
break;
|
|
}
|
|
case UART_ID_2:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_tx_pin(id));
|
|
gpio_dev_unmap(uart_hal_get_rx_pin(id));
|
|
gpio_dev_map(uart_hal_get_tx_pin(id), GPIO_DEV_UART3_TXD);
|
|
gpio_dev_map(uart_hal_get_rx_pin(id), GPIO_DEV_UART3_RXD);
|
|
bk_gpio_pull_up(uart_hal_get_tx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_rx_pin(id));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void uart_deinit_tx_gpio(uart_id_t id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case UART_ID_0:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_tx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_tx_pin(id));
|
|
break;
|
|
}
|
|
case UART_ID_1:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_tx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_tx_pin(id));
|
|
break;
|
|
}
|
|
case UART_ID_2:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_tx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_tx_pin(id));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void uart_deinit_rx_gpio(uart_id_t id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case UART_ID_0:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_rx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_rx_pin(id));
|
|
break;
|
|
}
|
|
case UART_ID_1:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_rx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_rx_pin(id));
|
|
break;
|
|
}
|
|
case UART_ID_2:
|
|
{
|
|
gpio_dev_unmap(uart_hal_get_rx_pin(id));
|
|
bk_gpio_pull_up(uart_hal_get_rx_pin(id));
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static bk_err_t uart_id_init_kfifo(uart_id_t id)
|
|
{
|
|
uint32_t fifo_size = CONFIG_KFIFO_SIZE;
|
|
//RX DMA needs bigger FIFO size when erase flash.
|
|
#if (CONFIG_UART_RX_DMA)
|
|
fifo_size = CONFIG_UART_RX_DMA_KFIFO_SIZE;
|
|
#endif
|
|
|
|
if (!s_uart_rx_kfifo[id]) {
|
|
s_uart_rx_kfifo[id] = kfifo_alloc(fifo_size);
|
|
if (!s_uart_rx_kfifo[id]) {
|
|
UART_LOGE("uart(%d) rx kfifo alloc failed\n", id);
|
|
return BK_ERR_NULL_PARAM;
|
|
}
|
|
}
|
|
return BK_OK;
|
|
}
|
|
|
|
static void uart_id_deinit_kfifo(uart_id_t id)
|
|
{
|
|
if (s_uart_rx_kfifo[id]) {
|
|
kfifo_free(s_uart_rx_kfifo[id]);
|
|
}
|
|
s_uart_rx_kfifo[id] = NULL;
|
|
}
|
|
|
|
/* 1. power up uart
|
|
* 2. set clock
|
|
* 3. set gpio as uart
|
|
*/
|
|
static bk_err_t uart_id_init_common(uart_id_t id)
|
|
{
|
|
bk_err_t ret = 0;
|
|
|
|
#if (CONFIG_SYSTEM_CTRL)
|
|
uart_clock_enable(id);
|
|
sys_drv_uart_select_clock(id, UART_SCLK_XTAL_26M);
|
|
#else
|
|
power_uart_pwr_up(id);
|
|
clk_set_uart_clk_26m(id);
|
|
#endif
|
|
|
|
uart_init_gpio(id);
|
|
ret = uart_id_init_kfifo(id);
|
|
uart_statis_id_init(id);
|
|
|
|
s_uart_sema[id].rx_blocked = false;
|
|
if (s_uart_sema[id].rx_int_sema == NULL) {
|
|
ret = rtos_init_semaphore(&(s_uart_sema[id].rx_int_sema), 1);
|
|
BK_ASSERT(kNoErr == ret); /* ASSERT VERIFIED */
|
|
}
|
|
s_uart[id].id_init_bits |= BIT(id);
|
|
s_uart[id].id_sw_fifo_enable_bits |= BIT(id);
|
|
|
|
#if CONFIG_UART_RX_DMA
|
|
//default not enable rx dma
|
|
s_uart[id].rx_dma_enable = 0;
|
|
#endif
|
|
#if CONFIG_UART_TX_DMA
|
|
//default not enable tx dma
|
|
s_uart[id].tx_dma_enable = 0;
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void uart_id_deinit_common(uart_id_t id)
|
|
{
|
|
s_uart[id].id_init_bits &= ~BIT(id);
|
|
#if CONFIG_UART_RX_DMA
|
|
s_uart[id].rx_dma_enable = 0;
|
|
#endif
|
|
#if CONFIG_UART_TX_DMA
|
|
s_uart[id].tx_dma_enable = 0;
|
|
#endif
|
|
|
|
uart_hal_stop_common(&s_uart[id].hal, id);
|
|
uart_hal_reset_config_to_default(&s_uart[id].hal, id);
|
|
#if (CONFIG_SYSTEM_CTRL)
|
|
uart_interrupt_disable(id);
|
|
uart_clock_disable(id);
|
|
#else
|
|
icu_disable_uart_interrupt(id);
|
|
power_uart_pwr_down(id);
|
|
#endif
|
|
uart_id_deinit_kfifo(id);
|
|
if(s_uart_sema[id].rx_int_sema)
|
|
{
|
|
rtos_deinit_semaphore(&(s_uart_sema[id].rx_int_sema));
|
|
s_uart_sema[id].rx_int_sema = NULL;
|
|
}
|
|
}
|
|
|
|
static inline bool uart_id_is_sw_fifo_enabled(uart_id_t id)
|
|
{
|
|
return !!(s_uart[id].id_sw_fifo_enable_bits & BIT(id));
|
|
}
|
|
|
|
#if CONFIG_UART_RX_DMA
|
|
static uint32_t uart_id_dma_read_fifo_frame(uart_id_t id, const kfifo_ptr_t rx_ptr)
|
|
{
|
|
//DMA stop
|
|
bk_dma_stop(s_uart[id].rx_dma_id);
|
|
|
|
//actual_trans length
|
|
uint16_t actual_trans_len = 0;
|
|
|
|
//update WRITE-Pointer by DMA write length
|
|
uint16_t dma_remain_length = bk_dma_get_remain_len(s_uart[id].rx_dma_id);
|
|
|
|
//check kfifo used data length
|
|
int before_kfifo_unused_size = kfifo_unused(s_uart_rx_kfifo[id]);
|
|
|
|
UART_LOGD("uart_id_dma_read_fifo_frame dma_remain_length[%d], before_kfifo_unused_size:%d\n",
|
|
dma_remain_length, before_kfifo_unused_size);
|
|
if(before_kfifo_unused_size > 0) {
|
|
actual_trans_len = (before_kfifo_unused_size - dma_remain_length);
|
|
}
|
|
|
|
UART_LOGD("uart_id_dma_read_fifo_frame id[%d], actual_trans_len:%d\n", id, actual_trans_len);
|
|
//buffer over-wrap:
|
|
//i.e:when erase flash,CPU can't get instruction from flash then can't handle this function.
|
|
//after Flash erase complete, UART handler come but DMA has copy more then s_uart_rx_kfifo[id]->size bytes data
|
|
if(actual_trans_len > s_uart_rx_kfifo[id]->size)
|
|
{
|
|
//TODO:
|
|
BK_ASSERT(0);
|
|
}
|
|
else
|
|
{
|
|
__attribute__((__unused__)) uart_statis_t *uart_statis = uart_statis_get_statis(id);
|
|
|
|
//data has been saved in buffer by DMA, only update write pointer
|
|
rx_ptr->in += actual_trans_len;
|
|
rx_ptr->in = rx_ptr->in & rx_ptr->mask;
|
|
|
|
UART_STATIS_SET(uart_statis->kfifo_status.in, rx_ptr->in);
|
|
}
|
|
|
|
int after_kfifo_unused_size = kfifo_unused(s_uart_rx_kfifo[id]);
|
|
if(after_kfifo_unused_size > 0) {
|
|
uint32_t dma_start_addr = (uint32_t)s_uart_rx_kfifo[id]->buffer + rx_ptr->in;
|
|
bk_dma_set_dest_start_addr(s_uart[id].rx_dma_id, dma_start_addr);
|
|
BK_LOG_ON_ERR(bk_dma_set_transfer_len(s_uart[id].rx_dma_id, (uint32_t)after_kfifo_unused_size));
|
|
bk_dma_start(s_uart[id].rx_dma_id);
|
|
} else {
|
|
UART_LOGE("Software FIFO is full, please read the data\r\n");
|
|
bk_uart_set_enable_rx(id, 0);
|
|
}
|
|
|
|
return actual_trans_len;
|
|
}
|
|
#endif
|
|
|
|
static uint32_t uart_id_read_fifo_frame(uart_id_t id, const kfifo_ptr_t rx_ptr)
|
|
{
|
|
uint8_t read_val = 0;
|
|
uint32_t rx_count = sizeof(read_val);
|
|
uint32_t unused = kfifo_unused(rx_ptr);
|
|
uint32_t kfifo_put_cnt = 0;
|
|
__attribute__((__unused__)) uart_statis_t *uart_statis = uart_statis_get_statis(id);
|
|
|
|
//TODO: optimize flow ctrl
|
|
while (uart_hal_is_fifo_read_ready(&s_uart[id].hal, id)) {
|
|
/* must read when fifo read ready, otherwise will loop forever */
|
|
read_val = uart_hal_read_byte(&s_uart[id].hal, id);
|
|
// UART_LOGD("read val:0x%x, rx_count/unused: %d/%d\n", read_val, rx_count, unused);
|
|
if (rx_count > unused) {
|
|
if (!uart_hal_is_flow_control_enabled(&s_uart[id].hal, id)) {
|
|
UART_LOGW("rx kfifo is full, out/in:%d/%d, unused:%d\n", rx_ptr->out, rx_ptr->in, unused);
|
|
UART_STATIS_INC(uart_statis->kfifo_status.full_cnt);
|
|
#if CFG_CLI_DEBUG
|
|
extern void cli_show_running_command(void);
|
|
cli_show_running_command();
|
|
#endif
|
|
}
|
|
} else {
|
|
kfifo_put_cnt += kfifo_put(rx_ptr, &read_val, sizeof(read_val));
|
|
UART_STATIS_INC(uart_statis->kfifo_status.put_cnt);
|
|
UART_STATIS_SET(uart_statis->kfifo_status.last_value, read_val);
|
|
}
|
|
unused = kfifo_unused(rx_ptr);
|
|
}
|
|
UART_STATIS_SET(uart_statis->kfifo_status.in, rx_ptr->in);
|
|
UART_STATIS_SET(uart_statis->kfifo_status.out, rx_ptr->out);
|
|
|
|
return kfifo_put_cnt;
|
|
}
|
|
|
|
void print_hex_dump(const char *prefix, const void *buf, int len)
|
|
{
|
|
int i;
|
|
const u8 *b = buf;
|
|
|
|
if (prefix)
|
|
BK_LOG_RAW("%s", prefix);
|
|
for (i = 0; i < len; i++)
|
|
BK_LOG_RAW("%02X ", b[i]);
|
|
BK_LOG_RAW("\n");
|
|
}
|
|
|
|
bk_err_t uart_write_byte(uart_id_t id, uint8_t data)
|
|
{
|
|
/* wait for fifo write ready
|
|
* optimize it when write very fast
|
|
* wait for fifo write ready will waste CPU performance
|
|
*/
|
|
BK_WHILE (!uart_hal_is_fifo_write_ready(&s_uart[id].hal, id));
|
|
uart_hal_write_byte(&s_uart[id].hal, id, data);
|
|
return BK_OK;
|
|
}
|
|
|
|
void uart_write_byte_for_ate(uart_id_t id, uint8_t *data, uint8_t cnt)
|
|
{
|
|
int i;
|
|
for(i = 0; i < cnt; i ++)
|
|
{
|
|
BK_WHILE (!uart_hal_is_fifo_write_ready(&s_uart[id].hal, id));
|
|
uart_hal_write_byte(&s_uart[id].hal, id, data[i]);
|
|
}
|
|
}
|
|
|
|
void uart_write_byte_for_fr(uint8_t *data, uint8_t cnt)
|
|
{
|
|
int i;
|
|
|
|
int port = UART_ID_2;
|
|
|
|
if (bk_get_printf_port() == port)
|
|
os_printf("!UART_ID_2\n");
|
|
|
|
BK_ASSERT (port != bk_get_printf_port());
|
|
|
|
for(i = 0; i < cnt; i ++)
|
|
{
|
|
BK_WHILE (!uart_hal_is_fifo_write_ready(&s_uart[port].hal, port));
|
|
uart_hal_write_byte(&s_uart[port].hal, port, data[i]);
|
|
}
|
|
}
|
|
|
|
|
|
bk_err_t uart_write_ready(uart_id_t id)
|
|
{
|
|
/* wait for fifo write ready
|
|
* optimize it when write very fast
|
|
* wait for fifo write ready will waste CPU performance
|
|
*/
|
|
if (!uart_hal_is_fifo_write_ready(&s_uart[id].hal, id)) {
|
|
return BK_FAIL;
|
|
}
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t uart_write_string(uart_id_t id, const char *string)
|
|
{
|
|
const char *p = string;
|
|
|
|
while (*string) {
|
|
if (*string == '\n') {
|
|
if (p == string || *(string - 1) != '\r')
|
|
uart_write_byte(id, '\r'); /* append '\r' */
|
|
}
|
|
uart_write_byte(id, *string++);
|
|
}
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t uart_read_ready(uart_id_t id)
|
|
{
|
|
if (!uart_hal_is_fifo_read_ready(&s_uart[id].hal, id)) {
|
|
return BK_FAIL;
|
|
}
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
int uart_read_byte(uart_id_t id)
|
|
{
|
|
int val = -1;
|
|
if (uart_hal_is_fifo_read_ready(&s_uart[id].hal, id)) {
|
|
val = uart_hal_read_byte(&s_uart[id].hal, id);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
int uart_read_byte_ex(uart_id_t id, uint8_t *ch)
|
|
{
|
|
int val = -1;
|
|
if (uart_hal_is_fifo_read_ready(&s_uart[id].hal, id)) {
|
|
*ch = uart_hal_read_byte(&s_uart[id].hal, id);
|
|
val = 0;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
uint32_t uart_get_length_in_buffer(uart_id_t id)
|
|
{
|
|
return kfifo_data_size(s_uart_rx_kfifo[id]);
|
|
}
|
|
|
|
static void uart_isr_register_functions(uart_id_t id)
|
|
{
|
|
switch(id)
|
|
{
|
|
case UART_ID_0:
|
|
bk_int_isr_register(INT_SRC_UART0, uart0_isr, NULL);
|
|
break;
|
|
case UART_ID_1:
|
|
bk_int_isr_register(INT_SRC_UART1, uart1_isr, NULL);
|
|
break;
|
|
case UART_ID_2:
|
|
bk_int_isr_register(INT_SRC_UART2, uart2_isr, NULL);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bk_err_t bk_uart_isr_set_priority(uart_id_t id, uint32_t int_priority)
|
|
{
|
|
icu_int_src_t int_src = INT_SRC_NONE;
|
|
switch(id)
|
|
{
|
|
case UART_ID_0:
|
|
int_src = INT_SRC_UART0;
|
|
break;
|
|
case UART_ID_1:
|
|
int_src = INT_SRC_UART1;
|
|
break;
|
|
case UART_ID_2:
|
|
int_src = INT_SRC_UART2;
|
|
break;
|
|
#if (SOC_UART_ID_NUM_PER_UNIT >= 4)
|
|
case UART_ID_3:
|
|
int_src = INT_SRC_UART3;
|
|
break;
|
|
#endif
|
|
default:
|
|
return BK_FAIL;
|
|
}
|
|
return bk_int_set_priority(int_src, int_priority);
|
|
}
|
|
|
|
uint32_t uart_id_to_pm_uart_id(uint32_t uart_id)
|
|
{
|
|
switch (uart_id)
|
|
{
|
|
case UART_ID_0:
|
|
return PM_DEV_ID_UART1;
|
|
|
|
case UART_ID_1:
|
|
return PM_DEV_ID_UART2;
|
|
|
|
case UART_ID_2:
|
|
return PM_DEV_ID_UART3;
|
|
|
|
default:
|
|
return PM_DEV_ID_UART1;
|
|
}
|
|
}
|
|
|
|
static bk_err_t uart_enter_deep_sleep(uint64_t sleep_time, void *args)
|
|
{
|
|
uart_id_t uart_id = (uart_id_t)args;
|
|
|
|
// disable TX firstly, then set tx_stopped to 1.
|
|
bk_uart_disable_tx_interrupt(uart_id);
|
|
|
|
// suspend, tx stopped after fifo empty.
|
|
while((bk_uart_is_tx_over(uart_id) == 0))
|
|
{
|
|
}
|
|
bk_uart_set_enable_tx(uart_id, 0);
|
|
|
|
bk_uart_set_enable_rx(uart_id, 0);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
#if CONFIG_UART_PM_CB_SUPPORT
|
|
static bk_err_t uart_pm_backup(uint64_t sleep_time, void *args)
|
|
{
|
|
uart_id_t uart_id = (uart_id_t)args;
|
|
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(uart_id);
|
|
UART_RETURN_ON_ID_NOT_INIT(uart_id);
|
|
|
|
if (!s_uart[uart_id].pm_bakeup_is_valid)
|
|
{
|
|
uart_hal_backup(&s_uart[uart_id].hal, s_uart[uart_id].pm_backup);
|
|
s_uart[uart_id].pm_bakeup_is_valid = 1;
|
|
}
|
|
return BK_OK;
|
|
}
|
|
|
|
static bk_err_t uart_pm_restore(uint64_t sleep_time, void *args)
|
|
{
|
|
uart_id_t uart_id = (uart_id_t)args;
|
|
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(uart_id);
|
|
UART_RETURN_ON_ID_NOT_INIT(uart_id);
|
|
|
|
if (s_uart[uart_id].pm_bakeup_is_valid)
|
|
{
|
|
uart_hal_restore(&s_uart[uart_id].hal, s_uart[uart_id].pm_backup);
|
|
s_uart[uart_id].pm_bakeup_is_valid = 0;
|
|
}
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_pm_backup(uart_id_t id)
|
|
{
|
|
if ((id == UART_ID_1) || (id == UART_ID_2))
|
|
{
|
|
uart_pm_backup(0, (void *)id);
|
|
return BK_OK;
|
|
}
|
|
return BK_FAIL;
|
|
}
|
|
#else
|
|
bk_err_t bk_uart_pm_backup(uart_id_t id)
|
|
{
|
|
return BK_OK;
|
|
}
|
|
#endif
|
|
|
|
bk_err_t bk_uart_driver_init(void)
|
|
{
|
|
if (s_uart_driver_is_init) {
|
|
return BK_OK;
|
|
}
|
|
|
|
os_memset(&s_uart_rx_isr, 0, sizeof(s_uart_rx_isr));
|
|
os_memset(&s_uart_tx_isr, 0, sizeof(s_uart_tx_isr));
|
|
for(uart_id_t id = UART_ID_0; id < SOC_UART_ID_NUM_PER_UNIT; id++)
|
|
{
|
|
#if (0 == CONFIG_SOC_BK7236XX) && (0 == CONFIG_SOC_BK7239XX) && (0 == CONFIG_SOC_BK7286XX)
|
|
uart_isr_register_functions(id);
|
|
s_uart[id].hal.id = id;
|
|
uart_hal_init(&s_uart[id].hal);
|
|
#endif
|
|
}
|
|
|
|
uart_statis_init();
|
|
s_uart_driver_is_init = true;
|
|
|
|
#ifndef CONFIG_BK_PRINTF_DISABLE
|
|
bk_printf_init();
|
|
#endif
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_driver_deinit(void)
|
|
{
|
|
if (!s_uart_driver_is_init)
|
|
return BK_OK;
|
|
|
|
for (uart_id_t id = UART_ID_0; id < SOC_UART_ID_NUM_PER_UNIT; id++) {
|
|
uart_id_deinit_common(id);
|
|
}
|
|
|
|
s_uart_driver_is_init = false;
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
int bk_uart_is_in_used(uart_id_t id)
|
|
{
|
|
return (s_uart[id].id_init_bits & BIT((id)));
|
|
}
|
|
|
|
int bk_uart_is_rx_dma_enabled(uart_id_t id)
|
|
{
|
|
return (s_uart[id].rx_dma_enable);
|
|
}
|
|
|
|
#if (CONFIG_UART_RX_DMA || CONFIG_UART_TX_DMA)
|
|
static inline dma_dev_t uart_id_to_dma_dev(uart_id_t id, bool rx)
|
|
{
|
|
uint32_t rx_id_offset = 0;
|
|
if(rx)
|
|
rx_id_offset = 1;
|
|
switch(id)
|
|
{
|
|
case UART_ID_0:
|
|
return DMA_DEV_UART1 + rx_id_offset;
|
|
|
|
case UART_ID_1:
|
|
return DMA_DEV_UART2 + rx_id_offset;
|
|
|
|
case UART_ID_2:
|
|
return DMA_DEV_UART3 + rx_id_offset;
|
|
|
|
default:
|
|
return DMA_DEV_UART1 + rx_id_offset;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if (CONFIG_UART_RX_DMA)
|
|
static void uart_rx_dma_fifo_full(dma_id_t dma_id)
|
|
{
|
|
bk_dma_stop(dma_id);
|
|
bk_printf("WARN:%s:dma_id=%d\r\n", __func__, dma_id);
|
|
}
|
|
|
|
|
|
|
|
static void uart_rx_dma_reset_dst_addr(uart_id_t id, uint32_t dma_start_addr, uint32_t len)
|
|
{
|
|
GLOBAL_INT_DECLARATION();
|
|
GLOBAL_INT_DISABLE();
|
|
bk_dma_stop(s_uart[id].rx_dma_id);
|
|
bk_dma_set_dest_start_addr(s_uart[id].rx_dma_id, dma_start_addr);
|
|
bk_dma_set_transfer_len(s_uart[id].rx_dma_id, len);
|
|
GLOBAL_INT_RESTORE();
|
|
bk_dma_start(s_uart[id].rx_dma_id);
|
|
}
|
|
|
|
static inline void uart_rx_dma_src_port_config(uart_id_t id, dma_port_config_t *cfg_ptr)
|
|
{
|
|
cfg_ptr->width = DMA_DATA_WIDTH_8BITS;
|
|
cfg_ptr->addr_inc_en = DMA_ADDR_INC_DISABLE,
|
|
cfg_ptr->addr_loop_en = DMA_ADDR_LOOP_DISABLE,
|
|
cfg_ptr->dev = uart_id_to_dma_dev(id, 1);
|
|
bk_printf("src dev=%d\r\n", cfg_ptr->dev);
|
|
cfg_ptr->end_addr = cfg_ptr->start_addr = (uint32_t)uart_hal_get_read_data_addr(&s_uart[id].hal, id) & 0xffffffffc;
|
|
}
|
|
|
|
static bk_err_t uart_rx_dma_init(uart_id_t id)
|
|
{
|
|
bk_err_t ret = BK_OK;
|
|
dma_config_t dma_cfg = {0};
|
|
|
|
//DMA DST config:Memory
|
|
dma_port_config_t dma_mem_port_config = {
|
|
.dev = DMA_DEV_DTCM,
|
|
.width = DMA_DATA_WIDTH_32BITS,
|
|
.addr_inc_en = DMA_ADDR_INC_ENABLE,
|
|
.addr_loop_en = DMA_ADDR_LOOP_DISABLE,
|
|
.start_addr = 0,
|
|
.end_addr = 0,
|
|
};
|
|
|
|
dma_cfg.dst = dma_mem_port_config;
|
|
//force enable sw fifo
|
|
bk_uart_enable_sw_fifo(id);
|
|
if(s_uart_rx_kfifo[id] == NULL)
|
|
{
|
|
ret = uart_id_init_kfifo(id);
|
|
if(ret != BK_OK)
|
|
return ret;
|
|
}
|
|
dma_cfg.dst.start_addr = (uint32_t)s_uart_rx_kfifo[id]->buffer;
|
|
if(dma_cfg.dst.start_addr == 0)
|
|
{
|
|
//TODO:
|
|
BK_ASSERT(0);
|
|
}
|
|
dma_cfg.dst.end_addr = dma_cfg.dst.start_addr + s_uart_rx_kfifo[id]->size;
|
|
|
|
//DMA SRC config:UART RX read port
|
|
uart_rx_dma_src_port_config(id, &dma_cfg.src);
|
|
|
|
dma_cfg.mode = DMA_WORK_MODE_SINGLE;
|
|
dma_cfg.chan_prio = 0; //UART speed is slow, so no need high priority
|
|
|
|
//init DMA config
|
|
dma_id_t dma_id = bk_dma_alloc(uart_id_to_dma_dev(id, 1));
|
|
if(dma_id < DMA_ID_MAX)
|
|
{
|
|
BK_LOG_ON_ERR(bk_dma_init(dma_id, &dma_cfg));
|
|
BK_LOG_ON_ERR(bk_dma_set_transfer_len(dma_id, s_uart_rx_kfifo[id]->size));
|
|
#if (CONFIG_SPE)
|
|
BK_LOG_ON_ERR(bk_dma_set_dest_sec_attr(dma_id, DMA_ATTR_SEC));
|
|
BK_LOG_ON_ERR(bk_dma_set_src_sec_attr(dma_id, DMA_ATTR_SEC));
|
|
#endif
|
|
bk_dma_register_isr(dma_id, NULL, uart_rx_dma_fifo_full);
|
|
BK_LOG_ON_ERR(bk_dma_enable_finish_interrupt(dma_id));
|
|
BK_LOG_ON_ERR(bk_dma_start(dma_id));
|
|
}
|
|
else
|
|
{
|
|
bk_printf("Err:uart rx dma alloc fail\r\n");
|
|
return BK_FAIL;
|
|
}
|
|
|
|
s_uart[id].rx_dma_id = dma_id;
|
|
s_uart[id].rx_dma_enable = 1;
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
static bk_err_t uart_rx_dma_deinit(uart_id_t id)
|
|
{
|
|
dma_id_t dma_id = s_uart[id].rx_dma_id;
|
|
s_uart[id].rx_dma_id = 0;
|
|
s_uart[id].rx_dma_enable = 0;
|
|
return bk_dma_free(uart_id_to_dma_dev(id, 1), dma_id);
|
|
}
|
|
#endif
|
|
|
|
#if (CONFIG_UART_TX_DMA)
|
|
static inline void uart_tx_dma_dst_port_config(uart_id_t id, dma_port_config_t *cfg_ptr)
|
|
{
|
|
cfg_ptr->width = DMA_DATA_WIDTH_8BITS;
|
|
cfg_ptr->addr_inc_en = DMA_ADDR_INC_DISABLE,
|
|
cfg_ptr->addr_loop_en = DMA_ADDR_LOOP_DISABLE,
|
|
cfg_ptr->dev = uart_id_to_dma_dev(id, 0);
|
|
//bk_printf("%s dst dev=%d\r\n", __func__, cfg_ptr->dev);
|
|
uint32_t fifo_address = (uint32_t)uart_hal_get_write_data_addr(&s_uart[id].hal, id) & 0xfffffffff;
|
|
//bk_printf("%s dst fifo_address=0x%x\r\n", __func__, fifo_address);
|
|
cfg_ptr->start_addr = fifo_address;
|
|
cfg_ptr->end_addr = fifo_address;
|
|
}
|
|
|
|
static void uart_tx_dma_write_done(dma_id_t dma_id)
|
|
{
|
|
UART_LOGD("%s:dma_id=%d\r\n", __func__, dma_id);
|
|
|
|
}
|
|
|
|
static bk_err_t uart_tx_dma_write_to_fifo(uart_id_t id, uint32_t data_address, uint32_t size)
|
|
{
|
|
dma_id_t dma_id = s_uart[id].tx_dma_id;
|
|
|
|
GLOBAL_INT_DECLARATION();
|
|
GLOBAL_INT_DISABLE();
|
|
|
|
BK_LOG_ON_ERR(bk_dma_set_transfer_len(dma_id, size));
|
|
BK_LOG_ON_ERR(bk_dma_set_src_addr(dma_id, data_address, data_address + size));
|
|
GLOBAL_INT_RESTORE();
|
|
|
|
BK_LOG_ON_ERR(bk_dma_start(dma_id));
|
|
|
|
return BK_OK;
|
|
}
|
|
static bk_err_t uart_tx_dma_init(uart_id_t id)
|
|
{
|
|
//DMA malloc chn
|
|
dma_id_t dma_id = bk_dma_alloc(uart_id_to_dma_dev(id, 0));
|
|
if(dma_id < DMA_ID_MAX) {
|
|
dma_config_t dma_cfg = {0};
|
|
uint32_t tx_dma_test_buffer[8] = {0};
|
|
//DMA DST config:UART TX write port
|
|
uart_tx_dma_dst_port_config(id, &dma_cfg.dst);
|
|
|
|
//DMA SRC config:Memory
|
|
dma_port_config_t dma_mem_port_config = {
|
|
.dev = DMA_DEV_DTCM,
|
|
.width = DMA_DATA_WIDTH_32BITS,
|
|
.addr_inc_en = DMA_ADDR_INC_ENABLE,
|
|
.addr_loop_en = DMA_ADDR_LOOP_DISABLE,
|
|
.start_addr = (uint32_t)(&tx_dma_test_buffer[0]),
|
|
.end_addr = (uint32_t)(&tx_dma_test_buffer[0]) + 8,
|
|
};
|
|
|
|
dma_cfg.src = dma_mem_port_config;
|
|
dma_cfg.mode = DMA_WORK_MODE_SINGLE;
|
|
dma_cfg.chan_prio = 0; //UART speed is slow, so no need high priority
|
|
dma_cfg.dest_wr_intlv = 4;
|
|
BK_LOG_ON_ERR(bk_dma_init(dma_id, &dma_cfg));
|
|
bk_dma_set_dest_burst_len(dma_id, BURST_LEN_SINGLE);
|
|
bk_dma_set_src_burst_len(dma_id, BURST_LEN_SINGLE);
|
|
#if (CONFIG_SPE)
|
|
BK_LOG_ON_ERR(bk_dma_set_dest_sec_attr(dma_id, DMA_ATTR_SEC));
|
|
BK_LOG_ON_ERR(bk_dma_set_src_sec_attr(dma_id, DMA_ATTR_SEC));
|
|
#endif
|
|
BK_LOG_ON_ERR(bk_dma_register_isr(dma_id, NULL, uart_tx_dma_write_done));
|
|
BK_LOG_ON_ERR(bk_dma_enable_finish_interrupt(dma_id));
|
|
|
|
} else {
|
|
bk_printf("Err:uart tx dma alloc fail\r\n");
|
|
return BK_FAIL;
|
|
}
|
|
s_uart[id].tx_dma_id = dma_id;
|
|
s_uart[id].tx_dma_enable = 1;
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
static bk_err_t uart_tx_dma_deinit(uart_id_t id)
|
|
{
|
|
dma_id_t dma_id = s_uart[id].tx_dma_id;
|
|
s_uart[id].tx_dma_id = 0;
|
|
s_uart[id].tx_dma_enable = 0;
|
|
return bk_dma_free(uart_id_to_dma_dev(id, 0), dma_id);
|
|
}
|
|
#endif
|
|
|
|
bk_err_t bk_uart_init(uart_id_t id, const uart_config_t *config)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
BK_RETURN_ON_NULL(config);
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_RETURN_ON_BAUD_RATE_NOT_SUPPORT(config->baud_rate);
|
|
UART_CHECK_SECURE(id);
|
|
|
|
#if CONFIG_UART_PM_CB_SUPPORT
|
|
pm_cb_conf_t uart_enter_config = {
|
|
.cb = (pm_cb)uart_pm_backup,
|
|
.args = (void *)id
|
|
};
|
|
|
|
if (id == UART_ID_1) {
|
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_UART1, PM_POWER_MODULE_STATE_ON);
|
|
bk_pm_sleep_register_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_UART2, &uart_enter_config, NULL);
|
|
bk_pm_module_lv_sleep_state_clear(PM_DEV_ID_UART2);
|
|
} else if (id == UART_ID_2) {
|
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_UART2, PM_POWER_MODULE_STATE_ON);
|
|
bk_pm_sleep_register_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_UART3, &uart_enter_config, NULL);
|
|
bk_pm_module_lv_sleep_state_clear(PM_DEV_ID_UART3);
|
|
}
|
|
#endif
|
|
|
|
pm_cb_conf_t enter_config = {
|
|
.cb = (pm_cb)uart_enter_deep_sleep,
|
|
.args = (void *)id
|
|
};
|
|
pm_cb_conf_t exit_config = {
|
|
.cb = NULL,
|
|
.args = (void *)PM_CB_PRIORITY_1
|
|
};
|
|
u8 pm_uart_port = uart_id_to_pm_uart_id(id);
|
|
|
|
bk_pm_sleep_register_cb(PM_MODE_DEEP_SLEEP, pm_uart_port, &enter_config, &exit_config);
|
|
|
|
#if CONFIG_SOC_BK7236XX || (CONFIG_SOC_BK7239XX) || (CONFIG_SOC_BK7286XX)
|
|
uart_isr_register_functions(id);
|
|
s_uart[id].hal.id = id;
|
|
uart_hal_init(&s_uart[id].hal);
|
|
#endif
|
|
|
|
#if (CONFIG_SYSTEM_CTRL)
|
|
uart_interrupt_enable(id);
|
|
#else
|
|
icu_enable_uart_interrupt(id);
|
|
#endif
|
|
|
|
uart_id_init_common(id);
|
|
#if (CONFIG_SYSTEM_CTRL)
|
|
if (config->src_clk == UART_SCLK_APLL)
|
|
sys_drv_uart_select_clock(id, UART_SCLK_APLL);
|
|
else
|
|
sys_drv_uart_select_clock(id, UART_SCLK_XTAL_26M);
|
|
|
|
#else
|
|
if (config->src_clk == UART_SCLK_DCO) {
|
|
clk_set_uart_clk_dco(id);
|
|
} else {
|
|
clk_set_uart_clk_26m(id);
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_UART_RX_DMA
|
|
if(config->rx_dma_en)
|
|
{
|
|
//DMA init RX
|
|
uart_rx_dma_init(id);
|
|
}
|
|
#else //avoid set err parameter.
|
|
if(config->rx_dma_en)
|
|
{
|
|
UART_LOGW("uart(%d)Please enable MACRO CONFIG_UART_RX_DMA then set DMA enable parameter\n", id);
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_UART_TX_DMA
|
|
if(config->tx_dma_en)
|
|
{
|
|
//DMA init TX
|
|
uart_tx_dma_init(id);
|
|
}
|
|
#else //avoid set err parameter.
|
|
if(config->tx_dma_en)
|
|
{
|
|
UART_LOGW("uart(%d)Please enable MACRO CONFIG_UART_TX_DMA then set DMA enable parameter\n", id);
|
|
}
|
|
#endif
|
|
|
|
uart_hal_init_uart(&s_uart[id].hal, id, config);
|
|
uart_hal_start_common(&s_uart[id].hal, id);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_deinit(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
|
|
#if CONFIG_UART_RX_DMA
|
|
uart_rx_dma_deinit(id);
|
|
#endif
|
|
#if CONFIG_UART_TX_DMA
|
|
uart_tx_dma_deinit(id);
|
|
#endif
|
|
|
|
uart_id_deinit_common(id);
|
|
|
|
#if CONFIG_UART_PM_CB_SUPPORT
|
|
if (id == UART_ID_1) {
|
|
bk_pm_sleep_unregister_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_UART2, true, false);
|
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_UART1, PM_POWER_MODULE_STATE_OFF);
|
|
} else if (id == UART_ID_2) {
|
|
bk_pm_sleep_unregister_cb(PM_MODE_LOW_VOLTAGE, PM_DEV_ID_UART3, true, false);
|
|
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_BAKP_UART2, PM_POWER_MODULE_STATE_OFF);
|
|
}
|
|
#endif
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_baud_rate(uart_id_t id, uint32_t baud_rate)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
UART_RETURN_ON_BAUD_RATE_NOT_SUPPORT(baud_rate);
|
|
uint32_t uart_clk = clk_get_uart_clk(id);
|
|
uart_hal_set_baud_rate(&s_uart[id].hal, id, uart_clk, baud_rate);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_data_bits(uart_id_t id, uart_data_bits_t data_bits)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_data_bits(&s_uart[id].hal, id, data_bits);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_stop_bits(uart_id_t id, uart_stop_bits_t stop_bits)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_stop_bits(&s_uart[id].hal, id, stop_bits);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_parity(uart_id_t id, uart_parity_t partiy)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_parity(&s_uart[id].hal, id, partiy);
|
|
return BK_OK;
|
|
}
|
|
|
|
#if CONFIG_ENABLE_FILTER_GLITCH
|
|
bk_err_t bk_uart_set_glitch_width(uart_id_t id, uint32_t width)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_glitch_width(&s_uart[id].hal, width);
|
|
return BK_OK;
|
|
}
|
|
|
|
uint32_t bk_uart_get_glitch_width(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
return uart_hal_get_glitch_width(&s_uart[id].hal);
|
|
}
|
|
|
|
bk_err_t bk_uart_enable_filter_glitch(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_enable_glitch_cancel(&s_uart[id].hal);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_disable_filter_glitch(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_disable_glitch_cancel(&s_uart[id].hal);
|
|
|
|
return BK_OK;
|
|
}
|
|
#endif
|
|
|
|
bk_err_t bk_uart_enable_tx_interrupt(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_enable_tx_interrupt(&s_uart[id].hal, id);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_disable_tx_interrupt(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_disable_tx_interrupt(&s_uart[id].hal, id);
|
|
uart_hal_clear_id_tx_interrupt_status(&s_uart[id].hal, id);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_enable_rx_interrupt(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_enable_rx_interrupt(&s_uart[id].hal, id);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_disable_rx_interrupt(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_disable_rx_interrupt(&s_uart[id].hal, id);
|
|
uart_hal_clear_id_rx_interrupt_status(&s_uart[id].hal, id);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_register_rx_isr(uart_id_t id, uart_isr_t isr, void *param)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
|
|
GLOBAL_INT_DECLARATION();
|
|
GLOBAL_INT_DISABLE();
|
|
s_uart_rx_isr[id].callback = isr;
|
|
s_uart_rx_isr[id].param = param;
|
|
GLOBAL_INT_RESTORE();
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_register_tx_isr(uart_id_t id, uart_isr_t isr, void *param)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
|
|
GLOBAL_INT_DECLARATION();
|
|
GLOBAL_INT_DISABLE();
|
|
s_uart_tx_isr[id].callback = isr;
|
|
s_uart_tx_isr[id].param = param;
|
|
GLOBAL_INT_RESTORE();
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
static uart_callback_t s_last_uart_rx_isr = {0};
|
|
|
|
bk_err_t bk_uart_take_rx_isr(uart_id_t id, uart_isr_t isr, void *param)
|
|
{
|
|
UART_PM_CHECK_RESTORE(id);
|
|
|
|
s_last_uart_rx_isr.callback = s_uart_rx_isr[id].callback;
|
|
s_last_uart_rx_isr.param = s_uart_rx_isr[id].param;
|
|
|
|
BK_RETURN_ON_ERR(bk_uart_disable_sw_fifo(id));
|
|
BK_RETURN_ON_ERR(bk_uart_register_rx_isr(id, isr, param));
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_recover_rx_isr(uart_id_t id)
|
|
{
|
|
UART_PM_CHECK_RESTORE(id);
|
|
|
|
bk_uart_register_rx_isr(id, s_last_uart_rx_isr.callback, s_last_uart_rx_isr.param);
|
|
|
|
#if (!CONFIG_SHELL_ASYNCLOG)
|
|
bk_uart_enable_sw_fifo(id);
|
|
#else
|
|
if (id != bk_get_printf_port()) {
|
|
bk_uart_enable_sw_fifo(id);
|
|
}
|
|
#endif
|
|
|
|
s_last_uart_rx_isr.callback = NULL;
|
|
s_last_uart_rx_isr.param = NULL;
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_write_bytes(uart_id_t id, const void *data, uint32_t size)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_RETURN_ON_ID_NOT_INIT(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
|
|
#if (CONFIG_UART_TX_DMA)
|
|
if(s_uart[id].tx_dma_enable) {
|
|
//UART_LOGE("%s id:%d data:0x%x &data[0]:0x%x size:%d\r\n", __func__, id, data, &((uint8 *)data)[0], size);
|
|
uart_tx_dma_write_to_fifo(id, (uint32_t)data, size);
|
|
|
|
} else
|
|
#endif
|
|
{
|
|
for (int i = 0; i < size; i++) {
|
|
uart_write_byte(id, ((uint8 *)data)[i]);
|
|
}
|
|
}
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_read_bytes(uart_id_t id, void *data, uint32_t size, uint32_t timeout_ms)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_RETURN_ON_ID_NOT_INIT(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
|
|
if (uart_id_is_sw_fifo_enabled(id)) {
|
|
__attribute__((__unused__)) uart_statis_t* uart_statis = uart_statis_get_statis(id);
|
|
GLOBAL_INT_DECLARATION();
|
|
GLOBAL_INT_DISABLE();
|
|
uint32_t kfifo_data_len = kfifo_data_size(s_uart_rx_kfifo[id]);
|
|
/* Only kfifo_data_len=0, wait for semaphore */
|
|
if (kfifo_data_len == 0) {
|
|
UART_LOGD("kfifo is empty, wait for recv data\r\n");
|
|
/* when sema_cnt=0, rx_blocked=true, otherwise rx_blocked=false */
|
|
s_uart_sema[id].rx_blocked = true;
|
|
GLOBAL_INT_RESTORE();
|
|
#if CONFIG_RTC_TIMER_PRECISION_TEST
|
|
uint32_t ret = rtos_get_semaphore(&(s_uart_sema[id].rx_int_sema), BEKEN_WAIT_FOREVER);
|
|
#else
|
|
uint32_t ret = rtos_get_semaphore(&(s_uart_sema[id].rx_int_sema), timeout_ms);
|
|
#endif
|
|
if (ret == kTimeoutErr) {
|
|
if (!s_uart_sema[id].rx_blocked) {
|
|
rtos_get_semaphore(&(s_uart_sema[id].rx_int_sema), timeout_ms);
|
|
}
|
|
GLOBAL_INT_DISABLE();
|
|
s_uart_sema[id].rx_blocked = false;
|
|
GLOBAL_INT_RESTORE();
|
|
UART_LOGW("recv data timeout:%d\n", timeout_ms);
|
|
UART_STATIS_INC(uart_statis->recv_timeout_cnt);
|
|
return BK_ERR_UART_RX_TIMEOUT;
|
|
}
|
|
} else {
|
|
GLOBAL_INT_RESTORE();
|
|
}
|
|
|
|
kfifo_data_len = kfifo_data_size(s_uart_rx_kfifo[id]); /* updata kfifo data size */
|
|
UART_LOGD("kfifo data length is %d.\n", kfifo_data_len);
|
|
if (size >= kfifo_data_len) {
|
|
#if CONFIG_UART_RX_DMA
|
|
uint32_t dma_start_addr = (uint32_t)s_uart_rx_kfifo[id]->buffer;
|
|
uart_rx_dma_reset_dst_addr(id, dma_start_addr, s_uart_rx_kfifo[id]->size);
|
|
bk_uart_set_enable_rx(id, 1);
|
|
#endif
|
|
if (kfifo_data_len) {
|
|
kfifo_get(s_uart_rx_kfifo[id], (uint8_t *)data, kfifo_data_len);
|
|
} else {
|
|
UART_LOGW("kfifo data is empty\n");
|
|
UART_STATIS_INC(uart_statis->kfifo_status.empty_cnt);
|
|
}
|
|
UART_STATIS_SET(uart_statis->kfifo_status.in, s_uart_rx_kfifo[id]->in);
|
|
UART_STATIS_SET(uart_statis->kfifo_status.out, s_uart_rx_kfifo[id]->out);
|
|
|
|
return kfifo_data_len;
|
|
}
|
|
kfifo_get(s_uart_rx_kfifo[id], (uint8_t *)data, size);
|
|
UART_STATIS_SET(uart_statis->kfifo_status.in, s_uart_rx_kfifo[id]->in);
|
|
UART_STATIS_SET(uart_statis->kfifo_status.out, s_uart_rx_kfifo[id]->out);
|
|
|
|
return size;
|
|
}else {
|
|
int ret = 0;
|
|
uint8_t rx_data;
|
|
int read_count = 0;
|
|
uint8_t *read_buffer = (uint8_t *)data;
|
|
int actual_bytes_to_read = size;
|
|
|
|
/* read all data from rx-FIFO. */
|
|
while (actual_bytes_to_read) {
|
|
ret = uart_read_byte_ex(id, &rx_data);
|
|
if (ret == -1)
|
|
break;
|
|
|
|
read_buffer[read_count] = rx_data;
|
|
read_count++;
|
|
|
|
actual_bytes_to_read--;
|
|
}
|
|
|
|
return read_count;
|
|
}
|
|
}
|
|
|
|
bk_err_t bk_uart_set_rx_full_threshold(uart_id_t id, uint8_t threshold)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_rx_fifo_threshold(&s_uart[id].hal, id, threshold);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_tx_empty_threshold(uart_id_t id, uint8_t threshold)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_tx_fifo_threshold(&s_uart[id].hal, id, threshold);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_rx_timeout(uart_id_t id, uart_rx_stop_detect_time_t timeout_thresh)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_rx_stop_detect_time(&s_uart[id].hal, id, timeout_thresh);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_disable_rx(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_disable_rx(&s_uart[id].hal, id);
|
|
uart_deinit_rx_gpio(id);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_disable_tx(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_disable_tx(&s_uart[id].hal, id);
|
|
uart_deinit_tx_gpio(id);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_enable_rx(uart_id_t id, bool enable)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_rx_enable(&s_uart[id].hal, id, enable);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_enable_tx(uart_id_t id, bool enable)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_tx_enable(&s_uart[id].hal, id, enable);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_set_hw_flow_ctrl(uart_id_t id, uint8_t rx_threshold)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_set_hw_flow_ctrl(&s_uart[id].hal, id, rx_threshold);
|
|
uart_hal_enable_flow_control(&s_uart[id].hal, id);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_disable_hw_flow_ctrl(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_NOT_INIT();
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
UART_PM_CHECK_RESTORE(id);
|
|
uart_hal_disable_hw_flow_ctrl(&s_uart[id].hal, id);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_enable_sw_fifo(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
s_uart[id].id_sw_fifo_enable_bits |= BIT(id);
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_uart_disable_sw_fifo(uart_id_t id)
|
|
{
|
|
UART_RETURN_ON_INVALID_ID(id);
|
|
s_uart[id].id_sw_fifo_enable_bits &= ~BIT(id);
|
|
return BK_OK;
|
|
}
|
|
|
|
uint32_t bk_uart_get_ate_detect_gpio(void)
|
|
{
|
|
return uart_hal_get_tx_pin(CONFIG_UART_ATE_PORT);
|
|
}
|
|
|
|
gpio_id_t bk_uart_get_rx_gpio(uart_id_t id)
|
|
{
|
|
return uart_hal_get_rx_pin(id);
|
|
}
|
|
|
|
bool bk_uart_is_tx_over(uart_id_t id)
|
|
{
|
|
return uart_hal_is_tx_fifo_empty(&s_uart[id].hal, id);
|
|
}
|
|
|
|
uint32_t uart_wait_tx_over(void)
|
|
{
|
|
return uart_hal_wait_tx_over();
|
|
}
|
|
|
|
uint32_t uart_get_int_enable_status(uart_id_t id)
|
|
{
|
|
UART_PM_CHECK_RESTORE(id);
|
|
return uart_hal_get_int_enable_status(&s_uart[id].hal, id);
|
|
}
|
|
|
|
uint32_t uart_get_interrupt_status(uart_id_t id)
|
|
{
|
|
return uart_hal_get_interrupt_status(&s_uart[id].hal, id);
|
|
}
|
|
|
|
void uart_clear_interrupt_status(uart_id_t id, uint32_t int_status)
|
|
{
|
|
uart_hal_clear_interrupt_status(&s_uart[id].hal, id, int_status);
|
|
}
|
|
|
|
/* read int enable status
|
|
* read int status
|
|
* clear int status
|
|
*/
|
|
static void uart_isr_common(uart_id_t id)
|
|
{
|
|
uint32_t int_status = 0;
|
|
uint32_t int_enable_status = 0;
|
|
uint32_t status = 0;
|
|
UART_STATIS_DEC();
|
|
|
|
int_status = uart_hal_get_interrupt_status(&s_uart[id].hal, id);
|
|
int_enable_status = uart_hal_get_int_enable_status(&s_uart[id].hal, id);
|
|
status = int_status & int_enable_status;
|
|
uart_hal_clear_interrupt_status(&s_uart[id].hal, id, int_status);
|
|
UART_STATIS_GET(uart_statis, id);
|
|
UART_STATIS_INC(uart_statis->uart_isr_cnt);
|
|
|
|
if (uart_hal_is_rx_interrupt_triggered(&s_uart[id].hal, id, status)) //rx end or rx fifo full
|
|
{
|
|
//overflow,rx_para_err,rx_stop_err
|
|
if(int_status & (BIT(2) | BIT(3) | BIT(4)))
|
|
{
|
|
#if (CONFIG_UART_RX_DMA)
|
|
//TODO:Discard the RX FIFO data,set WR_PTR to RD_PTR
|
|
if(s_uart[id].rx_dma_enable)
|
|
{
|
|
uint32_t discard_len = s_uart_rx_kfifo[id]->out - s_uart_rx_kfifo[id]->in;
|
|
s_uart_rx_kfifo[id]->in = s_uart_rx_kfifo[id]->out;
|
|
#if CONFIG_UART_ERR_INTERRUPT
|
|
UART_LOGW("uart rx error(0x%x)!,discard_len=%d\r\n", (int_status & (BIT(2) | BIT(3) | BIT(4))), discard_len);
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
int ret = 0;
|
|
uint8_t rx_data;
|
|
|
|
/* read all data from rx-FIFO. */
|
|
while (1)
|
|
{
|
|
ret = uart_read_byte_ex(id, &rx_data);
|
|
if (ret == -1)
|
|
{
|
|
#if CONFIG_UART_ERR_INTERRUPT
|
|
UART_LOGW("uart rx error(0x%x) triggered!\r\n", (int_status & (BIT(2) | BIT(3) | BIT(4))));
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UART_STATIS_INC(uart_statis->rx_isr_cnt);
|
|
UART_STATIS_SET(uart_statis->rx_fifo_cnt, uart_hal_get_rx_fifo_cnt(&s_uart[id].hal, id));
|
|
if (uart_id_is_sw_fifo_enabled(id))
|
|
{
|
|
#if CONFIG_UART_RX_DMA
|
|
if(s_uart[id].rx_dma_enable)
|
|
{
|
|
//force all of the UART RX FIFO data to DMA RAM space
|
|
bk_dma_flush_src_buffer(s_uart[id].rx_dma_id);
|
|
if (uart_id_dma_read_fifo_frame(id, s_uart_rx_kfifo[id]) > 0)
|
|
{
|
|
if (s_uart_sema[id].rx_int_sema && s_uart_sema[id].rx_blocked)
|
|
{
|
|
rtos_set_semaphore(&(s_uart_sema[id].rx_int_sema));
|
|
s_uart_sema[id].rx_blocked = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if (uart_id_read_fifo_frame(id, s_uart_rx_kfifo[id]) > 0)
|
|
{
|
|
if (s_uart_sema[id].rx_int_sema && s_uart_sema[id].rx_blocked)
|
|
{
|
|
rtos_set_semaphore(&(s_uart_sema[id].rx_int_sema));
|
|
s_uart_sema[id].rx_blocked = false;
|
|
}
|
|
}
|
|
|
|
if (s_uart_rx_isr[id].callback)
|
|
{
|
|
s_uart_rx_isr[id].callback(id, s_uart_rx_isr[id].param);
|
|
}
|
|
}
|
|
else if (s_uart_rx_isr[id].callback)
|
|
{
|
|
s_uart_rx_isr[id].callback(id, s_uart_rx_isr[id].param);
|
|
}
|
|
else
|
|
{
|
|
int ret = 0;
|
|
uint8_t rx_data;
|
|
|
|
/* read all data from rx-FIFO. */
|
|
while (1)
|
|
{
|
|
ret = uart_read_byte_ex(id, &rx_data);
|
|
if (ret == -1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (uart_hal_is_tx_interrupt_triggered(&s_uart[id].hal, id, status))
|
|
{
|
|
if (s_uart_tx_isr[id].callback)
|
|
{
|
|
s_uart_tx_isr[id].callback(id, s_uart_tx_isr[id].param);
|
|
}
|
|
}
|
|
}
|
|
|
|
void uart0_isr(void)
|
|
{
|
|
uart_isr_common(UART_ID_0);
|
|
}
|
|
|
|
void uart1_isr(void)
|
|
{
|
|
uart_isr_common(UART_ID_1);
|
|
}
|
|
|
|
void uart2_isr(void)
|
|
{
|
|
uart_isr_common(UART_ID_2);
|
|
}
|
|
|