Forum: Mikrocontroller und Digitale Elektronik ST32F4xx SPI1 DMA funktioniert nicht


von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich brauche mal ein paar hilfreiche Augen, denn meine scheinen gerade 
nicht zu reichen. Ich will den SPI1 auf einem STM32F446RE aktivieren. 
Ohne DMA funktioniert das auch so weit. Mit DMA ist allerdings kein 
einziger Takt auf dem Oszilloskop zu sehen und beim zweiten Aufruf der 
DMA-Sende-Funktion wird unendlich lange gewartet, bis das 
"NDTR"-Register keine zu sendenden Bytes mehr anzeigt.
1
#include "spi.h"
2
#include "hw_config.h"
3
#include "myassert.h"
4
#include "nstdlib.h"
5
#include "wallclock.h"
6
7
8
/** Auswahl SPI, Ports und Pins */
9
enum spi_hard_e
10
{
11
    spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7,
12
    spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15,
13
    spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12,
14
};
15
16
17
/* In hw_config.h : */
18
#define SPI_HARD spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7
19
//#define SPI_HARD spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12
20
21
22
#if defined( STM32F4XX )
23
24
    #include "stm32f4xx_rcc.h"
25
    #include "stm32f4xx_spi.h"
26
27
28
    /** Globale Variablen *************************************************************************/
29
    /* - */
30
31
32
33
    /** Hardware-SPI fuer schnelle Anwendungen (z.B. GLCD)
34
      - duplex mode (RM0390 S. 850f.)
35
      - Steigende Flanke, Zweite Flanke -> CPHA=0, CPOL=0
36
        */
37
    void spi_hard_init(void)
