diff --git a/src/cdc_sump.c b/src/cdc_sump.c index 474df14..51eb4fd 100644 --- a/src/cdc_sump.c +++ b/src/cdc_sump.c @@ -26,6 +26,8 @@ * */ +#include + #include "tusb.h" #include "led.h" @@ -248,20 +250,20 @@ static void sump_set_chunk_size(void) picoprobe_debug("%s(): 0x%04x\n", __func__, sump.chunk_size); } -/* hardware handling ======================================================= */ +/* data capture ============================================================ */ -static void sump_dma_done(void) +static void sump_capture_done(void) { - sump_hw_xfer_stop(); + sump_hw_capture_stop(); /*uint64_t us = time_us_64() - sump.timestamp_start; picoprobe_debug("%s(): sampling time = %llu.%llu\n", __func__, us / 1000000ull, us % 1000000ull);*/ sump.state = SUMP_STATE_DUMP; } -static int sump_dma_next(uint32_t pos) +static int sump_capture_next(uint32_t pos) { if (sump.state != SUMP_STATE_TRIGGER) { - sump_dma_done(); + sump_capture_done(); return 0; } @@ -283,28 +285,28 @@ static int sump_dma_next(uint32_t pos) uint32_t delay_bytes = sump.delay_count * sump.width; tmp = sump.chunk_size - (pos % sump.chunk_size); if (tmp >= delay_bytes) { - sump_dma_done(); + sump_capture_done(); return 0; } return delay_bytes - tmp; } -uint8_t *sump_dma_get_next_dest(uint32_t numch) +uint8_t *sump_capture_get_next_dest(uint32_t numch) { return sump.buffer + (sump.dma_pos + numch * sump.chunk_size) % SUMP_MEMORY_SIZE; } -void sump_dma_irq_callback_cancelstuff(void) +void sump_capture_callback_cancel(void) { - sump_dma_done(); + sump_capture_done(); sump.state = SUMP_STATE_ERROR; } -void sump_dma_irq_callback(uint32_t ch, uint32_t numch) +void sump_capture_callback(uint32_t ch, uint32_t numch) { // reprogram the current DMA channel to the tail if (sump.next_count <= sump.chunk_size) { - sump.next_count = sump_dma_next(sump.dma_pos); + sump.next_count = sump_capture_next(sump.dma_pos); if (sump.state == SUMP_STATE_DUMP) return; } else { sump.next_count -= sump.chunk_size; @@ -320,7 +322,7 @@ void sump_dma_irq_callback(uint32_t ch, uint32_t numch) // set the last DMA segment to correct size to avoid overwrites uint32_t mask = sump.next_count / sump.chunk_size; - sump_hw_dma_setup_next(ch, mask, sump.chunk_size, sump.next_count, sump.width); + sump_hw_capture_setup_next(ch, mask, sump.chunk_size, sump.next_count, sump.width); } } @@ -352,7 +354,7 @@ static void sump_xfer_start(uint8_t state) // limit chunk size for slow sampling sump_set_chunk_size(); - /*sump.timestamp_start =*/ sump_hw_xfer_start(sump.width, sump.flags, + /*sump.timestamp_start =*/ sump_hw_capture_start(sump.width, sump.flags, sump.chunk_size, sump.buffer); sump.state = state; @@ -365,18 +367,22 @@ static void sump_do_meta(void) char cpu[32]; uint8_t buf[128], *ptr = buf, *wptr = buf; - uint32_t sysclk = sump_hw_get_sysclk() / SAMPLING_DIVIDER; - sprintf(cpu, "RP2040 %uMhz", sysclk / ONE_MHZ); ptr = sump_add_metas(ptr, SUMP_META_NAME, "Picoprobe Logic Analyzer v1"); - ptr = sump_add_metas(ptr, SUMP_META_FPGA_VERSION, "No FPGA :-( PIO+DMA!"); + sump_hw_get_hw_name(cpu); + ptr = sump_add_metas(ptr, SUMP_META_FPGA_VERSION, cpu); + sump_hw_get_cpu_name(cpu); ptr = sump_add_metas(ptr, SUMP_META_CPU_VERSION, cpu); - ptr = sump_add_meta4(ptr, SUMP_META_SAMPLE_RATE, sysclk); + ptr = sump_add_meta4(ptr, SUMP_META_SAMPLE_RATE, sump_hw_get_sysclk() / SAMPLING_DIVIDER); ptr = sump_add_meta4(ptr, SUMP_META_SAMPLE_RAM, SUMP_MEMORY_SIZE); ptr = sump_add_meta1(ptr, SUMP_META_PROBES_B, SAMPLING_BITS); ptr = sump_add_meta1(ptr, SUMP_META_PROTOCOL_B, 2); *ptr++ = SUMP_META_END; + + assert(ptr < &buf[128] && "Stack overflow! aaaa!"); + while (wptr != ptr) wptr += tud_cdc_n_write(CDC_INTF, wptr, ptr - wptr); + tud_cdc_n_write_flush(CDC_INTF); } @@ -417,7 +423,7 @@ static void sump_do_finish(void) { if (sump.state == SUMP_STATE_TRIGGER || sump.state == SUMP_STATE_SAMPLING) { sump.state = SUMP_STATE_DUMP; - sump_dma_done(); + sump_capture_done(); return; } } diff --git a/src/cdc_sump.h b/src/cdc_sump.h index 5afd560..3b5c67f 100644 --- a/src/cdc_sump.h +++ b/src/cdc_sump.h @@ -63,9 +63,9 @@ inline static int SUMP_CMD_IS_SHORT(int cmd) { uint32_t sump_calc_sysclk_divider(); -uint8_t *sump_dma_get_next_dest(uint32_t numch); -void sump_dma_irq_callback_cancelstuff(void); -void sump_dma_irq_callback(uint32_t ch, uint32_t numch); +uint8_t *sump_capture_get_next_dest(uint32_t numch); +void sump_capture_callback_cancel(void); +void sump_capture_callback(uint32_t ch, uint32_t numch); void cdc_sump_init(void); void cdc_sump_deinit(void); @@ -73,14 +73,17 @@ void cdc_sump_task(void); /* --- */ +void sump_hw_get_cpu_name(char cpu[32]); +void sump_hw_get_hw_name(char hw[32]); + uint32_t sump_hw_get_sysclk(void); void sump_hw_init(void); void sump_hw_deinit(void); -void sump_hw_dma_setup_next(uint32_t ch, uint32_t mask, uint32_t chunk_size, uint32_t next_count, uint8_t width); -void sump_hw_xfer_start(uint8_t width, int flags, uint32_t chunk_size, uint8_t *destbuf); -void sump_hw_xfer_stop(void); +void sump_hw_capture_setup_next(uint32_t ch, uint32_t mask, uint32_t chunk_size, uint32_t next_count, uint8_t width); +void sump_hw_capture_start(uint8_t width, int flags, uint32_t chunk_size, uint8_t *destbuf); +void sump_hw_capture_stop(void); void sump_hw_stop(void); #endif diff --git a/src/cdc_sump_pico.c b/src/cdc_sump_pico.c index 065477d..ebb2556 100644 --- a/src/cdc_sump_pico.c +++ b/src/cdc_sump_pico.c @@ -1,4 +1,7 @@ +#include + +#include #include #include #include @@ -54,6 +57,17 @@ uint32_t sump_hw_get_sysclk(void) return clock_get_hz(clk_sys); } +void sump_hw_get_cpu_name(char cpu[32]) +{ + snprintf(cpu, 32, "RP2040 @ %u MHz", + sump_hw_get_sysclk() / (ONE_MHZ * SAMPLING_DIVIDER)); +} +void sump_hw_get_hw_name(char hw[32]) +{ + snprintf(hw, 32, "RP2040 rev%hhu, ROM v%hhu", + rp2040_chip_version(), rp2040_rom_version()); +} + static void sump_pio_init(uint8_t width, bool nogr0) { uint32_t gpio = SAMPLING_GPIO_FIRST; @@ -196,7 +210,7 @@ static void sump_dma_chain_to_self(uint32_t ch) dma_channel_set_config(ch, &cfg, false); } -void sump_hw_dma_setup_next(uint32_t ch, uint32_t mask, uint32_t chunk_size, uint32_t next_count, uint8_t width) +void sump_hw_capture_setup_next(uint32_t ch, uint32_t mask, uint32_t chunk_size, uint32_t next_count, uint8_t width) { if ((next_count % chunk_size) == 0) { ch = (mask + dma_curr_idx - 1) % SUMP_DMA_CHANNELS; @@ -233,14 +247,14 @@ static void __isr sump_hw_dma_irq_handler(void) dma_curr_idx = (dma_curr_idx + 1) % SUMP_DMA_CHANNELS; - dma_channel_set_write_addr(ch, sump_dma_get_next_dest(SUMP_DMA_CHANNELS), false); + dma_channel_set_write_addr(ch, sump_capture_get_next_dest(SUMP_DMA_CHANNELS), false); //sump_irq_debug("%s(): %u: w=0x%08x, state=%u\n", __func__, ch, sump_dma_get_next_dest(), sump.state); - sump_dma_irq_callback(ch, SUMP_DMA_CHANNELS); + sump_capture_callback(ch, SUMP_DMA_CHANNELS); // are we slow? if (++loop == SUMP_DMA_CHANNELS) { - sump_dma_irq_callback_cancelstuff(); + sump_capture_callback_cancel(); break; } } @@ -254,11 +268,13 @@ static void sump_dma_program(uint32_t ch, uint32_t pos, uint8_t width, uint32_t channel_config_set_dreq(&cfg, pio_get_dreq(SAMPLING_PIO, SAMPLING_PIO_SM, false)); channel_config_set_chain_to(&cfg, SUMP_DMA_CH_FIRST + ((ch + 1) % SUMP_DMA_CHANNELS)); channel_config_set_transfer_data_size(&cfg, width == 1 ? DMA_SIZE_8 : DMA_SIZE_16); + dma_channel_configure(SUMP_DMA_CH_FIRST + ch, &cfg, destbuf + pos, &SAMPLING_PIO->rxf[SAMPLING_PIO_SM], chunk_size / width, false); + picoprobe_debug("%s() %u: w=0x%08x r=0x%08x t=0x%08x -> %u\n", __func__, SUMP_DMA_CH_FIRST + ch, destbuf + pos, @@ -267,7 +283,7 @@ static void sump_dma_program(uint32_t ch, uint32_t pos, uint8_t width, uint32_t SUMP_DMA_CH_FIRST + ((ch + 1) % SUMP_DMA_CHANNELS)); } -/*uint64_t*/void sump_hw_xfer_start(uint8_t width, int flags, uint32_t chunk_size, uint8_t *destbuf) +/*uint64_t*/void sump_hw_capture_start(uint8_t width, int flags, uint32_t chunk_size, uint8_t *destbuf) { sump_pio_init(width, flags & SUMP_FLAG1_GR0_DISABLE); @@ -286,15 +302,16 @@ static void sump_dma_program(uint32_t ch, uint32_t pos, uint8_t width, uint32_t // let's go uint32_t irq_state = save_and_disable_interrupts(); pio_sm_set_enabled(SAMPLING_PIO, SAMPLING_PIO_SM, true); - if (pwm_mask) - pwm_set_mask_enabled(pwm_mask); + + if (pwm_mask) pwm_set_mask_enabled(pwm_mask); + dma_channel_start(SUMP_DMA_CH_FIRST); irq_set_enabled(SAMPLING_DMA_IRQ, true); restore_interrupts(irq_state); //return time_us_64(); } -void sump_hw_xfer_stop(void) +void sump_hw_capture_stop(void) { pio_sm_set_enabled(SAMPLING_PIO, SAMPLING_PIO_SM, false); irq_set_enabled(SAMPLING_DMA_IRQ, false);