STMH7 + SPI + DMA

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Аватара пользователя
Cheeseman
Открыл глаза
Сообщения: 48
Зарегистрирован: Пн июл 31, 2017 10:53:04

STMH7 + SPI + DMA

Сообщение Cheeseman »

Всем привет. Пытаюсь подключить 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)? Судя по примерам в интернете можно брать любые, не нашел в даташите от чего выбор зависит.
Реклама
Adrift
Вымогатель припоя
Сообщения: 540
Зарегистрирован: Вт окт 01, 2024 15:22:33

Re: STMH7 + SPI + DMA

Сообщение Adrift »

[uquote="Cheeseman",url="/forum/viewtopic.php?p=4741609#p4741609"]И как выбирать номер stream (DMA1_Stream4)? Судя по примерам в интернете можно брать любые, не нашел в даташите от чего выбор зависит.[/uquote]
Что у вас эти строки делают? От них выбор и должен зависеть.

Код: Выделить всё

  DMAMUX1_Channel0->CCR = (39 << DMAMUX_CxCR_DMAREQ_ID_Pos); // прием
  DMAMUX1_Channel1->CCR = (40 << DMAMUX_CxCR_DMAREQ_ID_Pos); // передача
И почему номера 10/11? Они соответствуют DMA2_Stream2/3...
Реклама
Аватара пользователя
Cheeseman
Открыл глаза
Сообщения: 48
Зарегистрирован: Пн июл 31, 2017 10:53:04

Re: STMH7 + SPI + DMA

Сообщение Cheeseman »

Там не 10, 11, а 0, 1.
переделал на stream 1 вместо 4, пока также
забыл указать функцию отправки пакета

Код: Выделить всё

void SPI1_dmaTransmit() {  
  // Для этого выключаем канал DMA, меням регистр с длинной и снова включаем:
  DMA1_Stream1->CR &= ~DMA_SxCR_EN;
  while (DMA1_Stream1->CR & DMA_SxCR_EN) {} // ждем, пока DMA выключится
  DMA1_Stream1->NDTR = qca7k_spiDataSize;
  DMA1_Stream1->CR |= DMA_SxCR_EN;
}
сейчас при инициализации DMA1_Stream1
Adrift
Вымогатель припоя
Сообщения: 540
Зарегистрирован: Вт окт 01, 2024 15:22:33

Re: STMH7 + SPI + DMA

Сообщение Adrift »

[uquote="Cheeseman",url="/forum/viewtopic.php?p=4741622#p4741622"]Там не 10, 11, а 0, 1.[/uquote]
Точно ) Но все равно не правильно.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Cheeseman
Открыл глаза
Сообщения: 48
Зарегистрирован: Пн июл 31, 2017 10:53:04

Re: STMH7 + SPI + DMA

Сообщение Cheeseman »

В даташите не вижу, какой steam привязывается к какой периферии. Вижу только, что DMA request MUX input под номером 40 соответствует spi2_tx_dma. Я и подумал, что любому stream можно задать значение 40, чтобы отвечал за spi2 tx dma. Куда смотреть?

UPD: сейчас инициализация на передачу выглядит так:

Код: Выделить всё

  // передача
  DMA1_Stream1->CR = 0;                                                         // выкл DMA
  while (DMA1_Stream1->CR & DMA_SxCR_EN) {}                                     // ждем, пока DMA выключится
  DMA1_Stream1->PAR = (uint32_t)&SPI2->TXDR;
  DMA1_Stream1->M0AR = (uint32_t)qca7k_spi_txBuf; 
  DMA1_Stream1->CR |= (1u << DMA_SxCR_DIR_Pos);                                 // Memory to peripheral
  DMA1_Stream1->CR |= DMA_SxCR_MINC | DMA_SxCR_TEIE | DMA_SxCR_TCIE;            // инкремент памяти, разрешение прерываний
  DMA1_Stream1->CR |= (3u << DMA_SxCR_PL_Pos);                                  // Very high priority
  DMA1_Stream1->CR &= ~DMA_SxCR_MSIZE;                                          // 8 бит
  DMA1_Stream1->CR &= ~DMA_SxCR_PSIZE;
  DMA1_Stream1->FCR &= ~DMA_SxFCR_DMDIS;                                        // direct mode(без fifo)
  DMA1_Stream1->NDTR = ARRAY_SIZE(qca7k_spi_txBuf);   
  DMA1->LIFCR |= DMA_LIFCR_CHTIF1 | DMA_LIFCR_CTCIF1 | DMA_LIFCR_CTEIF1;        // очистка флагов
Ну и далее везде DMA1_Stream1
Реклама
Adrift
Вымогатель припоя
Сообщения: 540
Зарегистрирован: Вт окт 01, 2024 15:22:33

Re: STMH7 + SPI + DMA

Сообщение Adrift »

[uquote="Cheeseman",url="/forum/viewtopic.php?p=4741627#p4741627"]Я и подумал, что любому stream можно задать значение 40, чтобы отвечал за spi2 tx dma.[/uquote]
Так и есть, но стримы DMA и каналы DMAMUX должны совпадать.
Реклама
Аватара пользователя
Cheeseman
Открыл глаза
Сообщения: 48
Зарегистрирован: Пн июл 31, 2017 10:53:04

Re: STMH7 + SPI + DMA

Сообщение Cheeseman »

Разобрался кароч. Закинул свой буфер в область памяти AXI SRAM и всё полетело :)
Ответить

Вернуться в «ARM»