Forum: Mikrocontroller und Digitale Elektronik stm32f103 dma-spi


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von grundschüler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
versuche meinen vs1052 code auf dma umzustellen.

Das Beschicken des mp3-Modulds funktioniert jetz - als Vorbereitung zur 
dma - ohne Warteschleife per Interrupt:
1
void SysTick_Handler(){//1ms
2
3
4
    /* Increment performance counter */
5
  //disk_timerproc();  /* Disk timer process */
6
7
  if(Timer_fat)Timer_fat--;
8
9
  if(Timer_down)
10
    Timer_down--;
11
12
  timer_smh++;
13
  timer_timeout_up_ms++;
14
15
16
  if(timer_smh%5==0){
17
18
    if ((vs_status & (1<<0))){
19
        if ((GPIOB->IDR & (1<<4))) {
20
        GPIOA->ODR |=(1<<9);//xdcs
21
          GPIOA->ODR &=~(1<<9);//xdcs
22
23
          uint8_t i;
24
          for (i=0;i<32;i++){
25
            SPI2->DR = *vs_pt++;
26
            while (!(SPI2->SR & SPI_SR_RXNE));//0_rxne 1_txe 7_bsy// ok
27
            (SPI2->DR);//return
28
            zlisr++;
29
          }
30
          if (zlisr > vs_buffer_size-1){
31
            vs_status &= ~(1<<0);
32
          }
33
        }
34
      }
35
#endif
36
  }//%5
37
38
39
40
Ein Problem habe ich mit strcpy:
41
42
[c]/**/
43
u16 j;
44
for(j=0;j<1965;j++){
45
  vs_buffer[1965+j]=hello_mp3[+j];
46
  vs_buffer[j]=hello_mp3[+j];
47
}
48
49
strcpy(vs_buffer,hello_mp3);
50
51
//vs_pt = hello_mp3; // Point "p" to the beginning of array
52
vs_pt = vs_buffer; // Point "p" to the beginning of array
53
vs_status |= (1<<0);
54
xdcs_h;
55
zlisr=0;

Wenn ich die for-Schleife auskommentiere, kommt im mp3-modul nichts mehr 
an owohl der Speicherinhalt nach dem Debugger der gleiche ist.

Woran könnte das liegen?

von bittereMedizin (Gast)


Bewertung
0 lesenswert
nicht lesenswert
du hast doch offensichtlich ein Problem mit deinem spi-code. Bevor du
jetzt auf dma umstellst, wäre Fehlersuche und Fehlerbehebung angebracht.

von grundschüler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
bittereMedizin schrieb:
> du hast doch offensichtlich ein Problem mit deinem spi-code.

??? Ich will es ja nicht völlig ausschließen, es ist aber eigentlich 
problemloser code:
1
kk_init_spi2(
2
    u8 modus // 0: ph0/pol0 1:ph1/pol1
3
        ){
4
5
    //pinout
6
    RCC->APB2ENR |= RCC_APB2Periph_GPIOB;
7
    setGPIO_CRHL(B,12,GPIO_OUT_PP);//nss
8
    setGPIO_CRHL(B,13,GPIO_AF_PP);//clk
9
    setGPIO_CRHL(B,14,GPIO_AF_OPD);//miso
10
    pinSET(B,14);//pullup
11
    setGPIO_CRHL(B,15,GPIO_AF_PP);//mosi
12
13
    //spi_enable
14
    RCC->APB1ENR |= RCC_APB1Periph_SPI2;
15
    SPI2->CR1 = SPI_CR1_SSM|SPI_CR1_SSI|SPI_CR1_MSTR|SPI_CR1_SPE;
16
17
    //modus
18
    if(modus)SPI2->CR1 |= SPI_CR1_CPHA|SPI_CR1_CPOL;
19
20
    //dma
21
  #define TXDMAEN (1<<1)
22
//  SPI2->CR2 |= (TXDMAEN);
23
    }

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
grundschüler schrieb:
> strcpy(vs_buffer,hello_mp3);

MP3 Daten können 0x00 enthalten und werden nicht mit 0x00 abgeschlossen.

Daher immer memcpy() und nicht strcpy() verwenden.

von grundschüler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Jim M. schrieb:
> grundschüler schrieb:
>> strcpy(vs_buffer,hello_mp3);
>
> MP3 Daten können 0x00 enthalten und werden nicht mit 0x00 abgeschlossen.
>
> Daher immer memcpy() und nicht strcpy() verwenden.

strcpy hört bei 0 auf?
Danke, das leuchtet ein.

von dasrotemopped (Gast)


Bewertung
0 lesenswert
nicht lesenswert
https://learn.adafruit.com/adafruit-music-maker-shield-vs1053-mp3-wav-wave-ogg-vorbis-player/downloads

wartest du darauf, das der DMA Transfer beendet wurde bevor du das 2. 
Device an SPI ansprichst ? Und wie kannst du DMA benutzen wenn du 
zwischen 2 CS umschalten musst ?

von Robin S. (der_r)


Bewertung
0 lesenswert
nicht lesenswert
grundschüler schrieb:
> strcpy hört bei 0 auf?
> Danke, das leuchtet ein.

Ja,
Strings sind in C nichts weiter als ein Char-Array, welches am Ende noch 
ein Terminator-Zeichen hat. Da die Arraygröße aus Sicht der meisten 
Funktionen unbekannt ist, arbeiten die einfach so lange, bis dieses 
Zeichen erreicht wird.

Das Zeichen wird '\0' geschrieben, wobei '\0' der 0 (siehe 
ASCII-Tabelle) entspricht.

von grundschüler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
dasrotemopped schrieb:
> wartest du darauf, das der DMA Transfer beendet wurde bevor du das 2.
> Device an SPI ansprichst ? Und wie kannst du DMA benutzen wenn du
> zwischen 2 CS umschalten musst ?

Nur dieser Teil
1
          uint8_t i;
2
          for (i=0;i<32;i++){
3
            SPI2->DR = *vs_pt++;
4
            while (!(SPI2->SR & SPI_SR_RXNE));//0_rxne 1_txe 7_bsy// ok
5
            (SPI2->DR);//return
6
            zlisr++;
7
          }

wird durch den dma-Aufruf ersetzt. Da ist - bis auf RXNE - kein 
Warteteil und kein CS drin. Müsste also so per dma klappen...

von dasrotemopped (Gast)


Bewertung
0 lesenswert
nicht lesenswert
stimmt meine Vermutung, Nucleo-F103RB + Adafruit Music Maker Shield  ?
Wenn nicht, wie ist deine aktuelle Pinbelegung / Doppelbelegung für 
SDcard und VS1052 ?


Gruß,

dasrotemopped.

von grundschüler (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
dasrotemopped schrieb:
> Nucleo-F103RB

nein, 103c8, läuft alles erstaunlich gut. Wenn  die dma läuft, stell ich 
den code ein.

von grundschüler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
bei der dma hängt es noch:

1
void dma1chan5_m_to_spi2(void){
2
    DMA_InitTypeDef DMA_InitStructure;
3
4
    #define TXDMAEN (1<<1)
5
  SPI2->CR2 |= (TXDMAEN);
6
7
  DMA_DeInit(DMA1_Channel5);
8
  //1. periph adr
9
     DMA_InitStructure.DMA_PeripheralBaseAddr = &SPI2->DR;
10
     DMA_InitStructure.DMA_MemoryBaseAddr = vs_buffer;//xHelloMP3;
11
     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
12
     DMA_InitStructure.DMA_BufferSize = 32;//1695;//cndtr Byte????
13
     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
14
     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
15
     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
16
     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
17
     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//circular
18
     DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
19
     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
20
     DMA_Init(DMA1_Channel5, &DMA_InitStructure);
21
22
     DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);
23
24
     // Enable the SPI DMA TX Interrupt
25
     NVIC_InitTypeDef NVIC_InitStructure;
26
     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
27
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
28
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
29
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
30
     NVIC_Init(&NVIC_InitStructure);
31
32
}
33
//==========================================================
34
void DMA1_Channel5_IRQHandler(){
35
GPIOA->ODR |=(1<<9);//xdcs
36
DMA_ClearFlag(DMA1_FLAG_TC5);
37
}
38
39
//==========================================================
40
41
im systick;
42
  if(timer_smh%5==0){
43
44
//kein DMA
45
    if ((vs_status & (1<<0))){
46
        if ((GPIOB->IDR & (1<<4))) {
47
          GPIOA->ODR &=~(1<<9);//xdcs
48
          uint8_t i;
49
          for (i=0;i<32;i++){
50
            SPI2->DR = *vs_pt++;
51
            while (!(SPI2->SR & SPI_SR_RXNE));//0_rxne 1_txe 7_bsy// ok
52
            (SPI2->DR);//return
53
            vs_zl_buffer++;
54
          }
55
          if (vs_zl_buffer > vs_buffer_size-1){
56
            vs_status &= ~(1<<0);
57
          }
58
             GPIOA->ODR |=(1<<9);//xdcs
59
         }
60
      }
61
62
//DMA
63
    if ((vs_status & (1<<1))){
64
           GPIOA->ODR &=~(1<<9);//xdcs
65
       if (vs_zl_buffer < vs_buffer_size){
66
           DMA1_Channel5->CMAR=vs_zl_buffer+=32;
67
           DMA_Cmd(DMA1_Channel5, ENABLE);
68
         }else{
69
           vs_status &= ~(1<<1);
70
            GPIOA->ODR |=(1<<9);//xdcs
71
        }
72
    }
73
74
  }//%5

irgendwie geht der dma-trigger nicht. Jemand eine Idee?

von grundschüler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
habe jetzt das Diller DMA-example gefunden. Der Startcode für eine 
einzelne DMA-übertragung ist sehr umständlich:
1
         SPI2->DR;//fifo leeren von mir
2
        DMA_Cmd(DMA1_Channel4, DISABLE);
3
        DMA_Cmd(DMA1_Channel5, DISABLE);
4
        DMA_SetCurrDataCounter(DMA1_Channel4, 2);
5
        DMA_SetCurrDataCounter(DMA1_Channel5, 2);
6
        GPIO_WriteBit(GPIOB, GPIO_Pin_12, RESET);
7
        DMA_Cmd(DMA1_Channel4, ENABLE);
8
        DMA_Cmd(DMA1_Channel5, ENABLE);
versuche das jetzt auf mein Projekt umzubasteln.

von grundschüler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
noch nicht alltagstauglich, aber man hört jetzt was per dma im vs-modul:
1
  if(timer_smh%3==0){
2
3
//kein DMA
4
    if ((vs_status & (1<<0))){
5
        if ((GPIOB->IDR & (1<<4))) {
6
          GPIOA->ODR &=~(1<<9);//xdcs
7
          uint8_t i;
8
          for (i=0;i<32;i++){
9
            SPI2->DR = *vs_pt++;
10
            while (!(SPI2->SR & SPI_SR_RXNE));//0_rxne 1_txe 7_bsy// ok
11
            (SPI2->DR);//return
12
            vs_zl_buffer++;
13
          }
14
          if (vs_zl_buffer > vs_buffer_size-1){
15
            vs_status &= ~(1<<0);
16
          }
17
             GPIOA->ODR |=(1<<9);//xdcs
18
         }
19
      }
20
21
//DMA
22
    if ((vs_status & (1<<1))){
23
           GPIOA->ODR &=~(1<<9);//xdcs
24
       if (vs_zl_buffer < vs_buffer_size){
25
 //        u8 *adr=vs_buffer+vs_zl_buffer;
26
         DMA1_Channel5->CMAR=vs_buffer+vs_zl_buffer;//;
27
         vs_zl_buffer+=32;
28
      DMA_Cmd(DMA1_Channel4, DISABLE);
29
      DMA_Cmd(DMA1_Channel5, DISABLE);
30
      DMA_SetCurrDataCounter(DMA1_Channel4, 32);
31
      DMA_SetCurrDataCounter(DMA1_Channel5, 32);
32
      GPIO_WriteBit(GPIOB, GPIO_Pin_12, RESET);
33
      DMA_Cmd(DMA1_Channel4, ENABLE);
34
      DMA_Cmd(DMA1_Channel5, ENABLE);
35
         }else{
36
           vs_status &= ~(1<<1);
37
            GPIOA->ODR |=(1<<9);//xdcs
38
        }
39
    }
40
41
  }//%5

das Zeitintervall musste ich von 5 auf 3ms verkürzen. Außerdem fällt das 
lcd-modul nach Einsatz der dma aus. Aber grundsätzlich geht die DMA

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.