summaryrefslogtreecommitdiff
path: root/gm_platform/fw/adc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gm_platform/fw/adc.c')
-rw-r--r--gm_platform/fw/adc.c47
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;