Forum: Mikrocontroller und Digitale Elektronik stm32f103 dma-spi


von grundschüler (Gast)


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)


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)


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)


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)


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)


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)


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)


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)


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:

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)


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)


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)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.