Skip to content

Commit be797d1

Browse files
authored
Merge pull request betaflight#6837 from jflyper/bfdev-poc-dma-channel-spec
Introduce per peripheral dma channel spec option
2 parents 3bd0cdd + fe182bb commit be797d1

File tree

82 files changed

+1050
-187
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1050
-187
lines changed

make/source.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ COMMON_SRC = \
1818
drivers/bus_spi_pinconfig.c \
1919
drivers/buttons.c \
2020
drivers/display.c \
21+
drivers/dma_reqmap.c \
2122
drivers/exti.c \
2223
drivers/io.c \
2324
drivers/light_led.c \

src/main/drivers/adc_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ typedef struct adcTagMap_s {
5353
typedef struct adcDevice_s {
5454
ADC_TypeDef* ADCx;
5555
rccPeriphTag_t rccADC;
56+
#if !defined(USE_DMA_SPEC)
5657
#if defined(STM32F4) || defined(STM32F7)
5758
DMA_Stream_TypeDef* DMAy_Streamx;
5859
uint32_t channel;
5960
#else
6061
DMA_Channel_TypeDef* DMAy_Channelx;
6162
#endif
63+
#endif
6264
#if defined(STM32F7)
6365
ADC_HandleTypeDef ADCHandle;
6466
DMA_HandleTypeDef DmaHandle;

src/main/drivers/adc_stm32f30x.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ void adcInit(const adcConfig_t *config)
119119
}
120120

121121
ADCDevice device = ADC_CFG_TO_DEV(config->device);
122+
122123
if (device == ADCINVALID) {
123124
return;
124125
}

src/main/drivers/adc_stm32f4xx.c

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "build/debug.h"
3030

3131
#include "drivers/accgyro/accgyro.h"
32+
#include "drivers/dma_reqmap.h"
3233
#include "drivers/system.h"
3334

3435
#include "drivers/io.h"
@@ -49,10 +50,31 @@
4950
#endif
5051

5152
const adcDevice_t adcHardware[] = {
52-
{ .ADCx = ADC1, .rccADC = RCC_APB2(ADC1), .DMAy_Streamx = ADC1_DMA_STREAM, .channel = DMA_Channel_0 },
53+
{
54+
.ADCx = ADC1,
55+
.rccADC = RCC_APB2(ADC1),
56+
#if !defined(USE_DMA_SPEC)
57+
.DMAy_Streamx = ADC1_DMA_STREAM,
58+
.channel = DMA_Channel_0
59+
#endif
60+
},
5361
#if !defined(STM32F411xE)
54-
{ .ADCx = ADC2, .rccADC = RCC_APB2(ADC2), .DMAy_Streamx = ADC2_DMA_STREAM, .channel = DMA_Channel_1 },
55-
{ .ADCx = ADC3, .rccADC = RCC_APB2(ADC3), .DMAy_Streamx = ADC3_DMA_STREAM, .channel = DMA_Channel_2 }
62+
{
63+
.ADCx = ADC2,
64+
.rccADC = RCC_APB2(ADC2),
65+
#if !defined(USE_DMA_SPEC)
66+
.DMAy_Streamx = ADC2_DMA_STREAM,
67+
.channel = DMA_Channel_1
68+
#endif
69+
},
70+
{
71+
.ADCx = ADC3,
72+
.rccADC = RCC_APB2(ADC3),
73+
#if !defined(USE_DMA_SPEC)
74+
.DMAy_Streamx = ADC3_DMA_STREAM,
75+
.channel = DMA_Channel_2
76+
#endif
77+
}
5678
#endif
5779
};
5880

@@ -212,6 +234,7 @@ void adcInit(const adcConfig_t *config)
212234
}
213235

214236
ADCDevice device = ADC_CFG_TO_DEV(config->device);
237+
215238
if (device == ADCINVALID) {
216239
return;
217240
}
@@ -280,16 +303,33 @@ void adcInit(const adcConfig_t *config)
280303
ADC_DMACmd(adc.ADCx, ENABLE);
281304
ADC_Cmd(adc.ADCx, ENABLE);
282305

