[STM32F4] I2S macht nichts PLL-Clock-Problem?!

OP Persönliche Seite #5053740
Lesenswert?

Guten Morgen,

ich hab da ein sehr seltsames Problem ...

Ich war mit ST's HAL unzufrieden und erstellte ein neues Projekt, das 
ohne HAL auskommt.

Funktioniert im Prinzip besser, aber mein I2S macht nichts und ich 
glaube, es liegt an der Clock-Configuration (warum weiter unten).

Hier der Initialisierungs-Code für die I2S:
1
  // stm32f429
2

3
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
4
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
5
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
6
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
7
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
8

9
  /*Configure GPIO Pin : PG13 */
10
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
11
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
12
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
13
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
14
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
15
  GPIO_Init(GPIOG, &GPIO_InitStruct);
16

17
  GPIO_ResetBits(GPIOG, GPIO_Pin_13);  // unmute
18

19
    /**I2S3 GPIO Configuration
20
    PA4     ------> I2S3_WS
21
    PD6     ------> I2S3_SD
22
    PB3     ------> I2S3_CK
23
    */
24

25
  GPIO_PinAFConfig(GPIOB, GPIO_Pin_3, GPIO_AF_SPI3);
26
  GPIO_PinAFConfig(GPIOD, GPIO_Pin_6, 5);//GPIO_AF_SPI3);
27
  GPIO_PinAFConfig(GPIOA, GPIO_Pin_4, GPIO_AF_SPI3);
28

29
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
30
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
31
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
32
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
33
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
34
  GPIO_Init(GPIOA, &GPIO_InitStruct);
35

36
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
37
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
38
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
39
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
40
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
41
  GPIO_Init(GPIOD, &GPIO_InitStruct);
42

43
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
44
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
45
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
46
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
47
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
48
  GPIO_Init(GPIOB, &GPIO_InitStruct);
49

50

51
  I2S_InitTypeDef I2S_InitStruct;
52
  I2S_StructInit(&I2S_InitStruct);
53

54
//  wird in SetSysClock in system_stm32f4xx.c gemacht
55
//  testweise auch hier mal probiert, ändern aber nichts
56
//  RCC_PLLI2SConfig(172, 2, 7);
57
//  RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
58
//  RCC_PLLI2SCmd(ENABLE);
59
//  RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY);
60

61
  I2S_InitStruct.I2S_Mode = I2S_Mode_MasterTx;
62
  I2S_InitStruct.I2S_Standard = I2S_Standard_Phillips;
63
  I2S_InitStruct.I2S_DataFormat = I2S_DataFormat_16b; /*I2S_DataFormat_16b;*/
64
  I2S_InitStruct.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
65
  I2S_InitStruct.I2S_AudioFreq = I2S_AudioFreq_11k;//I2S_AudioFreq_44k;
66
  I2S_InitStruct.I2S_CPOL = I2S_CPOL_Low;
67
  I2S_Init(SPI3, &I2S_InitStruct);
68
  I2S_Cmd(SPI3, ENABLE);
69

70
  for (int i = 0; i < DMASIZE; i++) {
71
    dmabuf[i] = (int16_t) ((rand() % 40000) - 20000);
72
  }
73
  for (;;) {
74
    for (int i = 0; i < DMASIZE; i++) {
75
      SPI_I2S_SendData(SPI3, dmabuf[i]);
76
      while (!(SPI3->SR & SPI_I2S_FLAG_TXE))
77
        ; // wait until transmit complete
78
    }
79
  }

Die Schleife, die ganz unten zufällige Daten über I2S rausschicken soll 
läuft im Prinzip - aber nicht im HAL-freien Projekt.

Auf keinem der I2S-Pins sieht man irgendwelche Pegel-wechsel.

Zu dieser Zeile hier:
1
GPIO_PinAFConfig(GPIOD, GPIO_Pin_6, 5);//GPIO_AF_SPI3);

HAL hatte den PD6 mit AF5 statt AF6 initialisiert, was im HAL-Projekt 
auch funktioniert. Keine Ahnung weshalb und im Manual hatte ich nichts 
dazu gefunden ... Hat jemand vlt eine Idee? Hab beides ausprobiert, geht 
beides nicht.

Hier noch die Initialisierung meiner Clocks (1 zu 1 aus der 
system_stm32f4xx.c aus einem ST-CMSIS-Example-Code für I2S):
1
// 168MHz HCLK, APB1 48MHz, APB2 96MHz
2
#define PLL_M      4
3
#define PLL_N      168
4
#define PLL_P      2
5
#define PLL_Q      7
6

7
// 49,142MHz I2S
8
#define PLLI2S_N   172
9
#define PLLI2S_R   7
10

