summaryrefslogtreecommitdiff
path: root/board/twinkie/sniffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/twinkie/sniffer.c')
-rw-r--r--board/twinkie/sniffer.c402
1 files changed, 0 insertions, 402 deletions
diff --git a/board/twinkie/sniffer.c b/board/twinkie/sniffer.c
deleted file mode 100644
index 00effb8539..0000000000
--- a/board/twinkie/sniffer.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/* Copyright 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "atomic.h"
-#include "clock.h"
-#include "common.h"
-#include "console.h"
-#include "dma.h"
-#include "gpio.h"
-#include "hwtimer.h"
-#include "hooks.h"
-#include "injector.h"
-#include "link_defs.h"
-#include "registers.h"
-#include "task.h"
-#include "timer.h"
-#include "usb_descriptor.h"
-#include "usb_hw.h"
-#include "util.h"
-#include "ina2xx.h"
-
-/* Size of one USB packet buffer */
-#define EP_BUF_SIZE 64
-
-#define EP_PACKET_HEADER_SIZE 4
-/* Size of the payload (packet minus the header) */
-#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)
-
-/* Task event for the USB transfer interrupt */
-#define USB_EVENT TASK_EVENT_CUSTOM_BIT(0)
-
-/* Bitmap of enabled capture channels : CC1+CC2 by default */
-static uint8_t channel_mask = 0x3;
-
-/* edge timing samples */
-static uint8_t samples[2][RX_COUNT];
-/* bitmap of the samples sub-buffer filled with DMA data */
-static volatile uint32_t filled_dma;
-/* timestamps of the beginning of DMA buffers */
-static uint16_t sample_tstamp[4];
-/* sequence number of the beginning of DMA buffers */
-static uint16_t sample_seq[4];
-
-/* 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;
-
-static inline void led_set_activity(int ch)
-{
- static int accumul[2];
- static uint32_t last_ts[2];
- uint32_t now = __hw_clock_source_read();
- int delta = now - last_ts[ch];
- last_ts[ch] = now;
- accumul[ch] = MAX(0, accumul[ch] + (30000 - delta));
- gpio_set_level(ch ? GPIO_LED_R_L : GPIO_LED_G_L, !accumul[ch]);
-}
-
-static inline void led_set_record(void)
-{
- gpio_set_level(GPIO_LED_B_L, 0);
-}
-
-static inline void led_reset_record(void)
-{
- gpio_set_level(GPIO_LED_B_L, 1);
-}
-
-/* USB descriptors */
-const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_VENDOR) = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = USB_IFACE_VENDOR,
- .bAlternateSetting = 0,
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass = USB_CLASS_VENDOR_SPEC,
- .bInterfaceProtocol = 0,
- .iInterface = USB_STR_SNIFFER,
-};
-const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_VENDOR,
- USB_EP_SNIFFER) = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 0x80 | USB_EP_SNIFFER,
- .bmAttributes = 0x02 /* Bulk IN */,
- .wMaxPacketSize = USB_MAX_PACKET_SIZE,
- .bInterval = 1
-};
-
-/* USB callbacks */
-static void ep_tx(void)
-{
- static int b; /* current buffer index */
- if (btable_ep[USB_EP_SNIFFER].tx_count) {
- /* we have transmitted the previous buffer, toggle it */
- free_usb |= 1 << b;
- b = b ? 0 : 1;
- btable_ep[USB_EP_SNIFFER].tx_addr = usb_sram_addr(ep_buf[b]);
- }
- /* re-enable data transmission if we have available data */
- btable_ep[USB_EP_SNIFFER].tx_count = (free_usb & (1<<b)) ? 0
- : EP_BUF_SIZE;
- STM32_TOGGLE_EP(USB_EP_SNIFFER, EP_TX_MASK, EP_TX_VALID, 0);
- /* wake up the processing */
- task_set_event(TASK_ID_SNIFFER, USB_EVENT);
-}
-
-static void ep_event(enum usb_ep_event evt)
-{
- if (evt != USB_EVENT_RESET)
- return;
-
- /* Bulk IN endpoint */
- btable_ep[USB_EP_SNIFFER].tx_addr = usb_sram_addr(ep_buf[0]);
- btable_ep[USB_EP_SNIFFER].tx_count = EP_BUF_SIZE;
- STM32_USB_EP(USB_EP_SNIFFER) = (USB_EP_SNIFFER << 0) /*Endpoint Num*/ |
- (3 << 4) /* TX Valid */ |
- (0 << 9) /* Bulk EP */ |
- (0 << 12) /* RX Disabled */;
-}
-USB_DECLARE_EP(USB_EP_SNIFFER, ep_tx, ep_tx, ep_event);
-
-
-/* --- RX operation using comparator linked to timer --- */
-/* RX on CC1 is using COMP1 triggering TIM1 CH1 */
-#define TIM_RX1 1
-#define DMAC_TIM_RX1 STM32_DMAC_CH6
-#define TIM_RX1_CCR_IDX 1
-/* RX on CC1 is using COMP2 triggering TIM2 CH4 */
-#define TIM_RX2 2
-#define DMAC_TIM_RX2 STM32_DMAC_CH7
-#define TIM_RX2_CCR_IDX 4
-
-/* Clock divider for RX edges timings (2.4Mhz counter from 48Mhz clock) */
-#define RX_CLOCK_DIV (20 - 1)
-
-static const struct dma_option dma_tim_cc1 = {
- DMAC_TIM_RX1, (void *)&STM32_TIM_CCRx(TIM_RX1, TIM_RX1_CCR_IDX),
- STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT |
- STM32_DMA_CCR_CIRC | STM32_DMA_CCR_TCIE | STM32_DMA_CCR_HTIE
-};
-
-static const struct dma_option dma_tim_cc2 = {
- DMAC_TIM_RX2, (void *)&STM32_TIM_CCRx(TIM_RX2, TIM_RX2_CCR_IDX),
- STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT |
- STM32_DMA_CCR_CIRC | STM32_DMA_CCR_TCIE | STM32_DMA_CCR_HTIE
-};
-
-/* sequence number for sample buffers */
-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;
- int idx = !(stat & STM32_DMA_ISR_HTIF(DMAC_TIM_RX1));
- uint32_t mask = idx ? 0xFF00 : 0x00FF;
- uint32_t next = idx ? 0x0001 : 0x0100;
-
- sample_tstamp[idx] = __hw_clock_source_read();
- sample_seq[idx] = ((seq++ << 3) & 0x0ff8) |
- (SNIFFER_CHANNEL_CC1<<12);
- if (filled_dma & next) {
- oflow++;
- sample_seq[idx] |= 0x8000;
- } else {
- led_set_record();
- }
- filled_dma |= mask;
- dma->ifcr = STM32_DMA_ISR_ALL(DMAC_TIM_RX1);
- led_set_activity(0);
-}
-
-void tim_rx2_handler(uint32_t stat)
-{
- stm32_dma_regs_t *dma = STM32_DMA1_REGS;
- int idx = !(stat & STM32_DMA_ISR_HTIF(DMAC_TIM_RX2));
- uint32_t mask = idx ? 0xFF000000 : 0x00FF0000;
- uint32_t next = idx ? 0x00010000 : 0x01000000;
-
- idx += 2;
- sample_tstamp[idx] = __hw_clock_source_read();
- sample_seq[idx] = ((seq++ << 3) & 0x0ff8) |
- (SNIFFER_CHANNEL_CC2<<12);
- if (filled_dma & next) {
- oflow++;
- sample_seq[idx] |= 0x8000;
- } else {
- led_set_record();
- }
- filled_dma |= mask;
- dma->ifcr = STM32_DMA_ISR_ALL(DMAC_TIM_RX2);
- led_set_activity(1);
-}
-
-void tim_dma_handler(void)
-{
- stm32_dma_regs_t *dma = STM32_DMA1_REGS;
- uint32_t stat = dma->isr & (STM32_DMA_ISR_HTIF(DMAC_TIM_RX1)
- | STM32_DMA_ISR_TCIF(DMAC_TIM_RX1)
- | STM32_DMA_ISR_HTIF(DMAC_TIM_RX2)
- | STM32_DMA_ISR_TCIF(DMAC_TIM_RX2));
- if (stat & STM32_DMA_ISR_ALL(DMAC_TIM_RX2))
- tim_rx2_handler(stat);
- else
- tim_rx1_handler(stat);
- /* time to process the samples */
- task_set_event(TASK_ID_SNIFFER, USB_EVENT);
-}
-DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_4_7, tim_dma_handler, 1);
-
-static void rx_timer_init(int tim_id, timer_ctlr_t *tim, int ch_idx, int up_idx)
-{
- int bit_idx = 8 * ((ch_idx - 1) % 2);
- /* --- set counter for RX timing : 2.4Mhz rate, free-running --- */
- __hw_timer_enable_clock(tim_id, 1);
- /* Timer configuration */
- tim->cr1 = 0x0004;
- tim->cr2 = 0x0000;
- /* Auto-reload value : 8-bit free running counter */
- tim->arr = 0xFF;
- /* Counter reloading event after 106us */
- tim->ccr[1] = 0xFF;
- /* Timer ICx input configuration */
- if (ch_idx <= 2)
- tim->ccmr1 = 1 << bit_idx;
- else
- tim->ccmr2 = 1 << bit_idx;
- tim->ccer = 0xB << ((ch_idx - 1) * 4);
- /* TODO: add input filtering */
- /* configure DMA request on CCRx update and overflow/update event */
- tim->dier = (1 << (8 + ch_idx)) | (1 << (8 + up_idx));
- /* set prescaler to /26 (F=2.4Mhz, T=0.4us) */
- tim->psc = RX_CLOCK_DIV;
- /* Reload the pre-scaler and reset the counter, clear CCRx */
- tim->egr = 0x001F;
- /* clear update event from reloading */
- tim->sr = 0;
-}
-
-
-
-void sniffer_init(void)
-{
- /* remap TIM1 CH1/2/3 to DMA channel 6 */
- STM32_SYSCFG_CFGR1 |= BIT(28);
-
- /* TIM1 CH1 for CC1 RX */
- rx_timer_init(TIM_RX1, (void *)STM32_TIM_BASE(TIM_RX1),
- TIM_RX1_CCR_IDX, 2);
- /* TIM3 CH4 for CC2 RX */
- rx_timer_init(TIM_RX2, (void *)STM32_TIM_BASE(TIM_RX2),
- TIM_RX2_CCR_IDX, 2);
-
- /* turn on COMP/SYSCFG */
- STM32_RCC_APB2ENR |= BIT(0);
- STM32_COMP_CSR = STM32_COMP_CMP1EN | STM32_COMP_CMP1MODE_HSPEED |
- STM32_COMP_CMP1INSEL_VREF12 |
- STM32_COMP_CMP1OUTSEL_TIM1_IC1 |
- STM32_COMP_CMP1HYST_HI |
- STM32_COMP_CMP2EN | STM32_COMP_CMP2MODE_HSPEED |
- STM32_COMP_CMP2INSEL_VREF12 |
- STM32_COMP_CMP2OUTSEL_TIM2_IC4 |
- STM32_COMP_CMP2HYST_HI;
-
- /* start sampling the edges on the CC lines using the RX timers */
- dma_start_rx(&dma_tim_cc1, RX_COUNT, samples[0]);
- dma_start_rx(&dma_tim_cc2, RX_COUNT, samples[1]);
- task_enable_irq(STM32_IRQ_DMA_CHANNEL_4_7);
- /* start RX timers on CC1 and CC2 */
- STM32_TIM_CR1(TIM_RX1) |= 1;
- STM32_TIM_CR1(TIM_RX2) |= 1;
-}
-DECLARE_HOOK(HOOK_INIT, sniffer_init, HOOK_PRIO_DEFAULT);
-
-/* state of the simple text tracer */
-extern int trace_mode;
-
-/* Task to post-process the samples and copy them the USB endpoint buffer */
-void sniffer_task(void)
-{
- int u = 0; /* current USB buffer index */
- int d = 0; /* current DMA buffer index */
- int off = 0; /* DMA buffer offset */
-
- 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 & BIT(d))) {
- d = (d + 1) & 31;
- off += EP_PAYLOAD_SIZE;
- 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]
- + (EP_PACKET_HEADER_SIZE>>1))),
- samples[d >> 4]+off,
- EP_PAYLOAD_SIZE);
- atomic_clear_bits((uint32_t *)&free_usb, 1 << u);
- u = !u;
- atomic_clear_bits((uint32_t *)&filled_dma, 1 << d);
- }
- led_reset_record();
-
- if (trace_mode != TRACE_MODE_OFF) {
- uint8_t curr = recording_enable(0);
- trace_packets();
- recording_enable(curr);
- }
- }
-}
-
-int wait_packet(int pol, uint32_t min_edges, uint32_t timeout_us)
-{
- stm32_dma_chan_t *chan = dma_get_channel(pol ? DMAC_TIM_RX2
- : DMAC_TIM_RX1);
- uint32_t t0 = __hw_clock_source_read();
- uint32_t c0 = chan->cndtr;
- uint32_t t_gap = t0;
- uint32_t c_gap = c0;
- uint32_t total_edges = 0;
-
- while (1) {
- uint32_t t = __hw_clock_source_read();
- uint32_t c = chan->cndtr;
- if (t - t0 > timeout_us) /* Timeout */
- break;
- if (min_edges) { /* real packet detection */
- int nb = (int)c_gap - (int)c;
- if (nb < 0)
- nb = RX_COUNT - nb;
- if (nb > 3) { /* NOT IDLE */
- t_gap = t;
- c_gap = c;
- total_edges += nb;
- } else {
- if ((t - t_gap) > 20 &&
- (total_edges - (t - t0)/256) >= min_edges)
- /* real gap after the packet */
- break;
- }
- }
- }
- return (__hw_clock_source_read() - t0 > timeout_us);
-}
-
-uint8_t recording_enable(uint8_t new_mask)
-{
- uint8_t old_mask = channel_mask;
- uint8_t diff = channel_mask ^ new_mask;
- /* start/stop RX timers according to the channel mask */
- if (diff & 1) {
- if (new_mask & 1)
- STM32_TIM_CR1(TIM_RX1) |= 1;
- else
- STM32_TIM_CR1(TIM_RX1) &= ~1;
- }
- if (diff & 2) {
- if (new_mask & 2)
- STM32_TIM_CR1(TIM_RX2) |= 1;
- else
- STM32_TIM_CR1(TIM_RX2) &= ~1;
- }
- channel_mask = new_mask;
- return old_mask;
-}
-
-static void sniffer_sysjump(void)
-{
- /* Stop DMA before jumping to avoid memory corruption */
- recording_enable(0);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, sniffer_sysjump, HOOK_PRIO_DEFAULT);
-
-static int command_sniffer(int argc, char **argv)
-{
- ccprintf("Seq number:%d Overflows: %d\n", seq, oflow);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(sniffer, command_sniffer,
- "[]", "Buffering status");