306+
#ifdef USE_DMA_SPEC
307+
const dmaChannelSpec_t *dmaSpec = dmaGetChannelSpec(DMA_PERIPH_ADC, device, config->dmaopt[device]);
283308

309+
if (!dmaSpec) {
310+
return;
311+
}
312+
313+
dmaInit(dmaGetIdentifier(dmaSpec->ref), OWNER_ADC, RESOURCE_INDEX(device));
314+
315+
DMA_DeInit(dmaSpec->ref);
316+
#else
284317
dmaInit(dmaGetIdentifier(adc.DMAy_Streamx), OWNER_ADC, 0);
285318

286319
DMA_DeInit(adc.DMAy_Streamx);
320+
#endif
287321

288322
DMA_InitTypeDef DMA_InitStructure;
289323

290324
DMA_StructInit(&DMA_InitStructure);
291325
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&adc.ADCx->DR;
326+
327+
#ifdef USE_DMA_SPEC
328+
DMA_InitStructure.DMA_Channel = dmaSpec->channel;
329+
#else
292330
DMA_InitStructure.DMA_Channel = adc.channel;
331+
#endif
332+
293333
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)adcValues;
294334
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
295335
DMA_InitStructure.DMA_BufferSize = configuredAdcChannels;
@@ -299,9 +339,14 @@ void adcInit(const adcConfig_t *config)
299339
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
300340
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
301341
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
302-
DMA_Init(adc.DMAy_Streamx, &DMA_InitStructure);
303342

343+
#ifdef USE_DMA_SPEC
344+
DMA_Init(dmaSpec->ref, &DMA_InitStructure);
345+
DMA_Cmd(dmaSpec->ref, ENABLE);
346+
#else
347+
DMA_Init(adc.DMAy_Streamx, &DMA_InitStructure);
304348
DMA_Cmd(adc.DMAy_Streamx, ENABLE);
349+
#endif
305350

306351
ADC_SoftwareStartConv(adc.ADCx);
307352
}

src/main/drivers/adc_stm32f7xx.c

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,19 @@
2727
#ifdef USE_ADC
2828

2929
#include "drivers/accgyro/accgyro.h"
30-
#include "drivers/system.h"
31-
30+
#include "drivers/dma.h"
31+
#include "drivers/dma_reqmap.h"
3232
#include "drivers/io.h"
33-
#include "io_impl.h"
34-
#include "rcc.h"
35-
#include "dma.h"
36-
33+
#include "drivers/io_impl.h"
34+
#include "drivers/rcc.h"
3735
#include "drivers/sensor.h"
36+
#include "drivers/system.h"
3837

39-
#include "adc.h"
40-
#include "adc_impl.h"
38+
#include "drivers/adc.h"
39+
#include "drivers/adc_impl.h"
4140

4241
#include "pg/adc.h"
4342

44-
45-
#ifndef ADC_INSTANCE
46-
#define ADC_INSTANCE ADC1
47-
#endif
48-
49-
#ifndef ADC1_DMA_STREAM
50-
#define ADC1_DMA_STREAM DMA2_Stream4
51-
#endif
52-
5343
// Copied from stm32f7xx_ll_adc.h
5444

5545
#define VREFINT_CAL_VREF ( 3300U) /* Analog voltage reference (Vref+) value with which temperature sensor has been calibrated in production (tolerance: +-10 mV) (unit: mV). */
@@ -71,9 +61,30 @@
7161
#endif
7262

