Merge pull request #323 from WestberryTech/chibios-21.11.x-wb

Added support for WB32 MCU of ADC and DMAC.
This commit is contained in:
Fabien Poussin 2022-05-14 12:17:13 +02:00 committed by GitHub
commit a4072ada3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 2142 additions and 16 deletions

View File

@ -164,5 +164,11 @@
#define WB32_USB_USB1_IRQ_PRIORITY 13
#define WB32_USB_HOST_WAKEUP_DURATION 10
/*
* ADC driver system settings.
*/
#define WB32_ADC_USE_ADC1 FALSE
#define WB32_ADC_ADC1_DMA_PRIORITY 2
#define WB32_ADC_ADC1_IRQ_PRIORITY 6
#endif /* MCUCONF_H */

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/ADCv1/hal_adc_lld.c
endif
else
PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/ADCv1/hal_adc_lld.c
endif
PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/ADCv1

View File

@ -0,0 +1,272 @@
/*
Copyright (C) 2022 Westberry Technology (ChangZhou) Corp., Ltd
Licensed 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.
*/
/**
* @file ADCv1/hal_adc_lld.c
* @brief WB32 ADC subsystem low level driver source.
*
* @addtogroup ADC
* @{
*/
#include "hal.h"
#if HAL_USE_ADC || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define SARENR_SAREN_BB BIT_BAND_ADDR(&ANCTL->SARENR, 0)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief ADC driver identifier.*/
#if WB32_ADC_USE_ADC1 || defined(__DOXYGEN__)
ADCDriver ADCD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Shared ADC DMA ISR service routine.
*
* @param[in] adcp pointer to the @p ADCDriver object
* @param[in] flags pre-shifted content of the ISR register
*/
static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
/* DMA errors handling.*/
if ((flags & WB32_DMAC_IT_ERR) != 0) {
/* DMA, this could help only if the DMA tries to access an unmapped
address space or violates alignment rules.*/
_adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
}
else {
if ((flags & WB32_DMAC_IT_TFR) != 0) {
/* Transfer complete processing.*/
_adc_isr_full_code(adcp);
}
/* Because WB32 DMAC hasn't half transfer interrupt,
so it use transfer complete interrupt. */
else if ((flags & WB32_DMAC_IT_TFR) != 0) {
/* Half transfer processing.*/
_adc_isr_half_code(adcp);
}
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ADC driver initialization.
*
* @notapi
*/
void adc_lld_init(void) {
uint32_t tmpreg1 = 0;
#if WB32_ADC_USE_ADC1
/* Driver initialization.*/
adcObjectInit(&ADCD1);
ADCD1.adc = ADC;
ADCD1.dmastp = NULL;
ADCD1.dmamode = WB32_DMA_CHCFG_HWHIF(WB32_DMAC_HWHIF_ADC_Regular) | \
WB32_DMA_CHCFG_PL(WB32_ADC_ADC1_DMA_PRIORITY) | \
WB32_DMA_CHCFG_PSIZE_HWORD | \
WB32_DMA_CHCFG_MSIZE_HWORD | \
WB32_DMA_CHCFG_DIR_P2M | \
WB32_DMA_CHCFG_MINC | \
WB32_DMA_CHCFG_CIRC;
/* Temporary activation.*/
rccEnableADC();
PWR->ANAKEY1 = 0x03;
PWR->ANAKEY2 = 0x0C;
*(__IO uint32_t*) SARENR_SAREN_BB = (uint32_t)ENABLE;
PWR->ANAKEY1 = 0x00;
PWR->ANAKEY2 = 0x00;
tmpreg1 = (uint8_t)(((WB32_PCLK1 / 6000000) >> 1) - 1);
ADC->CR3 = ((tmpreg1 << 8) | ADC_CR3_12BIT);
ADC->CR1 = 0;
ADC->CR2 = ADC_CR2_ADON;
/* Calibration.*/
ADC->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
while ((ADC->CR2 & ADC_CR2_CAL) != 0)
;
/* Reset calibration just to be safe.*/
ADC->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
while ((ADC->CR2 & ADC_CR2_RSTCAL) != 0)
;
/* Return the ADC in low power mode.*/
ADC->CR2 = 0;
rccDisableADC();
#endif
}
/**
* @brief Configures and activates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*
* @notapi
*/
void adc_lld_start(ADCDriver *adcp) {
/* If in stopped state then enables the ADC clocks.*/
if (adcp->state == ADC_STOP) {
#if WB32_ADC_USE_ADC1
if (&ADCD1 == adcp) {
adcp->dmastp = dmaStreamAllocI(WB32_ADC_ADC1_DMA_STREAM,
WB32_ADC_ADC1_IRQ_PRIORITY,
(wb32_dmaisr_t)adc_lld_serve_rx_interrupt,
(void *)adcp);
osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
dmaStreamSetSource(adcp->dmastp, &ADC->DR);
dmaStreamEnableInterrupt(adcp->dmastp, WB32_DMAC_IT_TFR);
PWR->ANAKEY1 = 0x03;
PWR->ANAKEY2 = 0x0C;
*(__IO uint32_t*) SARENR_SAREN_BB = (uint32_t)ENABLE;
PWR->ANAKEY1 = 0x00;
PWR->ANAKEY2 = 0x00;
rccEnableADC();
}
#endif /* WB32_ADC_USE_ADC1 */
/* ADC setup, the calibration procedure has already been performed
during initialization.*/
adcp->adc->CR1 = 0;
adcp->adc->CR2 = 0;
}
}
/**
* @brief Deactivates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*
* @notapi
*/
void adc_lld_stop(ADCDriver *adcp) {
/* If in ready state then disables the ADC clock.*/
if (adcp->state == ADC_READY) {
#if WB32_ADC_USE_ADC1
if (&ADCD1 == adcp) {
ADC->CR1 = 0;
ADC->CR2 = 0;
dmaStreamFreeI(adcp->dmastp);
adcp->dmastp = NULL;
rccDisableADC();
PWR->ANAKEY1 = 0x03;
PWR->ANAKEY2 = 0x0C;
*(__IO uint32_t*) SARENR_SAREN_BB = (uint32_t)DISABLE;
PWR->ANAKEY1 = 0x00;
PWR->ANAKEY2 = 0x00;
}
#endif
}
}
/**
* @brief Starts an ADC conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*
* @notapi
*/
void adc_lld_start_conversion(ADCDriver *adcp) {
uint32_t cr2, mode;
uint32_t tmpreg1 = 0;
const ADCConversionGroup *grpp = adcp->grpp;
/* DMA setup.*/
mode = adcp->dmamode;
if (grpp->circular) {
mode |= WB32_DMA_CHCFG_CIRC;
if (adcp->depth > 1) {
/* If circular buffer depth > 1, then the half transfer interrupt
is enabled in order to allow streaming processing.*/
mode |= WB32_DMA_CHCFG_TCIE;
}
}
dmaStreamSetDestination(adcp->dmastp, adcp->samples);
dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
(uint32_t)adcp->depth);
dmaStreamSetMode(adcp->dmastp, mode);
dmaStreamEnable(adcp->dmastp);
/* ADC setup.*/
adcp->adc->CR1 = grpp->cr1 | ADC_CR1_SCAN;
cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_ADON;
if ((cr2 & (ADC_CR2_EXTTRIG | ADC_CR2_JEXTTRIG)) == 0)
cr2 |= ADC_CR2_CONT;
tmpreg1 = (uint8_t)(((WB32_PCLK1 / 6000000) >> 1) - 1);
adcp->adc->CR2 = grpp->cr2 | cr2;
adcp->adc->SMPR1 = grpp->smpr1;
adcp->adc->SMPR2 = grpp->smpr2;
adcp->adc->SQR1 = grpp->sqr1;
adcp->adc->SQR2 = grpp->sqr2;
adcp->adc->SQR3 = grpp->sqr3;
adcp->adc->CR3 = ((tmpreg1 << 8) | ADC_CR3_12BIT);
/* ADC start by writing ADC_CR2_ADON a second time.*/
adcp->adc->CR2 = cr2;
}
/**
* @brief Stops an ongoing conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*
* @notapi
*/
void adc_lld_stop_conversion(ADCDriver *adcp) {
dmaStreamDisable(adcp->dmastp);
adcp->adc->CR2 = 0;
}
#endif /* HAL_USE_ADC */
/** @} */

View File

