我有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);
}
}
删除 - 不喜欢这种讨论。 –