cancel
Showing results for 
Search instead for 
Did you mean: 

Weirdest thing happening with STM32H7 I2S hardware

CLeo.1
Senior II

Hi guys! I am having the biggest issue with the I2S right now

What is happening: For whatever reason the I2S does not want to transmit any samples VIA DMA. Doesnt matter what I do what I try.

The weird thing happening: The I2S WS, SCLK wont work. Only if the DMA associated with the Tx part is enable (DMA1_Stream1) which I find so weird. All it does it set the WS pin to HIGH

What I have tried:

  • Verified the registers are correctly setup
  • Ensure with measuring tools the right signals are shooting out (WS, MCLK, SCLK) when the DMA1_Stream1 is enable
  • Swapped out the ADC/DAC for another one
  • Ensured the ADC is sending out its digital signal
  • Ensured the STM32 is receiving samples and transmitting to the Tx Buffer associated with the DMA

How the code works.

The code waits around till an UART signal is received VIA the DMA, once received in goes into a super loop where it process UART signals

Depending on what UART signal was received it will enable not only the I2S peripheral but setup the clock, Interrupt, anything to make the I2S running with DMA etc...

Then the stm32 should now be ready to take in I2S signals and spit them out

Code: (Using PasteBin as code is too long here)

Main.c

https://pastebin.com/GZCTs8Sd

I2S_Factory.c (Setups GPIO, and DMA)

https://pastebin.com/tDXjzVaX

Audio_Selector.c (Setups the I2S Clock, interrupt, and DMA)

https://pastebin.com/mHjDgZaX

DSP_FACTORY.c (Where in takes in the Rx Samples and transfer it to the Tx Buffer for transitmission)

https://pastebin.com/WNt9TSrA

Any help would be amazing, I am stumped right now its not even funny.

25 REPLIES 25
TDK
Guru

0x00000000240004ac is in the AXI SRAM.

0x0000000008000f60 is in FLASH, but that's just code, not a buffer.

Why do you think those are in ITCM?

If you feel a post has answered your question, please click "Accept as Solution".

Oh cause of this, weird 0693W00000Ba9BJQAZ.png

Right I see my mistake now correct its in the D1 Domain, what else could it be then

CLeo.1
Senior II

Alright @TDK​ I broke down the I2S module and now I am having issue just even getting the I2S working. All is happening the WS pin get set HIGH

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
 
#include "main.h"
#include <stdint.h>
 
 int RxBuff_inline[4];
 int TxBuff_inline[4];
 
uint8_t I2S1_TC = 0;
uint8_t I2S1_HC = 0;
 
void INIT_DMA(void);
 