7363
const adcDevice_t adcHardware[] = {
74-
{ .ADCx = ADC1, .rccADC = RCC_APB2(ADC1), .DMAy_Streamx = ADC1_DMA_STREAM, .channel = DMA_CHANNEL_0 },
75-
{ .ADCx = ADC2, .rccADC = RCC_APB2(ADC2), .DMAy_Streamx = ADC2_DMA_STREAM, .channel = DMA_CHANNEL_1 },
76-
{ .ADCx = ADC3, .rccADC = RCC_APB2(ADC3), .DMAy_Streamx = ADC3_DMA_STREAM, .channel = DMA_CHANNEL_2 }
64+
{
65+
.ADCx = ADC1,
66+
.rccADC = RCC_APB2(ADC1),
67+
#if !defined(USE_DMA_SPEC)
68+
.DMAy_Streamx = ADC1_DMA_STREAM,
69+
.channel = DMA_CHANNEL_0
70+
#endif
71+
},
72+
{
73+
.ADCx = ADC2,
74+
.rccADC = RCC_APB2(ADC2),
75+
#if !defined(USE_DMA_SPEC)
76+
.DMAy_Streamx = ADC2_DMA_STREAM,
77+
.channel = DMA_CHANNEL_1
78+
#endif
79+
},
80+
{
81+
.ADCx = ADC3,
82+
.rccADC = RCC_APB2(ADC3),
83+
#if !defined(USE_DMA_SPEC)
84+
.DMAy_Streamx = ADC3_DMA_STREAM,
85+
.channel = DMA_CHANNEL_2
86+
#endif
87+
}
7788
};
7889

7990
/* note these could be packed up for saving space */
@@ -236,7 +247,8 @@ void adcInit(const adcConfig_t *config)
236247
adcOperatingConfig[ADC_CURRENT].tag = config->current.ioTag; //CURRENT_METER_ADC_CHANNEL;
237248
}
238249

239-
ADCDevice device = adcDeviceByInstance(ADC_INSTANCE);
250+
ADCDevice device = ADC_CFG_TO_DEV(config->device);
251+
240252
if (device == ADCINVALID) {
241253
return;
242254
}
@@ -299,9 +311,22 @@ void adcInit(const adcConfig_t *config)
299311
}
300312
}
301313

302-
dmaInit(dmaGetIdentifier(adc.DMAy_Streamx), OWNER_ADC, 0);
314+
#ifdef USE_DMA_SPEC
315+
const dmaChannelSpec_t *dmaspec = dmaGetChannelSpec(DMA_PERIPH_ADC, device, config->dmaopt[device]);
316+
317+
if (!dmaspec) {
318+
return;
319+
}
303320

321+
dmaInit(dmaGetIdentifier(dmaspec->ref), OWNER_ADC, 0);
322+
adc.DmaHandle.Init.Channel = dmaspec->channel;
323+
adc.DmaHandle.Instance = dmaspec->ref;
324+
#else
325+
dmaInit(dmaGetIdentifier(adc.DMAy_Streamx), OWNER_ADC, 0);
304326
adc.DmaHandle.Init.Channel = adc.channel;
327+
adc.DmaHandle.Instance = adc.DMAy_Streamx;
328+
#endif
329+
305330
adc.DmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
306331
adc.DmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
307332
adc.DmaHandle.Init.MemInc = configuredAdcChannels > 1 ? DMA_MINC_ENABLE : DMA_MINC_DISABLE;
@@ -313,7 +338,7 @@ void adcInit(const adcConfig_t *config)
313338
adc.DmaHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
314339
adc.DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE;
315340
adc.DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE;
316-
adc.DmaHandle.Instance = adc.DMAy_Streamx;
341+
317342