38
    {
39
        SPI_InitTypeDef  SPI_InitStructure;
40
        SPI_TypeDef* SPIx;
41
        GPIO_InitTypeDef GPIO_InitStructure;
42
        GPIO_TypeDef *SCK_GPIOx, *MISO_GPIOx, *MOSI_GPIOx;
43
        uint32_t      SCK_Pin_x,  MISO_Pin_x,  MOSI_Pin_x;
44
        uint8_t SPIx_IRQn;
45
46
47
        switch( SPI_HARD )
48
        {
49
            case spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7:
50
                /* Enable the SPI clock */
51
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
52
53
                SCK_GPIOx  = GPIOA;
54
                SCK_Pin_x  = GPIO_Pin_5;
55
                MISO_GPIOx = GPIOA;
56
                MISO_Pin_x = GPIO_Pin_6;
57
                MOSI_GPIOx = GPIOA;
58
                MOSI_Pin_x = GPIO_Pin_7;
59
60
                SPIx = SPI1;
61
                SPIx_IRQn = SPI1_IRQn;
62
63
                /* Connect SPI pins to AF5 */
64
                GPIO_PinAFConfig(SCK_GPIOx,  GPIO_PinSource5, GPIO_AF_SPI1);
65
                GPIO_PinAFConfig(MISO_GPIOx, GPIO_PinSource6, GPIO_AF_SPI1);
66
                GPIO_PinAFConfig(MOSI_GPIOx, GPIO_PinSource7, GPIO_AF_SPI1);
67
68
                break;
69
70
            case spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15:
71
                /* ungetestet */
72
73
                /* Enable the SPI clock */
74
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
75
76
                SCK_GPIOx  = GPIOB;
77
                SCK_Pin_x  = GPIO_Pin_13;
78
                MISO_GPIOx = GPIOB;
79
                MISO_Pin_x = GPIO_Pin_14;
80
                MOSI_GPIOx = GPIOB;
81
                MOSI_Pin_x = GPIO_Pin_15;
82
83
                SPIx = SPI2;
84
                SPIx_IRQn = SPI2_IRQn;
85
86
                /* Connect SPI pins to AF5 */
87
                GPIO_PinAFConfig(SCK_GPIOx,  GPIO_PinSource13, GPIO_AF_SPI2);
88
                GPIO_PinAFConfig(MISO_GPIOx, GPIO_PinSource14, GPIO_AF_SPI2);
89
                GPIO_PinAFConfig(MOSI_GPIOx, GPIO_PinSource15, GPIO_AF_SPI2);
90
91
                break;
92
93
            case spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12:
94
95
                /* Enable the SPI clock */
96
                RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
97
98
                SCK_GPIOx  = GPIOC;
99
                SCK_Pin_x  = GPIO_Pin_10;
100
                MISO_GPIOx = GPIOC;
101
                MISO_Pin_x = GPIO_Pin_11;
102
                MOSI_GPIOx = GPIOC;
103
                MOSI_Pin_x = GPIO_Pin_12;
104
105
                SPIx = SPI3;
106
                SPIx_IRQn = SPI3_IRQn;
107
108
                /* Connect SPI pins to AF 6 */
109
                GPIO_PinAFConfig(SCK_GPIOx,  GPIO_PinSource10, GPIO_AF_SPI3);
110
                GPIO_PinAFConfig(MISO_GPIOx, GPIO_PinSource11, GPIO_AF_SPI3);
111
                GPIO_PinAFConfig(MOSI_GPIOx, GPIO_PinSource12, GPIO_AF_SPI3);
112
113
                break;
114
            default:
115
                error("Not implemented for other SPI");
116
        }
117
118
119
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
120
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
121
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
122
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
123
124
        /* SPI SCK pin configuration */
125
        GPIO_InitStructure.GPIO_Pin = SCK_Pin_x;
126
        GPIO_Init(SCK_GPIOx, &GPIO_InitStructure);
127
128
        /* SPI  MISO pin configuration */
129
        GPIO_InitStructure.GPIO_Pin =  MISO_Pin_x;
130
        GPIO_Init(MISO_GPIOx, &GPIO_InitStructure);
131
132
        /* SPI  MISO pin configuration */
133
        GPIO_InitStructure.GPIO_Pin =  MOSI_Pin_x;
134
        GPIO_Init(MOSI_GPIOx, &GPIO_InitStructure);
135
136
        SPI_I2S_DeInit(SPIx);
137
138
        /* SPI configuration */
139
        /* SPIx->CR1 RXONLY */
140
        /* SPIx->CR1.SSI=0 (active low) */
141
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
142
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
143
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
144
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
145
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
146
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; /* spaeter noch anpassen */
147
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
148
        SPI_InitStructure.SPI_CRCPolynomial = 7; /* unnoetig */
149
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
150
        SPI_Init(SPIx, &SPI_InitStructure);
151
152
153
        /* DMA Configuration - vorerst nur nur fuer SPI1 */
154
        /* DMA1 Clock */
155
        assert( SPIx == SPI1 );
156
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
157
158
        DMA_InitTypeDef DMA_InitStruct;
159
        DMA_StructInit(&DMA_InitStruct);
160
        DMA_InitStruct.DMA_Channel = DMA_Channel_3;
161
        DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR);
162
        DMA_InitStruct.DMA_Memory0BaseAddr = 0;
163
        DMA_InitStruct.DMA_BufferSize = 0;
164
        DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
165
        DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
166
        DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
167
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
168
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
169
        DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
170
        DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
171
        DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
172
        DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
173
        DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
174
        DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
175
        DMA_Init(DMA2_Stream3, &DMA_InitStruct);
176
177
        /* DMA-Interrupt wird erst behandelt, wenn Chip Select implementiert wird*/
178
        //DMA_ITConfig(DMA1_Stream6, DMA_IT_TC, ENABLE);
179
        DMA_Cmd(DMA2_Stream3, ENABLE);
180
181
182
        /* Configure the SPI interrupt priority */
183
        /* Interrupts 0, 1, 2 sind anderweitig belegt und werden auch aufgerufen */
184
        /*NVIC_SetPriority(SPIx_IRQn, 4); */
185
        /*NVIC_EnableIRQ(SPIx_IRQn); */