@ -0,0 +1,300 @@
/*
Copyright (C) 2022 Westberry Technology (ChangZhou) Corp., Ltd
Licensed 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.
*/
/**
* @file ADCv1/hal_adc_lld.h
* @brief WB32 ADC subsystem low level driver header.
*
* @addtogroup ADC
* @{
*/
#ifndef HAL_ADC_LLD_H
#define HAL_ADC_LLD_H
#if HAL_USE_ADC || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Triggers selection
* @{
*/
#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @brief Trigger source. */
#define ADC_CR2_EXTSEL_SWSTART (7 << 17) /**< @brief Software trigger. */
/** @} */
/**
* @name Available analog channels
* @{
*/
#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */
#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */
#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */
#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */
#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */
#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */
#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */
#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */
#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */
#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */
#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */
#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */
#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */
#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */
#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */
#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */
#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/
#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */
/** @} */
/**
* @name Sampling rates
* @{
*/
#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */
#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */
#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */
#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */
#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */
#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */
#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */
#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */
/** @} */
/**
* @name Bit definition for ADC_CR2 register
* @{
*/
#define ADC_CR2_DMA (0x1U << 8) /**< @brief ADC DMA transfer enable. */
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief ADC driver enable switch.
* @details If set to @p TRUE the support for ADC is included.
* @note The default is @p TRUE.
*/
#if !defined(WB32_ADC_USE_ADC1) || defined(__DOXYGEN__)
#define WB32_ADC_USE_ADC1 FALSE
#endif
/**
* @brief ADC interrupt priority level setting.
*/
#if !defined(WB32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define WB32_ADC_ADC1_IRQ_PRIORITY 5
#endif
/** @} */
/**
* @brief ADC usbed DMAC channel setting.
*/
#if !defined(WB32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__)
#define WB32_ADC_ADC1_DMA_STREAM WB32_DMA_STREAM_ID(1, 0)
#endif
/** @} */
/**
* @brief ADC usbed DMAC channel priority setting.
*/
#if !defined(WB32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
#define WB32_ADC_ADC1_DMA_PRIORITY 2
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if WB32_ADC_USE_ADC1 && !WB32_HAS_ADC
#error "ADC not present in the selected device"
#endif
#if !WB32_ADC_USE_ADC1
#error "ADC driver activated but no ADC peripheral assigned"
#endif
#if !defined(WB32_DMA_REQUIRED)
#define WB32_DMA_REQUIRED
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief ADC sample data type.
*/
typedef uint16_t adcsample_t;
/**
* @brief Channels number in a conversion group.
*/
typedef uint16_t adc_channels_num_t;
/**
* @brief Possible ADC failure causes.
* @note Error codes are architecture dependent and should not relied
* upon.
*/
typedef enum {
ADC_ERR_DMAFAILURE = 0 /**< DMA operations failure. */
} adcerror_t;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Low level fields of the ADC driver structure.
*/
#define adc_lld_driver_fields \
/* Pointer to the ADCx registers block.*/ \
ADC_TypeDef *adc; \
/* Pointer to associated DMA channel.*/ \
const wb32_dma_stream_t *dmastp; \
/* DMA mode bit mask.*/ \
uint32_t dmamode \
/**
* @brief Low level fields of the ADC configuration structure.
*/
#define adc_lld_config_fields \
/* Dummy configuration, it is not needed.*/ \
uint32_t dummy
/**
* @brief Low level fields of the ADC configuration structure.
*/
#define adc_lld_configuration_group_fields \
/* ADC CR1 register initialization data. \
NOTE: All the required bits must be defined into this field except \
@p ADC_CR1_SCAN that is enforced inside the driver.*/ \
uint32_t cr1; \
/* ADC CR2 register initialization data. \
NOTE: All the required bits must be defined into this field except \
@p ADC_CR2_DMA, @p ADC_CR2_CONT and @p ADC_CR2_ADON that are \
enforced inside the driver.*/ \
uint32_t cr2; \
/* ADC SMPR1 register initialization data. \
NOTE: In this field must be specified the sample times for channels \
10...17.*/ \
uint32_t smpr1; \
/* ADC SMPR2 register initialization data. \
NOTE: In this field must be specified the sample times for channels \
0...9.*/ \
uint32_t smpr2; \
/* ADC SQR1 register initialization data. \
NOTE: Conversion group sequence 13...16 + sequence length.*/ \
uint32_t sqr1; \
/* ADC SQR2 register initialization data. \
NOTE: Conversion group sequence 7...12.*/ \
uint32_t sqr2; \
/* ADC SQR3 register initialization data. \
NOTE: Conversion group sequence 1...6.*/ \
uint32_t sqr3
/**
* @name Sequences building helper macros
* @{
*/
/**
* @brief Number of channels in a conversion sequence.
*/
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
#define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
#define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
/** @} */
/**
* @name Sampling rate settings helper macros
* @{
*/
#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor
sampling time. */
#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference
sampling time. */
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if WB32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
extern ADCDriver ADCD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void adc_lld_init(void);
void adc_lld_start(ADCDriver *adcp);
void adc_lld_stop(ADCDriver *adcp);
void adc_lld_start_conversion(ADCDriver *adcp);
void adc_lld_stop_conversion(ADCDriver *adcp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_ADC */
#endif /* HAL_ADC_LLD_H */
/** @} */

View File

@ -0,0 +1,2 @@
PLATFORMSRC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/DMAv1/wb32_dma.c
PLATFORMINC_CONTRIB += $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/DMAv1

View File

@ -0,0 +1,473 @@
/*
Copyright (C) 2022 Westberry Technology (ChangZhou) Corp., Ltd
Licensed 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.
*/
/**
* @file DMAv1/wb32_dma.c
* @brief DMA helper driver code.
*
* @addtogroup WB32_DMA
* @details DMA sharing helper driver. In the WB32 the DMA streams are a
* shared resource, this driver allows to allocate and free DMA
* streams at runtime in order to allow all the other device
* drivers to coordinate the access to the resource.
* @note The DMA ISR handlers are all declared into this module because
* sharing, the various device drivers can associate a callback to
* ISRs when allocating streams.
* @{
*/
#include "hal.h"
/* The following macro is only defined if some driver requiring DMA services
has been enabled.*/
#if defined(WB32_DMA_REQUIRED) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/**
* @brief Mask of the DMA1 streams in @p dma_streams_mask.
*/
#define WB32_DMA1_STREAMS_MASK ((1U << WB32_DMAC1_NUM_CHANNELS) - 1U)
/**
* @brief Mask of the DMA2 streams in @p dma_streams_mask.
*/
#define WB32_DMA2_STREAMS_MASK (((1U << WB32_DMAC2_NUM_CHANNELS) - 1U) \
<< WB32_DMAC1_NUM_CHANNELS)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*
* Default ISR collision masks.
*/
#if !defined(WB32_DMAC1_CH0_CMASK)
#define WB32_DMAC1_CH0_CMASK (1U << 0U)
#endif
#if !defined(WB32_DMAC1_CH1_CMASK)
#define WB32_DMAC1_CH1_CMASK (1U << 1U)
#endif
#if !defined(WB32_DMAC1_CH2_CMASK)
#define WB32_DMAC1_CH2_CMASK (1U << 2U)
#endif
#if !defined(WB32_DMAC2_CH0_CMASK)
#define WB32_DMAC2_CH0_CMASK (1U << (WB32_DMAC1_NUM_CHANNELS + 0U))
#endif
#if !defined(WB32_DMAC2_CH1_CMASK)
#define WB32_DMAC2_CH1_CMASK (1U << (WB32_DMAC1_NUM_CHANNELS + 1U))
#endif
#if !defined(WB32_DMAC2_CH2_CMASK)
#define WB32_DMAC2_CH2_CMASK (1U << (WB32_DMAC1_NUM_CHANNELS + 2U))
#endif
/**
* @brief DMA streams descriptors.
* @details This table keeps the association between an unique stream
* identifier and the involved physical registers.
* @note Don't use this array directly, use the appropriate wrapper macros
* instead: @p WB32_DMA1_STREAM1, @p WB32_DMA1_STREAM2 etc.
*/
const wb32_dma_stream_t _WB32_DMAC_CHANNELS[WB32_DMAC_CHANNELS] = {
#if WB32_DMAC1_NUM_CHANNELS > 0
{DMAC1, WB32_DMAC_CH0, WB32_DMAC1_CH0_CMASK, 0, WB32_DMAC1_NUMBER},
#endif
#if WB32_DMAC1_NUM_CHANNELS > 1
{DMAC1, WB32_DMAC_CH1, WB32_DMAC1_CH1_CMASK, 1, WB32_DMAC1_NUMBER},
#endif
#if WB32_DMAC1_NUM_CHANNELS > 2
{DMAC1, WB32_DMAC_CH2, WB32_DMAC1_CH2_CMASK, 2, WB32_DMAC1_NUMBER},
#endif
#if WB32_DMAC2_NUM_CHANNELS > 0
{DMAC2, WB32_DMAC_CH0, WB32_DMAC2_CH0_CMASK, 0 + WB32_DMAC1_NUM_CHANNELS, WB32_DMAC2_NUMBER},
#endif
#if WB32_DMAC2_NUM_CHANNELS > 1
{DMAC2, WB32_DMAC_CH1, WB32_DMAC2_CH1_CMASK, 1 + WB32_DMAC1_NUM_CHANNELS, WB32_DMAC2_NUMBER},
#endif
#if WB32_DMAC2_NUM_CHANNELS > 2
{DMAC2, WB32_DMAC_CH2, WB32_DMAC2_CH2_CMASK, 2 + WB32_DMAC1_NUM_CHANNELS, WB32_DMAC2_NUMBER},
#endif
};
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Global DMA-related data structures.
*/
static struct {
/**
* @brief Mask of the allocated streams.
*/
uint32_t allocated_mask;
/**
* @brief Mask of the enabled streams ISRs.
*/
uint32_t isr_mask;
/**
* @brief DMA IRQ redirectors.
*/
struct {
/**
* @brief DMA callback function.
*/
wb32_dmaisr_t func;
/**
* @brief DMA callback parameter.
*/
void *param;
} streams[WB32_DMAC_CHANNELS];
} dma;
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if defined(WB32_DMAC1_IRQ_VECTOR) || defined(__DOXYGEN__)
/**
* @brief DMA1 stream x shared ISR.
*
* @isr
*/
OSAL_IRQ_HANDLER(WB32_DMAC1_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
#if WB32_DMAC1_NUM_CHANNELS > 0
dmaServeInterrupt(WB32_DMA1_STREAM1);
#endif
#if WB32_DMAC1_NUM_CHANNELS > 1
dmaServeInterrupt(WB32_DMA1_STREAM2);
#endif
#if WB32_DMAC1_NUM_CHANNELS > 2
dmaServeInterrupt(WB32_DMA1_STREAM3);
#endif
OSAL_IRQ_EPILOGUE();
}
#endif
#if defined(WB32_DMAC2_IRQ_VECTOR) || defined(__DOXYGEN__)
/**
* @brief DMA2 stream x shared ISR.
*
* @isr
*/
OSAL_IRQ_HANDLER(WB32_DMAC2_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
#if WB32_DMAC2_NUM_CHANNELS > 0
dmaServeInterrupt(WB32_DMA2_STREAM1);
#endif
#if WB32_DMAC2_NUM_CHANNELS > 0
dmaServeInterrupt(WB32_DMA2_STREAM2);
#endif
#if WB32_DMAC2_NUM_CHANNELS > 0
dmaServeInterrupt(WB32_DMA2_STREAM3);
#endif
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief WB32 DMA helper initialization.
*
* @init
*/
void dmaInit(void) {
int i;
dma.allocated_mask = 0U;
dma.isr_mask = 0U;
#if WB32_DMAC2_NUM_CHANNELS > 0
rccResetDMAC1();
#endif
#if WB32_DMAC2_NUM_CHANNELS > 0
rccResetDMAC2();
#endif
for (i = 0; i < WB32_DMAC_CHANNELS; i++) {
dma.streams[i].func = NULL;
}
}
/**
* @brief Allocates a DMA stream.
* @details The stream is allocated and, if required, the DMA clock enabled.
* The function also enables the IRQ vector associated to the stream
* and initializes its priority.
*
* @param[in] id numeric identifiers of a specific stream or:
* - @p WB32_DMA_STREAM_ID_ANY for any stream.
* - @p WB32_DMA_STREAM_ID_ANY_DMA1 for any stream
* on DMA1.
* - @p WB32_DMA_STREAM_ID_ANY_DMA2 for any stream
* on DMA2.
* .
* @param[in] priority IRQ priority for the DMA stream
* @param[in] func handling function pointer, can be @p NULL
* @param[in] param a parameter to be passed to the handling function
* @return Pointer to the allocated @p wb32_dma_stream_t
* structure.
* @retval NULL if a/the stream is not available.
*
* @iclass
*/
const wb32_dma_stream_t *dmaStreamAllocI(uint32_t id,
uint32_t priority,
wb32_dmaisr_t func,
void *param) {
uint32_t i, startid, endid;
osalDbgCheckClassI();
if (id < WB32_DMAC_CHANNELS) {
startid = id;
endid = id;
} else {
osalDbgCheck(false);
return NULL;
}
for (i = startid; i <= endid; i++) {
uint32_t mask = (1U << i);
if ((dma.allocated_mask & mask) == 0U) {
const wb32_dma_stream_t *dmastp = WB32_DMA_STREAM(i);
/* Installs the DMA handler.*/
dma.streams[i].func = func;
dma.streams[i].param = param;
dma.allocated_mask |= mask;
/* Enabling DMA clocks required by the current streams set.*/
if ((WB32_DMA1_STREAMS_MASK & mask) != 0U) {
/* Enable DMAC1 clock */
rccEnableDMAC1();
/* DMAC1 DeInit */
rccResetDMAC1();
}
#if WB32_DMAC2_NUM_CHANNELS > 0
if ((WB32_DMA2_STREAMS_MASK & mask) != 0U) {
/* Enable DMAC2 clock */
rccEnableDMAC2();
/* DMAC2 DeInit */
rccResetDMAC2();
}
#endif
/* enable dmac */
dmastp->dmac->DmaCfgReg = 0x01;
/* Enables the associated IRQ vector if not already enabled and if a
callback is defined.*/
if (func != NULL) {
if ((dma.isr_mask & dmastp->cmask) == 0U) {
nvicEnableVector(dmastp->vector, priority);
}
dma.isr_mask |= mask;
}
/* Putting the stream in a known state.*/
dmaStreamDisable(dmastp);
return dmastp;
}
}
return NULL;
}
/**
* @brief Allocates a DMA stream.
* @details The stream is allocated and, if required, the DMA clock enabled.
* The function also enables the IRQ vector associated to the stream
* and initializes its priority.
*
* @param[in] id numeric identifiers of a specific stream or:
* - @p WB32_DMA_STREAM_ID_ANY for any stream.
* - @p WB32_DMA_STREAM_ID_ANY_DMA1 for any stream
* on DMA1.
* - @p WB32_DMA_STREAM_ID_ANY_DMA2 for any stream
* on DMA2.
* .
* @param[in] priority IRQ priority for the DMA stream
* @param[in] func handling function pointer, can be @p NULL
* @param[in] param a parameter to be passed to the handling function
* @return Pointer to the allocated @p wb32_dma_stream_t
* structure.
* @retval NULL if a/the stream is not available.
*
* @api
*/
const wb32_dma_stream_t *dmaStreamAlloc(uint32_t id,
uint32_t priority,
wb32_dmaisr_t func,
void *param) {
const wb32_dma_stream_t *dmastp;
osalSysLock();
dmastp = dmaStreamAllocI(id, priority, func, param);
osalSysUnlock();
return dmastp;
}
/**
* @brief Releases a DMA stream.
* @details The stream is freed and, if required, the DMA clock disabled.
* Trying to release a unallocated stream is an illegal operation
* and is trapped if assertions are enabled.
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @iclass
*/
void dmaStreamFreeI(const wb32_dma_stream_t *dmastp) {
uint32_t selfindex = (uint32_t)dmastp->selfindex;
osalDbgCheck(dmastp != NULL);
/* Check if the streams is not taken.*/
osalDbgAssert((dma.allocated_mask & (1 << selfindex)) != 0U,
"not allocated");
/* Marks the stream as not allocated.*/
dma.allocated_mask &= ~(1U << selfindex);
dma.isr_mask &= ~(1U << selfindex);
/* Disables the associated IRQ vector if it is no more in use.*/
if ((dma.isr_mask & dmastp->cmask) == 0U) {
nvicDisableVector(dmastp->vector);
}
/* Removes the DMA handler.*/
dma.streams[selfindex].func = NULL;
dma.streams[selfindex].param = NULL;
/* Shutting down clocks that are no more required, if any.*/
if ((dma.allocated_mask & WB32_DMA1_STREAMS_MASK) == 0U) {
/* Disable DMAC1 clock */
rccDisableDMAC1();
}
#if WB32_DMAC2_NUM_CHANNELS > 0
if ((dma.allocated_mask & WB32_DMA2_STREAMS_MASK) == 0U) {
/* Disable DMAC2 clock */
rccDisableDMAC2();
}
#endif
}
/**
* @brief Releases a DMA stream.
* @details The stream is freed and, if required, the DMA clock disabled.
* Trying to release a unallocated stream is an illegal operation
* and is trapped if assertions are enabled.
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @api
*/
void dmaStreamFree(const wb32_dma_stream_t *dmastp) {
osalSysLock();
dmaStreamFreeI(dmastp);
osalSysUnlock();
}
/**
* @brief Serves a DMA IRQ.
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @special
*/
void dmaServeInterrupt(const wb32_dma_stream_t *dmastp) {
uint32_t IT_flag;
uint32_t selfindex = (uint32_t)dmastp->selfindex;
uint32_t mask = (uint32_t)(0x01U << ((dmastp)->channel));
uint32_t regaddr = ((uint32_t)(&((dmastp)->dmac->StatusTfr)) + WB32_DMAC_IT_TFR);
if ((*((__I uint32_t *)(regaddr))) & mask) {
IT_flag = WB32_DMAC_IT_TFR;
if (dma.streams[selfindex].func) {
dma.streams[selfindex].func(dma.streams[selfindex].param, IT_flag);
}
}
regaddr = ((uint32_t)(&((dmastp)->dmac->StatusTfr)) + WB32_DMAC_IT_BLOCK);
if ((*((__I uint32_t *)(regaddr))) & mask) {
IT_flag = WB32_DMAC_IT_BLOCK;
if (dma.streams[selfindex].func) {
dma.streams[selfindex].func(dma.streams[selfindex].param, IT_flag);
}
}
regaddr = ((uint32_t)(&((dmastp)->dmac->StatusTfr)) + WB32_DMAC_IT_SRCTRAN);
if ((*((__I uint32_t *)(regaddr))) & mask) {
IT_flag = WB32_DMAC_IT_SRCTRAN;
if (dma.streams[selfindex].func) {
dma.streams[selfindex].func(dma.streams[selfindex].param, IT_flag);
}
}
regaddr = ((uint32_t)(&((dmastp)->dmac->StatusTfr)) + WB32_DMAC_IT_DSTTRAN);
if ((*((__I uint32_t *)(regaddr))) & mask) {
IT_flag = WB32_DMAC_IT_DSTTRAN;
if (dma.streams[selfindex].func) {
dma.streams[selfindex].func(dma.streams[selfindex].param, IT_flag);
}
}
regaddr = ((uint32_t)(&((dmastp)->dmac->StatusTfr)) + WB32_DMAC_IT_ERR);
if ((*((__I uint32_t *)(regaddr))) & mask) {
IT_flag = WB32_DMAC_IT_ERR;
if (dma.streams[selfindex].func) {
dma.streams[selfindex].func(dma.streams[selfindex].param, IT_flag);
}
}
}
#endif /* WB32_DMA_REQUIRED */
/** @} */

View File

@ -0,0 +1,884 @@
/*
Copyright (C) 2022 Westberry Technology (ChangZhou) Corp., Ltd
Licensed 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.
*/
/**
* @file DMAv1/wb32_dma.h
* @brief DMA helper driver header.
*
* @addtogroup WB32_DMA
* @{
*/
#ifndef WB32_DMA_H
#define WB32_DMA_H
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Total number of DMA streams.
* @details This is the total number of streams among all the DMA units.
*/
#define WB32_DMAC_CHANNELS (WB32_DMAC1_NUM_CHANNELS + \
WB32_DMAC2_NUM_CHANNELS)
/**
* @brief Mask of the ISR bits passed to the DMA callback functions.
*/
#define WB32_DMA_ISR_MASK 0x0E
/**
* @brief Returns the request line associated to the specified stream.
*
* @param[in] id the unique numeric stream identifier
* @param[in] c a stream/request association word, one request per
* nibble
* @return Returns the request associated to the stream.
*/
#define WB32_DMA_GETCHANNEL(id, c) \
(((uint32_t)(c) >> (((uint32_t)(id) % (uint32_t)WB32_DMAC1_NUM_CHANNELS) * 4U)) & 15U)
/**
* @brief Checks if a DMA priority is within the valid range.
* @param[in] prio DMA priority
*
* @retval The check result.
* @retval false invalid DMA priority.
* @retval true correct DMA priority.
*/
#define WB32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 7U))
/**
* @brief Checks if a DMA stream id is within the valid range.
*
* @param[in] id DMA stream id
* @retval The check result.
* @retval false invalid DMA channel.
* @retval true correct DMA channel.
*/
#define WB32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
((id) < WB32_DMAC_CHANNELS))
/**
* @brief Returns an unique numeric identifier for a DMA stream.
*
* @param[in] dma the DMA unit number
* @param[in] stream the stream number
* @return An unique numeric stream identifier.
*/
#define WB32_DMA_STREAM_ID(dma, stream) \
((((dma)-1) * WB32_DMAC1_NUM_CHANNELS) + (stream))
/**
* @brief Returns a DMA stream identifier mask.
*
*
* @param[in] dma the DMA unit number
* @param[in] stream the stream number
* @return A DMA stream identifier mask.
*/
#define WB32_DMA_STREAM_ID_MSK(dma, stream) \
(1U << WB32_DMA_STREAM_ID(dma, stream))
/**
* @brief Checks if a DMA stream unique identifier belongs to a mask.
*
* @param[in] id the stream numeric identifier
* @param[in] mask the stream numeric identifiers mask
*
* @retval The check result.
* @retval false id does not belong to the mask.
* @retval true id belongs to the mask.
*/
#define WB32_DMA_IS_VALID_ID(id, mask) (((1U << (id)) & (mask)))
/**
* @name DMA streams identifiers
* @{
*/
/**
* @brief Returns a pointer to a wb32_dma_stream_t structure.
*
* @param[in] id the stream numeric identifier
* @return A pointer to the wb32_dma_stream_t constant structure
* associated to the DMA stream.
*/
#define WB32_DMA_STREAM(id) (&_WB32_DMAC_CHANNELS[id])
#if WB32_DMAC1_NUM_CHANNELS > 0
#define WB32_DMA1_STREAM1 WB32_DMA_STREAM(0)
#endif
#if WB32_DMAC1_NUM_CHANNELS > 1
#define WB32_DMA1_STREAM2 WB32_DMA_STREAM(1)
#endif
#if WB32_DMAC1_NUM_CHANNELS > 2
#define WB32_DMA1_STREAM3 WB32_DMA_STREAM(2)
#endif
#if WB32_DMAC2_NUM_CHANNELS > 0
#define WB32_DMA2_STREAM1 WB32_DMA_STREAM(WB32_DMAC1_NUM_CHANNELS + 0)
#endif
#if WB32_DMAC2_NUM_CHANNELS > 1
#define WB32_DMA2_STREAM2 WB32_DMA_STREAM(WB32_DMAC1_NUM_CHANNELS + 1)
#endif
#if WB32_DMAC2_NUM_CHANNELS > 2
#define WB32_DMA2_STREAM3 WB32_DMA_STREAM(WB32_DMAC1_NUM_CHANNELS + 2)
#endif
/** @} */
/** @defgroup DMAC_Interrupt
* @{
*/
#define WB32_DMAC_INTERRUPT_EN (0x1U << 0)
#define WB32_DMAC_INTERRUPT_DIS (0x0U << 0)
/**
* @}
*/
/** @defgroup DMAC_DestinationTransferWidth
* @{
*/
#define WB32_DMAC_DST_WIDTH_BYTE (0x0U << 1)
#define WB32_DMAC_DST_WIDTH_HWORD (0x1U << 1)
#define WB32_DMAC_DST_WIDTH_WORD (0x2U << 1)
/**
* @}
*/
/** @defgroup DMAC_SourceTransferWidth
* @{
*/
#define WB32_DMAC_SRC_WIDTH_BYTE (0x0U << 4)
#define WB32_DMAC_SRC_WIDTH_HWORD (0x1U << 4)
#define WB32_DMAC_SRC_WIDTH_WORD (0x2U << 4)
/**
* @}
*/
/** @defgroup DMAC_DestinationAddrInc
* @{
*/
#define WB32_DMAC_DST_ADDR_INC (0x0U << 7)
#define WB32_DMAC_DST_ADDR_DEC (0x1U << 7)
#define WB32_DMAC_DST_ADDR_NOC (0x2U << 7)
/**
* @}
*/
/** @defgroup DMAC_SourceAddrInc
* @{
*/
#define WB32_DMAC_SRC_ADDR_INC (0x0U << 9)
#define WB32_DMAC_SRC_ADDR_DEC (0x1U << 9)
#define WB32_DMAC_SRC_ADDR_NOC (0x2U << 9)
/**
* @}
*/
/** @defgroup DMAC_DestinationTransactionLength
* @{
*/
#define WB32_DMAC_DST_TRS_LEN_1 (0x0U << 11)
#define WB32_DMAC_DST_TRS_LEN_4 (0x1U << 11)
#define WB32_DMAC_DST_TRS_LEN_8 (0x2U << 11)
/**
* @}
*/
/** @defgroup DMAC_SourceTransactionLength
* @{
*/
#define WB32_DMAC_SRC_TRS_LEN_1 (0x0U << 14)
#define WB32_DMAC_SRC_TRS_LEN_4 (0x1U << 14)
#define WB32_DMAC_SRC_TRS_LEN_8 (0x2U << 14)
/**
* @}
*/
/** @defgroup DMAC_TransferTypeAndFlowControl
* @{
*/
#define WB32_DMAC_TRF_TFC_M2MD (0x0U << 20)
#define WB32_DMAC_TRF_TFC_M2PD (0x1U << 20)
#define WB32_DMAC_TRF_TFC_P2MD (0x2U << 20)
#define WB32_DMAC_TRF_TFC_P2PD (0x3U << 20)
/* The following definitions is only used for DMACx channel0. */
#define WB32_DMAC_TRF_TFC_P2MP (0x4U << 20)
#define WB32_DMAC_TRF_TFC_P2PSP (0x5U << 20)
#define WB32_DMAC_TRF_TFC_M2PP (0x6U << 20)
#define WB32_DMAC_TRF_TFC_P2PDP (0x7U << 20)
/**
* @}
*/
/** @defgroup DMAC_DestinationMasterInterface
* @{
*/
#define WB32_DMAC_SRC_MASTER_IF_APB (0x0U << 25)
#define WB32_DMAC_SRC_MASTER_IF_AHB (0x1U << 25)
/**
* @}
*/
/** @defgroup DMAC_SourceMasterInterface
* @{
*/
#define WB32_DMAC_DST_MASTER_IF_APB (0x0U << 23)
#define WB32_DMAC_DST_MASTER_IF_AHB (0x1U << 23)
/**
* @}
*/
/** @defgroup DMAC_SourceHandshakingInterfaceSelect
* @{
*/
#define WB32_DMAC_SRC_HIFS_HW (0x0U << 11)
#define WB32_DMAC_SRC_HIFS_SW (0x1U << 11)
/**
* @}
*/
/** @defgroup DMAC_DestinationHandshakingInterfaceSelect
* @{
*/
#define WB32_DMAC_DST_HIFS_HW (0x0U << 10)
#define WB32_DMAC_DST_HIFS_SW (0x1U << 10)
/**
* @}
*/
/** @defgroup DMAC_SourceHandshakingInterfacePolarity
* @{
*/
#define WB32_DMAC_SRC_HIFP_HIGH (0x0U << 19)
#define WB32_DMAC_SRC_HIFP_LOW (0x1U << 19)
/**
* @}
*/
/** @defgroup DMAC_DestinationHandshakingInterfacePolarity
* @{
*/
#define WB32_DMAC_DST_HIFP_HIGH (0x0U << 18)
#define WB32_DMAC_DST_HIFP_LOW (0x1U << 18)
/**
* @}
*/
/** @defgroup DMAC_AutomaticSourceReload
* @{
*/
#define WB32_DMAC_SRC_AUTO_RELOAD_EN (0x1U << 30)
#define WB32_DMAC_SRC_AUTO_RELOAD_DIS (0x0U << 30)
/**
* @}
*/
/** @defgroup DMAC_AutomaticDestinationReload
* @{
*/
#define WB32_DMAC_DST_AUTO_RELOAD_EN (0x1U << 31)
#define WB32_DMAC_DST_AUTO_RELOAD_DIS (0x0U << 30)
/**
* @}
*/
/** @defgroup DMAC_FlowControlMode
* @{
*/
#define WB32_DMAC_FC_MODE0 (0x0U << 0)
#define WB32_DMAC_FC_MODE1 (0x1U << 0)
/**
* @}
*/
/** @defgroup DMAC_FIFOMode
* @{
*/
#define WB32_DMAC_FIFO_MODE0 (0x0U << 1)
#define WB32_DMAC_FIFO_MODE1 (0x1U << 1)
/**
* @}
*/
/** @defgroup DMAC_interrupts_definitions
* @{
*/
#define WB32_DMAC_IT_TFR (0x0U << 3)
#define WB32_DMAC_IT_BLOCK (0x1U << 3)
#define WB32_DMAC_IT_SRCTRAN (0x2U << 3)
#define WB32_DMAC_IT_DSTTRAN (0x3U << 3)
#define WB32_DMAC_IT_ERR (0x4U << 3)
/**
* @}
*/
/** @defgroup DMAC_channel
* @{
*/
#define WB32_DMAC_CH0 (0x0U << 0)
#define WB32_DMAC_CH1 (0x0U << 1)
#define WB32_DMAC_CH2 (0x0U << 2)
/**
* @}
*/
/** @defgroup DMAC_HardwareHandshakingInterface
* @{
*/
/* The following definitions is only used for DMAC1. */
#define WB32_DMAC_HWHIF_TIM1_UP 2
#define WB32_DMAC_HWHIF_TIM1_COM 1
#define WB32_DMAC_HWHIF_TIM1_CH1 0
#define WB32_DMAC_HWHIF_TIM1_CH2 6
#define WB32_DMAC_HWHIF_TIM1_CH3 3
#define WB32_DMAC_HWHIF_TIM1_CH4 1
#define WB32_DMAC_HWHIF_TIM1_TRIG 1
#define WB32_DMAC_HWHIF_TIM2_UP 0
#define WB32_DMAC_HWHIF_TIM2_CH1 2
#define WB32_DMAC_HWHIF_TIM2_CH2 5
#define WB32_DMAC_HWHIF_TIM2_CH3 4
#define WB32_DMAC_HWHIF_TIM2_CH4 5
#define WB32_DMAC_HWHIF_TIM3_UP 6
#define WB32_DMAC_HWHIF_TIM3_CH1 3
#define WB32_DMAC_HWHIF_TIM3_CH3 0
#define WB32_DMAC_HWHIF_TIM3_CH4 6
#define WB32_DMAC_HWHIF_TIM3_TRIG 3
#define WB32_DMAC_HWHIF_TIM4_UP 5
#define WB32_DMAC_HWHIF_TIM4_CH1 4
#define WB32_DMAC_HWHIF_TIM4_CH2 1
#define WB32_DMAC_HWHIF_TIM4_CH3 2
#define WB32_DMAC_HWHIF_QSPI_RX 7
#define WB32_DMAC_HWHIF_QSPI_TX 8
#define WB32_DMAC_HWHIF_SPIS1_RX 9
#define WB32_DMAC_HWHIF_SPIS1_TX 10
#define WB32_DMAC_HWHIF_UART1_RX 11
#define WB32_DMAC_HWHIF_UART1_TX 12
#define WB32_DMAC_HWHIF_ADC_Regular 13
#define WB32_DMAC_HWHIF_ADC_Injected 14
/* The following definitions is only used for DMAC2. */
#define WB32_DMAC_HWHIF_SPIM2_RX 0
#define WB32_DMAC_HWHIF_SPIM2_TX 1
#define WB32_DMAC_HWHIF_SPIS2_RX 2
#define WB32_DMAC_HWHIF_SPIS2_TX 3
#define WB32_DMAC_HWHIF_UART2_RX 4
#define WB32_DMAC_HWHIF_UART2_TX 5
#define WB32_DMAC_HWHIF_UART3_RX 6
#define WB32_DMAC_HWHIF_UART3_TX 7
#define WB32_DMAC_HWHIF_I2C1_RX 8
#define WB32_DMAC_HWHIF_I2C1_TX 9
#define WB32_DMAC_HWHIF_I2C2_RX 10
#define WB32_DMAC_HWHIF_I2C2_TX 11
/**
* @}
*/
/** @defgroup DMAC configuration parameters for use simple config.
* @{
*/
#define WB32_DMA_CHCFG_SIZE_MASK (0x1FFU)
#define WB32_DMA_CHCFG_EN (0x01U << 0)
#define WB32_DMA_CHCFG_TCIE (0x01U << 1)
#define WB32_DMA_CHCFG_HTIE (0x01U << 2)
#define WB32_DMA_CHCFG_TEIE (0x01U << 3)
#define WB32_DMA_CHCFG_DIR_MASK (0x03U << 4)
#define WB32_DMA_CHCFG_DIR_M2M (0x00U << 4)
#define WB32_DMA_CHCFG_DIR_M2P (0x01U << 4)
#define WB32_DMA_CHCFG_DIR_P2M (0x02U << 4)
#define WB32_DMA_CHCFG_CIRC (0x01U << 6)
#define WB32_DMA_CHCFG_PINC (0x01U << 7)
#define WB32_DMA_CHCFG_MINC (0x01U << 8)
#define WB32_DMA_CHCFG_PSIZE_MASK (0x03U << 9)
#define WB32_DMA_CHCFG_PSIZE_BYTE (0x00U << 9)
#define WB32_DMA_CHCFG_PSIZE_HWORD (0x01U << 9)
#define WB32_DMA_CHCFG_PSIZE_WORD (0x02U << 9)
#define WB32_DMA_CHCFG_MSIZE_MASK (0x03U << 11)
#define WB32_DMA_CHCFG_MSIZE_BYTE (0x00U << 11)
#define WB32_DMA_CHCFG_MSIZE_HWORD (0x01U << 11)
#define WB32_DMA_CHCFG_MSIZE_WORD (0x02U << 11)
#define WB32_DMA_CHCFG_PL_MASK (0x07U << 13)
#define WB32_DMA_CHCFG_PL(n) ((n) << 13)
#define WB32_DMA_CHCFG_HWHIF_MASK (0xFFU << 16)
#define WB32_DMA_CHCFG_HWHIF(n) ((n) << 16)
/**
* @}
*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if !defined(WB32_DMAC1_NUM_CHANNELS)
#error "WB32_DMAC1_NUM_CHANNELS not defined in registry"
#endif
#if !defined(WB32_DMAC2_NUM_CHANNELS)
#error "WB32_DMAC2_NUM_CHANNELS not defined in registry"
#endif
#if (WB32_DMAC1_NUM_CHANNELS < 0) || (WB32_DMAC1_NUM_CHANNELS > 3)
#error "unsupported channels configuration"
#endif
#if (WB32_DMAC2_NUM_CHANNELS < 0) || (WB32_DMAC2_NUM_CHANNELS > 3)
#error "unsupported channels configuration"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a DMA callback.
*
* @param[in] p parameter for the registered function
* @param[in] flags pre-shifted content of the ISR register, the bits
* are aligned to bit zero
*/
typedef void (*wb32_dmaisr_t)(void *p, uint32_t flags);
/**
* @brief WB32 DMA stream descriptor structure.
*/
typedef struct {
DMAC_TypeDef *dmac; /**< @brief Associated DMA. */
uint8_t channel; /**< @brief Associated DMA channel. */
uint32_t cmask; /**< @brief Mask of streams sharing
the same ISR. */
uint8_t selfindex; /**< @brief Index to self in array. */
uint8_t vector; /**< @brief Associated IRQ vector. */
} wb32_dma_stream_t;
/**
* @brief WB32 DMA channel configuration structure.
*/
typedef struct {
uint32_t dst_addr; /**< @brief Set the destination base address. */
uint32_t src_addr; /**< @brief Set the source base address. */
uint32_t interrupt; /**< @brief Set the channel interrupt is enable
or not. */
uint32_t dst_width; /**< @brief Set the destination transfer width. */
uint32_t src_width; /**< @brief Set the source transfer width. */
uint32_t dst_addr_inc; /**< @brief Set whether to increment or decrement
the destination address on every destination
transfer. */
uint32_t src_addr_inc; /**< @brief Set whether to increment or decrement
the source address on every source transfer. */
uint32_t trf_tfc; /**< @brief Set the transfer type and flow control. */
uint32_t dst_master_if; /**< @brief Set the Master Interface layer where the
destination device (peripheral or memory) resides. */
uint32_t src_master_if; /**< @brief Set the Master Interface layer from which
the source device (peripheral or memory) is
accessed. */
uint32_t dst_auto_reload; /**< @brief Set the automatic destination reload feature
enable or not. */
uint32_t src_auto_reload; /**< @brief Set the automatic source reload feature
enable or not. */
uint8_t dst_hwhif; /**< @brief Set the hardware handshaking interface to
the source of this channel. */
uint8_t src_hwhif; /**< @brief Set the hardware handshaking interface to
the source of this channel. */
uint8_t ch_priority; /**< @brief Set the channel priority. A priority of 2
is the highest priority, and 0 is the lowest. */
uint8_t prot_ctl; /**< @brief Set the protection control, used to drive
the AHB HPROT[3:1] bus. The default value must be 1.*/
/* Generally, the default value of the following parameters is 0. */
uint32_t dst_trs_len; /**< @brief Set the destination burst transaction
length. */
uint32_t src_trs_len; /**< @brief Set the source burst transaction length. */
uint32_t dst_hifs; /**< @brief Set which of the handshaking interfaces-hardware
or software - is active for destination requests on
this channel. */
uint32_t src_hifs; /**< @brief Set which of the handshaking interfaces-hardware
or software - is active for source requests on this
channel. */
uint32_t dst_hifp; /**< @brief Set the destination handshaking interface
polarity. */
uint32_t src_hifp; /**< @brief Set the source handshaking interface polarity. */
uint32_t fc_mode; /**< @brief Set the flow control mode. */
uint32_t fifo_mode; /**< @brief Set the FIFO mode. */
uint16_t brs_maxlen; /**< @brief Set the Maximum AMBA burst length that is
used for DMA transfers on this channel. */
} wb32_dmac_chinit_t;
/**
* @}
*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @name Macro Functions
* @{
*/
/**
* @brief Associates a peripheral data register to a DMA stream.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @param[in] addr value to be written in the SAR register
*
* @special
*/
#define dmaStreamSetSource(dmastp, addr) { \
(dmastp)->dmac->Ch[(dmastp)->channel].SAR = (uint32_t)(addr); \
}
/**
* @brief Associates a memory destination to a DMA stream.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @param[in] addr value to be written in the DAR register
*
* @special
*/
#define dmaStreamSetDestination(dmastp, addr) { \
(dmastp)->dmac->Ch[(dmastp)->channel].DAR = (uint32_t)(addr); \
}
/**
* @brief Sets the number of transfers to be performed.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @param[in] size value to be written in the CTLH register Size must be less than 511
*
* @special
*/
#define dmaStreamSetTransactionSize(dmastp, size) { \
(dmastp)->dmac->Ch[(dmastp)->channel].CTLH = (uint32_t)((size) & 0x1FF); \
}
/**
* @brief Returns the number of transfers to be performed.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @return The number of transfers to be performed.
*
* @special
*/
#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->dmac->Ch[(dmastp)->channel].CTLH))
/**
* @brief Programs the stream mode settings.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @param[in] mode value to be written in that CTLL/CFGL/CFGH register
*
* @special
*/
#define dmaStreamSetMode(dmastp, mode) { \
switch ((uint32_t)(mode) & WB32_DMA_CHCFG_DIR_MASK) { \
case WB32_DMA_CHCFG_DIR_M2M: /* M2M */ \
(dmastp)->dmac->Ch[(dmastp)->channel].CFGL = WB32_DMAC_TRF_TFC_M2MD | \
WB32_DMAC_SRC_MASTER_IF_AHB | \
WB32_DMAC_DST_MASTER_IF_AHB | \
(((mode) & WB32_DMA_CHCFG_PSIZE_MASK) >> 5) | \
(((mode) & WB32_DMA_CHCFG_MSIZE_MASK) >> 10) | \
((!((mode) & WB32_DMA_CHCFG_PINC)) << 10) | \
((!((mode) & WB32_DMA_CHCFG_MINC)) << 8); \
(dmastp)->dmac->Ch[(dmastp)->channel].CFGH = (1U << 2); \
break; \
case WB32_DMA_CHCFG_DIR_M2P: /* M2P */ \
(dmastp)->dmac->Ch[(dmastp)->channel].CTLL = WB32_DMAC_TRF_TFC_M2PD | \
WB32_DMAC_SRC_MASTER_IF_AHB | \
WB32_DMAC_DST_MASTER_IF_APB | \
(((mode) & WB32_DMA_CHCFG_MSIZE_MASK) >> 7) | \
(((mode) & WB32_DMA_CHCFG_PSIZE_MASK) >> 8) | \
((!((mode) & WB32_DMA_CHCFG_MINC)) << 10) | \
((!((mode) & WB32_DMA_CHCFG_PINC)) << 8); \
(dmastp)->dmac->Ch[(dmastp)->channel].CFGH = (((mode) & WB32_DMA_CHCFG_HWHIF_MASK) >> 5) | \
(1U << 2); \
break; \
case WB32_DMA_CHCFG_DIR_P2M: /* P2M */ \
(dmastp)->dmac->Ch[(dmastp)->channel].CTLL = WB32_DMAC_TRF_TFC_P2MD | \
WB32_DMAC_SRC_MASTER_IF_APB | \
WB32_DMAC_DST_MASTER_IF_AHB | \
(((mode) & WB32_DMA_CHCFG_PSIZE_MASK) >> 5) | \
(((mode) & WB32_DMA_CHCFG_MSIZE_MASK) >> 10) | \
((!((mode) & WB32_DMA_CHCFG_PINC)) << 10) | \
((!((mode) & WB32_DMA_CHCFG_MINC)) << 8); \
(dmastp)->dmac->Ch[(dmastp)->channel].CFGH = (((mode) & WB32_DMA_CHCFG_HWHIF_MASK) >> 9) | \
(1U << 2); \
break; \
} \
(dmastp)->dmac->Ch[(dmastp)->channel].CFGL = (((mode) & WB32_DMA_CHCFG_PL_MASK) >> 8) | \
(((mode) & WB32_DMA_CHCFG_CIRC) << 24) | \
(((mode) & WB32_DMA_CHCFG_CIRC) << 25); \
if ((mode) & (WB32_DMA_CHCFG_TCIE | WB32_DMA_CHCFG_HTIE)) { \
(dmastp)->dmac->Ch[(dmastp)->channel].CTLL |= WB32_DMAC_INTERRUPT_EN; \
dmaStreamEnableInterrupt(dmastp, WB32_DMAC_IT_TFR); \
} \
if ((mode) & WB32_DMA_CHCFG_TEIE) { \
(dmastp)->dmac->Ch[(dmastp)->channel].CTLL |= WB32_DMAC_INTERRUPT_EN; \
dmaStreamEnableInterrupt(dmastp, WB32_DMAC_IT_ERR); \
} \
}
#define dmaStreamSetModeI(dmastp, mode) { \
(dmastp)->dmac->Ch[(dmastp)->channel].CTLL = (mode).interrupt | \
(mode).dst_width | \
(mode).src_width | \
(mode).dst_addr_inc | \
(mode).src_addr_inc | \
(mode).dst_trs_len | \
(mode).src_trs_len | \
(mode).trf_tfc | \
(mode).dst_master_if | \
(mode).src_master_if; \
(dmastp)->dmac->Ch[(dmastp)->channel].CFGL = ((mode).ch_priority << 5) | \
(mode).dst_hifs | \
(mode).src_hifs | \
(mode).dst_hifp | \
(mode).src_hifp | \
((mode).brs_maxlen << 20) | \
(mode).src_auto_reload | \
(mode).dst_auto_reload; \
(dmastp)->dmac->Ch[(dmastp)->channel].CFGH = (mode).fc_mode | \
(mode).fifo_mode | \
((mode).prot_ctl << 2) | \
((mode).src_hwhif << 7) | \
((mode).dst_hwhif << 11); \
}
/**
* @brief DMA stream enable interrupt configuration.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @param[in] it_flag specifies the DMAC interrupt source to be enabled or disabled.
*
* @special
*/
#define dmaStreamEnableInterrupt(dmastp, it_flag) { \
uint32_t mask = (uint32_t)(0x01U << ((dmastp)->channel)); \
uint32_t regaddr = ((uint32_t)(&((dmastp)->dmac->MaskTfr)) + it_flag); \
*((__O uint32_t *)(regaddr)) = (mask << 8) | mask; \
}
/**
* @brief DMA stream disable interrupt configuration.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @param[in] it_flag specifies the DMAC interrupt source to be enabled or disabled.
*
* @special
*/
#define dmaStreamDisableInterrupt(dmastp, it_flag) { \
uint32_t mask = (uint32_t)(0x01U << ((dmastp)->channel)); \
uint32_t regaddr = ((uint32_t)(&((dmastp)->dmac->MaskTfr)) + it_flag); \
*((__O uint32_t *)(regaddr)) = (mask << 8); \
}
/**
* @brief DMA stream enable interrupt configuration all.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @special
*/
#define dmaStreamEnableInterruptAll(dmastp) { \
dmaStreamEnableInterrupt(dmastp, WB32_DMAC_IT_TFR); \
dmaStreamEnableInterrupt(dmastp, WB32_DMAC_IT_BLOCK); \
dmaStreamEnableInterrupt(dmastp, WB32_DMAC_IT_SRCTRAN); \
dmaStreamEnableInterrupt(dmastp, WB32_DMAC_IT_DSTTRAN); \
dmaStreamEnableInterrupt(dmastp, WB32_DMAC_IT_ERR); \
}
/**
* @brief DMA stream disable interrupt configuration all.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @special
*/
#define dmaStreamDisableInterruptAll(dmastp) { \
dmaStreamDisableInterrupt(dmastp, WB32_DMAC_IT_TFR); \
dmaStreamDisableInterrupt(dmastp, WB32_DMAC_IT_BLOCK); \
dmaStreamDisableInterrupt(dmastp, WB32_DMAC_IT_SRCTRAN); \
dmaStreamDisableInterrupt(dmastp, WB32_DMAC_IT_DSTTRAN); \
dmaStreamDisableInterrupt(dmastp, WB32_DMAC_IT_ERR); \
}
/**
* @brief DMA stream interrupt sources clear.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @special
*/
#define dmaStreamClearInterrupt(dmastp) { \
uint32_t mask = (uint32_t)(0x01U << ((dmastp)->channel)); \
uint32_t regaddr = ((uint32_t)(&((dmastp)->dmac->ClearTfr)) + WB32_DMAC_IT_TFR); \
*((__O uint32_t *)(regaddr)) = mask; \
regaddr = ((uint32_t)(&((dmastp)->dmac->ClearTfr)) + WB32_DMAC_IT_BLOCK); \
*((__O uint32_t *)(regaddr)) = mask; \
regaddr = ((uint32_t)(&((dmastp)->dmac->ClearTfr)) + WB32_DMAC_IT_SRCTRAN); \
*((__O uint32_t *)(regaddr)) = mask; \
regaddr = ((uint32_t)(&((dmastp)->dmac->ClearTfr)) + WB32_DMAC_IT_DSTTRAN); \
*((__O uint32_t *)(regaddr)) = mask; \
regaddr = ((uint32_t)(&((dmastp)->dmac->ClearTfr)) + WB32_DMAC_IT_ERR); \
*((__O uint32_t *)(regaddr)) = mask; \
}
/**
* @brief DMA stream enable.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @special
*/
#define dmaStreamEnable(dmastp) { \
uint32_t mask = (uint32_t)(0x01U << ((dmastp)->channel)); \
(dmastp)->dmac->ChEnReg = (mask << 8) | mask; \
}
/**
* @brief DMA stream disable.
* @details The function disables the specified stream and then clears any
* pending interrupt.
* @note This function can be invoked in both ISR or thread context.
* @note Interrupts enabling flags are set to zero after this call, see
* bug 3607518.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*
* @special
*/
#define dmaStreamDisable(dmastp) { \
uint32_t mask = (uint32_t)(0x01U << ((dmastp)->channel)); \
(dmastp)->dmac->ChEnReg = (mask << 8); \
dmaStreamDisableInterruptAll(dmastp); \
dmaStreamClearInterrupt(dmastp); \
}
/**
* @brief Starts a memory to memory operation using the specified stream.
* @note The default transfer data mode is "byte to byte" but it can be
* changed by specifying extra options in the @p mode parameter.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
* @param[in] mode value to be written in the CCR register, this value
* is implicitly ORed with:
* - @p WB32_DMAC_SRC_ADDR_INC
* - @p WB32_DMAC_DST_ADDR_INC
* - @p WB32_DMAC_TRF_TFC_M2MD
* .
* @param[in] src source address
* @param[in] dst destination address
* @param[in] n number of data units to copy
*/
#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \
(mode).src_addr_inc = WB32_DMAC_SRC_ADDR_INC; \
(mode).dst_addr_inc = WB32_DMAC_DST_ADDR_INC; \
(mode).trf_tfc = WB32_DMAC_TRF_TFC_M2MD; \
dmaStreamSetSource(dmastp, src); \
dmaStreamSetDestination(dmastp, dst); \
dmaStreamSetTransactionSize(dmastp, n); \
dmaStreamSetMode(dmastp, mode); \
dmaStreamEnable(dmastp); \
}
/**
* @brief Polled wait for DMA transfer end.
* @pre The stream must have been allocated using @p dmaStreamAlloc().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a wb32_dma_stream_t structure
*/
#define dmaWaitCompletion(dmastp) { \
while (((dmastp)->dmac->Ch[(dmastp)->channel].CTLH & 0x00000FFFU) > 0U) \
; \
dmaStreamDisable(dmastp); \
}
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if !defined(__DOXYGEN__)
extern const wb32_dma_stream_t _WB32_DMAC_CHANNELS[WB32_DMAC_CHANNELS];
#endif
#ifdef __cplusplus
extern "C"
{
#endif
void dmaInit(void);
const wb32_dma_stream_t *dmaStreamAllocI(uint32_t id,
uint32_t priority,
wb32_dmaisr_t func,
void *param);
const wb32_dma_stream_t *dmaStreamAlloc(uint32_t id,
uint32_t priority,
wb32_dmaisr_t func,
void *param);
void dmaStreamFreeI(const wb32_dma_stream_t *dmastp);
void dmaStreamFree(const wb32_dma_stream_t *dmastp);
void dmaServeInterrupt(const wb32_dma_stream_t *dmastp);
#ifdef __cplusplus
}
#endif
#endif /* WB32_DMA_H */
/** @} */

