AnsweredAssumed Answered

TIM2 TRGO not triggering ADC1

Question asked by gtoonstra on Nov 12, 2014
Latest reply on May 28, 2017 by minthemerciless
Hello,

I've been trying to trigger ADC1 conversions for transfer through DMA afterwards, but unsuccessful so far. I searched and verified examples, verified all code and registers and cannot figure it out so far. I'm using a new STM32F042C6 chip on a custom made board, so some hardware issue cannot be eliminated. Hopefully, someone can point out what I may be doing wrong. I'm using libopencm3 as an abstraction.

Configuration code to enable clocks:

static void config_clock( void )
{
    rcc_clock_setup_in_hse_8mhz_out_48mhz();
    rcc_periph_clock_enable(RCC_GPIOA);
    rcc_periph_clock_enable(RCC_GPIOB);
    rcc_periph_clock_enable(RCC_DMA);
    rcc_periph_clock_enable(RCC_SPI1);
    rcc_periph_clock_enable(RCC_ADC);
    rcc_periph_clock_enable(RCC_CAN);

    rcc_periph_clock_enable(RCC_USART1);
    rcc_periph_clock_enable(RCC_TIM1);
    rcc_periph_clock_enable(RCC_TIM2);
    rcc_periph_clock_enable(RCC_TIM3);
    rcc_periph_clock_enable(RCC_TIM14);
}


Code to configure timer2:

void config_tim2( void )
{
    uint32_t timer = TIM2;
    /* Time Base configuration */
    timer_reset(timer);
    timer_set_mode(timer, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    timer_set_period(timer, 1000);
    timer_set_prescaler(timer, 47);
    /* Generate TRGO on every update. */
    timer_set_master_mode(timer, TIM_CR2_MMS_UPDATE);
    timer_enable_counter(timer);
}


Code to configure adc:

static uint8_t channel_array[] = { ADC_CHANNEL3, ADC_CHANNEL4, ADC_CHANNEL5 };

void config_adc( void )
{
    // Enable ADC interrupt for checking.
    nvic_enable_irq(NVIC_ADC_COMP_IRQ);
    nvic_set_priority(NVIC_ADC_COMP_IRQ, 0);

    adc_power_off(ADC1);
    adc_set_clk_source(ADC1, ADC_CLKSOURCE_ADC);
    adc_calibrate_start(ADC1);
    adc_calibrate_wait_finish(ADC1);
    adc_set_operation_mode(ADC1, ADC_MODE_SCAN);

    // this selects TIM2-TRGO
    adc_enable_external_trigger_regular(ADC1, ADC_CFGR1_EXTSEL_VAL(0b010), ADC_CFGR1_EXTEN_RISING );
    adc_set_right_aligned(ADC1);
    adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_239DOT5);
    adc_set_regular_sequence(ADC1, NUM_CHANNELS, channel_array);
    adc_set_resolution(ADC1, ADC_RESOLUTION_12BIT);
    adc_disable_analog_watchdog(ADC1);

    adc_power_on(ADC1);

    /* Wait for ADC starting up. */
    int i;
    for (i = 0; i < 800000; i++) {    /* Wait a bit. */
        __asm__("nop");
    }

    adc_enable_overrun_interrupt( ADC1 );
    adc_enable_eoc_sequence_interrupt( ADC1 );
    adc_enable_eoc_interrupt( ADC1 );

    adc_enable_dma( ADC1 );

    dma_channel_reset(DMA1, DMA_CHANNEL1);

    // DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
    dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &ADC1_DR );

    //DMA1_Channel1->CMAR = (uint32_t)(ADC_array);
    dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t)ADC_array);
    
    //DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNEL;
    dma_set_number_of_data(DMA1, DMA_CHANNEL1, NUM_CHANNELS);

    dma_set_read_from_memory(DMA1, DMA_CHANNEL1);

    // DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0
    //                | DMA_CCR_TEIE | DMA_CCR_TCIE ;
    dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1);
    dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_16BIT);
    dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_16BIT);
    dma_enable_transfer_error_interrupt(DMA1, DMA_CHANNEL1);
    dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL1);
    dma_set_priority(DMA1, DMA_CHANNEL1, DMA_CCR_PL_HIGH);

    // Enable DMA interrupt.
    nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ);
    nvic_set_priority(NVIC_DMA1_CHANNEL1_IRQ, 0);

    //DMA1_Channel1->CCR |= DMA_CCR_EN;
    dma_enable_channel(DMA1, DMA_CHANNEL1);

    //ADC_CR(ADC1) |= ADC_CR_ADSTART;
    //adc_start_conversion_regular( ADC1 );
}


Timer2 registers:

(gdb) x/20x 0x40000000
0x40000000:    0x00000001    0x00000020    0x00000000    0x00000000
0x40000010:    0x0000001f    0x00000000    0x00000000    0x00000000
0x40000020:    0x00000000    0x00000235    0x0000002f    0x000003e8


ADC1 registers:

(gdb) x/20x 0x40012400
0x40012400:    0x00000001    0x0000001c    0x00000001    0x00000481
0x40012410:    0x00001000    0x00000007    0x00000000    0x00000000
0x40012420:    0x0fff0000    0x00000000    0x00000038    0x00000000


I found this code, which indicates that I can't be too far off with my code.

How can I verify that TRGO actually gets generated? 

When I change the timer2 to generate an interrupt together with an isr, the isr does get called. This is on the UIE (UG) event and it is continuously called.

The errata for this chip only indicated a legal disclaimer update, so I couldn't find anything.

When I enable the "ADC_CR_ADSTART", the ADC kicks off and performs a conversion, but only once.

Outcomes