Updage from NeuG 0.11

This commit is contained in:
NIIBE Yutaka
2013-09-25 13:39:33 +09:00
parent fae8c726b1
commit 8dc4022944
5 changed files with 329 additions and 178 deletions

View File

@@ -1,5 +1,7 @@
/*
* adc_stm32f103.c - ADC driver for STM32F103
* In this ADC driver, there are NeuG specific parts.
* You need to modify to use this as generic ADC driver.
*
* Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -75,17 +77,11 @@
#endif
#define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
#define NEUG_DMA_MODE_SAMPLE \
#define NEUG_DMA_MODE \
( STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY) \
| STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD \
| STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE \
| STM32_DMA_CR_TEIE)
#define NEUG_DMA_MODE_CRC32 \
( STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY) \
| STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD \
| STM32_DMA_CR_MINC \
| STM32_DMA_CR_TCIE | STM32_DMA_CR_TEIE)
| STM32_DMA_CR_TEIE )
#define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF) \
| ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_SENSOR)
@@ -167,71 +163,54 @@ void adc_start (void)
ADC2->SQR3 = NEUG_ADC_SETTING2_SQR3;
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
/*
* We could just let ADC run continuously always and only enable DMA
* to receive stable data from ADC. But our purpose is not to get
* correct data but noise. In fact, we can get more noise when we
* start/stop ADC each time.
*/
ADC2->CR2 = 0;
ADC1->CR2 = 0;
#else
/* Start conversion. */
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
#endif
}
static int adc_mode;
static uint32_t *adc_ptr;
static int adc_size;
static uint32_t adc_buf[64];
uint32_t adc_buf[64];
static void adc_start_conversion_internal (void)
void adc_start_conversion (int offset, int count)
{
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
DMA1_Channel1->CMAR = (uint32_t)&adc_buf[offset]; /* SetMemory0 */
DMA1_Channel1->CNDTR = count; /* Counter */
DMA1_Channel1->CCR = NEUG_DMA_MODE | DMA_CCR1_EN; /* Mode */
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
/* Power on */
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
/* Start conversion. tSTAB is 1uS, but we don't follow the spec. */
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
#else
/*
* Start conversion. tSTAB is 1uS, but we don't follow the spec, to
* get more noise.
*/
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
#endif
}
void adc_start_conversion (int mode, uint32_t *p, int size)
{
adc_mode = mode;
adc_ptr = p;
adc_size = size;
if (mode == ADC_SAMPLE_MODE)
{
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
DMA1_Channel1->CMAR = (uint32_t)p; /* SetMemory0 */
DMA1_Channel1->CNDTR = (uint32_t)size / 4; /* counter */
DMA1_Channel1->CCR = NEUG_DMA_MODE_SAMPLE; /*mode*/
DMA1_Channel1->CCR |= DMA_CCR1_EN; /* Enable */
}
else
{
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
DMA1_Channel1->CMAR = (uint32_t)adc_buf; /* SetMemory0 */
DMA1_Channel1->CNDTR = size; /* counter */
DMA1_Channel1->CCR = NEUG_DMA_MODE_CRC32; /*mode*/
DMA1_Channel1->CCR |= DMA_CCR1_EN; /* Enable */
}
adc_start_conversion_internal ();
}
static void adc_stop_conversion (void)
{
DMA1_Channel1->CCR &= ~DMA_CCR1_EN;
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
ADC1->CR2 = 0;
ADC2->CR2 = 0;
#else
ADC2->CR2 &= ~ADC_CR2_CONT;
ADC1->CR2 &= ~ADC_CR2_CONT;
ADC1->CR2 = 0;
#endif
}
@@ -248,43 +227,46 @@ void adc_stop (void)
}
static void adc_lld_serve_rx_interrupt (uint32_t flags)
{
if ((flags & STM32_DMA_ISR_TEIF) != 0) /* DMA errors */
{
/* Should never happened. If any, it's coding error. */
/* Access an unmapped address space or alignment violation. */
adc_stop_conversion ();
}
else
{
if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
{
adc_stop_conversion ();
static uint32_t adc_err;
if (adc_mode != ADC_SAMPLE_MODE)
{
int i;
for (i = 0; i < adc_size;)
{
CRC->DR = adc_buf[i++];
CRC->DR = adc_buf[i++];
CRC->DR = adc_buf[i++];
CRC->DR = adc_buf[i++];
*adc_ptr++ = CRC->DR;
}
}
}
}
}
void adc_wait (chopstx_intr_t *intr)
/*
* Return 0 on success.
* Return 1 on error.
*/
int adc_wait_completion (chopstx_intr_t *intr)
{
uint32_t flags;
chopstx_intr_wait (intr);
flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause. */
DMA1->IFCR = STM32_DMA_ISR_MASK; /* Clear interrupt of channel 1. */
adc_lld_serve_rx_interrupt (flags);
while (1)
{
chopstx_intr_wait (intr);
flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause. */
/*
* Clear interrupt cause of channel 1.
*
* Note that CGIFx=0, as CGIFx=1 clears all of GIF, HTIF, TCIF
* and TEIF.
*/
DMA1->IFCR = (flags & ~1);
if ((flags & STM32_DMA_ISR_TEIF) != 0) /* DMA errors */
{
/* Should never happened. If any, it's coding error. */
/* Access an unmapped address space or alignment violation. */
adc_err++;
adc_stop_conversion ();
return 1;
}
else if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
{
adc_stop_conversion ();
return 0;
}
/*
* Even if STM32_DMA_CR_HTIE is unset, we come here with HTIF=1,
* with unknown reason. Just ignore the interrupt by HTIF to
* continue more data.
*/
}
}