void INIT_DMA() {
 
	//Setting Clock for 192kHz
		//N = 122
		//P = 4
		//M = 10
		//FRACT = 7209
 
		// RCC_PLL2DIVR
		// MASKING:
		RCC -> PLL2DIVR &= ~RCC_PLL2DIVR_P2;
		RCC -> PLL2DIVR &= ~RCC_PLL2DIVR_N2;
		// WRITING:
		RCC -> PLL2DIVR |= RCC_PLL2DIVR_P2_DIV8; // P
		RCC -> PLL2DIVR |= RCC_PLL2DIVR_N2_MULT122; // N
 
		// RCC_PLLCKSELR
		// MASKING:
		RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM2;
		// WRITING:
		RCC -> PLLCKSELR |= RCC_PLLCKSELR_DIVM2_DIV10; // M
 
		// RCC_PLL2FRACR
		// MASKING:
		RCC -> PLL2FRACR &= ~RCC_PLL2FRACR_FRACN2;
		// WRITING:
		RCC -> PLL2FRACR |= RCC_PLL2FRACR_FRACN_7209; // FRAC
 
		// RCC_PLLCFGR
		// MASKING:
		RCC -> PLLCFGR &= ~RCC_PLLCFGR_DIVP2EN;
		RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLL2RGE;
		RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLL2VCOSEL;
		RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLL2FRACEN;
		// WRITING:
		RCC -> PLLCFGR |= RCC_PLLCFGR_DIVP2EN;
		RCC -> PLLCFGR |= RCC_PLLCFGR_PLL2RGE_4_8;
		RCC -> PLLCFGR |= RCC_PLLCFGR_PLL2VCOSEL_192_836;
		RCC -> PLLCFGR |= RCC_PLLCFGR_PLL2FRACEN;
 
		// RCC_CR
		// MASKING:
		RCC -> CR &= ~RCC_CR_PLL2ON;
		// WRITING:
		RCC -> CR |= RCC_CR_PLL2ON;
		// WAITING:
		while (((RCC -> CR) & (RCC_CR_PLL2RDY)) == 0){};
 
		// ENALBING CLOCKS
 
		// RCC_AHB4ENR
		// MASKING:
		RCC -> AHB4ENR &= ~ RCC_AHB4ENR_GPIOAEN;
		RCC -> AHB4ENR &= ~ RCC_AHB4ENR_GPIOCEN;
		// WRITING:
		RCC -> AHB4ENR |= RCC_AHB4ENR_GPIOAEN;
	    RCC -> AHB4ENR |= RCC_AHB4ENR_GPIOCEN;
 
	    // RCC_APB2ENR
	    // MASKING:
	    RCC -> APB2ENR &= ~RCC_APB2ENR_SPI1EN;
	    // WRITING:
	    RCC -> APB2ENR |= RCC_APB2ENR_SPI1EN;
 
	    // CHANGING CLOCKS OF PERIPHERALS
	    // RCC_D2CCIP1R
	    // MASKING;
	    RCC -> D2CCIP1R &= ~RCC_D2CCIP1R_SPI123SEL;
	    // WRITING:
	    RCC -> D2CCIP1R |=  RCC_D2CCIP1R_SPI123SEL_PLL2_P_CK;
 
	    // CHANGING GPIO PINS TO ALETERNATIVE
	    // GPIOx_MODER
	    // MASKING
	    GPIOA -> MODER &= ~GPIO_MODER_MODE4;
	    GPIOA -> MODER &= ~GPIO_MODER_MODE5;
	    GPIOA -> MODER &= ~GPIO_MODER_MODE6;
	    GPIOA -> MODER &= ~GPIO_MODER_MODE7;
	    GPIOC -> MODER &= ~GPIO_MODER_MODE4;
	    // WRITING:
	    GPIOA -> MODER |= GPIO_MODER_MODE4_ALT;
	    GPIOA -> MODER |= GPIO_MODER_MODE5_ALT;
	    GPIOA -> MODER |= GPIO_MODER_MODE6_ALT;
	    GPIOA -> MODER |= GPIO_MODER_MODE7_ALT;
	    GPIOC -> MODER |= GPIO_MODER_MODE4_ALT;
 
 
	   // GPIOC -> OSPEEDR &= ~GPIO_OSPEEDR_OSPEED4;
	    //GPIOC -> OSPEEDR |= GPIO_OSPEEDR_OSPEED4_VERY_HIGH;
 
	    //SETTING ALT FUNCTIONS TO PINS
	    // GPIOx_AFRL
	    // MASKING:
	    GPIOA -> AFR[0] &= ~GPIO_AFRL_AFSEL4;
	    GPIOA -> AFR[0] &= ~GPIO_AFRL_AFSEL5;
	    GPIOA -> AFR[0] &= ~GPIO_AFRL_AFSEL6;
	    GPIOA -> AFR[0] &= ~GPIO_AFRL_AFSEL7;
	    GPIOC -> AFR[0] &= ~GPIO_AFRL_AFSEL4;
	    // WRITING;
	    GPIOA -> AFR[0] |= GPIO_AFRL_AFSEL4_AF5;
	    GPIOA -> AFR[0] |= GPIO_AFRL_AFSEL5_AF5;
	    GPIOA -> AFR[0] |= GPIO_AFRL_AFSEL6_AF5;
	    GPIOA -> AFR[0] |= GPIO_AFRL_AFSEL7_AF5;
	    GPIOC -> AFR[0] |= GPIO_AFRL_AFSEL4_AF5;
 
	    // ENABLING DMA1
	    // RCC_AHB1ENR
	    // MASKING:
 
	      // DMA_SxCR
	      // WRITING:
	     // DMA1_Stream0 -> CR |= DMA_SxCR_EN;
	      //DMA1_Stream1 -> CR |= DMA_SxCR_EN;
 
	    // Setting up the SPI/I2S Peripheral
	    // MASKING:
	      SPI1->I2SCFGR = 0x00;
	      		             SPI1->I2SCFGR |= (SPI_I2SCFGR_MCKOE)              |
	      							          (SPI_I2SCFGR_I2SDIV_2)           |
	      							          (SPI_I2SCFGR_I2SSTD_I2STAND)        |
											  (SPI_I2SCFGR_DATFMT_LAlign) |
	      							          (SPI_I2SCFGR_I2SCFG_MASTER_FULLDUPLEX) |
	      							          (SPI_I2SCFGR_I2SMOD_I2S_PCM_MODE);
	      		           SPI1->I2SCFGR |= (SPI_I2SCFGR_CHNEL_32BIT_WIDE);
	      		           SPI1->I2SCFGR |= (SPI_I2SCFGR_DATALEN_24BIT);
	      		           		 SPI1->CR1 |= SPI_CR1_SPE;
	      		           			 SPI1->CR1 |= SPI_CR1_CSTART;
 
		NVIC_EnableIRQ(DMA1_Stream0_IRQn);
		NVIC_SetPriority(DMA1_Stream0_IRQn,0);
}
 
 
int main (void) {
 
INIT_DMA();
 
 
 
while (1) {
 
 
	if (I2S1_HC) {
		 for (int i = 0; i < 2; i ++){
 
			 TxBuff_inline[i] = (int)RxBuff_inline[i];
					}
 
					    //DMA1_Stream1->CR |= DMA_SxCR_EN;
					    I2S1_HC = 0;
	}
 
	if (I2S1_TC) {
		 for (int i = 2; i < 4; i ++){
 
 
 
			 TxBuff_inline[i] = RxBuff_inline[i];
 
 
						}
 
						     //DMA1_Stream1->CR |= DMA_SxCR_EN;
						     I2S1_TC = 0;
	}
 
}
 
 
}
 
 
void DMA1_Stream0_IRQHandler() {
 
	if (((DMA1->LISR) & (DMA_LISR_HTIF0)) != 0) {
	      DMA1->LIFCR |= DMA_LIFCR_CHTIF0;
 
		  I2S1_HC = 1;
	}
 
	if (((DMA1->LISR) & (DMA_LISR_TCIF0)) != 0) {
		  DMA1->LIFCR |= DMA_LIFCR_CTCIF0;
 
		  I2S1_TC = 1;
	}
}