318343
if (HAL_DMA_Init(&adc.DmaHandle) != HAL_OK)
319344
{

src/main/drivers/dma_reqmap.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* This file is part of Cleanflight and Betaflight.
3+
*
4+
* Cleanflight and Betaflight are free software. You can redistribute
5+
* this software and/or modify this software under the terms of the
6+
* GNU General Public License as published by the Free Software
7+
* Foundation, either version 3 of the License, or (at your option)
8+
* any later version.
9+
*
10+
* Cleanflight and Betaflight are distributed in the hope that they
11+
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
12+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+
* See the GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this software.
17+
*
18+
* If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
#include <stdint.h>
22+
23+
#include "platform.h"
24+
25+
#ifdef USE_DMA_SPEC
26+
27+
#include "drivers/adc.h"
28+
#include "drivers/bus_spi.h"
29+
#include "drivers/serial.h"
30+
#include "drivers/serial_uart.h"
31+
32+
#include "drivers/dma_reqmap.h"
33+
34+
typedef struct dmaRequestMapping_s {
35+
dmaPeripheral_e device;
36+
uint8_t index;
37+
dmaChannelSpec_t channelSpec[2];
38+
} dmaRequestMapping_t;
39+
40+
#if defined(STM32F4) || defined(STM32F7)
41+
#define D(d, s, c) { DMA_CODE(d, s, c), DMA ## d ## _Stream ## s, c }
42+
43+
static const dmaRequestMapping_t dmaRequestMapping[] = {
44+
#ifdef USE_SPI
45+
// Everything including F405 and F446
46+
{ DMA_PERIPH_SPI_TX, SPIDEV_1, { D(2, 3, 3), D(2, 5, 3) } },
47+
{ DMA_PERIPH_SPI_RX, SPIDEV_1, { D(2, 0, 3), D(2, 2, 3) } },
48+
{ DMA_PERIPH_SPI_TX, SPIDEV_2, { D(1, 4, 0) } },
49+
{ DMA_PERIPH_SPI_RX, SPIDEV_2, { D(1, 3, 0) } },
50+
{ DMA_PERIPH_SPI_TX, SPIDEV_3, { D(1, 5, 0), D(1, 7, 0) } },
51+
{ DMA_PERIPH_SPI_RX, SPIDEV_3, { D(1, 0, 0), D(1, 2, 0) } },
52+
53+
#if defined(STM32F411xE) || defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F765xx) || defined(STM32F722xx)
54+
{ DMA_PERIPH_SPI_TX, SPIDEV_4, { D(2, 1, 4) } },
55+
{ DMA_PERIPH_SPI_RX, SPIDEV_4, { D(2, 0, 4) } },
56+
57+
#ifdef USE_EXTENDED_SPI_DEVICE
58+
{ DMA_PERIPH_SPI_TX, SPIDEV_5, { D(2, 6, 7) } },
59+
{ DMA_PERIPH_SPI_RX, SPIDEV_5, { D(2, 5, 7) } },
60+
61+
#if !defined(STM32F722xx)
62+
{ DMA_PERIPH_SPI_TX, SPIDEV_6, { D(2, 5, 1) } },
63+
{ DMA_PERIPH_SPI_RX, SPIDEV_6, { D(2, 6, 1) } },
64+
#endif
65+
#endif // USE_EXTENDED_SPI_DEVICE
66+
#endif
67+
#endif // USE_SPI
68+
69+
#ifdef USE_ADC
70+
{ DMA_PERIPH_ADC, ADCDEV_1, { D(2, 0, 0), D(2, 4, 0) } },
71+
{ DMA_PERIPH_ADC, ADCDEV_2, { D(2, 2, 1), D(2, 3, 1) } },
72+
{ DMA_PERIPH_ADC, ADCDEV_3, { D(2, 0, 2), D(2, 1, 2) } },
73+
#endif
74+
75+
#ifdef USE_SDCARD_SDIO
76+
{ DMA_PERIPH_SDIO, 0, { D(2, 3, 4), D(2, 6, 4) } },
77+
#endif
78+
79+
#ifdef USE_UART
80+
{ DMA_PERIPH_UART_TX, UARTDEV_1, { D(2, 7, 4) } },
81+
{ DMA_PERIPH_UART_RX, UARTDEV_1, { D(2, 5, 4), D(2, 2, 4) } },
82+
{ DMA_PERIPH_UART_TX, UARTDEV_2, { D(1, 6, 4) } },
83+
{ DMA_PERIPH_UART_RX, UARTDEV_2, { D(1, 5, 4) } },
84+
{ DMA_PERIPH_UART_TX, UARTDEV_3, { D(1, 3, 4) } },
85+
{ DMA_PERIPH_UART_RX, UARTDEV_3, { D(1, 1, 4) } },
86+
{ DMA_PERIPH_UART_TX, UARTDEV_4, { D(1, 4, 4) } },
87+
{ DMA_PERIPH_UART_RX, UARTDEV_4, { D(1, 2, 4) } },
88+
{ DMA_PERIPH_UART_TX, UARTDEV_5, { D(1, 7, 4) } },
89+
{ DMA_PERIPH_UART_RX, UARTDEV_5, { D(1, 0, 4) } },
90+
{ DMA_PERIPH_UART_TX, UARTDEV_6, { D(2, 6, 5), D(2, 7, 5) } },
91+
{ DMA_PERIPH_UART_RX, UARTDEV_6, { D(2, 1, 5), D(2, 2, 5) } },
92+
#endif
93+
};
94+
#undef D
95+
#else // STM32F3
96+
// The embedded ADC24_DMA_REMAP conditional should be removed
97+
// when (and if) F3 is going generic.
98+
#define D(d, c) { DMA_CODE(d, 0, c), DMA ## d ## _Channel ## c }
99+
static const dmaRequestMapping_t dmaRequestMapping[17] = {
100+
#ifdef USE_SPI
101+
{ DMA_PERIPH_SPI_TX, 1, { D(1, 3) } },
102+
{ DMA_PERIPH_SPI_RX, 1, { D(1, 2) } },
103+
{ DMA_PERIPH_SPI_TX, 2, { D(1, 5) } },
104+
{ DMA_PERIPH_SPI_RX, 2, { D(1, 4) } },
105+
{ DMA_PERIPH_SPI_TX, 3, { D(2, 2) } },
106+
{ DMA_PERIPH_SPI_RX, 3, { D(2, 1) } },
107+
#endif
108+
109+
#ifdef USE_ADC
110+
{ DMA_PERIPH_ADC, 1, { D(1, 1) } },
111+
#ifdef ADC24_DMA_REMAP
112+
{ DMA_PERIPH_ADC, 2, { D(2, 3) } },
113+
#else
114+
{ DMA_PERIPH_ADC, 2, { D(2, 1) } },
115+
#endif
116+
{ DMA_PERIPH_ADC, 3, { D(2, 5) } },
117+
#endif
118+
119+
#ifdef USE_UART
120+
{ DMA_PERIPH_UART_TX, 1, { D(1, 4) } },
121+
{ DMA_PERIPH_UART_RX, 1, { D(1, 5) } },
122+
123+
{ DMA_PERIPH_UART_TX, 2, { D(1, 7) } },
124+
{ DMA_PERIPH_UART_RX, 2, { D(1, 6) } },
125+
{ DMA_PERIPH_UART_TX, 3, { D(1, 2) } },
126+
{ DMA_PERIPH_UART_RX, 3, { D(1, 3) } },
127+
{ DMA_PERIPH_UART_TX, 4, { D(2, 5) } },
128+
{ DMA_PERIPH_UART_RX, 4, { D(2, 3) } },
129+
};
130+
#endif
131+
#undef D
132+
#endif
133+
134+
const dmaChannelSpec_t *dmaGetChannelSpec(dmaPeripheral_e device, uint8_t index, int8_t opt)
135+
{
136+
if (opt < 0 || opt >= 2) {
137+
return NULL;
138+
}
139+
140+
for (unsigned i = 0 ; i < ARRAYLEN(dmaRequestMapping) ; i++) {
141+
const dmaRequestMapping_t *periph = &dmaRequestMapping[i];
142+
if (periph->device == device && periph->index == index && periph->channelSpec[opt].ref) {
143+
return &periph->channelSpec[opt];
144+
}
145+
}
146+
147+
return NULL;
148+
}
149+
#endif // USE_DMA_SPEC

0 commit comments

Comments
 (0)