summaryrefslogtreecommitdiff
path: root/board/twinkie
diff options
context:
space:
mode:
authorDawei Li <daweili@google.com>2015-06-29 11:29:23 -0700
committerchrome-bot <chrome-bot@chromium.org>2015-08-28 01:19:33 -0700
commit97a1d1671b224b4b6bfda0029edf6c02f932f7a7 (patch)
tree2484e083aa9cec16e7d2ef3f315a03658f63f3fb /board/twinkie
parent405ac321486d28fdf4ab36b010c8f86d168b75b3 (diff)
downloadchrome-ec-97a1d1671b224b4b6bfda0029edf6c02f932f7a7.tar.gz
twinkie firmware: add support for vbus voltage and current
The format of an ep packet header (8 bytes) : Packets for cc1: [sample_tstamp, sample_seq, vbus_voltage, tstamp_offset] Packets for cc2: [sample_tstamp, sample_seq, vbus_current, tstamp_offset] Updated: use array to implement a circular queue; when a forming a packet, remove one element from the queue. In this way, we can capture more samples of vbus information. Updated: when sniffer task has not started sending packets, most recent vbus info is always stored at the first position of the queue, making sure that the first reported vbus info is the most recent one. Updated: allow user to compile the original version or the new version of the source code. In ec/board/twinkie/board.h Use #define CONFIG_USBC_SNIFFER_HEADER_V1, if you do not want twinkie to send out vbus info; Use #define CONFIG_USBC_SNIFFER_HEADER_V2, if you want twinkie to send out vbus info. Signed-off-by: Dawei Li <daweili@google.com> BUG=chrome-os-partner:42703 BRANCH=none TEST=BEGIN connect Twinkie to a waveform generator, record data using: sudo sigrok-cli -d chromium-twinkie --continuous -o test.sr then check the resulting waveforms on pulseview. END Change-Id: Ifdb6402eb7d998ffb25128c510d1780491b11872 Reviewed-on: https://chromium-review.googlesource.com/282388 Commit-Ready: Sheng-liang Song <ssl@chromium.org> Tested-by: Dawei Li <daweili@google.com> Reviewed-by: Sheng-liang Song <ssl@chromium.org>
Diffstat (limited to 'board/twinkie')
-rw-r--r--board/twinkie/board.h7
-rw-r--r--board/twinkie/sniffer.c185
2 files changed, 184 insertions, 8 deletions
diff --git a/board/twinkie/board.h b/board/twinkie/board.h
index 71aceecb1f..6ae82bac7e 100644
--- a/board/twinkie/board.h
+++ b/board/twinkie/board.h
@@ -25,6 +25,13 @@
#define CONFIG_USB_PD_TCPC
#define CONFIG_USB_PD_TCPM_STUB
#define CONFIG_PD_USE_DAC_AS_REF
+/*
+ * use #define CONFIG_USBC_SNIFFER_HEADER_V1
+ * if you do not want twinkie to send out vbus info;
+ * use #define CONFIG_USBC_SNIFFER_HEADER_V2
+ * if you want twinkie to send out vbus info.
+ */
+#define CONFIG_USBC_SNIFFER_HEADER_V1
#define CONFIG_HW_CRC
#ifndef HAS_TASK_PD /* PD sniffer mode */
diff --git a/board/twinkie/sniffer.c b/board/twinkie/sniffer.c
index bb2f0834a5..86bbc7ee54 100644
--- a/board/twinkie/sniffer.c
+++ b/board/twinkie/sniffer.c
@@ -18,11 +18,26 @@
#include "timer.h"
#include "usb.h"
#include "util.h"
-
+#include "ina2xx.h"
+
+#ifdef CONFIG_USBC_SNIFFER_HEADER_V2
+struct sniffer_sample_header {
+ uint16_t seq;
+ uint16_t tstamp;
+ uint16_t vbus_value; /* can be voltage or current */
+ int16_t sample_tstamp;
+};
+#endif
/* Size of one USB packet buffer */
#define EP_BUF_SIZE 64
+
+#ifdef CONFIG_USBC_SNIFFER_HEADER_V2
+#define EP_PACKET_HEADER_SIZE (sizeof(struct sniffer_sample_header))
+#else
+#define EP_PACKET_HEADER_SIZE 4
+#endif
/* Size of the payload (packet minus the header) */
-#define EP_PAYLOAD_SIZE (EP_BUF_SIZE - 4)
+#define EP_PAYLOAD_SIZE (EP_BUF_SIZE - EP_PACKET_HEADER_SIZE)
/* Buffer enough to avoid overflowing due to USB latencies on both sides */
#define RX_COUNT (16 * EP_PAYLOAD_SIZE)
@@ -42,11 +57,103 @@ static uint16_t sample_tstamp[4];
/* sequence number of the beginning of DMA buffers */
static uint16_t sample_seq[4];
+#ifdef CONFIG_USBC_SNIFFER_HEADER_V2
+/* after how long the deferred reads will wake up for the next read */
+#define DEFERRED_READ_TIME_US 8000
+#define VBUS_ARRAY_SIZE 8
+/* vbus voltage information: the voltage value and the timestamp offset */
+struct vbus_vol_info {
+ uint16_t vol;
+ uint16_t tstamp; /* the average time of before read and after read*/
+};
+
+/* vbus current information: the voltage value and the timestamp offset */
+struct vbus_curr_info {
+ int16_t curr;
+ uint16_t tstamp; /* the average time of before read and after read*/
+};
+
+/* an array-implemented circular queue to hold multiple vbus values */
+static struct vbus_vol_info vbus_vol_array[VBUS_ARRAY_SIZE];
+static uint32_t vbus_vol_head;
+static uint32_t vbus_vol_tail;
+
+static struct vbus_curr_info vbus_curr_array[VBUS_ARRAY_SIZE];
+static uint32_t vbus_curr_head;
+static uint32_t vbus_curr_tail;
+
+/* whether the sniffer task have started sending packet */
+static int flag_started;
+#endif
+
/* Bulk endpoint double buffer */
static usb_uint ep_buf[2][EP_BUF_SIZE / 2] __usb_ram;
/* USB Buffers not used, ready to be filled */
static volatile uint32_t free_usb = 3;
+#ifdef CONFIG_USBC_SNIFFER_HEADER_V2
+static void vbus_vol_read_deferred(void)
+{
+ /* read may be interrupted, use average of start & end as the tstamp */
+ /* Unit: ms */
+ uint16_t tstamp_bf;
+ uint16_t tstamp_af;
+ /* Unit: mV */
+ uint16_t vol;
+ uint16_t temp_tail;
+
+ if (flag_started == 0 || (flag_started == 1 &&
+ ((vbus_vol_tail - vbus_vol_head) < VBUS_ARRAY_SIZE))) {
+ /* if sniffer isn't started, always write to the first position */
+ temp_tail = (flag_started == 0) ?
+ 0 : (vbus_vol_tail & (VBUS_ARRAY_SIZE - 1));
+ tstamp_bf = __hw_clock_source_read();
+ vol = ((ina2xx_read(0, INA2XX_REG_BUS_VOLT)*5) >> 2); /* *125/100 */
+ tstamp_af = __hw_clock_source_read();
+ if (tstamp_bf > tstamp_af)
+ vbus_vol_array[temp_tail].tstamp =
+ ((tstamp_bf + tstamp_af + 0xFFFF)>>1) & 0xFFFF;
+ else
+ vbus_vol_array[temp_tail].tstamp = (tstamp_bf + tstamp_af)>>1;
+ vbus_vol_array[temp_tail].vol = vol;
+ vbus_vol_tail = (flag_started == 0) ? 1 : vbus_vol_tail + 1;
+ }
+
+ hook_call_deferred(vbus_vol_read_deferred, DEFERRED_READ_TIME_US);
+}
+DECLARE_DEFERRED(vbus_vol_read_deferred);
+
+static void vbus_curr_read_deferred(void)
+{
+ /* Unit: ms */
+ uint16_t tstamp_bf;
+ uint16_t tstamp_af;
+ /* Unit: mA */
+ uint16_t curr;
+ uint16_t temp_tail;
+
+ if (flag_started == 0 || (flag_started == 1 &&
+ ((vbus_curr_tail - vbus_curr_head) < VBUS_ARRAY_SIZE))) {
+ /* if sniffer isn't started, always write to the first position */
+ temp_tail = (flag_started == 0) ?
+ 0 : vbus_curr_tail & (VBUS_ARRAY_SIZE - 1);
+ tstamp_bf = __hw_clock_source_read();
+ curr = ina2xx_read(0, INA2XX_REG_CURRENT);
+ tstamp_af = __hw_clock_source_read();
+ if (tstamp_bf > tstamp_af)
+ vbus_curr_array[temp_tail].tstamp =
+ ((tstamp_bf + tstamp_af + 0xFFFF)>>1) & 0xFFFF;
+ else
+ vbus_curr_array[temp_tail].tstamp = (tstamp_bf + tstamp_af)>>1;
+ vbus_curr_array[temp_tail].curr = curr;
+ vbus_curr_tail = (flag_started == 0) ? 1 : vbus_curr_tail + 1;
+ }
+
+ hook_call_deferred(vbus_curr_read_deferred, DEFERRED_READ_TIME_US);
+}
+DECLARE_DEFERRED(vbus_curr_read_deferred);
+#endif
+
static inline void led_set_activity(int ch)
{
static int accumul[2];
@@ -151,6 +258,11 @@ static volatile uint32_t seq;
/* Buffer overflow count */
static uint32_t oflow;
+#define SNIFFER_CHANNEL_CC1 0
+#define SNIFFER_CHANNEL_CC2 1
+
+#define get_channel(b) (((b) >> 12) & 0x1)
+
void tim_rx1_handler(uint32_t stat)
{
stm32_dma_regs_t *dma = STM32_DMA1_REGS;
@@ -159,7 +271,8 @@ void tim_rx1_handler(uint32_t stat)
uint32_t next = idx ? 0x0001 : 0x0100;
sample_tstamp[idx] = __hw_clock_source_read();
- sample_seq[idx] = ((seq++ << 3) & 0x0ff8) | (0<<12) /* CC1 */;
+ sample_seq[idx] = ((seq++ << 3) & 0x0ff8) |
+ (SNIFFER_CHANNEL_CC1<<12);
if (filled_dma & next) {
oflow++;
sample_seq[idx] |= 0x8000;
@@ -180,7 +293,8 @@ void tim_rx2_handler(uint32_t stat)
idx += 2;
sample_tstamp[idx] = __hw_clock_source_read();
- sample_seq[idx] = ((seq++ << 3) & 0x0ff8) | (1<<12) /* CC2 */;
+ sample_seq[idx] = ((seq++ << 3) & 0x0ff8) |
+ (SNIFFER_CHANNEL_CC2<<12);
if (filled_dma & next) {
oflow++;
sample_seq[idx] |= 0x8000;
@@ -237,8 +351,23 @@ static void rx_timer_init(int tim_id, timer_ctlr_t *tim, int ch_idx, int up_idx)
tim->sr = 0;
}
+
+
void sniffer_init(void)
{
+#ifdef CONFIG_USBC_SNIFFER_HEADER_V2
+ vbus_vol_head = 0;
+ vbus_vol_tail = 0;
+ vbus_curr_head = 0;
+ vbus_curr_tail = 0;
+
+ /* whether the sniffer task have started sending packet */
+ flag_started = 0;
+
+ hook_call_deferred(vbus_vol_read_deferred, 0);
+ hook_call_deferred(vbus_curr_read_deferred, 0);
+#endif
+
/* remap TIM1 CH1/2/3 to DMA channel 6 */
STM32_SYSCFG_CFGR1 |= 1 << 28;
@@ -280,10 +409,19 @@ void sniffer_task(void)
int d = 0; /* current DMA buffer index */
int off = 0; /* DMA buffer offset */
+#ifdef CONFIG_USBC_SNIFFER_HEADER_V2
+ int ch; /* sniffer channel */
+ uint16_t vol = 0; /* voltage */
+ uint16_t vol_tstamp; /* timestamp in us */
+ uint16_t curr = 0; /* current */
+ uint16_t curr_tstamp;
+ uint16_t temp_vol_head;
+ uint16_t temp_curr_head;
+#endif
+
while (1) {
/* Wait for a new buffer of samples or a new USB free buffer */
task_wait_event(-1);
-
/* send the available samples over USB if we have a buffer*/
while (filled_dma && free_usb) {
while (!(filled_dma & (1 << d))) {
@@ -292,11 +430,42 @@ void sniffer_task(void)
if (off >= RX_COUNT)
off = 0;
}
+
ep_buf[u][0] = sample_seq[d >> 3] | (d & 7);
ep_buf[u][1] = sample_tstamp[d >> 3];
- memcpy_to_usbram(((void *)usb_sram_addr(ep_buf[u] + 2)),
- samples[d >> 4]+off, EP_PAYLOAD_SIZE);
- atomic_clear(&free_usb, 1 << u);
+
+#ifdef CONFIG_USBC_SNIFFER_HEADER_V2
+ flag_started = 1;
+ ch = get_channel(ep_buf[u][0]);
+ if (SNIFFER_CHANNEL_CC1 == ch) {
+ if (vbus_vol_tail - vbus_vol_head > 0) {
+ /* get a value from the queue */
+ temp_vol_head = vbus_vol_head & (VBUS_ARRAY_SIZE - 1);
+ vol = vbus_vol_array[temp_vol_head].vol;
+ vol_tstamp = vbus_vol_array[temp_vol_head].tstamp;
+ ++vbus_vol_head;
+ }
+ ep_buf[u][2] = vol; /* use previous values if queue empty*/
+ ep_buf[u][3] = vol_tstamp - ep_buf[u][1];
+
+ } else if (SNIFFER_CHANNEL_CC2 == ch) {
+ if (vbus_curr_tail - vbus_curr_head > 0) {
+ temp_curr_head = vbus_curr_head & (VBUS_ARRAY_SIZE - 1);
+ curr = vbus_curr_array[temp_curr_head].curr;
+ curr_tstamp = vbus_curr_array[temp_curr_head].tstamp;
+ ++vbus_curr_head;
+ }
+ ep_buf[u][2] = curr;
+ ep_buf[u][3] = curr_tstamp - ep_buf[u][1];
+ }
+#endif
+
+ memcpy_to_usbram(
+ ((void *)usb_sram_addr(ep_buf[u]
+ + (EP_PACKET_HEADER_SIZE>>1))),
+ samples[d >> 4]+off,
+ EP_PAYLOAD_SIZE);
+ atomic_clear((uint32_t *)&free_usb, 1 << u);
u = !u;
atomic_clear(&filled_dma, 1 << d);
}