2017-07-26 53 views
0

我有STM32F7迪斯科板与STM32F723IEK MCU。试图从定时器触发DMA请求会导致DMA错误,但仅限于连接到DMA1的APB1组(TIM2到TIM7等)的定时器。与连接到DMA2的TIM1和TIM8一样,工作正常。该错误表现为在相应的DMA LISR或HISR寄存器中设置TEIFx标志,DMA在第一次事务后立即禁用。 NDTR寄存器减1。在STM32F7 DMA由APB1定时器触发失败

根据数据表,TEIF错误可能由“总线错误”触发。我理解为例如试图访问不能从DMA总线访问的外设。但是,使用DMA2和TIM1/TIM8的同一设置可以很好地工作,而不必更改DMA地址。所以这个问题似乎与DMA请求有关,而不是数据事务本身。鉴于有很多为DMA1定义的定时器通道,这当然应该起作用。

我试图改变DMA设置,但这没有什么区别。测试程序的相关部分如下。完整版https://github.com/ak-hard/stm32-dma-tim/blob/master/main.c仅略大,除CMSIS和STM32设备头之外没有依赖关系。

我想知道是否有人可以评论或重现此问题。

const struct 
{ 
    TIM_TypeDef *tim; 
    DMA_TypeDef *dma; 
    DMA_Stream_TypeDef *stream; 
    unsigned channel; 
} CFG = { 
// uncomment the needed combination below, only TIM1 and TIM8 work 
// TIM1, DMA2, DMA2_Stream5, 6 
    TIM8, DMA2, DMA2_Stream1, 7 
// TIM2, DMA1, DMA1_Stream1, 3 
// TIM2, DMA1, DMA1_Stream7, 3 
// TIM3, DMA1, DMA1_Stream2, 5 
// TIM4, DMA1, DMA1_Stream6, 2 
// TIM5, DMA1, DMA1_Stream0, 6 
// TIM5, DMA1, DMA1_Stream6, 6 
// TIM6, DMA1, DMA1_Stream1, 7 
// TIM7, DMA1, DMA1_Stream2, 1 
// TIM7, DMA1, DMA1_Stream4, 1 
}; 

enum 
{ 
    DMA_SxCR_DIR_P2M = 0, 
    DMA_SxCR_PSIZE_WORD = DMA_SxCR_PSIZE_1, 
    DMA_SxCR_MSIZE_WORD = DMA_SxCR_MSIZE_1, 
}; 

#define DMA_SxCR_CHSEL_NUM(ch) ((ch) << DMA_SxCR_CHSEL_Pos) 

uint32_t buf; 

void start(void) 
{ 
    SysTick->LOAD = 0xffffffu; 
    SysTick->VAL = 0; 
    SysTick->CTRL = 5; 

    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; 
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM8EN; 
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM4EN | RCC_APB1ENR_TIM5EN 
      | RCC_APB1ENR_TIM6EN | RCC_APB1ENR_TIM7EN; 
    RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN | RCC_AHB1ENR_DMA2EN; 

    LED_PORT->MODER |= 1 << (2 * LED_PIN); 
    LED_PORT->OSPEEDR |= 3 << (2 * LED_PIN); // fastest speed 

    CFG.tim->CR1 |= TIM_CR1_ARPE; 
    CFG.tim->ARR = 16; 
    CFG.tim->PSC = 1000; 
    CFG.tim->EGR = TIM_EGR_UG; // Generate Update Event to copy ARR to its shadow 
    CFG.tim->DIER |= TIM_DIER_UDE; 
    CFG.stream->CR |= DMA_SxCR_CHSEL_NUM(CFG.channel) | DMA_SxCR_DIR_P2M | DMA_SxCR_PSIZE_WORD | DMA_SxCR_MSIZE_WORD; 
    CFG.stream->NDTR = 16; 
    CFG.stream->PAR = (uint32_t) &GPIOA->IDR; 
    CFG.stream->M0AR = (uint32_t) &buf; 
    CFG.stream->CR |= DMA_SxCR_EN; 
    CFG.tim->CR1 |= TIM_CR1_CEN; 

    // wait until DMA state changes 
    while (CFG.dma->LISR == 0 && CFG.dma->HISR == 0) 
     delay_ms(1); 

    // check for any TEIFx bits 
    int error = (CFG.dma->LISR | CFG.dma->HISR) & 0x02080208; 

    while (1) 
    { 
     LED_PORT->ODR ^= 1 << LED_PIN; 
     delay_ms(error ? 100 : 500); 
    } 
} 
+0

删除 - 不喜欢这种讨论。 –

回答

1

这里有一个答案,但它因为某种原因被删除。感谢它的作者。看看总线矩阵,很明显DMA1的外围总线是连接到APB1的只有。它实际上不是矩阵的一部分。这可能意味着DMA1只能处理从/到APB1外设的传输。由于GPIO是AHB外设,因此无法从DMA1访问。这也应该适用于其他APB2(例如SPI1)和AHB外围设备(例如OTGFS)。通常,从DMA1访问AHB或APB2外设是没有意义的,因为它们的请求不会路由到DMA1。但是,计时器可能需要像GPIO那样复杂的情况。

我个人认为这一点可以在文档中更明显。