View File

@ -71,10 +71,10 @@
#define PAL_WB32_ALTERNATE(n) ((n) << 7U)
#define PAL_WB32_CURRENT_MASK (3U << 11U)
#define PAL_WB32_CURRENT_LEVEL0 (0U << 11U)
#define PAL_WB32_CURRENT_LEVEL1 (1U << 11U)
#define PAL_WB32_CURRENT_LEVEL2 (2U << 11U)
#define PAL_WB32_CURRENT_LEVEL3 (3U << 11U)
#define PAL_WB32_CURRENT_LEVEL0 (0U << 11U)
#define PAL_WB32_CURRENT_LEVEL1 (1U << 11U)
#define PAL_WB32_CURRENT_LEVEL2 (2U << 11U)
#define PAL_WB32_CURRENT_LEVEL3 (3U << 11U)
/**
* @brief Alternate function.

View File

@ -34,6 +34,7 @@
#include "wb32_registry.h"
#include "wb32_tim.h"
#include "wb32_dma.h"
/*===========================================================================*/
/* Driver constants. */

View File

@ -24,11 +24,13 @@ endif #ifeq ($(USE_SMART_BUILD), yes)
# Drivers compatible with the platform.
include ${CHIBIOS_CONTRIB}/os/hal/ports/WB32/LLD/GPIOv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/DMAv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/I2Cv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/UARTv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/SPIv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/USBv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/ADCv1/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC_CONTRIB)

