mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
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:
@@ -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
|
||||
****************************************************************************/
|
||||
|
||||
@@ -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
|
||||
****************************************************************************/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user