stm32f103 dma-spi

Gast #4889583
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?
Gast #4889620
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
    }
#4889656
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.
Gast #4889670
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...
Gast #4889829
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?
Gast #4890402
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.
Gast #4890441
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

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