View File

@ -133,8 +133,8 @@
* @api
*/
#define rccEnableAHB(mask) { \
RCC->AHBENR |= (mask); \
(void)RCC->AHBENR; \
RCC->AHBENR1 |= (mask); \
(void)RCC->AHBENR1; \
}
/**
@ -145,8 +145,8 @@
* @api
*/
#define rccDisableAHB(mask) { \
RCC->AHBENR &= ~(mask); \
(void)RCC->AHBENR; \
RCC->AHBENR1 &= ~(mask); \
(void)RCC->AHBENR1; \
}
/**
@ -157,8 +157,8 @@
* @api
*/
#define rccResetAHB(mask) { \
RCC->AHBRSTR |= (mask); \
RCC->AHBRSTR &= ~(mask); \
RCC->AHBRSTR1 |= (mask); \
RCC->AHBRSTR1 &= ~(mask); \
(void)RCC->AHBRSTR; \
}
/** @} */
@ -502,6 +502,93 @@
#define rccResetUART3() rccResetAPB2(RCC_APB2RSTR_UART3RST)
/** @} */
/**
* @name ADC peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the ADC peripheral clock.
*
* @api
*/
#define rccEnableADC() rccEnableAPB1(RCC_APB1ENR_ADCEN)
/**
* @brief Disables the ADC peripheral clock.
*
* @api
*/
#define rccDisableADC() rccDisableAPB1(RCC_APB1ENR_ADCEN)
/**
* @brief Resets the ADC peripheral.
*
* @api
*/
#define rccResetADC() rccResetAPB1(RCC_APB1RSTR_ADCRST)
/** @} */
/**
* @name DMAC peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the DMAC1 peripheral clock.
*
* @api
*/
#define rccEnableDMAC1() do { \
rccEnableAHB(RCC_AHBENR1_DMAC1BREN); \
rccEnableAPB1(RCC_APB1ENR_DMAC1EN); \
} while (false)
/**
* @brief Disables the DMAC1 peripheral clock.
*
* @api
*/
#define rccDisableDMAC1() do { \
rccDisableAHB(RCC_AHBENR1_DMAC1BREN); \
rccDisableAPB1(RCC_APB1ENR_DMAC1EN); \
} while (false)
/**
* @brief Resets the DMAC1 peripheral.
*
* @api
*/
#define rccResetDMAC1() rccResetAPB1(RCC_APB1RSTR_DMAC1RST)
/**
* @brief Enables the DMAC2 peripheral clock.
*
* @api
*/
#define rccEnableDMAC2() do { \
rccEnableAHB(RCC_AHBENR1_DMAC2BREN); \
rccEnableAPB2(RCC_APB2ENR_DMAC2EN); \
} while (false)
/**
* @brief Disables the DMAC2 peripheral clock.
*
* @api
*/
#define rccDisableDMAC2() do { \
rccDisableAHB(RCC_AHBENR1_DMAC2BREN); \
rccDisableAPB2(RCC_APB2ENR_DMAC2EN); \
} while (false)
/**
* @brief Resets the DMAC2 peripheral.
*
* @api
*/
#define rccResetDMAC2() rccResetAPB2(RCC_APB2RSTR_DMAC2RST)
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/