186
187
188
        /* Enable the Rx buffer not empty interrupt */
189
        /* SPI2->CR2 RXNEIE Bit wird gesetzt */
190
        SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_RXNE, DISABLE);
191
192
193
        /* Enable the SPI peripheral */
194
        SPI_Cmd(SPIx, ENABLE);
195
    }
196
197
198
199
200
201
    /** Abschalten
202
     *
203
     * @note Keine komplette Deinitialisierung noetig, sleep modi werden nicht benutzt */
204
    void spi_hard_deinit(void)
205
    {
206
        SPI_TypeDef* SPIx;
207
        switch( SPI_HARD )
208
        {
209
            case spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7:
210
                SPIx = SPI1;
211
212
            case spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15:
213
                SPIx = SPI2;
214
                break;
215
216
            case spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12:
217
                SPIx = SPI3;
218
                break;
219
        }
220
        SPI_Cmd(SPIx, DISABLE);
221
    }
222
223
224
225
226
    /** Einzelnes Byte ueber SPI senden, nichts empfangen, MSB first */
227
    uint8_t spi_hard_sendbyte(uint8_t byte)
228
    {
229
        uint8_t in = 0;
230
231
        SPI_TypeDef* SPIx;
232
        switch( SPI_HARD )
233
        {
234
            case spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7:
235
                SPIx = SPI1;
236
                break;
237
238
            case spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15:
239
                SPIx = SPI2;
240
                break;
241
242
            case spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12:
243
                SPIx = SPI3;
244
                break;
245
        }
246
247
        /*!< Loop while DR register in not empty */
248
        while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
249
250
        /*!< Send byte through the SPI1 peripheral */
251
        SPI_I2S_SendData(SPIx, byte);
252
253
        /*!< Wait to receive a byte */
254
        while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
255
256
        /*!< Return the byte read from the SPI bus */
257
        in = SPI_I2S_ReceiveData(SPIx);
258
259
        return in;
260
    }
261
262
263
264
    /** Daten per DMA senden - bleibt immer stecken*/
265
    void spi_hard_senddma(uint8_t *data, size_t len)
266
    {
267
        static uint32_t cnt = 0;
268
        cnt++;
269
270
        DMA_Stream_TypeDef* DMAy_Streamx = DMA2_Stream3;
271
272
        /* Warten bis vorheriger Transfer abgeschlossen */
273
        while( DMAy_Streamx->NDTR != 0 );
274
275
        DMA_Cmd(DMAy_Streamx, DISABLE);
276
        //DMA_ITConfig(DMAy_Streamx, DMA_IT_TC, DISABLE);
277
278
        /* Neuen Block fuers Senden vorbereiten */
279
        DMAy_Streamx->M0AR = (uint32_t) data;
280
        DMA_SetCurrDataCounter(DMAy_Streamx, len);
281
282
        if( len )
283
        {
284
            //DMA_ITConfig(DMAy_Streamx, DMA_IT_TC, ENABLE);
285
            DMA_Cmd(DMAy_Streamx, ENABLE);
286
        }
287
    }

Egal wie groß oder wie klein das Array ist, was spi_hard_senddma() 
übergeben wird - beim zweiten  Aufruf ist in NDTR immer noch die volle 
Länge drin. Was ja auch zum Bild auf dem Oszilloskop passt, weil nichts 
gesendet wird. Es sieht aus, als fehle irgendeine Form der 
Sende-Freigabe.

Was sehen eure Augen mehr als meine?

von GL (Gast)


Lesenswert?

Hab mir das ganze jetzt nicht durchgelesen, aber prinzipiell sollte ein 
SPI DMA Transfer mit 3-4 Zeilen erschlagen sein. Guck mal in die 
Beispiele, die die Cube mitliefert.

Beitrag #5951147 wurde von einem Moderator gelöscht.
von Walter T. (nicolas)


Lesenswert?

Die Streams für TX und RX waren vertauscht.

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.