keil/include/components/uci/src/uci_uart_driver.c
@@ -1,5 +1,5 @@
/*
 * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and
 * Copyright (c) 2019-2025 Beijing Hanwei Innovation Technology Ltd. Co. and
 * its subsidiaries and affiliates (collectly called MKSEMI).
 *
 * All rights reserved.
@@ -46,26 +46,47 @@
#include "uwb_api.h"
#include "uci_tl_comm.h"
#include "uci_tl_task.h"
#include "math.h"
#include "board.h"
#if UCI_INTF_PORT == 0
#if (UCI_INTF_PORT == 0) && (UCI_INTF_UART_WITH_IDLE_DET == 0)
#define FINE_TUNING_FACTOR (1.3)
#if 1
#define UCI_PORT UART_ID0
#define UART_BASE (UART0)
#define RX_DMA_CH (DMA_CH4)
#else
#define UCI_PORT UART_ID1
#define UART_BASE (UART1)
#define RX_DMA_CH (DMA_CH6)
#endif
static void uci_tl_up_req(void);
static void uci_tl_timer_notify(void);
static void uci_tl_setup(void);
static bool uci_tl_up_is_active(void);
static void uci_rx_header_callback(void *dev, uint32_t err_code);
static void rx_over_callback(void *dev, uint32_t err_code);
static void uci_rx_callback(void *dev, uint32_t err_code);
static void uci_tx_over_callback(void *dev, uint32_t err_code);
static void uci_tl_stop_rx(void);
static void uci_tl_restart_rx(void);
#if !UCI_INTF_UART_HS
static void uci_tl_reset(void);
#endif
extern int uci_validate(uint8_t *buf);
uci_tl_dev_t g_uci_tl_dev = {
    .uci_tl_setup = &uci_tl_setup,
#if UCI_INTF_UART_HS
    .uci_tl_resume = &uci_tl_setup,
#else
    .uci_tl_resume = &uci_tl_reset,
#endif
    .uci_tl_rx_stop = &uci_tl_stop_rx,
    .uci_tl_rx_restart = &uci_tl_restart_rx,
    .uci_tl_up_is_active = &uci_tl_up_is_active,
    .uci_tl_up_req = &uci_tl_up_req,
    .uci_tl_timer_notify = &uci_tl_timer_notify,
@@ -83,6 +104,15 @@
                                         .int_tx = false};
static uint8_t recv_buff[UCI_RX_BUFF_SIZE] = {0};
static struct DMA_LINK_DESC_T desc = {
    .dst_addr = (uint32_t)&recv_buff[UCI_HEADER_SIZE],
    .nxt = NULL,
    .size = UCI_RX_BUFF_SIZE - UCI_HEADER_SIZE,
};
const static uint8_t retry_ntf[] = {0x60, 0x01, 0x00, 0x01, 0x0A};
static struct UCI_TL_MSG_T *tl_up_msg = NULL;
static bool tx_idle = true;
@@ -106,47 +136,111 @@
    rx_idle = true;
    gpio_enable_irq(HOST2SLAVE_HS_GPIO, GPIO_IRQ_TYPE_FALLING_EDGE, host2slave_gpio_callback);
#else
    uart_receive(UCI_PORT, recv_buff, UCI_HEADER_SIZE, uci_rx_header_callback);
    memset(recv_buff, 0, UCI_HEADER_SIZE);
    desc.size = UCI_RX_BUFF_SIZE - UCI_HEADER_SIZE;
    uart_dma_receive_with_llp(UCI_PORT, recv_buff, UCI_HEADER_SIZE, &desc, uci_rx_callback);
#endif
}
static void uci_rx_header_callback(void *dev, uint32_t err_code)
#if !UCI_INTF_UART_HS
static void uci_tl_reset(void)
{
    if (err_code != DMA_INT_TYPE_DONE)
    {
        uart_receive(UCI_PORT, recv_buff, UCI_HEADER_SIZE, uci_rx_header_callback);
        return;
    }
    uart_open(UCI_PORT, &uci_uart_cfg);
}
#endif
    if (uci_validate(recv_buff))
static void uci_tl_send_ntf(const uint8_t *msg, uint16_t len)
{
    struct UCI_TL_MSG_T *p = WsfBufAlloc((uint16_t)(len + sizeof(struct UCI_TL_MSG_T)));
    if (p != NULL)
    {
        uint16_t payload_len = *(recv_buff + 3) & 0xFFU;
        if (payload_len)
        {
            WsfTimerStartMs(&g_uci_tl_dev.tl_timer, 50, WSF_TIMER_ONE_SHOT);
            uart_receive(UCI_PORT, recv_buff + UCI_HEADER_SIZE, payload_len, rx_over_callback);
        }
        else
        {
            rx_over_callback(dev, err_code);
        }
    }
    else
    {
        uart_receive(UCI_PORT, recv_buff, UCI_HEADER_SIZE, uci_rx_header_callback);
        p->msg_length = len;
        memcpy(p->msg, msg, len);
        WsfQueueEnq(&g_uci_tl_dev.tl_up_queue, p);
        g_uci_tl_dev.uci_tl_up_done_notify();
    }
}
static void rx_over_callback(void *dev, uint32_t err_code)
static void uci_rx_callback(void *dev, uint32_t err_code)
{
    if (err_code != DMA_INT_TYPE_DONE)
    uint16_t frame_len;
    uint32_t lock;
    if (err_code != DMA_INT_TYPE_DONE || (UART_BASE->STATUS & UART_STATUS_OE_MSK))
    {
        return;
        uci_tl_send_ntf(retry_ntf, sizeof(retry_ntf));
        goto exit;
    }
    WsfTimerStop(&g_uci_tl_dev.tl_timer);
    if (((recv_buff[0] >> 5) & 0x0F) > 3)
    {
        LOG_INFO(TRACE_MODULE_UCI, "Unkown MT field:%X\r\n", (recv_buff[0] >> 5) & 0x0F);
        goto exit;
    }
    uint16_t frame_len = *(recv_buff + 3) + UCI_HEADER_SIZE;
    frame_len = (uint16_t)(((*(recv_buff + 2)) << 8) + *(recv_buff + 3) + UCI_HEADER_SIZE);
    if (frame_len > UCI_RX_BUFF_SIZE)
    {
        LOG_INFO(TRACE_MODULE_UCI, "Message length(%d) is too long\r\n", frame_len);
        goto exit;
    }
    lock = int_lock();
    while ((UART_BASE->STATUS & (1 << 0)) && (DMA->CH[RX_DMA_CH].DATA_SIZE != 0))
    {
    }
    UART_BASE->CTRL0 = UART_CTRL0_FIFO_ENABLE_MSK;
    while (DMA->STATUS1 & (1 << RX_DMA_CH))
    {
    }
    if (((DMA->CH[RX_DMA_CH].CFG & 0x000F0000) >> 16) == 1)
    {
        uint32_t remain;
        if (DMA->CH[RX_DMA_CH].DATA_SIZE == 0)
        {
            if (DMA->CH[RX_DMA_CH].CHAIN_PTR != 0)
            {
                // first transmission completed, second transmission has not started yet.
                remain = frame_len - UCI_HEADER_SIZE;
                desc.size = remain;
            }
            else
            {
                // second transmission completed.
                remain = 0;
            }
        }
        else
        {
            // second transmission started, has not finished yet.
            if (frame_len > (UCI_RX_BUFF_SIZE - DMA->CH[RX_DMA_CH].DATA_SIZE))
            {
                remain = frame_len - (UCI_RX_BUFF_SIZE - DMA->CH[RX_DMA_CH].DATA_SIZE);
                DMA->CH[RX_DMA_CH].DATA_SIZE = remain;
            }
            else
            {
                remain = 0;
            }
        }
        if (remain > 0)
        {
            UART_BASE->CTRL0 = UART_CTRL0_FIFO_ENABLE_MSK | UART_CTRL0_DMA_MODE_MSK;
            int_unlock(lock);
            mk_timer_list_start_timer(&g_uci_tl_dev.tl_timer, UCI_HS_TIMEOUT_MS, MK_TIMER_ONE_SHOT);
            return;
        }
    }
    UART_BASE->CTRL0 = UART_CTRL0_FIFO_ENABLE_MSK | UART_CTRL0_DMA_MODE_MSK;
    int_unlock(lock);
    if (WsfQueueCount(&g_uci_tl_dev.tl_down_queue) < UCI_MAX_DL_ITEMS)
    {
@@ -170,13 +264,19 @@
        g_uci_tl_dev.uci_tl_down_notify();
    }
exit:
    mk_timer_list_stop_timer(&g_uci_tl_dev.tl_timer);
    uart_rx_force_abort_dma(UCI_PORT, NULL);
    power_mode_clear(POWER_UNIT_UCI_RX);
#if (UCI_INTF_UART_HS)
    rx_idle = true;
    return;
#else
    uart_receive(UCI_PORT, recv_buff, UCI_HEADER_SIZE, uci_rx_header_callback);
    memset(recv_buff, 0, UCI_HEADER_SIZE);
    desc.size = UCI_RX_BUFF_SIZE - UCI_HEADER_SIZE;
    uart_dma_receive_with_llp(UCI_PORT, recv_buff, UCI_HEADER_SIZE, &desc, uci_rx_callback);
#endif
}
@@ -197,8 +297,10 @@
    if (!gpio_pin_get_val(HOST2SLAVE_HS_GPIO) && rx_idle)
    {
        rx_idle = false;
        WsfTimerStartMs(&g_uci_tl_dev.tl_timer, UCI_HS_TIMEOUT_MS, WSF_TIMER_ONE_SHOT);
        uart_receive(UCI_PORT, recv_buff, UCI_HEADER_SIZE, uci_rx_header_callback);
        mk_timer_list_start_timer(&g_uci_tl_dev.tl_timer, UCI_HS_TIMEOUT_MS, MK_TIMER_ONE_SHOT);
        memset(recv_buff, 0, UCI_HEADER_SIZE);
        desc.size = UCI_RX_BUFF_SIZE - UCI_HEADER_SIZE;
        uart_dma_receive_with_llp(UCI_PORT, recv_buff, UCI_HEADER_SIZE, &desc, uci_rx_callback);
        power_mode_request(POWER_UNIT_UCI_RX, POWER_MODE_SLEEP);
    }
}
@@ -243,7 +345,7 @@
static bool uci_tl_up_is_active(void)
{
    if (!uart_fifo_busy(UCI_PORT) && !tx_idle)
    if (!uart_tx_in_progress(UCI_PORT) && !tx_idle)
    {
#if (UCI_INTF_UART_HS)
        gpio_pin_set(SLAVE2HOST_HS_GPIO);
@@ -257,9 +359,41 @@
static void uci_tl_timer_notify(void)
{
    LOG_INFO(TRACE_MODULE_UCI, "UCI message rx timeout\r\n");
    mk_timer_list_stop_timer(&g_uci_tl_dev.tl_timer);
    uart_rx_force_abort_dma(UCI_PORT, NULL);
    power_mode_clear(POWER_UNIT_UCI_RX);
    uci_tl_send_ntf(retry_ntf, sizeof(retry_ntf));
#if (UCI_INTF_UART_HS)
    rx_idle = true;
    return;
#else
    memset(recv_buff, 0, UCI_HEADER_SIZE);
    desc.size = UCI_RX_BUFF_SIZE - UCI_HEADER_SIZE;
    uart_dma_receive_with_llp(UCI_PORT, recv_buff, UCI_HEADER_SIZE, &desc, uci_rx_callback);
#endif
}
static void uci_tl_stop_rx(void)
{
#if (UCI_INTF_UART_HS)
#else
    mk_timer_list_stop_timer(&g_uci_tl_dev.tl_timer);
    uart_rx_force_abort_dma(UCI_PORT, NULL);
#endif
}
static void uci_tl_restart_rx(void)
{
#if (UCI_INTF_UART_HS)
#else
    memset(recv_buff, 0, UCI_HEADER_SIZE);
    desc.size = UCI_RX_BUFF_SIZE - UCI_HEADER_SIZE;
    uart_dma_receive_with_llp(UCI_PORT, recv_buff, UCI_HEADER_SIZE, &desc, uci_rx_callback);
#endif
}