altos: Allow STM DMA channels to be reserved for one use
authorKeith Packard <keithp@keithp.com>
Mon, 9 Apr 2012 07:05:18 +0000 (00:05 -0700)
committerKeith Packard <keithp@keithp.com>
Mon, 9 Apr 2012 07:05:18 +0000 (00:05 -0700)
This allows a single user of a DMA channel to reserve it for use
without needing to lock the mutex; this is required for DMA from the
ADC to work on megametrum as it wants to start DMA from an interrupt
handler, which cannot block on a mutex.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/stm/ao_adc_stm.c
src/stm/ao_arch_funcs.h
src/stm/ao_dma_stm.c

index d758e629bac7461eae6ed52097f19e6d78afb620..729551c4b036673512976e451bc6b2b980896098 100644 (file)
@@ -221,5 +221,7 @@ ao_adc_init(void)
        /* Clear any stale status bits */
        stm_adc.sr = 0;
        ao_adc_ready = 1;
+
+       ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
        ao_cmd_register(&ao_adc_cmds[0]);
 }
index a42fe10f3cf9b3d5356b77407b6df46ee9099eae..7dc576d1bb9792f20c1b7953afd5e593a7f62af3 100644 (file)
@@ -61,6 +61,9 @@ ao_dma_done_transfer(uint8_t index);
 void
 ao_dma_abort(uint8_t index);
 
+void
+ao_dma_alloc(uint8_t index);
+
 void
 ao_dma_init(void);
 
index 785235a8023cfe94512ce35c5a34ef46c7201182..21390748b86dae82eddaec7e2662be60e38aa6a2 100644 (file)
@@ -26,6 +26,7 @@ struct ao_dma_config {
 uint8_t ao_dma_done[NUM_DMA];
 
 static struct ao_dma_config ao_dma_config[NUM_DMA];
+static uint8_t ao_dma_allocated[NUM_DMA];
 static uint8_t ao_dma_mutex[NUM_DMA];
 static uint8_t ao_dma_active;
 
@@ -60,7 +61,12 @@ ao_dma_set_transfer(uint8_t          index,
                    uint16_t            count,
                    uint32_t            ccr)
 {
-       ao_mutex_get(&ao_dma_mutex[index]);
+       if (ao_dma_allocated[index]) {
+               if (ao_dma_mutex[index])
+                       ao_panic(AO_PANIC_DMA);
+               ao_dma_mutex[index] = 1;
+       } else
+               ao_mutex_get(&ao_dma_mutex[index]);
        ao_arch_critical(
                if (ao_dma_active++ == 0)
                        stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
@@ -93,7 +99,10 @@ ao_dma_done_transfer(uint8_t index)
                if (--ao_dma_active == 0)
                        stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN);
                );
-       ao_mutex_put(&ao_dma_mutex[index]);
+       if (ao_dma_allocated[index])
+               ao_dma_mutex[index] = 0;
+       else
+               ao_mutex_put(&ao_dma_mutex[index]);
 }
 
 void
@@ -102,6 +111,14 @@ ao_dma_abort(uint8_t index)
        stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
 }
 
+void
+ao_dma_alloc(uint8_t index)
+{
+       if (ao_dma_allocated[index])
+               ao_panic(AO_PANIC_DMA);
+       ao_dma_allocated[index] = 1;
+}
+
 void
 ao_dma_init(void)
 {
@@ -110,6 +127,8 @@ ao_dma_init(void)
        for (index = 0; index < STM_NUM_DMA; index++) {
                stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index);
                stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4);
+               ao_dma_allocated[index] = 0;
+               ao_dma_mutex[index] = 0;
        }
        
 }