drivers/rpmsg: implement timestamp support for rpmsg_port

Add TX/RX timestamp tracking for rpmsg_port to enable latency
measurement and debugging:

- Add rpmsg_port_get_timestamp() to retrieve buffer timestamps
- Add rpmsg_port_update_timestamp() to record timestamps at TX/RX time
- Integrate timestamp recording in rpmsg_port_spi and rpmsg_port_spi_slave
- Reserve space for rpmsg_timestamp_s in buffer size calculations

Signed-off-by: liaoao <liaoao@xiaomi.com>
This commit is contained in:
liaoao
2025-02-17 17:25:56 +08:00
committed by Xiang Xiao
parent 198a8fe108
commit 425a760799
4 changed files with 71 additions and 3 deletions
+59 -3
View File
@@ -27,6 +27,7 @@
#include <debug.h>
#include <execinfo.h>
#include <stdio.h>
#include <time.h>
#include <nuttx/irq.h>
#include <nuttx/kmalloc.h>
@@ -50,6 +51,9 @@
****************************************************************************/
static void rpmsg_port_dump(FAR struct rpmsg_s *rpmsg);
static int rpmsg_port_get_timestamp(FAR struct rpmsg_s *rpmsg,
FAR const void *data,
FAR struct rpmsg_timestamp_s *ts);
/****************************************************************************
* Private Data
@@ -62,6 +66,7 @@ static const struct rpmsg_ops_s g_rpmsg_port_ops =
NULL,
NULL,
rpmsg_port_dump,
rpmsg_port_get_timestamp,
};
/****************************************************************************
@@ -253,7 +258,7 @@ rpmsg_port_get_tx_payload_buffer(FAR struct rpmsg_device *rdev,
}
*len = hdr->len - sizeof(struct rpmsg_port_header_s) -
sizeof(struct rpmsg_hdr);
sizeof(struct rpmsg_hdr) - sizeof(struct rpmsg_timestamp_s);
return RPMSG_LOCATE_DATA(hdr->buf);
}
@@ -379,7 +384,7 @@ static int rpmsg_port_get_tx_buffer_size(FAR struct rpmsg_device *rdev)
metal_container_of(rdev, struct rpmsg_port_s, rdev);
return port->txq.len - sizeof(struct rpmsg_port_header_s) -
sizeof(struct rpmsg_hdr);
sizeof(struct rpmsg_hdr) - sizeof(struct rpmsg_timestamp_s);
}
/****************************************************************************
@@ -392,7 +397,34 @@ static int rpmsg_port_get_rx_buffer_size(FAR struct rpmsg_device *rdev)
metal_container_of(rdev, struct rpmsg_port_s, rdev);
return port->rxq.len - sizeof(struct rpmsg_port_header_s) -
sizeof(struct rpmsg_hdr);
sizeof(struct rpmsg_hdr) - sizeof(struct rpmsg_timestamp_s);
}
/****************************************************************************
* Name: rpmsg_port_get_timestamp
****************************************************************************/
static int rpmsg_port_get_timestamp(FAR struct rpmsg_s *rpmsg,
FAR const void *data,
FAR struct rpmsg_timestamp_s *ts)
{
FAR struct rpmsg_port_s *port = (FAR struct rpmsg_port_s *)rpmsg;
FAR const struct rpmsg_hdr *rphdr = RPMSG_LOCATE_HDR(data);
FAR const struct rpmsg_port_header_s *hdr =
metal_container_of(rphdr, struct rpmsg_port_header_s, buf);
FAR const struct rpmsg_timestamp_s *rpts =
(FAR const struct rpmsg_timestamp_s *)((uint8_t *)hdr + port->rxq.len -
sizeof(struct rpmsg_timestamp_s));
if (hdr->len > port->rxq.len - sizeof(struct rpmsg_timestamp_s))
{
return -EINVAL;
}
ts->tx_nsec = rpts->tx_nsec;
ts->rx_nsec = rpts->rx_nsec;
return RPMSG_SUCCESS;
}
/****************************************************************************
@@ -704,6 +736,30 @@ void rpmsg_port_queue_add_buffer(FAR struct rpmsg_port_queue_s *queue,
rpmsg_port_post(&queue->ready.sem);
}
/****************************************************************************
* Name: rpmsg_port_update_timestamp
****************************************************************************/
void rpmsg_port_update_timestamp(FAR struct rpmsg_port_queue_s *queue,
FAR struct rpmsg_port_header_s *hdr,
bool tx)
{
FAR struct rpmsg_timestamp_s *rpts =
(FAR struct rpmsg_timestamp_s *)((uint8_t *)hdr + queue->len -
sizeof(struct rpmsg_timestamp_s));
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
if (tx)
{
rpts->tx_nsec = 1000000000ull * ts.tv_sec + ts.tv_nsec;
}
else if (hdr->len <= queue->len - sizeof(struct rpmsg_timestamp_s))
{
rpts->rx_nsec = 1000000000ull * ts.tv_sec + ts.tv_nsec;
}
}
/****************************************************************************
* Name: rpmsg_port_drop_packets
****************************************************************************/
+8
View File
@@ -274,6 +274,14 @@ uint16_t rpmsg_port_queue_nused(FAR struct rpmsg_port_queue_s *queue)
return atomic_read(&queue->ready.num);
}
/****************************************************************************
* Name: rpmsg_port_update_timestamp
****************************************************************************/
void rpmsg_port_update_timestamp(FAR struct rpmsg_port_queue_s *queue,
FAR struct rpmsg_port_header_s *hdr,
bool tx);
/****************************************************************************
* Name: rpmsg_port_drop_packets
****************************************************************************/
+2
View File
@@ -311,6 +311,7 @@ static void rpmsg_port_spi_exchange(FAR struct rpmsg_port_spi_s *rpspi)
rpmsginfo("irq send cmd:%u avail:%u\n", txhdr->cmd, txhdr->avail);
rpmsg_port_spi_pm_action(rpspi, true);
rpmsg_port_update_timestamp(&rpspi->port.txq, txhdr, true);
SPI_SELECT(rpspi->spi, rpspi->devid, true);
SPI_EXCHANGE(rpspi->spi, txhdr, rpspi->rxhdr,
RPMSG_PORT_SPI_BYTES2WORDS(rpspi, rpspi->port.txq.len));
@@ -332,6 +333,7 @@ static void rpmsg_port_spi_complete_handler(FAR void *arg)
rpmsginfo("received cmd:%u avail:%u\n",
rpspi->rxhdr->cmd, rpspi->rxhdr->avail);
rpmsg_port_update_timestamp(&rpspi->port.rxq, rpspi->rxhdr, false);
if (rpspi->txhdr != NULL)
{
rpmsg_port_queue_return_buffer(&rpspi->port.txq, rpspi->txhdr);
+2
View File
@@ -280,6 +280,7 @@ static void rpmsg_port_spi_exchange(FAR struct rpmsg_port_spi_s *rpspi)
rpmsginfo("send cmd:%u avail:%u\n", txhdr->cmd, txhdr->avail);
rpmsg_port_spi_pm_action(rpspi, true);
rpmsg_port_update_timestamp(&rpspi->port.txq, txhdr, true);
SPIS_CTRLR_ENQUEUE(rpspi->spictrlr, txhdr,
RPMSG_PORT_SPI_BYTES2WORDS(rpspi, rpspi->port.txq.len));
IOEXP_WRITEPIN(rpspi->ioe, rpspi->sreq, 1);
@@ -411,6 +412,7 @@ static void rpmsg_port_spi_slave_notify(FAR struct spi_slave_dev_s *dev,
rpmsginfo("received cmd:%u avail:%u\n",
rpspi->rxhdr->cmd, rpspi->rxhdr->avail);
rpmsg_port_update_timestamp(&rpspi->port.rxq, rpspi->rxhdr, false);
if (rpspi->txhdr != NULL)
{
rpmsg_port_queue_return_buffer(&rpspi->port.txq, rpspi->txhdr);