11
static void SetSysClock(void)
12
{
13
/******************************************************************************/
14
/*            PLL (clocked by HSE) used as System clock source                */
15
/******************************************************************************/
16
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
17

18
  /* Enable HSE */
19
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
20

21
  /* Wait till HSE is ready and if Time out is reached exit */
22
  do
23
  {
24
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
25
    StartUpCounter++;
26
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
27

28
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
29
  {
30
    HSEStatus = (uint32_t)0x01;
31
  }
32
  else
33
  {
34
    HSEStatus = (uint32_t)0x00;
35
  }
36

37
  if (HSEStatus == (uint32_t)0x01)
38
  {
39
    /* Select regulator voltage output Scale 1 mode */
40
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
41
    PWR->CR |= PWR_CR_VOS;
42

43
    /* HCLK = SYSCLK / 1*/
44
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
45

46
#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx)
47
    /* PCLK2 = HCLK / 2*/
48
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
49

50
    /* PCLK1 = HCLK / 4*/
51
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
52
#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */
53

54
#if defined (STM32F401xx)
55
    /* PCLK2 = HCLK / 2*/
56
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
57

58
    /* PCLK1 = HCLK / 4*/
59
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
60
#endif /* STM32F401xx */
61

62
    /* Configure the main PLL */
63
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
64
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
65

66
    /* Enable the main PLL */
67
    RCC->CR |= RCC_CR_PLLON;
68

69
    /* Wait till the main PLL is ready */
70
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
71
    {
72
    }
73

74
#if defined (STM32F427_437xx) || defined (STM32F429_439xx)
75
    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
76
    PWR->CR |= PWR_CR_ODEN;
77
    while((PWR->CSR & PWR_CSR_ODRDY) == 0)
78
    {
79
    }
80
    PWR->CR |= PWR_CR_ODSWEN;
81
    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
82
    {
83
    }
84
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
85
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
86
#endif /* STM32F427_437x || STM32F429_439xx  */
87

88
#if defined (STM32F40_41xxx)
89
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
90
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
91
#endif /* STM32F40_41xxx  */
92

93
#if defined (STM32F401xx)
94
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
95
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;
96
#endif /* STM32F401xx */
97

98
    /* Select the main PLL as system clock source */
99
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
100
    RCC->CFGR |= RCC_CFGR_SW_PLL;
101

102
    /* Wait till the main PLL is used as system clock source */
103
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
104
    {
105
    }
106
  }
107
  else
108
  { /* If HSE fails to start-up, the application will have wrong clock
109
         configuration. User can add here some code to deal with this error */
110
  }
111

112
/******************************************************************************/
113
/*                          I2S clock configuration                           */
114
/******************************************************************************/
115
  /* PLLI2S clock used as I2S clock source */
116
  RCC->CFGR &= ~RCC_CFGR_I2SSRC;
117

118
  /* Configure PLLI2S */
119
  RCC->PLLI2SCFGR = (PLLI2S_N << 6) | (PLLI2S_R << 28);
120

121
  /* Enable PLLI2S */
122
  RCC->CR |= ((uint32_t)RCC_CR_PLLI2SON);
123

124
  /* Wait till PLLI2S is ready */
125
  while((RCC->CR & RCC_CR_PLLI2SRDY) == 0)
126
  {
127
  }
128

129
}

Ganz unten wird die I2SPLL initialisiert.

Das sollte eigentlich passen, aber aus meinem I2S kommt nichts...

Wenn ich in einem funktionierenden HAL-Projekt die Clock-Configuration 
durch die obige SetSysClock ersetze, dann funktioniert dort I2S auch 
nicht mehr.

Muss wohl irgendwas mit dem Clock zu tun haben, hab es aber nicht 
herausgefunden und nach einem Tag debugging bin ich mittlerweile völlig 
ratlos.

VG
Mampf
(Firma: matzetronics) #5053751
Lesenswert?

Mampf F. schrieb:
> Muss wohl irgendwas mit dem Clock zu tun haben, hab es aber nicht
> herausgefunden und nach einem Tag debugging bin ich mittlerweile völlig
> ratlos.

Das hat mich beim STM32F407 (Dicovery Board) auch eine Weile 
beschäftigt. Über die serielle habe ich mir dann die Register ausgegeben 
und festgestellt, das der I2S Prescaler nicht richtig gesetzt wurde. 
Mein Projekt nutzt allerdings 48kHz Samplefrequenz, deswegen sieht das 
hier etwas anders aus:
1
#define I2SDIV 0x0103;
2
// init the Pins for I2S Alternate Function 
3
//...
4

5
/* now set the parameters for the I2S Interface itself */
6
    I2S_StructInit(&I2S_InitStructure);
7
    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
8
    I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
9
    I2S_InitStructure.I2S_MCLKOutput = ENABLE;
10
    I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_48k;
11
    I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
12
    I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
13
    I2S_Init(SPI3,&I2S_InitStructure);
14
// set the MCLK Output enable bit and prescaler , cause the initfunction is bugged 
15
    SPI3->I2SPR = I2S_MCLKOutput_Enable | I2SDIV;
16
// Configure the I2S Tx empty IRQ
17
// ...
Wenn du keine Masterclock brauchst, setzt du stattdessen nur den 
Teilerwert ein ohne das gesetzte 'I2S_MCLKOutput_Enable' Bit.
Bei mir hat es sich bewährt, nach jedem Init irgendeiner Funktion einen 
Ausgang blinken zu lassen (das Disco Board hat ja genug LEDs).
(Firma: matzetronics) #5053755
Lesenswert?

Mampf F. schrieb:
> Matthias S. schrieb:
>> Über die serielle habe ich mir dann die Register ausgegeben
>> und festgestellt, das der I2S Prescaler nicht richtig gesetzt wurde.
>
> Puh, hört sich auch nach viel Debugging-Freude an :)
>
> Hmm, das ist eigentlich seltsam ... Die I2S-Init-Routing liest die
> Clock-Prescaler der PLLI2S und errechnet daraus die Clock-Frequenz und
> ermittelt daraus die I2S-Interface-Einstellungen.
>
> Wenn die Prescaler vorher falsch waren, wär das I2S-Interface völlig
> falsch konfiguriert worden.
>
> Oder die Funktion macht den Prescaler selbst dann irgendwie kaputt.
>
> Ich muss gestehen, ich hab den PLL-Clock noch nicht nach einem I2S_Init
> durchgeführt, vlt wäre das des Rätsels Lösung gewesen.
>
> Danke schonmal!