Piranha
Chief II

Why are you using the SPI peripheral, not the much more appropriate SAI peripheral?

Here are the definitions:
GPIOA->MODER |= (GPIO_MODER_MODE4_AF) | = (0x2UL << GPIO_MODER_MODE4_Pos) 
(GPIO_MODER_MODE5_AF) | = (0x2UL << GPIO_MODER_MODE5_Pos) 
(GPIO_MODER_MODE6_AF) | = (0x2UL << GPIO_MODER_MODE6_Pos) 
(GPIO_MODER_MODE7_AF) ; = (0x2UL << GPIO_MODER_MODE7_Pos) 

And what is this? That is not even a correct C syntax...

For audio usage SAI is the preferred choice. Compared to SPI it wins in all aspects simultaneously:

  • More protocols, internal FIFO and other features.
  • More flexibility regarding channels, data bit number and position.
  • Not over-engineered and is simper to use.
  • Has less hardware bugs. Actually current errata still has none.
CLeo.1
Senior II

I mean you aint wrong and ill probably do it if I can get this working. Further more I still dont know why the MOSI line is still silent.

@TDK​ Alright did what you have said.

  1. Ensured the data used by the DMA is in the regions where the DMA can access it
  2. I created the most minimal working example I can, just setting up the Clock, DMA, I2S, and interrupt thats it.
  3. No errors are being reported by the DMA nor the SPI and I still see no activity on the MOSI line.
  4. Doubled checked the clocks are set right, and once again the WS, SCLK, and MCLK are outputting normally, MISO is working properly
  5. Tested the DAC, thats working properly
  6. Lost really lost
TDK
Guru

> I broke down the I2S module and now I am having issue just even getting the I2S working

You don't enable the DMA clock or set up DMA1_Stream0 anywhere in there.

You don't enable the RXDMAEN or TXDMAEN bits anywhere.

Possibly other things.

Do you have it up and running without using DMA? That would be a smart first step IMO.

If you feel a post has answered your question, please click "Accept as Solution".