Всем привет. Пытаюсь подключить SPI + DMA на контроллере stm32H743ZI. Не могу настроить данную связку. Вот код инициализации DMA
Код:
void DMA_Init(void) {
RCC->AHB2ENR |= RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN;
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
DMAMUX1_Channel0->CCR = (39 << DMAMUX_CxCR_DMAREQ_ID_Pos); // прием
DMAMUX1_Channel1->CCR = (40 << DMAMUX_CxCR_DMAREQ_ID_Pos); // передача
// передача
DMA1_Stream4->CR = 0; // выкл DMA
while (DMA1_Stream4->CR & DMA_SxCR_EN) {} // ждем, пока DMA выключится
DMA1_Stream4->PAR = (uint32_t)&SPI2->TXDR;
DMA1_Stream4->M0AR = (uint32_t)qca7k_spi_txBuf;
DMA1_Stream4->CR |= (1u << DMA_SxCR_DIR_Pos); // Memory to peripheral
DMA1_Stream4->CR |= DMA_SxCR_MINC | DMA_SxCR_TEIE | DMA_SxCR_TCIE; // инкремент памяти, разрешение прерываний
DMA1_Stream4->CR |= (3u << DMA_SxCR_PL_Pos); // Very high priority
DMA1_Stream4->CR &= ~DMA_SxCR_MSIZE; // 8 бит
DMA1_Stream4->CR &= ~DMA_SxCR_PSIZE;
DMA2_Stream4->FCR &= ~DMA_SxFCR_DMDIS; // direct mode(без fifo)
DMA1_Stream4->NDTR = ARRAY_SIZE(qca7k_spi_txBuf);
DMA1->HIFCR |= DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTCIF4 | DMA_HIFCR_CTEIF4; // очистка флагов
//прием
DMA1_Stream0->CR = 0; // выкл DMA
while (DMA1_Stream0->CR & DMA_SxCR_EN) {} // ждем, пока DMA выключится
DMA1_Stream0->PAR = (uint32_t)&SPI2->RXDR;
DMA1_Stream0->M0AR = (uint32_t)qca7k_spi_rxBuf;
DMA1_Stream0->CR = DMA_SxCR_MINC | DMA_SxCR_TEIE | DMA_SxCR_TCIE | DMA_SxCR_CIRC; // инкремент памяти
DMA1_Stream0->CR &= ~DMA_SxCR_DIR;
DMA1_Stream0->CR |= (3u << DMA_SxCR_PL_Pos); // Very high priority
DMA1_Stream0->CR &= ~DMA_SxCR_MSIZE; // 8 бит
DMA1_Stream0->CR &= ~DMA_SxCR_PSIZE;
DMA1_Stream0->NDTR = ARRAY_SIZE(qca7k_spi_rxBuf);
DMA1->LIFCR |= DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTCIF0 | DMA_LIFCR_CTEIF0; // очистка флагов
// Включаем прерывание по приему и устанавливаем его приоритет
NVIC_EnableIRQ(DMA1_Stream4_IRQn);
NVIC_SetPriority(DMA1_Stream4_IRQn, 2);
}
/*******************************************************************************
* @brief Обработчик прерывания DMA1 по передаче (канал SPI2)
*******************************************************************************/
void DMA1_Stream4_IRQHandler(void) {
// Обработчик передачи:
if (DMA1->HISR & DMA_HISR_TCIF4) {
DMA1->HIFCR |= DMA_HIFCR_CTCIF4; // очистка флагов
} else if (DMA1->HISR & DMA_HISR_TEIF4) {
DMA1->HIFCR |= DMA_HIFCR_CTEIF4;
DMA1_Stream4->CR &= ~DMA_SxCR_EN; // выкл DMA
while (DMA1_Stream4->CR & DMA_SxCR_EN) {} // ждем, пока DMA выключится
}
}
/*******************************************************************************
* @brief Обработчик прерывания DMA1 по приему (канал SPI2)
*******************************************************************************/
void DMA1_Stream0_IRQHandler(void) {
// Обработчик приема:
if (DMA1->LISR & DMA_LISR_TCIF0) {
DMA1->LIFCR |= DMA_LIFCR_CTCIF0; // очистка флагов
DMA1_Stream0->CR &= ~DMA_SxCR_EN; // выкл канал DMA, понадобится снова включим
// Выключаем прерывание по приему
NVIC_DisableIRQ(DMA1_Stream0_IRQn);
CS_HIGH();
}
// если ошибка
else if (DMA1->LISR & DMA_LISR_TEIF0) {
DMA1->LIFCR |= DMA_LIFCR_CTEIF0;
DMA1_Stream0->CR &= ~DMA_SxCR_EN; // выкл DMA
while (DMA1_Stream0->CR & DMA_SxCR_EN) {} // ждем, пока DMA выключится
}
}
Без DMA SPI работает, частота настроена. При инициализации SPI с DMA в инициализации SPI просто включаю два флага TXDMAEN и RXDMAEN. При добавлении DMA ничего не отправляется.Где могут быть подводные камни? И как выбирать номер stream (DMA1_Stream4)? Судя по примерам в интернете можно брать любые, не нашел в даташите от чего выбор зависит.