Achso, noch eines, die I2SPLL sollte unbedingt konfiguriert werden, 
nicht auf System Init verlassen:
1
uint16_t PLL_N = 129,PLL_R = 3;
2
void I2S_PLL_Config(uint16_t N,uint16_t R) {
3
    // Set PLL Clock for I2S
4
    RCC_PLLI2SCmd(DISABLE);
5
    RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
6
    /* Configure PLLI2S */
7
    RCC_PLLI2SConfig(N,R);
8
    /* Enable PLLI2S */
9
    RCC_PLLI2SCmd(ENABLE);
10
    /* Wait till PLLI2S is ready */
11
    while (RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY)==RESET){};
12
}
und du solltest darauf warten, das sie soweit ist (letzte Zeile).
(Firma: matzetronics) #5054974
Lesenswert?

Mampf F. schrieb:
> Keinen Mux gibt das I2S von sich ... Ich glaube, ich werde mir jetzt mal
> funktionierende Beispiele suchen ...

Ich habe zum Testen auch erstmal auf DMA verzichtet und lade SPI3->DR 
per ISR für die Ausgabe bzw. hole mir von SPI2-DR per ISR den Input (das 
Dings hier soll einen 4-Kanal Multitrack Recorder ersetzen). Das ist 
schon eine Weile her, ich weiss aber, das ich mit dem Krams auch ganz 
schön gekämpft habe.

Du wirst meinen Code nicht 1zu1 übernehmen können, weil hier alles auf 
48kHz mit Masterclock konfiguriert ist, aber bei Interesse poste ichs 
gerne mal.
Ohne die serielle Ausgabe fürs Debuggen wäre ich aber vermutlich nicht 
drauf gekommen.
Den Stereo Ausgang macht bei mir der CS43L22 Chip auf dem Disco Board, 
der ADC am Eingang ist ein CS5341.
OP Persönliche Seite #5055184
Lesenswert?

Ich hab mich jetzt von dir inspirieren lassen und hab mir mal alle 
Register von GPIOA-H, RCC und SPI3 quasi dumpen lassen ...

Das sieht dann so aus:
1
*((uint32_t*) 0x40020000)=0xa8000200;
2
*((uint32_t*) 0x40020004)=0x00000000;
3
*((uint32_t*) 0x40020008)=0x0c000000;
4
*((uint32_t*) 0x4002000c)=0x64000000;
5
*((uint32_t*) 0x40020010)=0x0000f7df;
6
*((uint32_t*) 0x40020014)=0x00000000;
7
*((uint32_t*) 0x40020018)=0x00000000;
8
<snip>
9
*((uint32_t*) 0x4002387c)=0x00000000;
10
*((uint32_t*) 0x40023880)=0x00000000;
11
*((uint32_t*) 0x40023884)=0x70002b00;

Und tatsächlich ... Mit dem zusätzlichen Code funktioniert es auch.

Jetzt kommentier ich Stück für Stück aus, bis das I2S nicht mehr 
funktioniert, dann müsste ich wissen, woran es liegt :)


WTF Das setzen der AFs hat nichts gemacht ...

u.A. GPIO_PinAFConfig(GPIOA, GPIO_Pin_4, GPIO_AF_SPI3);

Hmm, das ist ja oberseltsam!
Beitrag #5055212 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren