diff options
Diffstat (limited to 'gm_platform/fw/adc.c')
-rw-r--r-- | gm_platform/fw/adc.c | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/gm_platform/fw/adc.c b/gm_platform/fw/adc.c index 2a33171..e3aba5b 100644 --- a/gm_platform/fw/adc.c +++ b/gm_platform/fw/adc.c @@ -22,16 +22,22 @@ #include <stdlib.h> #include <assert.h> -volatile uint16_t adc_buf[100]; /* 100ms worth of data */ -uint32_t usart_overruns = 0; - -static void adc_dma_init(int burstlen); +static struct __attribute__((__packed__)) hl_adc_pkt { + struct ll_pkt ll; + uint16_t seq; + volatile uint16_t data[32]; +} adc_pkt[2]; +static uint16_t current_seq = 0; +static int current_buf = 0; + +static void adc_dma_init(void); static void adc_timer_init(int psc, int ivl); +static void adc_dma_launch(void); /* Mode that can be used for debugging */ void adc_configure_scope_mode(int sampling_interval_ns) { - adc_dma_init(sizeof(adc_buf)/sizeof(adc_buf[0])); + adc_dma_init(); /* Clock from PCLK/4 instead of the internal exclusive high-speed RC oscillator. */ ADC1->CFGR2 = (2<<ADC_CFGR2_CKMODE_Pos); /* Use PCLK/4=12MHz */ @@ -59,24 +65,28 @@ void adc_configure_scope_mode(int sampling_interval_ns) { adc_timer_init(12/*250ns/tick*/, cycles); } -static void adc_dma_init(int burstlen) { +static void adc_dma_init() { /* Configure DMA 1 Channel 1 to get rid of all the data */ DMA1_Channel1->CPAR = (unsigned int)&ADC1->DR; - DMA1_Channel1->CMAR = (unsigned int)&adc_buf; - DMA1_Channel1->CNDTR = burstlen; DMA1_Channel1->CCR = (0<<DMA_CCR_PL_Pos); DMA1_Channel1->CCR |= - DMA_CCR_CIRC /* circular mode so we can leave it running indefinitely */ - | (1<<DMA_CCR_MSIZE_Pos) /* 16 bit */ + (1<<DMA_CCR_MSIZE_Pos) /* 16 bit */ | (1<<DMA_CCR_PSIZE_Pos) /* 16 bit */ | DMA_CCR_MINC - | DMA_CCR_HTIE /* Enable half-transfer interrupt. */ | DMA_CCR_TCIE; /* Enable transfer complete interrupt. */ /* triggered on half-transfer and on transfer completion. We use this to send out the ADC data and to trap into GDB. */ NVIC_EnableIRQ(DMA1_Channel1_IRQn); - NVIC_SetPriority(DMA1_Channel1_IRQn, 3<<5); + NVIC_SetPriority(DMA1_Channel1_IRQn, 2<<5); + + adc_dma_launch(); +} +void adc_dma_launch() { + DMA1_Channel1->CCR &= ~DMA_CCR_EN; /* Disable channel */ + current_buf = !current_buf; + DMA1_Channel1->CMAR = (unsigned int)&(adc_pkt[current_buf].data); + DMA1_Channel1->CNDTR = ARRAY_LEN(adc_pkt[current_buf].data); DMA1_Channel1->CCR |= DMA_CCR_EN; /* Enable channel */ } @@ -103,18 +113,13 @@ void DMA1_Channel1_IRQHandler(void) { uint32_t isr = DMA1->ISR; /* Clear the interrupt flag */ DMA1->IFCR |= DMA_IFCR_CGIF1; + adc_dma_launch(); gdb_dump(); - static_assert(ARRAY_LEN(adc_buf) % 2 == 0, "ADC_BUFSIZE must be even for half-transfer uart tx logic to work"); - - int rc; - if (isr & DMA_ISR_HTIF2) /* half-transfer */ - rc = usart_send_packet_nonblocking((uint8_t *)adc_buf, sizeof(adc_buf)/2); - else /* end of transfer */ - rc = usart_send_packet_nonblocking((uint8_t *)adc_buf + ARRAY_LEN(adc_buf)/2, sizeof(adc_buf)/2); - if (rc) - usart_overruns++; + adc_pkt[!current_buf].seq = current_seq++; + /* Ignore return value since we can't do anything here. Overruns are logged in serial.c. */ + usart_send_packet_nonblocking(&adc_pkt[!current_buf].ll, sizeof(adc_pkt[!current_buf])); /* static int debug_buf_pos = 0; |