cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 I2S setup registers

defacato
Associate II
Posted on May 12, 2015 at 18:34

Hi all. I'm currently attempting to get the audio codec on the STM32F4 disco board working as I want to create a simple i2s codec library that will work with the Arduino/Libmaple port from Roger Clark (STM32Duino) I am not using th standard periph libraries but have the libmaple API which has most of the register definitions and atomics.

So far I have been able to get SPI3 working remapped to pins C10(sck) and C12(mosi) and have got I2C working on pins B6 and B9.

My problem is getting MCLK configured. I have the C7 pin configured in AF mode as output PP but am having difficulty actually enabling the clock. 

I would like to know if anyone has attempted to configure I2S using just registers or without the STD periph libraries with any success...

5 REPLIES 5
Posted on May 13, 2015 at 00:03

Read out and post the relevant RCC,  GPIO and SPI/I2S registers content.

JW
defacato
Associate II
Posted on May 13, 2015 at 13:48

Hi JW. Thanks for the interest. I notice you have experience with this codec from other posts so hope you can help (and scold me for really bad coding and register setup..) 

I hope you can make sense of this.

void setup()

{

i2s.end();   // de init

 gpio_set_mode(GPIOD,4,GPIO_OUTPUT_PP);  // codec reset pin

//i2c pin modes

gpio_set_mode(GPIOB,6,GPIO_AF_OUTPUT_OD);  // i2c clk

gpio_set_mode(GPIOB,9,GPIO_AF_OUTPUT_OD);  // i2c data

// i2c remap to B

gpio_set_af_mode(GPIOB,6,4);

gpio_set_af_mode(GPIOB,9,4);

//enable i2c & i2s clocks which are probably enables already but just to be sure

 rcc_clk_enable(RCC_I2C1);

  rcc_clk_enable(RCC_SPI3);

  

  RCC_BASE->CFGR &=(1<<(uint32)23);  // pll i2s

  RCC_BASE->CR |=(1<<(uint32)26);

  RCC_BASE->CR |= (0b1 << 26);

  /* PLLI2S clock used as I2S clock source */

    RCC_BASE->CR |=(1<<16); //HSE on

     RCC_BASE->CR |=(1<<24); // pll on

   

  /* Enable PLLI2S */

  RCC_BASE->CR |= (0x0f039583);  // from debug

//  while((RCC_BASE->CR & RCC_PLLI2SRDY) == 0)

//  {

//  }

  //i2s pins

  gpio_set_mode(GPIOC,10,GPIO_AF_OUTPUT_PP);

  gpio_set_mode(GPIOC,12,GPIO_AF_OUTPUT_PP);

  gpio_set_mode(GPIOC,7,GPIO_AF_OUTPUT_PP);

  

  //set remap to spi3

  gpio_set_af_mode(GPIOA,4,6);

  gpio_set_af_mode(GPIOC,7,6);

  gpio_set_af_mode(GPIOC,10,6);

  gpio_set_af_mode(GPIOC,12,6);

  

  //gpio turn off codec for now

  gpio_write_bit(GPIOD,4,0);

  //configure i2s

 /* SPI3_BASE->I2SCFGR |= 0b0000111000000000;

  SPI3_BASE->I2SPR |=   0b0000001100000011;

  SPI3_BASE->I2SPR |=   0b0000001100000011;*/ prescaler and turn on i2S MCLK 

  SPI3_BASE->I2SCFGR |=(SPI_I2SCFGR_I2SCFG_MASTER_TX);   // i2s in master transmitter mode.

  //i2c setup

  i2c_set_clk_control(I2C1,1);

  i2c_set_input_clk(I2C1,3);

  i2c_enable_ack(I2C1);

  i2c_master_enable(I2C1, 0);

 i2c_peripheral_enable(I2C1);

 codec_ctrl_init();

 //i2s begin

 i2s.begin();

 }

Posted on May 13, 2015 at 18:48

It's easier to read out and analyze the registers content after the setup.

Another thing to do, you may be able to direct the I2SPLL output to some of the MCO pins to check if the PLL is up and running.

JW

defacato
Associate II
Posted on May 17, 2015 at 12:14

Hi JW. OK, i've now got a signal on mclk and pa5 (WS). I used this configuration:

//PLL STUFF set i2s pll clocks and frequency

  RCC_BASE->CR |=(1<<26);

   RCC_BASE->CFGR &= ~RCC_CFGR_I2SSRC ;

   

  RCC_BASE->PLLI2SCFGR |=(PLLI2S_N << 6) | (PLLI2S_R << 28);

  RCC_BASE->CFGR |=(0 << 23);  // i2ssrc

  plli2son();   //(PLL I2S enable)

and :

SPI3_BASE->I2SPR |= (00000011100000011);   // set for mck on and 48K samplerate

bb_peri_set_bit(&dev->regs->I2SPR, SPI_I2SPR_MCKOE_BIT, 1);   // turn on mclk

SPI3_BASE->I2SCFGR |=(SPI_I2SCFGR_I2SCFG_MASTER_TX); 

    SPI3_BASE->I2SCFGR |= (SPI_I2SCFGR_I2SMOD_I2S );

SPI3_BASE->I2SCFGR |= ( SPI_I2SCFGR_I2SSTD_PHILLIPS);

SPI3_BASE->I2SCFGR |= ( SPI_I2SCFGR_DATLEN_16_BIT);

SPI3_BASE->I2SCFGR |= (  SPI_I2SCFGR_CKPOL_LOW);

SPI3_BASE->I2SCFGR |=(0b000010100000000);

so far so good. My spi3 pins are on GPIOC 10 (SCK), GPIOC 12 (MOSI) and GPIO7 (MCLK).

I am seeing signals on the sck mck and the ws pin but when I try to sen data out of the MOSI, I see nothing on my oscilloscope... the function I am using to send the data looks like this:

uint8 SPI1_send(uint8 data){

    SPI3_BASE->DR = data; // write data to be transmitted to the SPI data register

    while( !(SPI3_BASE->SR & SPI_SR_TXE) ); // wait until transmit complete

    while( !(SPI3_BASE->SR & SPI_SR_RXNE) ); // wait until receive complete

    while( SPI3_BASE->SR & SPI_SR_BSY ); // wait until SPI is not busy anymore

    return SPI3_BASE->DR; // return received data from SPI data register

}

i'm going nuts trying to work it out..

Posted on May 17, 2015 at 16:37

> SPI3_BASE->I2SPR |= (00000011100000011);

Isn't a ''0b'' missing from there?

I personally prefer to stick to the constants defined in stm32f4xx.h rather than use ''magic values''.

JW