Added DMA support for H5. Also added ADC DMA support.

Added logic to set hasdma to false. This is needed to enable or not enable interrupts on a per ADC basis. Made other minor formatting changes.

Fixed build issues with non ADC/DMA configurations.
This commit is contained in:
kywwilson11
2025-07-08 15:55:05 -05:00
committed by Alan C. Assis
parent 156ef05205
commit 0c1f9d482d
9 changed files with 1589 additions and 178 deletions
+69 -54
View File
@@ -881,6 +881,75 @@ config ARCH_BOARD_STM32H5_CUSTOM_CLOCKCONFIG
---help---
Enables special, board-specific STM32 clock configuration.
menu "ADC Configuration"
depends on STM32H5_ADC
config STM32H5_ADC_MAX_SAMPLES
int "The maximum number of channels that can be sampled"
default 16
---help---
The maximum number of samples which can be handled without
overrun depends on various factors. This is the user's
responsibility to correctly select this value.
Since the interface to update the sampling time is available
for all supported devices, the user can change the default
values in the board initialization logic and avoid ADC overrun.
config STM32H5_ADC1_DMA
bool "ADC1 DMA Enable"
depends on STM32H5_ADC1 && STM32H5_DMA
default n
---help---
If DMA is selected, then the ADC may be configured to support DMA
transfer, which is necessary if multiple channels are read or if
very high trigger frequencies are used.
config STM32H5_ADC1_DMA_BATCH
int "ADC1 DMA number of conversions"
depends on STM32H5_ADC1 && STM32H5_ADC1_DMA
default 1
---help---
This option allows you to select the number of regular group conversions
that will trigger a DMA callback transerring data to the upper-half driver.
By default, this value is 1, which means that data is transferred after
each group conversion.
config STM32H5_ADC1_DMA_CFG
bool "ADC1 DMA configuration"
depends on STM32H5_ADC1 && STM32H5_ADC1_DMA
default n
---help---
0 - ADC1 DMA in One Shot Mode, 1 - ADC1 DMA in Circular Mode
config STM32H5_ADC2_DMA
bool "ADC2 DMA Enable"
depends on STM32H5_ADC2 && STM32H5_DMA
default n
---help---
If DMA is selected, then the ADC may be configured to support DMA
transfer, which is necessary if multiple channels are read or if
very high trigger frequencies are used.
config STM32H5_ADC2_DMA_BATCH
int "ADC2 DMA number of conversions"
depends on STM32H5_ADC2 && STM32H5_ADC2_DMA
default 1
---help---
This option allows you to select the number of regular group conversions
that will trigger a DMA callback transerring data to the upper-half driver.
By default, this value is 1, which means that data is transferred after
each group conversion.
config STM32H5_ADC2_DMA_CFG
int "ADC2 DMA configuration"
depends on STM32H5_ADC2_DMA && STM32H5_DMA
range 0 1
default 0
---help---
0 - ADC2 DMA in One Shot Mode, 1 - ADC2 DMA in Circular Mode
endmenu # ADC Configuration
menu "SPI Configuration"
depends on STM32H5_SPI
@@ -4550,60 +4619,6 @@ endif # STM32H5_SERIALDRIVER
endmenu # U[S]ART Configuration
menu "ADC Configuration"
depends on STM32H5_ADC
config STM32H5_ADC_MAX_SAMPLES
int "The maximum number of channels that can be sampled"
default 16
---help---
The maximum number of samples which can be handled without
overrun depends on various factors. This is the user's
responsibility to correctly select this value.
Since the interface to update the sampling time is available
for all supported devices, the user can change the default
values in the board initialization logic and avoid ADC overrun.
config STM32H5_ADC1_DMA
bool "ADC1 DMA (not supported yet)"
depends on STM32H5_ADC1 && EXPERIMENTAL
default n
---help---
If DMA is selected, then the ADC may be configured to support
DMA transfer, which is necessary if multiple channels are read
or if very high trigger frequencies are used.
config STM32H5_ADC1_DMA_BATCH
int "ADC1 DMA number of conversions"
depends on STM32H5_ADC1 && STM32H5_ADC1_DMA
default 1
---help---
This option allows you to select the number of regular group conversions
that will trigger a DMA callback transerring data to the upper-half driver.
By default, this value is 1, which means that data is transferred after
each group conversion.
config STM32H5_ADC2_DMA
bool "ADC2 DMA (not supported yet)"
depends on STM32H5_ADC2 && EXPERIMENTAL
default n
---help---
If DMA is selected, then the ADC may be configured to support
DMA transfer, which is necessary if multiple channels are read
or if very high trigger frequencies are used.
config STM32H5_ADC2_DMA_BATCH
int "ADC2 DMA number of conversions"
depends on STM32H5_ADC2 && STM32H5_ADC2_DMA
default 1
---help---
This option allows you to select the number of regular group conversions
that will trigger a DMA callback transerring data to the upper-half driver.
By default, this value is 1, which means that data is transferred after
each group conversion.
endmenu
menu "Ethernet MAC Configuration"
depends on STM32H5_ETHMAC
+4
View File
@@ -88,6 +88,10 @@ ifeq ($(CONFIG_STM32H5_ETHMAC),y)
CHIP_CSRCS += stm32_ethernet.c
endif
ifeq ($(CONFIG_STM32H5_DMA),y)
CHIP_CSRCS += stm32_dma.c
endif
# Required chip type specific files
ifeq ($(CONFIG_STM32H5_STM32H5XXXX),y)
+9 -1
View File
@@ -30,6 +30,12 @@
#include <nuttx/config.h>
#include "chip.h"
#if defined(CONFIG_STM32H5_STM32H56XXX) || defined(CONFIG_STM32H5_STM32H57XXX)
# include "stm32h56x_dmasigmap.h"
#else
# error "Unsupported STM32 H5 DMA map"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -455,6 +461,8 @@
#define GPDMA_CXCR_PRIO_SHIFT (22) /* Bits 22-23: Priority level of ch x GPDMA transfer */
#define GPDMA_CXCR_PRIO_MASK (0b11 << GPDMA_CXCR_PRIO_SHIFT)
#define GPDMA_CXCR_ALLINTS (GPDMA_CXCR_TOIE|GPDMA_CXCR_SUSPEI|GPDMA_CXCR_USEIE|GPDMA_CXCR_ULEIE|GPDMA_CXCR_DTEIE|GPDMA_CXCR_HTIE|GPDMA_CXCR_TCIE)
/* Channel x transfer register 1 */
#define GPDMA_CXTR1_SDW_LOG2_SHIFT (0)
@@ -485,7 +493,7 @@
#define GPDMA_CXTR1_DBL_1(l) ((l) - 1 << GPDMA_CXTR1_DBL_1_SHIFT)
#define GPDMA_CXTR1_DBX (1 << 26) /* Destination byte exchange */
#define GPDMA_CXTR1_DHX (1 << 17) /* Destination half-word exchange */
#define GPDMA_CXTR1_DHX (1 << 27) /* Destination half-word exchange */
#define GPDMA_CXTR1_DAP (1 << 30) /* Destination allocated port */
#define GPDMA_CXTR1_DSEC (1 << 31) /* Security attribute of transfer to the destination */
@@ -0,0 +1,218 @@
/****************************************************************************
* arch/arm/src/stm32h5/hardware/stm32h56x_dmasigmap.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32H56X_DMASIGMAP_H
#define __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32H56X_DMASIGMAP_H
/* This file is valid for STM32H562/563/573 devices */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* GPDMA Request Number */
#define GPDMA_REQ_ADC1 (0)
#define GPDMA_REQ_ADC2 (1)
#define GPDMA_REQ_DAC1_CH1 (2)
#define GPDMA_REQ_DAC1_CH2 (3)
#define GPDMA_REQ_TIM6_UPD (4)
#define GPDMA_REQ_TIM7_UPD (5)
#define GPDMA_REQ_SPI1_RX (6)
#define GPDMA_REQ_SPI1_TX (7)
#define GPDMA_REQ_SPI2_RX (8)
#define GPDMA_REQ_SPI2_TX (9)
#define GPDMA_REQ_SPI3_RX (10)
#define GPDMA_REQ_SPI3_TX (11)
#define GPDMA_REQ_I2C1_RX (12)
#define GPDMA_REQ_I2C1_TX (13)
/* (14) RESERVED */
#define GPDMA_REQ_I2C2_RX (15)
#define GPDMA_REQ_I2C2_TX (16)
/* (17) RESERVED */
#define GPDMA_REQ_I2C3_RX (18)
#define GPDMA_REQ_I2C3_TX (19)
/* (20) RESERVED */
#define GPDMA_REQ_USART1_RX (21)
#define GPDMA_REQ_USART1_TX (22)
#define GPDMA_REQ_USART2_RX (23)
#define GPDMA_REQ_USART2_TX (24)
#define GPDMA_REQ_USART3_RX (25)
#define GPDMA_REQ_USART3_TX (26)
#define GPDMA_REQ_UART4_RX (27)
#define GPDMA_REQ_UART4_TX (28)
#define GPDMA_REQ_UART5_RX (29)
#define GPDMA_REQ_UART5_TX (30)
#define GPDMA_REQ_USART6_RX (31)
#define GPDMA_REQ_USART6_TX (32)
#define GPDMA_REQ_UART7_RX (33)
#define GPDMA_REQ_UART7_TX (34)
#define GPDMA_REQ_UART8_RX (35)
#define GPDMA_REQ_UART8_TX (36)
#define GPDMA_REQ_UART9_RX (37)
#define GPDMA_REQ_UART9_TX (38)
#define GPDMA_REQ_UART10_RX (39)
#define GPDMA_REQ_UART10_TX (40)
#define GPDMA_REQ_UART11_RX (41)
#define GPDMA_REQ_UART11_TX (42)
#define GPDMA_REQ_UART12_RX (43)
#define GPDMA_REQ_UART12_TX (44)
#define GPDMA_REQ_LPUART1_RX (45)
#define GPDMA_REQ_LPUART1_TX (46)
#define GPDMA_REQ_SPI4_RX (47)
#define GPDMA_REQ_SPI4_TX (48)
#define GPDMA_REQ_SPI5_RX (49)
#define GPDMA_REQ_SPI5_TX (50)
#define GPDMA_REQ_SPI6_RX (51)
#define GPDMA_REQ_SPI6_TX (52)
#define GPDMA_REQ_SAI1_A (53)
#define GPDMA_REQ_SAI1_B (54)
#define GPDMA_REQ_SAI2_A (55)
#define GPDMA_REQ_SAI2_B (56)
#define GPDMA_REQ_OSPI1 (57)
#define GPDMA_REQ_TIM1_CC1 (58)
#define GPDMA_REQ_TIM1_CC2 (59)
#define GPDMA_REQ_TIM1_CC3 (60)
#define GPDMA_REQ_TIM1_CC4 (61)
#define GPDMA_REQ_TIM1_UPD (62)
#define GPDMA_REQ_TIM1_TRG (63)
#define GPDMA_REQ_TIM1_COM (64)
#define GPDMA_REQ_TIM8_CC1 (65)
#define GPDMA_REQ_TIM8_CC2 (66)
#define GPDMA_REQ_TIM8_CC3 (67)
#define GPDMA_REQ_TIM8_CC4 (68)
#define GPDMA_REQ_TIM8_UPD (69)
#define GPDMA_REQ_TIM8_TIG (70)
#define GPDMA_REQ_TIM8_COM (71)
#define GPDMA_REQ_TIM2_CC1 (72)
#define GPDMA_REQ_TIM2_CC2 (73)
#define GPDMA_REQ_TIM2_CC3 (74)
#define GPDMA_REQ_TIM2_CC4 (75)
#define GPDMA_REQ_TIM2_UPD (76)
#define GPDMA_REQ_TIM3_CC1 (77)
#define GPDMA_REQ_TIM3_CC2 (78)
#define GPDMA_REQ_TIM3_CC3 (79)
#define GPDMA_REQ_TIM3_CC4 (80)
#define GPDMA_REQ_TIM3_UPD (81)
#define GPDMA_REQ_TIM3_TRG (82)
#define GPDMA_REQ_TIM4_CC1 (83)
#define GPDMA_REQ_TIM4_CC2 (84)
#define GPDMA_REQ_TIM4_CC3 (85)
#define GPDMA_REQ_TIM4_CC4 (86)
#define GPDMA_REQ_TIM4_UPD (87)
#define GPDMA_REQ_TIM5_CC1 (88)
#define GPDMA_REQ_TIM5_CC2 (89)
#define GPDMA_REQ_TIM5_CC3 (90)
#define GPDMA_REQ_TIM5_CC4 (91)
#define GPDMA_REQ_TIM5_UPD (92)
#define GPDMA_REQ_TIM5_TRG (93)
#define GPDMA_REQ_TIM15_CC1 (94)
#define GPDMA_REQ_TIM15_UPD (95)
#define GPDMA_REQ_TIM15_TRG (96)
#define GPDMA_REQ_TIM15_COM (97)
#define GPDMA_REQ_TIM16_CC1 (98)
#define GPDMA_REQ_TIM16_UPD (99)
#define GPDMA_REQ_TIM17_CC1 (100)
#define GPDMA_REQ_TIM17_UPD (101)
#define GPDMA_REQ_LPTIM1_IC1 (102)
#define GPDMA_REQ_LPTIM1_IC2 (103)
#define GPDMA_REQ_LPTIM1_UE (104)
#define GPDMA_REQ_LPTIM2_IC1 (105)
#define GPDMA_REQ_LPTIM2_IC2 (106)
#define GPDMA_REQ_LPTIM2_UE (107)
#define GPDMA_REQ_DCMI_PSSI (108)
#define GPDMA_REQ_AES_OUT (109)
#define GPDMA_REQ_AES_IN (110)
#define GPDMA_REQ_HASH_IN (111)
#define GPDMA_REQ_UCPD1_RX (112)
#define GPDMA_REQ_UCPD1_TX (113)
#define GPDMA_REQ_CORDIC_R (114)
#define GPDMA_REQ_CORDIC_W (115)
#define GPDMA_REQ_FMAC_R (116)
#define GPDMA_REQ_FMAC_W (117)
#define GPDMA_REQ_SAES_OUT (118)
#define GPDMA_REQ_SAES_IN (119)
#define GPDMA_REQ_I3C1_RX (120)
#define GPDMA_REQ_I3C1_TX (121)
#define GPDMA_REQ_I3C1_TC (122)
#define GPDMA_REQ_I3C1_RS (123)
#define GPDMA_REQ_I2C4_RX (124)
#define GPDMA_REQ_I2C4_TX (125)
/* (126) RESERVED */
#define GPDMA_REQ_LPTIM3_IC1 (127)
#define GPDMA_REQ_LPTIM3_IC2 (128)
#define GPDMA_REQ_LPTIM3_UE (129)
#define GPDMA_REQ_LPTIM5_IC1 (130)
#define GPDMA_REQ_LPTIM5_IC2 (131)
#define GPDMA_REQ_LPTIM5_UE (132)
#define GPDMA_REQ_LPTIM6_IC1 (133)
#define GPDMA_REQ_LPTIM6_IC2 (134)
#define GPDMA_REQ_LPTIM6_UE (135)
/* GPDMA Trigger Number */
#define GPDMA_TRIG_EXTI0 (0)
#define GPDMA_TRIG_EXTI1 (1)
#define GPDMA_TRIG_EXTI2 (2)
#define GPDMA_TRIG_EXTI3 (3)
#define GPDMA_TRIG_EXTI4 (4)
#define GPDMA_TRIG_EXTI5 (5)
#define GPDMA_TRIG_EXTI6 (6)
#define GPDMA_TRIG_EXTI7 (7)
#define GPDMA_TRIG_TAMP_TRG1 (8)
#define GPDMA_TRIG_TAMP_TRG2 (9)
#define GPDMA_TRIG_TAMP_TRG4 (10)
#define GPDMA_TRIG_LPTIM1_CH1 (11)
#define GPDMA_TRIG_LPTIM1_CH2 (12)
#define GPDMA_TRIG_LPTIM2_CH1 (13)
#define GPDMA_TRIG_LPTIM2_CH2 (14)
#define GPDMA_TRIG_RTC_ALRA_TRG (15)
#define GPDMA_TRIG_RTC_ALRB_TRG (16)
#define GPDMA_TRIG_RTC_WUT_TRG (17)
#define GPDMA_TRIG_GPDMA1_CH0_TC (18)
#define GPDMA_TRIG_GPDMA1_CH1_TC (19)
#define GPDMA_TRIG_GPDMA1_CH2_TC (20)
#define GPDMA_TRIG_GPDMA1_CH3_TC (21)
#define GPDMA_TRIG_GPDMA1_CH4_TC (22)
#define GPDMA_TRIG_GPDMA1_CH5_TC (23)
#define GPDMA_TRIG_GPDMA1_CH6_TC (24)
#define GPDMA_TRIG_GPDMA1_CH7_TC (25)
#define GPDMA_TRIG_GPDMA2_CH0_TC (26)
#define GPDMA_TRIG_GPDMA2_CH1_TC (27)
#define GPDMA_TRIG_GPDMA2_CH2_TC (28)
#define GPDMA_TRIG_GPDMA2_CH3_TC (29)
#define GPDMA_TRIG_GPDMA2_CH4_TC (30)
#define GPDMA_TRIG_GPDMA2_CH5_TC (31)
#define GPDMA_TRIG_GPDMA2_CH6_TC (32)
#define GPDMA_TRIG_GPDMA2_CH7_TC (33)
#define GPDMA_TRIG_TIM2_TRGO (34)
#define GPDMA_TRIG_TIM15_TRG0 (35)
#define GPDMA_TRIG_TIM12_TRGO (36)
#define GPDMA_TRIG_LPTIM3_CH1 (37)
#define GPDMA_TRIG_LPTIM3_CH2 (38)
#define GPDMA_TRIG_LPTIM4_AIT (39)
#define GPDMA_TRIG_LPTIM5_CH1 (40)
#define GPDMA_TRIG_LPTIM5_CH2 (41)
#define GPDMA_TRIG_LPTIM6_CH1 (42)
#define GPDMA_TRIG_LPTIM6_CH2 (43)
#endif /* __ARCH_ARM_SRC_STM32H5_HARDWARE_STM32H56X_DMASIGMAP_H */
+169 -26
View File
@@ -3,8 +3,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
@@ -49,6 +47,9 @@
#include "stm32_adc.h"
#include "stm32_tim.h"
#include "stm32_rcc.h"
#include "stm32_dma.h"
/* ADC "upper half" support must be enabled */
#ifdef CONFIG_ADC
@@ -64,11 +65,6 @@
/* ADC Channels/DMA *********************************************************/
#ifdef ADC_HAVE_DMA
# error "STM32H5 ADC does not have DMA support."
# undef ADC_HAVE_DMA
#endif
#define ADC_SMPR_DEFAULT ADC_SMPR_640p5
#define ADC_SMPR1_DEFAULT ((ADC_SMPR_DEFAULT << ADC_SMPR1_SMP0_SHIFT) | \
(ADC_SMPR_DEFAULT << ADC_SMPR1_SMP1_SHIFT) | \
@@ -105,10 +101,10 @@ struct stm32_dev_s
uint8_t cchannels; /* Number of configured channels */
uint8_t intf; /* ADC interface number */
uint8_t current; /* Current ADC channel being converted */
bool hasdma; /* True: This ADC supports DMA */
#ifdef ADC_HAVE_DMA
uint8_t dmachan; /* DMA channel needed by this ADC */
bool hasdma; /* True: This ADC supports DMA */
uint16_t dmabatch; /* Number of conversions for DMA batch */
bool circular; /* 0 = one-shot, 1 = circular */
#endif
#ifdef ADC_HAVE_TIMER
uint8_t trigger; /* Timer trigger channel: 0=CC1, 1=CC2, 2=CC3,
@@ -187,6 +183,13 @@ static void adc_timstart(struct stm32_dev_s *priv, bool enable);
static int adc_timinit(struct stm32_dev_s *priv);
#endif
#ifdef ADC_HAVE_DMA
static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t status,
void *arg);
static void adc_dmacfg(struct stm32_dev_s *priv,
struct stm32_gpdma_cfg_s *cfg);
#endif
/* ADC Interrupt Handler */
static int adc_interrupt(struct adc_dev_s *dev, uint32_t regval);
@@ -245,10 +248,16 @@ static struct stm32_dev_s g_adcpriv1 =
.freq = CONFIG_STM32H5_ADC1_SAMPLE_FREQUENCY,
#endif
#ifdef ADC1_HAVE_DMA
.dmachan = ADC1_DMA_CHAN,
.hasdma = true,
.r_dmabuffer = g_adc1_dmabuffer,
.dmabatch = CONFIG_STM32H5_ADC1_DMA_BATCH
.dmabatch = CONFIG_STM32H5_ADC1_DMA_BATCH,
# ifdef CONFIG_STM32H5_ADC1_DMA_CFG
.circular = true,
# else
.circular = false,
# endif
#else
.hasdma = false,
#endif
};
@@ -262,6 +271,12 @@ static struct adc_dev_s g_adcdev1 =
/* ADC2 state */
#ifdef CONFIG_STM32H5_ADC2
#ifdef ADC2_HAVE_DMA
static uint16_t g_adc2_dmabuffer[CONFIG_STM32H5_ADC_MAX_SAMPLES *
CONFIG_STM32H5_ADC2_DMA_BATCH];
#endif
static struct stm32_dev_s g_adcpriv2 =
{
.irq = STM32_IRQ_ADC2,
@@ -279,6 +294,18 @@ static struct stm32_dev_s g_adcpriv2 =
.pclck = ADC2_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32H5_ADC2_SAMPLE_FREQUENCY,
#endif
#ifdef ADC2_HAVE_DMA
.hasdma = true,
.r_dmabuffer = g_adc2_dmabuffer,
.dmabatch = CONFIG_STM32H5_ADC2_DMA_BATCH,
# ifdef CONFIG_STM32H5_ADC2_DMA_CFG
.circular = true,
# else
.circular = false,
# endif
#else
.hasdma = false,
#endif
};
static struct adc_dev_s g_adcdev2 =
@@ -777,6 +804,104 @@ static void adc_reset(struct adc_dev_s *dev)
adc_rccreset(priv, false);
}
/****************************************************************************
* Name: adc_dmaconvcallback
*
* Description:
* Callback for DMA. Called from the DMA transfer complete interrupt after
* all channels have been converted and transferred with DMA.
*
* Input Parameters:
*
* handle - handle to DMA
* status -
* arg - adc device
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef ADC_HAVE_DMA
static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t status, void *arg)
{
struct adc_dev_s *dev = (struct adc_dev_s *)arg;
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev->ad_priv;
struct stm32_gpdma_cfg_s dmacfg;
int i;
/* Verify that the upper-half has bound its callback */
if (priv->cb != NULL)
{
DEBUGASSERT(priv->cb->au_receive != NULL);
/* Deliver one sample per configured channel */
for (i = 0; i < priv->rnchannels * priv->dmabatch; i++)
{
priv->cb->au_receive(dev,
priv->chanlist[priv->current],
priv->r_dmabuffer[i]);
priv->current++;
if (priv->current >= priv->rnchannels)
{
priv->current = 0;
}
}
}
/* Restart DMA for the next conversion series */
if (priv->circular == 0)
{
adc_dmacfg(priv, &dmacfg);
stm32_dmasetup(priv->dma, &dmacfg);
stm32_dmastart(priv->dma, adc_dmaconvcallback, dev, false);
adc_startconv(priv, true);
}
}
/****************************************************************************
* Name: adc_dmacfg
*
* Description:
* Generate the required DMA configuration structure for oneshot mode based
* on the ADC configuration.
*
* Input Parameters:
* priv - ADC instance structure
* cfg - DMA configuration structure
* circular - 0 = oneshot, 1 = circular
*
* Returned Value:
* None
****************************************************************************/
static void adc_dmacfg(struct stm32_dev_s *priv,
struct stm32_gpdma_cfg_s *cfg)
{
const uint32_t sdw_log2 = 1; /* Always 16-bit half-word for ADC_DR */
cfg->src_addr = priv->base + STM32_ADC_DR_OFFSET;
cfg->dest_addr = (uintptr_t)priv->r_dmabuffer;
cfg->request = (priv->base == STM32_ADC1_BASE)
? GPDMA_REQ_ADC1
: GPDMA_REQ_ADC2;
cfg->priority = GPMDACFG_PRIO_LH;
cfg->mode = priv->circular ? GPDMACFG_MODE_CIRC : 0;
cfg->ntransfers = priv->cchannels * priv->dmabatch * (1u << sdw_log2);
cfg->tr1 = (sdw_log2 << GPDMA_CXTR1_SDW_LOG2_SHIFT)
| (sdw_log2 << GPDMA_CXTR1_DDW_LOG2_SHIFT)
| GPDMA_CXTR1_DINC; /* dest-inc, source fixed */
}
#endif
/****************************************************************************
* Name: adc_setup
*
@@ -795,6 +920,9 @@ static void adc_reset(struct adc_dev_s *dev)
static int adc_setup(struct adc_dev_s *dev)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev->ad_priv;
#ifdef ADC_HAVE_DMA
struct stm32_gpdma_cfg_s dmacfg;
#endif
int ret;
irqstate_t flags;
uint32_t clrbits;
@@ -842,15 +970,29 @@ static int adc_setup(struct adc_dev_s *dev)
#ifdef ADC_HAVE_DMA
if (priv->hasdma)
{
/* Enable One shot DMA */
/* Enable One-shot or Circular DMA.
* WARNING: This doesn't work in dual-ADC modes. [RM0481] ADC_CFGR
* register description (pg. 1122) - "In dual-ADC modes, this bit is
* not relevant and replaced by control bit DMACFG of the ADC_CCR
* register"
*/
setbits |= ADC_CFGR_DMAEN;
if (priv->circular)
{
setbits |= ADC_CFGR_DMACFG;
setbits |= ADC_CFGR_CONT;
}
else
{
clrbits |= ADC_CFGR_DMACFG;
clrbits |= ADC_CFGR_CONT;
}
}
#endif
/* Disable continuous mode */
#else
clrbits |= ADC_CFGR_CONT;
#endif
/* Disable external trigger for regular channels */
@@ -903,17 +1045,14 @@ static int adc_setup(struct adc_dev_s *dev)
stm32_dmafree(priv->dma);
}
priv->dma = stm32_dmachannel(priv->dmachan);
priv->dma = stm32_dmachannel(GPDMA_TTYPE_P2M);
stm32_dmasetup(priv->dma,
priv->base + STM32_ADC_DR_OFFSET,
(uint32_t)priv->r_dmabuffer,
priv->rnchannels * priv->dmabatch,
ADC_DMA_CONTROL_WORD);
adc_dmacfg(priv, &dmacfg);
stm32_dmasetup(priv->dma, &dmacfg);
stm32_dmastart(priv->dma, adc_dmaconvcallback, dev, false);
}
#endif
/* Set ADEN to wake up the ADC from Power Down. */
@@ -949,10 +1088,14 @@ static int adc_setup(struct adc_dev_s *dev)
adc_getreg(priv, STM32_ADC_SQR4_OFFSET));
ainfo("CCR: 0x%08" PRIx32 "\n", adc_getregm(priv, STM32_ADC_CCR_OFFSET));
/* Enable the ADC interrupt */
if (!priv->hasdma)
{
/* Enable the ADC interrupt */
ainfo("Enable the ADC interrupt: irq=%d\n", priv->irq);
up_enable_irq(priv->irq);
ainfo("Enable the ADC interrupt: irq=%d\n", priv->irq);
up_enable_irq(priv->irq);
}
priv->initialized = true;
+48 -95
View File
@@ -43,52 +43,58 @@
/* Timer devices may be used for different purposes. One special purpose is
* to control periodic ADC sampling. If CONFIG_STM32H5_TIMn is defined then
* CONFIG_STM32H5_TIMn_ADC must also be defined to indicate that timer "n"
* is intended to be used for that purpose. Timers 1,2,3,6 and 15 may be
* used on STM32H5X3, while STM32H5X6 adds support for timers 4 and 8 as
* well.
* is intended to be used for that purpose.
*/
#ifndef CONFIG_STM32H5_TIM1
# undef CONFIG_STM32H5_TIM1_ADC
# undef CONFIG_STM32H5_TIM1_ADC1
# undef CONFIG_STM32H5_TIM1_ADC2
# undef CONFIG_STM32H5_TIM1_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM2
# undef CONFIG_STM32H5_TIM2_ADC
# undef CONFIG_STM32H5_TIM2_ADC1
# undef CONFIG_STM32H5_TIM2_ADC2
# undef CONFIG_STM32H5_TIM2_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM3
# undef CONFIG_STM32H5_TIM3_ADC
# undef CONFIG_STM32H5_TIM3_ADC1
# undef CONFIG_STM32H5_TIM3_ADC2
# undef CONFIG_STM32H5_TIM3_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM4
# undef CONFIG_STM32H5_TIM4_ADC
# undef CONFIG_STM32H5_TIM4_ADC1
# undef CONFIG_STM32H5_TIM4_ADC2
# undef CONFIG_STM32H5_TIM4_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM6
# undef CONFIG_STM32H5_TIM6_ADC
# undef CONFIG_STM32H5_TIM6_ADC1
# undef CONFIG_STM32H5_TIM6_ADC2
# undef CONFIG_STM32H5_TIM6_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM8
# undef CONFIG_STM32H5_TIM8_ADC
# undef CONFIG_STM32H5_TIM8_ADC1
# undef CONFIG_STM32H5_TIM8_ADC2
# undef CONFIG_STM32H5_TIM8_ADC3
#endif
#ifndef CONFIG_STM32H5_TIM15
# undef CONFIG_STM32H5_TIM15_ADC
# undef CONFIG_STM32H5_TIM15_ADC1
# undef CONFIG_STM32H5_TIM15_ADC2
# undef CONFIG_STM32H5_TIM15_ADC3
#endif
/* DMA support */
#undef ADC_HAVE_DMA
#if defined(CONFIG_STM32H5_ADC1_DMA) || defined(CONFIG_STM32H5_ADC2_DMA)
# define ADC_HAVE_DMA 1
#endif
#if defined(CONFIG_STM32H5_ADC1_DMA)
# define ADC1_HAVE_DMA 1
#endif
#if defined(CONFIG_STM32H5_ADC2_DMA)
# define ADC2_HAVE_DMA 1
#endif
/* Timer configuration: If a timer trigger is specified, then get
@@ -213,72 +219,19 @@
# undef ADC_HAVE_TIMER
#endif
/* Timer 1 */
#define ADC1_EXTSEL_T1CC1 ADC_CFGR_EXTSEL_T1CC1
#define ADC1_EXTSEL_T1CC2 ADC_CFGR_EXTSEL_T1CC2
#define ADC1_EXTSEL_T1CC3 ADC_CFGR_EXTSEL_T1CC3
#define ADC1_EXTSEL_T1CC4 ADC_CFGR_EXTSEL_T1CC4
#define ADC1_EXTSEL_T1TRGO ADC_CFGR_EXTSEL_T1TRGO
#define ADC1_EXTSEL_T1TRGO2 ADC_CFGR_EXTSEL_T1TRGO2
#define ADC2_EXTSEL_T1CC1 ADC_CFGR_EXTSEL_T1CC1
#define ADC2_EXTSEL_T1CC2 ADC_CFGR_EXTSEL_T1CC2
#define ADC2_EXTSEL_T1CC3 ADC_CFGR_EXTSEL_T1CC3
#define ADC2_EXTSEL_T1CC4 ADC_CFGR_EXTSEL_T1CC4
#define ADC2_EXTSEL_T1TRGO ADC_CFGR_EXTSEL_T1TRGO
#define ADC2_EXTSEL_T1TRGO2 ADC_CFGR_EXTSEL_T1TRGO2
/* Timer 2 */
#define ADC1_EXTSEL_T2CC2 ADC_CFGR_EXTSEL_T2CC2
#define ADC1_EXTSEL_T2TRGO ADC_CFGR_EXTSEL_T2TRGO
#define ADC2_EXTSEL_T2CC2 ADC_CFGR_EXTSEL_T2CC2
#define ADC2_EXTSEL_T2TRGO ADC_CFGR_EXTSEL_T2TRGO
/* Timer 3 */
#define ADC1_EXTSEL_T3CC4 ADC_CFGR_EXTSEL_T3CC4
#define ADC1_EXTSEL_T3TRGO ADC_CFGR_EXTSEL_T3TRGO
#define ADC2_EXTSEL_T3CC4 ADC_CFGR_EXTSEL_T3CC4
#define ADC2_EXTSEL_T3TRGO ADC_CFGR_EXTSEL_T3TRGO
/* Timer 4 */
#define ADC1_EXTSEL_T4CC4 ADC_CFGR_EXTSEL_T4CC4
#define ADC1_EXTSEL_T4TRGO ADC_CFGR_EXTSEL_T4TRGO
#define ADC2_EXTSEL_T4CC4 ADC_CFGR_EXTSEL_T4CC4
#define ADC2_EXTSEL_T4TRGO ADC_CFGR_EXTSEL_T4TRGO
/* Timer 6 */
#define ADC1_EXTSEL_T6TRGO ADC_CFGR_EXTSEL_T6TRGO
#define ADC2_EXTSEL_T6TRGO ADC_CFGR_EXTSEL_T6TRGO
/* Timer 8 */
#define ADC1_EXTSEL_T8TRGO ADC_CFGR_EXTSEL_T8TRGO
#define ADC1_EXTSEL_T8TRGO2 ADC_CFGR_EXTSEL_T8TRGO2
#define ADC2_EXTSEL_T8TRGO ADC_CFGR_EXTSEL_T8TRGO
#define ADC2_EXTSEL_T8TRGO2 ADC_CFGR_EXTSEL_T8TRGO2
/* Timer 15 */
#define ADC1_EXTSEL_T15TRGO ADC_CFGR_EXTSEL_T15TRGO
#define ADC2_EXTSEL_T15TRGO ADC_CFGR_EXTSEL_T15TRGO
#if defined(CONFIG_STM32H5_TIM1_ADC1)
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC1
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1CC1
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC2
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1CC2
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC3
# define ADC1_EXTSEL_VALUE ADC_CFGR__EXTSEL_T1CC3
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1CC4
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1CC4
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T1TRGO2
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1TRGO2
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM1)"
# endif
@@ -286,13 +239,13 @@
# if CONFIG_STM32H5_ADC1_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 1
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2CC2
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T2CC2
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T2TRGO
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T2TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM2)"
# else
@@ -306,9 +259,9 @@
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3CC4
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T3CC4
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T3TRGO
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T3TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM3)"
# else
@@ -322,9 +275,9 @@
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4CC4
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T4CC4
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T4TRGO
# define ADC1_EXTSEL_VALUE ADC_CRFT_EXTSEL_T4TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM4)"
# else
@@ -340,7 +293,7 @@
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T6TRGO
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T6TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM6)"
# else
@@ -356,9 +309,9 @@
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T8TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T8TRGO2
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T8TRGO2
# else
# error "CONFIG_STM32H5_ADC1_TIMTRIG is out of range (TIM8)"
# endif
@@ -372,7 +325,7 @@
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 4
# define ADC1_EXTSEL_VALUE ADC1_EXTSEL_T15TRGO
# define ADC1_EXTSEL_VALUE ADC_CFGR_EXTSEL_T15TRGO
# elif CONFIG_STM32H5_ADC1_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC1_TIMTRIG is invalid (TIM15)"
# else
@@ -382,17 +335,17 @@
#if defined(CONFIG_STM32H5_TIM1_ADC2)
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC1
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1CC1
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC2
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1CC2
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC3
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1CC3
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1CC4
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1CC4
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T1TRGO2
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T1TRGO2
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM1)"
# endif
@@ -400,13 +353,13 @@
# if CONFIG_STM32H5_ADC2_TIMTRIG == 0
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 1
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2CC2
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T2CC2
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T2TRGO
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T2TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM2)"
# else
@@ -420,9 +373,9 @@
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM3)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3CC4
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T3CC4
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T3TRGO
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T3TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM3)"
# else
@@ -436,9 +389,9 @@
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 2
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM4)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4CC4
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T4CC4
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T4TRGO
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T4TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM4)"
# else
@@ -454,7 +407,7 @@
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM6)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T6TRGO
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T6TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM6)"
# else
@@ -470,9 +423,9 @@
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM8)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T8TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T8TRGO2
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T8TRGO2
# else
# error "CONFIG_STM32H5_ADC2_TIMTRIG is out of range (TIM8)"
# endif
@@ -486,7 +439,7 @@
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 3
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM15)"
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 4
# define ADC2_EXTSEL_VALUE ADC2_EXTSEL_T15TRGO
# define ADC2_EXTSEL_VALUE ADC_CFGR_EXTSEL_T15TRGO
# elif CONFIG_STM32H5_ADC2_TIMTRIG == 5
# error "CONFIG_STM32H5_ADC2_TIMTRIG is invalid (TIM15)"
# else
File diff suppressed because it is too large Load Diff
+307
View File
@@ -30,12 +30,150 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include "hardware/stm32_gpdma.h"
#ifdef CONFIG_DEBUG_DMA_INFO
# error "CONFIG_DEBUG_DMA_INFO not yet implemented."
# undef CONFIG_DEBUG_DMA_INFO
#endif
#ifdef CONFIG_STM32H5_DMACAPABLE
# error "CONFIG_STM32H5_DMACAPABLE not yet implemented."
# undef CONFIG_STM32H5_DMACAPABLE
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* These definitions provide the bit encoding of the 'status' parameter
* passed to the DMA callback function (see dma_callback_t).
*/
#define DMA_STATUS_TCF (1 << 0) /* Transfer Complete */
#define DMA_STATUS_HTF (1 << 1) /* Half Transfer */
#define DMA_STATUS_DTEF (1 << 2) /* Data transfer error */
#define DMA_STATUS_ULEF (1 << 3) /* Update link transfer error */
#define DMA_STATUS_USEF (1 << 4) /* User setting error */
#define DMA_STATUS_SUSPF (1 << 5) /* Completed suspension flag */
#define DMA_STATUS_TOF (1 << 6) /* Trigger overrun flag */
#define DMA_STATUS_ERROR (DMA_STATUS_DTEF | DMA_STATUS_ULEF | DMA_STATUS_USEF | DMA_STATUS_TOF)
#define DMA_STATUS_SUCCESS (DMA_STATUS_TCF | DMA_STATUS_HTEF)
/* GPDMA Mode Flags: WARNING!! NOT YET IMPLEMENTED! */
#define GPDMACFG_MODE_CIRC (1 << 0) /* Enable Circular mode */
#define GPDMACFG_MODE_PFC (1 << 1) /* Enable Peripheral flow control */
#define GPDMACFG_MODE_DB (1 << 2) /* Enable Double buffer mode */
/* Channel priority level
* Refer to PRIO field in GPDMA_CxCR register description (RM0481)
*/
#define GPDMACFG_PRIO_LL (0) /* Low priority, low weight */
#define GPDMACFG_PRIO_LM (1) /* Low priority, mid weight */
#define GPMDACFG_PRIO_LH (2) /* Low priority, high weight */
#define GPDMACFG_PRIO_H (3) /* High priority */
/****************************************************************************
* Public Types
****************************************************************************/
/* GPDMA transfer type enumeration */
enum gpdma_ttype_e
{
/* Peripheral-to-memory transfer */
GPDMA_TTYPE_P2M = 0,
/* Memory-to-peripheral transfer */
GPDMA_TTYPE_M2P,
/* Memory-to-memory transfer, linear addressing */
GPDMA_TTYPE_M2M_LINEAR,
/* 2D Addressing needed (NOT IMPLEMENTED YET) */
GPDMA_TTYPE_2D
};
#ifdef CONFIG_DEBUG_DMA_INFO
struct stm32_gpdma_reg_s
{
uint32_t cxlbar;
uint32_t cxfcr;
uint32_t cxsr;
uint32_t cxcr;
uint32_t cxtr1;
uint32_t cxtr2;
uint32_t cxbr1;
uint32_t cxsar;
uint32_t cxdar;
uint32_t cxtr3;
uint32_t cxbr2;
uint32_t cxllr;
};
#endif
struct stm32_gpdma_cfg_s
{
uint32_t src_addr;
uint32_t dest_addr;
/* CxTR1 register for specified channel. */
uint32_t tr1;
/* request: Accepts GPDMA_CXTR2_SWREQ, GPDMA_CXTR2_DREQ, and
* GPDMA_CXTR2_REQSEL(r) for r given by GPDMA_REQ_x
* macros defined in hardware/stm32h56x_dmasigmap.h
*/
uint16_t request;
/* Number of transfers, in units of the data width
* specified in tr1.
*/
uint16_t ntransfers;
/* Priority level: refer to GPDMACFG_PRIO defines above */
uint8_t priority;
/* mode flags, refer to GPDMACFG_MODE_X defines above. */
uint8_t mode;
};
/* DMA_HANDLE Provides an opaque reference that can be used to represent a
* DMA stream.
*/
typedef void *DMA_HANDLE;
/* Description:
* This is the type of the callback that is used to inform the user of the
* completion of the DMA. NOTE: The DMA module does *NOT* perform any
* cache operations. It is the responsibility of the DMA client to
* invalidate DMA buffers after completion of the DMA RX operations.
*
* Input Parameters:
* handle - Refers to the DMA channel or stream
* status - A bit encoded value that provides the completion status. See
* the DMA_STATUS_* definitions above.
* arg - A user-provided value that was provided when stm32_dmastart()
* was called.
*/
typedef void (*dma_callback_t)(DMA_HANDLE handle, uint8_t status, void *arg);
/****************************************************************************
* Public Data
****************************************************************************/
@@ -55,6 +193,175 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: stm32_dmachannel
*
* Description:
* Allocate a DMA channel based on provided transfer type. The driver will
* return the first available DMA channel compatible with the transfer type
*
* Input Parameters:
* type - Type of DMA transfer required
*
* Returned Value:
* On success, this function returns a non-NULL, void* DMA channel handle.
* NULL is returned on any failure. This function can fail only if no DMA
* channel is available.
*
* Assumptions:
* - The caller does not hold he DMA channel.
* - The caller can wait for the DMA channel to be freed if it is no
* available.
*
****************************************************************************/
DMA_HANDLE stm32_dmachannel(enum gpdma_ttype_e type);
/****************************************************************************
* Name: stm32_dmafree
*
* Description:
* Release a DMA channel.
*
* NOTE: The 'handle' used in this argument must NEVER be used again
* until stm32_dmachannel() is called again to re-gain access to the
* channel.
*
* Returned Value:
* None
*
* Assumptions:
* - The caller holds the DMA channel.
* - There is no DMA in progress
*
****************************************************************************/
void stm32_dmafree(DMA_HANDLE handle);
/****************************************************************************
* Name: stm32_dmasetup
*
* Description:
* Configure DMA before using
*
* Input Parameters:
* TODO: Figure out what the input parameter needs to be!!! H7 and F7 have
* very different implementations.
*
****************************************************************************/
void stm32_dmasetup(DMA_HANDLE handle, struct stm32_gpdma_cfg_s *cfg);
/****************************************************************************
* Name: stm32_dmastart
*
* Description:
* Start the DMA transfer. NOTE: The DMA module does *NOT* perform any
* cache operations. It is the responsibility of the DMA client to clean
* DMA buffers after starting of the DMA TX operations.
*
* Assumptions:
* - DMA handle allocated by stm32_dmachannel()
* - No DMA in progress
*
****************************************************************************/
void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg,
bool half);
/****************************************************************************
* Name: stm32_dmastop
*
* Description:
* Cancel the DMA. After stm32_dmastop() is called, the DMA channel is
* reset and stm32_dmasetup() must be called before stm32_dmastart() can be
* called again
*
* Assumptions:
* - DMA handle allocated by stm32_dmachannel()
*
****************************************************************************/
void stm32_dmastop(DMA_HANDLE handle);
/****************************************************************************
* Name: stm32_dmaresidual
*
* Description:
* Returns the number of bytes remaining to be transferred
*
* Assumptions:
* - DMA handle allocated by stm32_dmachannel()
*
****************************************************************************/
size_t stm32_dmaresidual(DMA_HANDLE handle);
/****************************************************************************
* Name: stm32_dmacapable
*
* Description:
* Check if the DMA controller can transfer data to/from given memory
* address with the given configuration. This depends on the internal
* connections in the ARM bus matrix of the processor. Note that this only
* applies to memory addresses, it will return false for any peripheral
* address.
*
* Input Parameters:
*
* maddr - starting memory address
* count - number of unit8 or uint16 or uint32 items as defined by MSIZE
* of ccr.
* ccr - DMA stream configuration register
*
* Returned Value:
* True, if transfer is possible.
*
****************************************************************************/
#ifdef CONFIG_STM32H5_DMACAPABLE
bool stm32_dmacapable(DMA_HANDLE handle, struct stm32_gpdma_cfg_s *cfg);
#else
# define stm32_dmacapable(handle, cfg) (true)
#endif
/****************************************************************************
* Name: stm32_dmasample
*
* Description:
* Sample DMA register contents
*
* Input Parameters:
* TODO: Figure these out!! Not sure if I need the struct like F7 or not?
*
* Assumptions:
* - DMA handle allocated by stm32_dmachannel()
*
****************************************************************************/
#ifdef CONFIG_DEBUG_DMA_INFO
void stm32_dmasample(DMA_HANDLE handle, struct stm32_dmaregs_s *regs);
#else
# define stm32_dmasample(handle,regs)
#endif
/****************************************************************************
* Name: stm32_dmadump
*
* Description:
* Dump previously sampled DMA register contents
*
* Assumptions:
* - DMA handle allocated by stm32_dmachannel()
*
****************************************************************************/
#ifdef CONFIG_DEBUG_DMA_INFO
void stm32_dmadump(DMA_HANDLE handle, const char *msg);
#else
# define stm32_dmadump(handle,msg)
#endif
#undef EXTERN
#if defined(__cplusplus)
}
+2 -2
View File
@@ -89,13 +89,13 @@ static inline void rcc_enableahb1(void)
regval = getreg32(STM32_RCC_AHB1ENR);
#ifdef CONFIG_STM32H5_GPDMA1
#ifdef CONFIG_STM32H5_DMA1
/* DMA 1 clock enable */
regval |= RCC_AHB1ENR_GPDMA1EN;
#endif
#ifdef CONFIG_STM32H5_GPDMA2
#ifdef CONFIG_STM32H5_DMA2
/* DMA 2 clock enable */
regval |= RCC_AHB1ENR_GPDMA2EN;