View File

@ -34,6 +34,7 @@
#include "wb32_registry.h"
#include "wb32_tim.h"
#include "wb32_dma.h"
/*===========================================================================*/
/* Driver constants. */

View File

@ -24,11 +24,13 @@ endif #ifeq ($(USE_SMART_BUILD), yes)
# Drivers compatible with the platform.
include ${CHIBIOS_CONTRIB}/os/hal/ports/WB32/LLD/GPIOv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/DMAv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/TIMv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/I2Cv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/UARTv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/SPIv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/USBv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/WB32/LLD/ADCv1/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC_CONTRIB)

View File

@ -133,8 +133,8 @@
* @api
*/
#define rccEnableAHB(mask) { \
RCC->AHBENR |= (mask); \
(void)RCC->AHBENR; \
RCC->AHBENR1 |= (mask); \
(void)RCC->AHBENR1; \
}
/**
@ -145,8 +145,8 @@
* @api
*/
#define rccDisableAHB(mask) { \
RCC->AHBENR &= ~(mask); \
(void)RCC->AHBENR; \
RCC->AHBENR1 &= ~(mask); \
(void)RCC->AHBENR1; \
}
/**
@ -157,8 +157,8 @@
* @api
*/
#define rccResetAHB(mask) { \
RCC->AHBRSTR |= (mask); \
RCC->AHBRSTR &= ~(mask); \
RCC->AHBRSTR1 |= (mask); \
RCC->AHBRSTR1 &= ~(mask); \
(void)RCC->AHBRSTR; \
}
/** @} */
@ -502,6 +502,93 @@
#define rccResetUART3() rccResetAPB2(RCC_APB2RSTR_UART3RST)
/** @} */
/**
* @name ADC peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the ADC peripheral clock.
*
* @api
*/
#define rccEnableADC() rccEnableAPB1(RCC_APB1ENR_ADCEN)
/**
* @brief Disables the ADC peripheral clock.
*
* @api
*/
#define rccDisableADC() rccDisableAPB1(RCC_APB1ENR_ADCEN)
/**
* @brief Resets the ADC peripheral.
*
* @api
*/
#define rccResetADC() rccResetAPB1(RCC_APB1RSTR_ADCRST)
/** @} */
/**
* @name DMAC peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the DMAC1 peripheral clock.
*
* @api
*/
#define rccEnableDMAC1() do { \
rccEnableAHB(RCC_AHBENR1_DMAC1BREN); \
rccEnableAPB1(RCC_APB1ENR_DMAC1EN); \
} while (false)
/**
* @brief Disables the DMAC1 peripheral clock.
*
* @api
*/
#define rccDisableDMAC1() do { \
rccDisableAHB(RCC_AHBENR1_DMAC1BREN); \
rccDisableAPB1(RCC_APB1ENR_DMAC1EN); \
} while (false)
/**
* @brief Resets the DMAC1 peripheral.
*
* @api
*/
#define rccResetDMAC1() rccResetAPB1(RCC_APB1RSTR_DMAC1RST)
/**
* @brief Enables the DMAC2 peripheral clock.
*
* @api
*/
#define rccEnableDMAC2() do { \
rccEnableAHB(RCC_AHBENR1_DMAC2BREN); \
rccEnableAPB2(RCC_APB2ENR_DMAC2EN); \
} while (false)
/**
* @brief Disables the DMAC2 peripheral clock.
*
* @api
*/
#define rccDisableDMAC2() do { \
rccDisableAHB(RCC_AHBENR1_DMAC2BREN); \
rccDisableAPB2(RCC_APB2ENR_DMAC2EN); \
} while (false)
/**
* @brief Resets the DMAC2 peripheral.
*
* @api
*/
#define rccResetDMAC2() rccResetAPB2(RCC_APB2RSTR_DMAC2RST)
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/