nis 0 16 октября, 2012 Опубликовано 16 октября, 2012 (изменено) · Жалоба Для одного из проектов протребовалось использовать DMA вместе с таймером 2. Алгоритм работы следующий: По событию совпадения с регистром сравнения 2 происходит запуск DMA1_Stream6. DMA пересылает 640 байт и переконфигурируется. Однако всегда происходит ошибка передачи DMA, пробовал вычленять и запускать только эту часть кода - аналогичный результат, также попробовал камни разных ревизий и серий - f407 rev A, Z; f417 rev A. Исходный код тестовой программы приведён внизу, также приложен архив с проектом (Coocox, GNU GCC). #include "stm32f4xx_rcc.h" #include "stm32f4xx_dma.h" #include "misc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_tim.h" char Buffer[640]; int main(void) { NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOD, &GPIO_InitStructure); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 1000; TIM_TimeBaseStructure.TIM_Prescaler = 160; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = 500; TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_DMACmd(TIM2, TIM_DMA_CC2, ENABLE); DMA_Cmd(DMA1_Stream6, DISABLE); DMA_DeInit(DMA1_Stream6); DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned int)&(GPIOD->ODR); DMA_InitStructure.DMA_Memory0BaseAddr = (unsigned int)&Buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = 640; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_Channel = DMA_Channel_3; DMA_Init(DMA1_Stream6, &DMA_InitStructure); DMA_ITConfig(DMA1_Stream6, DMA_IT_TC | DMA_IT_TE, ENABLE); DMA_Cmd(DMA1_Stream6, ENABLE); TIM_Cmd(TIM2, ENABLE); GPIO_SetBits(GPIOD, GPIO_Pin_All); GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_14); while(1) { GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_14); } } void DMA1_Stream6_IRQHandler(void) { TIM2->CR1 &= ~TIM_CR1_CEN; if (DMA1->HISR & DMA_HISR_TEIF6) GPIO_SetBits(GPIOD, GPIO_Pin_14); if (DMA1->HISR & DMA_HISR_TCIF6) { GPIO_SetBits(GPIOD, GPIO_Pin_12); DMA1_Stream6->M0AR = (unsigned int)&Buffer; DMA1_Stream6->CR |= DMA_SxCR_EN; } DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TC | DMA_IT_TE); TIM2->CR1 |= TIM_CR1_CEN; } Однако используя DMA2 всё проходит как надо: #include "stm32f4xx_rcc.h" #include "stm32f4xx_dma.h" #include "misc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_tim.h" char Buffer[640]; int main(void) { NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOD, &GPIO_InitStructure); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 1000; TIM_TimeBaseStructure.TIM_Prescaler = 1600; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = 500; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_DMACmd(TIM1, TIM_DMA_CC2, ENABLE); DMA_Cmd(DMA2_Stream2, DISABLE); DMA1->LIFCR |= DMA_LIFCR_CDMEIF2 | DMA_LIFCR_CFEIF2 | DMA_LIFCR_CHTIF2 | DMA_LIFCR_CTCIF2 | DMA_LIFCR_CTEIF2; DMA_DeInit(DMA2_Stream2); DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned int)&(GPIOD->ODR); DMA_InitStructure.DMA_Memory0BaseAddr = (unsigned int)&Buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = 640; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_Channel = DMA_Channel_6; DMA_Init(DMA2_Stream2, &DMA_InitStructure); DMA_ITConfig(DMA2_Stream2, DMA_IT_TC | DMA_IT_TE, ENABLE); DMA_Cmd(DMA2_Stream2, ENABLE); TIM_Cmd(TIM1, ENABLE); GPIO_SetBits(GPIOD, GPIO_Pin_All); GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_14); while(1) { GPIO_ResetBits(GPIOD, GPIO_Pin_12 | GPIO_Pin_14); } } void DMA2_Stream2_IRQHandler(void) { TIM1->CR1 &= ~TIM_CR1_CEN; if (DMA2->LISR & DMA_LISR_TEIF2) GPIO_SetBits(GPIOD, GPIO_Pin_14); if (DMA2->LISR & DMA_LISR_TCIF2) { GPIO_SetBits(GPIOD, GPIO_Pin_12); DMA2_Stream2->M0AR = (unsigned int)&Buffer; DMA2_Stream2->CR |= DMA_SxCR_EN; } DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TC | DMA_IT_TE); TIM1->CR1 |= TIM_CR1_CEN; } void assert_param(unsigned int error) { ; } В общем я в замешательстве, errata по поводу этой ошибки ничего не говорит, гугл тоже. Изменено 16 октября, 2012 пользователем IgorKossak [codebox] для длинного кода!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flexz 0 16 октября, 2012 Опубликовано 16 октября, 2012 · Жалоба См. мануал: Figure 1. System architecture и Figure 22. System implementation of two DMA controllers. DMA1 не имеет связи с AHB1, а GPIO как раз там. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nis 0 16 октября, 2012 Опубликовано 16 октября, 2012 (изменено) · Жалоба Спасибо, опять моя невнимательность сыграла со мной злую шутку. Изменено 16 октября, 2012 пользователем IgorKossak бездумное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tolyaha 1 18 октября, 2012 Опубликовано 18 октября, 2012 · Жалоба Спасибо, опять моя невнимательность сыграла со мной злую шутку. Это не только невнимательность, ST эмщики как будто специально скрывали в даташите этот недостаток. В разделе про DMA ни слова и поди догадайся про это, где-то там в другом конце шита на рисунке линии не проведено и все!!! Я тоже долго ломал голову, пока не нашел презентацию этого МК, где про это говорилось, тогда уже и отсутствие линии досмотрел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nis 0 23 октября, 2012 Опубликовано 23 октября, 2012 · Жалоба Это не только невнимательность, ST эмщики как будто специально скрывали в даташите этот недостаток. В разделе про DMA ни слова и поди догадайся про это, где-то там в другом конце шита на рисунке линии не проведено и все!!! Я тоже долго ломал голову, пока не нашел презентацию этого МК, где про это говорилось, тогда уже и отсутствие линии досмотрел. Вообще очень странно что в топовом контроллере полноценным(работающим по схеме память-память) DMA является только DMA2. Т.е по сути это накладывает кучу гемороя и пустого расхода таймеров. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться