Provisional STM32F2xx support.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3649 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
gdisirio 2011-12-22 12:38:21 +00:00
parent 3d37f49059
commit da9678f49a
26 changed files with 3234 additions and 405 deletions

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -0,0 +1,416 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file STM32F2xx/adc_lld.c
* @brief STM32F2xx ADC subsystem low level driver source.
*
* @addtogroup ADC
* @{
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_ADC || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define ADC1_DMA_CHANNEL \
STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN)
#define ADC2_DMA_CHANNEL \
STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN)
#define ADC3_DMA_CHANNEL \
STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/** @brief ADC1 driver identifier.*/
#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
ADCDriver ADCD1;
#endif
/** @brief ADC2 driver identifier.*/
#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__)
ADCDriver ADCD2;
#endif
/** @brief ADC3 driver identifier.*/
#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__)
ADCDriver ADCD3;
#endif
/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief 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 & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 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 {
/* It is possible that the conversion group has already be reset by the
ADC error handler, in this case this interrupt is spurious.*/
if (adcp->grpp != NULL) {
if ((flags & STM32_DMA_ISR_HTIF) != 0) {
/* Half transfer processing.*/
_adc_isr_half_code(adcp);
}
if ((flags & STM32_DMA_ISR_TCIF) != 0) {
/* Transfer complete processing.*/
_adc_isr_full_code(adcp);
}
}
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \
defined(__DOXYGEN__)
/**
* @brief ADC interrupt handler.
*
* @isr
*/
CH_IRQ_HANDLER(ADC1_2_3_IRQHandler) {
uint32_t sr;
CH_IRQ_PROLOGUE();
#if STM32_ADC_USE_ADC1
sr = ADC1->SR;
ADC1->SR = 0;
/* Note, an overflow may occur after the conversion ended before the driver
is able to stop the ADC, this is why the DMA channel is checked too.*/
if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) {
/* ADC overflow condition, this could happen only if the DMA is unable
to read data fast enough.*/
if (ADCD1.grpp != NULL)
_adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW);
}
/* TODO: Add here analog watchdog handling.*/
#endif /* STM32_ADC_USE_ADC1 */
#if STM32_ADC_USE_ADC2
sr = ADC2->SR;
ADC2->SR = 0;
/* Note, an overflow may occur after the conversion ended before the driver
is able to stop the ADC, this is why the DMA channel is checked too.*/
if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD2.dmastp) > 0)) {
/* ADC overflow condition, this could happen only if the DMA is unable
to read data fast enough.*/
if (ADCD2.grpp != NULL)
_adc_isr_error_code(&ADCD2, ADC_ERR_OVERFLOW);
}
/* TODO: Add here analog watchdog handling.*/
#endif /* STM32_ADC_USE_ADC2 */
#if STM32_ADC_USE_ADC3
sr = ADC3->SR;
ADC3->SR = 0;
/* Note, an overflow may occur after the conversion ended before the driver
is able to stop the ADC, this is why the DMA channel is checked too.*/
if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD3.dmastp) > 0)) {
/* ADC overflow condition, this could happen only if the DMA is unable
to read data fast enough.*/
if (ADCD3.grpp != NULL)
_adc_isr_error_code(&ADCD3, ADC_ERR_OVERFLOW);
}
/* TODO: Add here analog watchdog handling.*/
#endif /* STM32_ADC_USE_ADC3 */
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ADC driver initialization.
*
* @notapi
*/
void adc_lld_init(void) {
ADC->CCR = STM32_ADC_ADCPRE;
#if STM32_ADC_USE_ADC1
/* Driver initialization.*/
adcObjectInit(&ADCD1);
ADCD1.adc = ADC1;
ADCD1.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC1_DMA_STREAM);
ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) |
STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M |
STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
STM32_DMA_CR_EN;
#endif
#if STM32_ADC_USE_ADC2
/* Driver initialization.*/
adcObjectInit(&ADCD2);
ADCD2.adc = ADC2;
ADCD2.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC2_DMA_STREAM);
ADCD2.dmamode = STM32_DMA_CR_CHSEL(ADC2_DMA_CHANNEL) |
STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M |
STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
STM32_DMA_CR_EN;
#endif
#if STM32_ADC_USE_ADC3
/* Driver initialization.*/
adcObjectInit(&ADCD3);
ADCD3.adc = ADC3;
ADCD3.dmastp = STM32_DMA_STREAM(STM32_ADC_ADC3_DMA_STREAM);
ADCD3.dmamode = STM32_DMA_CR_CHSEL(ADC3_DMA_CHANNEL) |
STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) |
STM32_DMA_CR_DIR_P2M |
STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
STM32_DMA_CR_EN;
#endif
/* The shared vector is initialized on driver initialization and never
disabled.*/
nvicEnableVector(ADC_IRQn, CORTEX_PRIORITY_MASK(STM32_ADC_IRQ_PRIORITY));
}
/**
* @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 and DMA clocks.*/
if (adcp->state == ADC_STOP) {
#if STM32_ADC_USE_ADC1
if (&ADCD1 == adcp) {
bool_t b;
b = dmaStreamAllocate(adcp->dmastp,
STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
(void *)adcp);
chDbgAssert(!b, "adc_lld_start(), #1", "stream already allocated");
dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR);
rccEnableADC1(FALSE);
}
#endif /* STM32_ADC_USE_ADC1 */
#if STM32_ADC_USE_ADC2
if (&ADCD2 == adcp) {
bool_t b;
b = dmaStreamAllocate(adcp->dmastp,
STM32_ADC_ADC2_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
(void *)adcp);
chDbgAssert(!b, "adc_lld_start(), #2", "stream already allocated");
dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR);
rccEnableADC2(FALSE);
}
#endif /* STM32_ADC_USE_ADC2 */
#if STM32_ADC_USE_ADC3
if (&ADCD3 == adcp) {
bool_t b;
b = dmaStreamAllocate(adcp->dmastp,
STM32_ADC_ADC3_DMA_IRQ_PRIORITY,
(stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
(void *)adcp);
chDbgAssert(!b, "adc_lld_start(), #3", "stream already allocated");
dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR);
rccEnableADC3(FALSE);
}
#endif /* STM32_ADC_USE_ADC3 */
/* ADC initial setup, starting the analog part here in order to reduce
the latency when starting a conversion.*/
adcp->adc->CR1 = 0;
adcp->adc->CR2 = 0;
adcp->adc->CR2 = ADC_CR2_ADON;
}
}
/**
* @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) {
dmaStreamRelease(adcp->dmastp);
adcp->adc->CR1 = 0;
adcp->adc->CR2 = 0;
#if STM32_ADC_USE_ADC1
if (&ADCD1 == adcp)
rccDisableADC1(FALSE);
#endif
#if STM32_ADC_USE_ADC2
if (&ADCD2 == adcp)
rccDisableADC2(FALSE);
#endif
#if STM32_ADC_USE_ADC3
if (&ADCD3 == adcp)
rccDisableADC3(FALSE);
#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 mode;
const ADCConversionGroup *grpp = adcp->grpp;
/* DMA setup.*/
mode = adcp->dmamode;
if (grpp->circular) {
mode |= STM32_DMA_CR_CIRC;
}
if (adcp->depth > 1) {
/* If the buffer depth is greater than one then the half transfer interrupt
interrupt is enabled in order to allows streaming processing.*/
mode |= STM32_DMA_CR_HTIE;
}
dmaStreamSetMemory0(adcp->dmastp, adcp->samples);
dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
(uint32_t)adcp->depth);
dmaStreamSetMode(adcp->dmastp, mode);
/* ADC setup.*/
adcp->adc->SR = 0;
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;
/* ADC configuration and start, the start is performed using the method
specified in the CR2 configuration, usually ADC_CR2_SWSTART.*/
adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN;
adcp->adc->CR2 = grpp->cr2 | ADC_CR2_CONT | ADC_CR2_DMA |
ADC_CR2_DDS | ADC_CR2_ADON;
}
/**
* @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->CR1 = 0;
adcp->adc->CR2 = 0;
adcp->adc->CR2 = ADC_CR2_ADON;
}
/**
* @brief Enables the TSVREFE bit.
* @details The TSVREFE bit is required in order to sample the internal
* temperature sensor and internal reference voltage.
* @note This is an STM32-only functionality.
*/
void adcSTM32EnableTSVREFE(void) {
ADC->CCR |= ADC_CCR_TSVREFE;
}
/**
* @brief Disables the TSVREFE bit.
* @details The TSVREFE bit is required in order to sample the internal
* temperature sensor and internal reference voltage.
* @note This is an STM32-only functionality.
*/
void adcSTM32DisableTSVREFE(void) {
ADC->CCR &= ~ADC_CCR_TSVREFE;
}
/**
* @brief Enables the VBATE bit.
* @details The VBATE bit is required in order to sample the VBAT channel.
* @note This is an STM32-only functionality.
*/
void adcSTM32EnableVBATE(void) {
ADC->CCR |= ADC_CCR_VBATE;
}
/**
* @brief Disables the VBATE bit.
* @details The VBATE bit is required in order to sample the VBAT channel.
* @note This is an STM32-only functionality.
*/
void adcSTM32DisableVBATE(void) {
ADC->CCR &= ~ADC_CCR_VBATE;
}
#endif /* HAL_USE_ADC */
/** @} */

View File

@ -0,0 +1,569 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file STM32F2xx/adc_lld.h
* @brief STM32F2xx ADC subsystem low level driver header.
*
* @addtogroup ADC
* @{
*/
#ifndef _ADC_LLD_H_
#define _ADC_LLD_H_
#if HAL_USE_ADC || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @name Absolute Maximum Ratings
* @{
*/
/**
* @brief Maximum HSE clock frequency.
*/
#define STM32_ADCCLK_MIN 600000
/**
* @brief Maximum HSE clock frequency.
* @note This value is arbitrary defined, the current datasheet does not
* define a maximum value (it is TBD). A value of 36MHz is mentioned
* but without relationship to VDD ranges.
*/
#define STM32_ADCCLK_MAX 42000000
/** @} */
/**
* @name Triggers selection
* @{
*/
#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */
/** @} */
/**
* @name ADC clock divider settings
* @{
*/
#define ADC_CCR_ADCPRE_DIV2 0
#define ADC_CCR_ADCPRE_DIV4 1
#define ADC_CCR_ADCPRE_DIV6 2
#define ADC_CCR_ADCPRE_DIV8 3
/** @} */
/**
* @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.
@note Available onADC1 only. */
#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference.
@note Available onADC1 only. */
#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT.
@note Available onADC1 only. */
/** @} */
/**
* @name Sampling rates
* @{
*/
#define ADC_SAMPLE_3 0 /**< @brief 3 cycles sampling time. */
#define ADC_SAMPLE_15 1 /**< @brief 15 cycles sampling time. */
#define ADC_SAMPLE_28 2 /**< @brief 28 cycles sampling time. */
#define ADC_SAMPLE_56 3 /**< @brief 56 cycles sampling time. */
#define ADC_SAMPLE_84 4 /**< @brief 84 cycles sampling time. */
#define ADC_SAMPLE_112 5 /**< @brief 112 cycles sampling time. */
#define ADC_SAMPLE_144 6 /**< @brief 144 cycles sampling time. */
#define ADC_SAMPLE_480 7 /**< @brief 480 cycles sampling time. */
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief ADC common clock divider.
* @note This setting is influenced by the VDDA voltage and other
* external conditions, please refer to the STM32L15x datasheet
* for more info.<br>
* See section 6.3.15 "12-bit ADC characteristics".
*/
#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__)
#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV2
#endif
/**
* @brief ADC1 driver enable switch.
* @details If set to @p TRUE the support for ADC1 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__)
#define STM32_ADC_USE_ADC1 TRUE
#endif
/**
* @brief ADC2 driver enable switch.
* @details If set to @p TRUE the support for ADC2 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__)
#define STM32_ADC_USE_ADC2 TRUE
#endif
/**
* @brief ADC3 driver enable switch.
* @details If set to @p TRUE the support for ADC3 is included.
* @note The default is @p TRUE.
*/
#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__)
#define STM32_ADC_USE_ADC3 TRUE
#endif
/**
* @brief DMA stream used for ADC1 operations.
*/
#if !defined(STM32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
#endif
/**
* @brief DMA stream used for ADC2 operations.
*/
#if !defined(STM32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
#endif
/**
* @brief DMA stream used for ADC3 operations.
*/
#if !defined(STM32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__)
#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
#endif
/**
* @brief ADC1 DMA priority (0..3|lowest..highest).
*/
#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC_ADC1_DMA_PRIORITY 2
#endif
/**
* @brief ADC2 DMA priority (0..3|lowest..highest).
*/
#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC_ADC2_DMA_PRIORITY 2
#endif
/**
* @brief ADC3 DMA priority (0..3|lowest..highest).
*/
#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC_ADC3_DMA_PRIORITY 2
#endif
/**
* @brief ADC interrupt priority level setting.
* @note This setting is shared among ADC1, ADC2 and ADC3 because
* all ADCs share the same vector.
*/
#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC_IRQ_PRIORITY 5
#endif
/**
* @brief ADC1 DMA interrupt priority level setting.
*/
#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
#endif
/**
* @brief ADC2 DMA interrupt priority level setting.
*/
#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
#endif
/**
* @brief ADC3 DMA interrupt priority level setting.
*/
#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
#error "ADC1 not present in the selected device"
#endif
#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2
#error "ADC2 not present in the selected device"
#endif
#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3
#error "ADC3 not present in the selected device"
#endif
#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3
#error "ADC driver activated but no ADC peripheral assigned"
#endif
#if STM32_ADC_USE_ADC1 && \
!STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK)
#error "invalid DMA stream associated to ADC1"
#endif
#if STM32_ADC_USE_ADC2 && \
!STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK)
#error "invalid DMA stream associated to ADC2"
#endif
#if STM32_ADC_USE_ADC3 && \
!STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK)
#error "invalid DMA stream associated to ADC3"
#endif
/* ADC clock related settings and checks.*/
#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2
#define STM32_ADCCLK (STM32_PCLK2 / 2)
#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4
#define STM32_ADCCLK (STM32_PCLK2 / 4)
#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV6
#define STM32_ADCCLK (STM32_PCLK2 / 6)
#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV8
#define STM32_ADCCLK (STM32_PCLK2 / 8)
#else
#error "invalid STM32_ADC_ADCPRE value specified"
#endif
#if (STM32_ADCCLK < STM32_ADCCLK_MIN) || (STM32_ADCCLK > STM32_ADCCLK_MAX)
#error "STM32_ADCCLK outside acceptable range (STM32_ADCCLK_MIN...STM32_ADCCLK_MAX)"
#endif
#if !defined(STM32_DMA_REQUIRED)
#define STM32_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. */
ADC_ERR_OVERFLOW = 1 /**< ADC overflow condition. */
} adcerror_t;
/**
* @brief Type of a structure representing an ADC driver.
*/
typedef struct ADCDriver ADCDriver;
/**
* @brief ADC notification callback type.
*
* @param[in] adcp pointer to the @p ADCDriver object triggering the
* callback
* @param[in] buffer pointer to the most recent samples data
* @param[in] n number of buffer rows available starting from @p buffer
*/
typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n);
/**
* @brief ADC error callback type.
*
* @param[in] adcp pointer to the @p ADCDriver object triggering the
* callback
*/
typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err);
/**
* @brief Conversion group configuration structure.
* @details This implementation-dependent structure describes a conversion
* operation.
* @note The use of this configuration structure requires knowledge of
* STM32 ADC cell registers interface, please refer to the STM32
* reference manual for details.
*/
typedef struct {
/**
* @brief Enables the circular buffer mode for the group.
*/
bool_t circular;
/**
* @brief Number of the analog channels belonging to the conversion group.
*/
adc_channels_num_t num_channels;
/**
* @brief Callback function associated to the group or @p NULL.
*/
adccallback_t end_cb;
/**
* @brief Error callback or @p NULL.
*/
adcerrorcallback_t error_cb;
/* End of the mandatory fields.*/
/**
* @brief 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;
/**
* @brief 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;
/**
* @brief ADC SMPR1 register initialization data.
* @details In this field must be specified the sample times for channels
* 10...18.
*/
uint32_t smpr1;
/**
* @brief ADC SMPR2 register initialization data.
* @details In this field must be specified the sample times for channels
* 0...9.
*/
uint32_t smpr2;
/**
* @brief ADC SQR1 register initialization data.
* @details Conversion group sequence 13...16 + sequence length.
*/
uint32_t sqr1;
/**
* @brief ADC SQR2 register initialization data.
* @details Conversion group sequence 7...12.
*/
uint32_t sqr2;
/**
* @brief ADC SQR3 register initialization data.
* @details Conversion group sequence 1...6.
*/
uint32_t sqr3;
} ADCConversionGroup;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
uint32_t dummy;
} ADCConfig;
/**
* @brief Structure representing an ADC driver.
*/
struct ADCDriver {
/**
* @brief Driver state.
*/
adcstate_t state;
/**
* @brief Current configuration data.
*/
const ADCConfig *config;
/**
* @brief Current samples buffer pointer or @p NULL.
*/
adcsample_t *samples;
/**
* @brief Current samples buffer depth or @p 0.
*/
size_t depth;
/**
* @brief Current conversion group pointer or @p NULL.
*/
const ADCConversionGroup *grpp;
#if ADC_USE_WAIT || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
Thread *thread;
#endif
#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the peripheral.
*/
Mutex mutex;
#elif CH_USE_SEMAPHORES
Semaphore semaphore;
#endif
#endif /* ADC_USE_MUTUAL_EXCLUSION */
#if defined(ADC_DRIVER_EXT_FIELDS)
ADC_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Pointer to the ADCx registers block.
*/
ADC_TypeDef *adc;
/**
* @brief Pointer to associated SMA channel.
*/
const stm32_dma_stream_t *dmastp;
/**
* @brief DMA mode bit mask.
*/
uint32_t dmamode;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @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. */
#define ADC_SMPR1_SMP_VBAT(n) ((n) << 24) /**< @brief VBAT sampling time. */
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
extern ADCDriver ADCD1;
#endif
#if STM32_ADC_USE_ADC2 && !defined(__DOXYGEN__)
extern ADCDriver ADCD2;
#endif
#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__)
extern ADCDriver ADCD3;
#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);
void adcSTM32EnableTSVREFE(void);
void adcSTM32DisableTSVREFE(void);
void adcSTM32EnableVBATE(void);
void adcSTM32DisableVBATE(void);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_ADC */
#endif /* _ADC_LLD_H_ */
/** @} */

View File

@ -19,8 +19,8 @@
*/
/**
* @file STM32F2xx/hal_lld.c
* @brief STM32F2xx HAL subsystem low level driver source.
* @file STM32F4xx/hal_lld.c
* @brief STM32F4xx HAL subsystem low level driver source.
*
* @addtogroup HAL
* @{
@ -56,11 +56,13 @@
*/
void hal_lld_init(void) {
/* Reset of all peripherals.*/
// RCC->APB1RSTR = 0xFFFFFFFF;
// RCC->APB2RSTR = 0xFFFFFFFF;
// RCC->APB1RSTR = 0;
// RCC->APB2RSTR = 0;
/* Reset of all peripherals. AHB3 is not reseted because it could have
been initialized in the board initialization file (board.c).*/
rccResetAHB1(!0);
rccResetAHB2(!0);
rccResetAHB3(!0);
rccResetAPB1(!RCC_APB1RSTR_PWRRST);
rccResetAPB2(!0);
/* SysTick initialization using the system clock.*/
SysTick->LOAD = STM32_HCLK / CH_FREQUENCY - 1;
@ -69,7 +71,10 @@ void hal_lld_init(void) {
SysTick_CTRL_ENABLE_Msk |
SysTick_CTRL_TICKINT_Msk;
#if STM32_PVD_ENABLE
/* Programmable voltage detector initialization */
PWR->CR |= PWR_CR_PVDE | (STM32_PLS & STM32_PLS_MASK);
#endif /* STM32_PVD_ENABLE */
#if defined(STM32_DMA_REQUIRED)
dmaInit();
@ -83,16 +88,15 @@ void hal_lld_init(void) {
*
* @special
*/
#if defined(STM32F2XX) || defined(__DOXYGEN__)
/**
* @brief Clocks and internal voltage initialization.
*/
void stm32_clock_init(void) {
#if !STM32_NO_INIT
/* PWR clock enable.*/
RCC->APB1ENR = RCC_APB1ENR_PWREN;
/* PWR initialization.*/
PWR->CR = 0;
/* Initial clocks setup and wait for HSI stabilization, the MSI clock is
always enabled because it is the fallback clock when PLL the fails.*/
RCC->CR |= RCC_CR_HSION;
@ -134,7 +138,7 @@ void stm32_clock_init(void) {
#if STM32_ACTIVATE_PLLI2S
/* PLLI2S activation.*/
RCC->PLLI2SCFGR = STM32_PLI2SR_VALUE | STM32_PLLI2SN_VALUE;
RCC->PLLI2SCFGR = STM32_PLLI2SR_VALUE | STM32_PLLI2SN_VALUE;
RCC->CR |= RCC_CR_PLLI2SON;
while (!(RCC->CR & RCC_CR_PLLI2SRDY))
; /* Waits until PLLI2S is stable. */
@ -144,19 +148,21 @@ void stm32_clock_init(void) {
RCC->CFGR |= STM32_MCO2PRE | STM32_MCO2SEL | STM32_MCO1PRE | STM32_MCO1SEL |
STM32_RTCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
/* Flash setup. */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | STM32_FLASHBITS;
/* Flash setup.*/
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN |
STM32_FLASHBITS;
/* Switching to the configured clock source if it is different from MSI. */
/* Switching to the configured clock source if it is different from MSI.*/
#if (STM32_SW != STM32_SW_HSI)
RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */
RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */
while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
;
#endif
#endif /* STM32_NO_INIT */
/* SYSCFG clock enabled here because it is a multi-functional unit shared
among multiple drivers.*/
rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, TRUE);
}
#else
void stm32_clock_init(void) {}
#endif
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,312 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup STM32F2xx_DRIVERS STM32F2xx Drivers
* @details This section describes all the supported drivers on the STM32F2xx
* platform and the implementation details of the single drivers.
*
* @ingroup platforms
*/
/**
* @defgroup STM32F2xx_HAL STM32F2xx Initialization Support
* @details The STM32F2xx HAL support is responsible for system initialization.
*
* @section stm32f2xx_hal_1 Supported HW resources
* - PLL1.
* - PLL2.
* - RCC.
* - Flash.
* .
* @section stm32f2xx_hal_2 STM32F2xx HAL driver implementation features
* - PLL startup and stabilization.
* - Clock tree initialization.
* - Clock source selection.
* - Flash wait states initialization based on the selected clock options.
* - SYSTICK initialization based on current clock and kernel required rate.
* - DMA support initialization.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_ADC STM32F2xx ADC Support
* @details The STM32F2xx ADC driver supports the ADC peripherals using DMA
* channels for maximum performance.
*
* @section stm32f2xx_adc_1 Supported HW resources
* - ADC1.
* - ADC2.
* - ADC3.
* - DMA2.
* .
* @section stm32f2xx_adc_2 STM32F2xx ADC driver implementation features
* - Clock stop for reduced power usage when the driver is in stop state.
* - Streaming conversion using DMA for maximum performance.
* - Programmable ADC interrupt priority level.
* - Programmable DMA bus priority for each DMA channel.
* - Programmable DMA interrupt priority for each DMA channel.
* - DMA and ADC errors detection.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_EXT STM32F2xx EXT Support
* @details The STM32F2xx EXT driver uses the EXTI peripheral.
*
* @section stm32f2xx_ext_1 Supported HW resources
* - EXTI.
* .
* @section stm32f2xx_ext_2 STM32F2xx EXT driver implementation features
* - Each EXTI channel can be independently enabled and programmed.
* - Programmable EXTI interrupts priority level.
* - Capability to work as event sources (WFE) rather than interrupt sources.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_GPT STM32F2xx GPT Support
* @details The STM32F2xx GPT driver uses the TIMx peripherals.
*
* @section stm32f2xx_gpt_1 Supported HW resources
* - TIM1.
* - TIM2.
* - TIM3.
* - TIM4.
* - TIM5.
* - TIM8.
* .
* @section stm32f2xx_gpt_2 STM32F2xx GPT driver implementation features
* - Each timer can be independently enabled and programmed. Unused
* peripherals are left in low power mode.
* - Programmable TIMx interrupts priority level.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_ICU STM32F2xx ICU Support
* @details The STM32F2xx ICU driver uses the TIMx peripherals.
*
* @section stm32f2xx_icu_1 Supported HW resources
* - TIM1.
* - TIM2.
* - TIM3.
* - TIM4.
* - TIM5.
* - TIM8.
* .
* @section stm32f2xx_icu_2 STM32F2xx ICU driver implementation features
* - Each timer can be independently enabled and programmed. Unused
* peripherals are left in low power mode.
* - Programmable TIMx interrupts priority level.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_PAL STM32F2xx PAL Support
* @details The STM32F2xx PAL driver uses the GPIO peripherals.
*
* @section stm32f2xx_pal_1 Supported HW resources
* - GPIOA.
* - GPIOB.
* - GPIOC.
* - GPIOD.
* - GPIOE.
* - GPIOF.
* - GPIOG.
* - GPIOH.
* - GPIOI.
* .
* @section stm32f2xx_pal_2 STM32F2xx PAL driver implementation features
* The PAL driver implementation fully supports the following hardware
* capabilities:
* - 16 bits wide ports.
* - Atomic set/reset functions.
* - Atomic set+reset function (atomic bus operations).
* - Output latched regardless of the pad setting.
* - Direct read of input pads regardless of the pad setting.
* .
* @section stm32f2xx_pal_3 Supported PAL setup modes
* The STM32F2xx PAL driver supports the following I/O modes:
* - @p PAL_MODE_RESET.
* - @p PAL_MODE_UNCONNECTED.
* - @p PAL_MODE_INPUT.
* - @p PAL_MODE_INPUT_PULLUP.
* - @p PAL_MODE_INPUT_PULLDOWN.
* - @p PAL_MODE_INPUT_ANALOG.
* - @p PAL_MODE_OUTPUT_PUSHPULL.
* - @p PAL_MODE_OUTPUT_OPENDRAIN.
* - @p PAL_MODE_ALTERNATE (non standard).
* .
* Any attempt to setup an invalid mode is ignored.
*
* @section stm32f2xx_pal_4 Suboptimal behavior
* The STM32F2xx GPIO is less than optimal in several areas, the limitations
* should be taken in account while using the PAL driver:
* - Pad/port toggling operations are not atomic.
* - Pad/group mode setup is not atomic.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_PWM STM32F2xx PWM Support
* @details The STM32F2xx PWM driver uses the TIMx peripherals.
*
* @section stm32f2xx_pwm_1 Supported HW resources
* - TIM1.
* - TIM2.
* - TIM3.
* - TIM4.
* - TIM5.
* - TIM8.
* .
* @section stm32f2xx_pwm_2 STM32F2xx PWM driver implementation features
* - Each timer can be independently enabled and programmed. Unused
* peripherals are left in low power mode.
* - Four independent PWM channels per timer.
* - Programmable TIMx interrupts priority level.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_SERIAL STM32F2xx Serial Support
* @details The STM32F2xx Serial driver uses the USART/UART peripherals in a
* buffered, interrupt driven, implementation.
*
* @section stm32f2xx_serial_1 Supported HW resources
* The serial driver can support any of the following hardware resources:
* - USART1.
* - USART2.
* - USART3.
* - UART4.
* - UART5.
* - USART6.
* .
* @section stm32f2xx_serial_2 STM32F2xx Serial driver implementation features
* - Clock stop for reduced power usage when the driver is in stop state.
* - Each UART/USART can be independently enabled and programmed. Unused
* peripherals are left in low power mode.
* - Fully interrupt driven.
* - Programmable priority levels for each UART/USART.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_SPI STM32F2xx SPI Support
* @details The SPI driver supports the STM32F2xx SPI peripherals using DMA
* channels for maximum performance.
*
* @section stm32f2xx_spi_1 Supported HW resources
* - SPI1.
* - SPI2.
* - SPI3.
* - DMA1.
* - DMA2.
* .
* @section stm32f2xx_spi_2 STM32F2xx SPI driver implementation features
* - Clock stop for reduced power usage when the driver is in stop state.
* - Each SPI can be independently enabled and programmed. Unused
* peripherals are left in low power mode.
* - Programmable interrupt priority levels for each SPI.
* - DMA is used for receiving and transmitting.
* - Programmable DMA bus priority for each DMA channel.
* - Programmable DMA interrupt priority for each DMA channel.
* - Programmable DMA error hook.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_UART STM32F2xx UART Support
* @details The UART driver supports the STM32F2xx USART peripherals using DMA
* channels for maximum performance.
*
* @section stm32f2xx_uart_1 Supported HW resources
* The UART driver can support any of the following hardware resources:
* - USART1.
* - USART2.
* - USART3.
* - DMA1.
* - DMA2.
* .
* @section stm32f2xx_uart_2 STM32F2xx UART driver implementation features
* - Clock stop for reduced power usage when the driver is in stop state.
* - Each UART/USART can be independently enabled and programmed. Unused
* peripherals are left in low power mode.
* - Programmable interrupt priority levels for each UART/USART.
* - DMA is used for receiving and transmitting.
* - Programmable DMA bus priority for each DMA channel.
* - Programmable DMA interrupt priority for each DMA channel.
* - Programmable DMA error hook.
* .
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_PLATFORM_DRIVERS STM32F2xx Platform Drivers
* @details Platform support drivers. Platform drivers do not implement HAL
* standard driver templates, their role is to support platform
* specific functionalities.
*
* @ingroup STM32F2xx_DRIVERS
*/
/**
* @defgroup STM32F2xx_DMA STM32F2xx DMA Support
* @details This DMA helper driver is used by the other drivers in order to
* access the shared DMA resources in a consistent way.
*
* @section stm32f2xx_dma_1 Supported HW resources
* The DMA driver can support any of the following hardware resources:
* - DMA1.
* - DMA2.
* .
* @section stm32f2xx_dma_2 STM32F2xx DMA driver implementation features
* - Exports helper functions/macros to the other drivers that share the
* DMA resource.
* - Automatic DMA clock stop when not in use by any driver.
* - DMA streams and interrupt vectors sharing among multiple drivers.
* .
* @ingroup STM32F2xx_PLATFORM_DRIVERS
*/
/**
* @defgroup STM32F2xx_RCC STM32F2xx RCC Support
* @details This RCC helper driver is used by the other drivers in order to
* access the shared RCC resources in a consistent way.
*
* @section stm32f1xx_rcc_1 Supported HW resources
* - RCC.
* .
* @section stm32f2xx_rcc_2 STM32F2xx RCC driver implementation features
* - Peripherals reset.
* - Peripherals clock enable.
* - Periplerals clock disable.
* .
* @ingroup STM32F2xx_PLATFORM_DRIVERS
*/

View File

@ -1,12 +1,22 @@
# List of all the STM32L1xx platform files.
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F2xx/hal_lld.c \
# List of all the STM32F2xx platform files.
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32F2xx/stm32_dma.c \
${CHIBIOS}/os/hal/platforms/STM32F2xx/hal_lld.c \
${CHIBIOS}/os/hal/platforms/STM32F2xx/adc_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/ext_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/gpt_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/icu_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/pwm_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/serial_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c
${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/uart_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/i2c_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/GPIOv2/pal_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/RTCv2/rtc_lld.c \
# Required include directories
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/STM32F2xx \
${CHIBIOS}/os/hal/platforms/STM32 \
${CHIBIOS}/os/hal/platforms/STM32/GPIOv2
${CHIBIOS}/os/hal/platforms/STM32/GPIOv2 \
${CHIBIOS}/os/hal/platforms/STM32/RTCv2 \

View File

@ -19,10 +19,10 @@
*/
/**
* @file DMAv2/stm32_dma.c
* @file STM32F2xx/stm32_dma.c
* @brief Enhanced DMA helper driver code.
*
* @addtogroup STM32_DMA
* @addtogroup STM32F2xx_DMA
* @details DMA sharing helper driver. In the STM32 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
@ -76,22 +76,22 @@
* instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc.
*/
const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
{0, DMA1, DMA1_Stream0, &DMA1->LIFCR, 0},
{1, DMA1, DMA1_Stream1, &DMA1->LIFCR, 6},
{2, DMA1, DMA1_Stream2, &DMA1->LIFCR, 16},
{3, DMA1, DMA1_Stream3, &DMA1->LIFCR, 22},
{4, DMA1, DMA1_Stream4, &DMA1->HIFCR, 0},
{5, DMA1, DMA1_Stream5, &DMA1->HIFCR, 6},
{6, DMA1, DMA1_Stream6, &DMA1->HIFCR, 16},
{7, DMA1, DMA1_Stream7, &DMA1->HIFCR, 22},
{8, DMA2, DMA2_Stream0, &DMA2->LIFCR, 0},
{9, DMA2, DMA2_Stream1, &DMA2->LIFCR, 6},
{10, DMA2, DMA2_Stream2, &DMA2->LIFCR, 16},
{11, DMA2, DMA2_Stream3, &DMA2->LIFCR, 22},
{12, DMA2, DMA2_Stream4, &DMA2->HIFCR, 0},
{13, DMA2, DMA2_Stream5, &DMA2->HIFCR, 6},
{14, DMA2, DMA2_Stream6, &DMA2->HIFCR, 16},
{15, DMA2, DMA2_Stream7, &DMA2->HIFCR, 22},
{DMA1_Stream0, &DMA1->LIFCR, 0, 0, DMA1_Stream0_IRQn},
{DMA1_Stream1, &DMA1->LIFCR, 6, 1, DMA1_Stream1_IRQn},
{DMA1_Stream2, &DMA1->LIFCR, 16, 2, DMA1_Stream2_IRQn},
{DMA1_Stream3, &DMA1->LIFCR, 22, 3, DMA1_Stream3_IRQn},
{DMA1_Stream4, &DMA1->HIFCR, 0, 4, DMA1_Stream4_IRQn},
{DMA1_Stream5, &DMA1->HIFCR, 6, 5, DMA1_Stream5_IRQn},
{DMA1_Stream6, &DMA1->HIFCR, 16, 6, DMA1_Stream6_IRQn},
{DMA1_Stream7, &DMA1->HIFCR, 22, 7, DMA1_Stream7_IRQn},
{DMA2_Stream0, &DMA2->LIFCR, 0, 8, DMA2_Stream0_IRQn},
{DMA2_Stream1, &DMA2->LIFCR, 6, 9, DMA2_Stream1_IRQn},
{DMA2_Stream2, &DMA2->LIFCR, 16, 10, DMA2_Stream2_IRQn},
{DMA2_Stream3, &DMA2->LIFCR, 22, 11, DMA2_Stream3_IRQn},
{DMA2_Stream4, &DMA2->HIFCR, 0, 12, DMA2_Stream4_IRQn},
{DMA2_Stream5, &DMA2->HIFCR, 6, 13, DMA2_Stream5_IRQn},
{DMA2_Stream6, &DMA2->HIFCR, 16, 14, DMA2_Stream6_IRQn},
{DMA2_Stream7, &DMA2->HIFCR, 22, 15, DMA2_Stream7_IRQn},
};
/*===========================================================================*/
@ -102,8 +102,8 @@ const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
* @brief DMA ISR redirector type.
*/
typedef struct {
stm32_dmaisr_t dma_func;
void *dma_param;
stm32_dmaisr_t dma_func; /**< @brief DMA callback function. */
void *dma_param; /**< @brief DMA callback parameter. */
} dma_isr_redir_t;
/**
@ -467,7 +467,7 @@ bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
chDbgCheck(dmastp != NULL, "dmaAllocate");
/* Checks if the stream is already taken.*/
if ((dma_streams_mask & dmastp->mask) != 0)
if ((dma_streams_mask & (1 << dmastp->selfindex)) != 0)
return TRUE;
/* Marks the stream as allocated.*/
@ -476,20 +476,16 @@ bool_t dmaStreamAllocate(const stm32_dma_stream_t *dmastp,
dma_streams_mask |= (1 << dmastp->selfindex);
/* Enabling DMA clocks required by the current streams set.*/
if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0) {
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
RCC->AHB1LPENR |= RCC_AHB1LPENR_DMA1LPEN;
}
if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0) {
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
RCC->AHB1LPENR |= RCC_AHB1LPENR_DMA2LPEN;
}
if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0)
rccEnableDMA1(FALSE);
if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) != 0)
rccEnableDMA2(FALSE);
/* Putting the stream in a safe state.*/
dmaStreamDisable(dmastp);
dmaStreamClearInterrupt(dmastp);
dmastp->channel->CR = STM32_DMA_CR_RESET_VALUE;
dmastp->channel->FCR = STM32_DMA_FCR_RESET_VALUE;
dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE;
dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE;
/* Enables the associated IRQ vector if a callback is defined.*/
if (func != NULL)
@ -516,7 +512,7 @@ void dmaStreamRelease(const stm32_dma_stream_t *dmastp) {
chDbgCheck(dmastp != NULL, "dmaRelease");
/* Check if the streams is not taken.*/
chDbgAssert((dma_streams_mask & dmastp->mask) != 0,
chDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0,
"dmaRelease(), #1", "not allocated");
/* Disables the associated IRQ vector.*/
@ -526,14 +522,10 @@ void dmaStreamRelease(const stm32_dma_stream_t *dmastp) {
dma_streams_mask &= ~(1 << dmastp->selfindex);
/* Shutting down clocks that are no more required, if any.*/
if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0) {
RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA1EN;
RCC->AHB1LPENR &= ~RCC_AHB1LPENR_DMA1LPEN;
}
if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0) {
RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA2EN;
RCC->AHB1LPENR &= ~RCC_AHB1LPENR_DMA2LPEN;
}
if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0)
rccDisableDMA1(FALSE);
if ((dma_streams_mask & STM32_DMA2_STREAMS_MASK) == 0)
rccDisableDMA2(FALSE);
}
#endif /* STM32_DMA_REQUIRED */

View File

@ -19,12 +19,12 @@
*/
/**
* @file DMAv2/stm32_dma.h
* @file STM32F2xx/stm32_dma.h
* @brief Enhanced-DMA helper driver header.
* @note This file requires definitions from the ST STM32F2xx header file
* stm32f2xx.h.
*
* @addtogroup STM32_DMA
* @addtogroup STM32F2xx_DMA
* @{
*/
@ -46,30 +46,81 @@
*/
#define STM32_DMA_ISR_MASK 0x3D
/**
* @brief Returns the channel associated to the specified stream.
*
* @param[in] id the unique numeric stream identifier
* @param[in] c a stream/channel association word, one channel per
* nibble
* @return Returns the channel associated to the stream.
*/
#define STM32_DMA_GETCHANNEL(id, c) ((c) >> (((id) & 7) * 4))
/**
* @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 STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1) * 8) + (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 STM32_DMA_STREAM_ID_MSK(dma, stream) \
(1 << STM32_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 STM32_DMA_IS_VALID_ID(id, mask) (((1 << (id)) & (mask)))
/**
* @name DMA streams identifiers
* @{
*/
#define STM32_DMA1_STREAM0 (&_stm32_dma_streams[0])
#define STM32_DMA1_STREAM1 (&_stm32_dma_streams[1])
#define STM32_DMA1_STREAM2 (&_stm32_dma_streams[2])
#define STM32_DMA1_STREAM3 (&_stm32_dma_streams[3])
#define STM32_DMA1_STREAM4 (&_stm32_dma_streams[4])
#define STM32_DMA1_STREAM5 (&_stm32_dma_streams[5])
#define STM32_DMA1_STREAM6 (&_stm32_dma_streams[6])
#define STM32_DMA1_STREAM7 (&_stm32_dma_streams[7])
#define STM32_DMA2_STREAM0 (&_stm32_dma_streams[8])
#define STM32_DMA2_STREAM1 (&_stm32_dma_streams[9])
#define STM32_DMA2_STREAM2 (&_stm32_dma_streams[10])
#define STM32_DMA2_STREAM3 (&_stm32_dma_streams[11])
#define STM32_DMA2_STREAM4 (&_stm32_dma_streams[12])
#define STM32_DMA2_STREAM5 (&_stm32_dma_streams[13])
#define STM32_DMA2_STREAM6 (&_stm32_dma_streams[14])
#define STM32_DMA2_STREAM7 (&_stm32_dma_streams[15])
/**
* @brief Returns a pointer to a stm32_dma_stream_t structure.
*
* @param[in] id the stream numeric identifier
* @return A pointer to the stm32_dma_stream_t constant structure
* associated to the DMA stream.
*/
#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id])
#define STM32_DMA1_STREAM0 STM32_DMA_STREAM(0)
#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(1)
#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(2)
#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(3)
#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(4)
#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(5)
#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(6)
#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(7)
#define STM32_DMA2_STREAM0 STM32_DMA_STREAM(8)
#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(9)
#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(10)
#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(11)
#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(12)
#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(13)
#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(14)
#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(15)
/** @} */
/**
* @name CR register constants common to all DMA types
* @{
*/
#define STM32_DMA_CR_EN DMA_SxCR_EN
#define STM32_DMA_CR_TEIE DMA_SxCR_TEIE
@ -90,12 +141,15 @@
#define STM32_DMA_CR_MSIZE_BYTE 0
#define STM32_DMA_CR_MSIZE_HWORD DMA_SxCR_MSIZE_0
#define STM32_DMA_CR_MSIZE_WORD DMA_SxCR_MSIZE_1
#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_MSIZE_MASK | \
STM32_DMA_CR_MSIZE_MASK)
#define STM32_DMA_CR_PL_MASK DMA_SxCR_PL
#define STM32_DMA_CR_PL(n) ((n) << 16)
/** @} */
/**
* @name CR register constants only found in STM32F2xx
* @name CR register constants only found in STM32F2xx/STM32F2xx
* @{
*/
#define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE
#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL
@ -117,7 +171,8 @@
/** @} */
/**
* @name FCR register constants only found in STM32F2xx
* @name FCR register constants only found in STM32F2xx/STM32F2xx
* @{
*/
#define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE
#define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS
@ -155,7 +210,7 @@
* @brief STM32 DMA stream descriptor structure.
*/
typedef struct {
DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */
DMA_Stream_TypeDef *stream; /**< @brief Associated DMA stream. */
volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */
uint8_t ishift; /**< @brief Bits offset in xIFCR
register. */
@ -176,9 +231,15 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/* 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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
* @param[in] addr value to be written in the PAR register
@ -192,6 +253,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/**
* @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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
* @param[in] addr value to be written in the M0AR register
@ -218,6 +281,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/**
* @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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
* @param[in] size value to be written in the CNDTR register
@ -231,6 +296,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/**
* @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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
* @return The number of transfers to be performed.
@ -242,6 +309,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/**
* @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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
* @param[in] mode value to be written in the CR register
@ -255,6 +324,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/**
* @brief Programs the stream FIFO settings.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
* @param[in] mode value to be written in the FCR register
@ -268,18 +339,22 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/**
* @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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmachp pointer to a stm32_dma_stream_t structure
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
*
* @special
*/
#define dmaStreamEnable(dmachp) { \
#define dmaStreamEnable(dmastp) { \
(dmastp)->stream->CR |= STM32_DMA_CR_EN; \
}
/**
* @brief DMA stream disable.
* @note This function can be invoked in both ISR or thread context.
* @pre The stream must have been allocated using @p dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
*
@ -292,6 +367,8 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
/**
* @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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
*
@ -301,6 +378,46 @@ typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
*(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->ishift; \
}
/**
* @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 dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
* @param[in] mode value to be written in the CCR register, this value
* is implicitly ORed with:
* - @p STM32_DMA_CR_MINC
* - @p STM32_DMA_CR_PINC
* - @p STM32_DMA_CR_DIR_M2M
* - @p STM32_DMA_CR_EN
* .
* @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) { \
dmaStreamSetPeripheral(dmastp, src); \
dmaStreamSetMemory0(dmastp, dst); \
dmaStreamSetTransactionSize(dmastp, n); \
dmaStreamSetMode(dmastp, (mode) | \
STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \
STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \
}
/**
* @brief Polled wait for DMA transfer end.
* @pre The stream must have been allocated using @p dmaStreamAllocate().
* @post After use the stream can be released using @p dmaStreamRelease().
*
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
*/
#define dmaWaitCompletion(dmastp) \
while (((dmastp)->stream->CNDTR > 0) && \
((dmastp)->stream->CCR & STM32_DMA_CR_EN))
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/

View File

@ -0,0 +1,886 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file STM32F2xx/stm32_rcc.h
* @brief RCC helper driver header.
* @note This file requires definitions from the ST header file
* @p stm32f2xx.h.
*
* @addtogroup STM32F2xx_RCC
* @{
*/
#ifndef _STM32_RCC_
#define _STM32_RCC_
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @name Generic RCC operations
* @{
*/
/**
* @brief Enables the clock of one or more peripheral on the APB1 bus.
*
* @param[in] mask APB1 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableAPB1(mask, lp) { \
RCC->APB1ENR |= (mask); \
if (lp) \
RCC->APB1LPENR |= (mask); \
}
/**
* @brief Disables the clock of one or more peripheral on the APB1 bus.
*
* @param[in] mask APB1 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableAPB1(mask, lp) { \
RCC->APB1ENR &= ~(mask); \
if (lp) \
RCC->APB1LPENR &= ~(mask); \
}
/**
* @brief Resets one or more peripheral on the APB1 bus.
*
* @param[in] mask APB1 peripherals mask
*
* @api
*/
#define rccResetAPB1(mask) { \
RCC->APB1RSTR |= (mask); \
RCC->APB1RSTR = 0; \
}
/**
* @brief Enables the clock of one or more peripheral on the APB2 bus.
*
* @param[in] mask APB2 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableAPB2(mask, lp) { \
RCC->APB2ENR |= (mask); \
if (lp) \
RCC->APB2LPENR |= (mask); \
}
/**
* @brief Disables the clock of one or more peripheral on the APB2 bus.
*
* @param[in] mask APB2 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableAPB2(mask, lp) { \
RCC->APB2ENR &= ~(mask); \
if (lp) \
RCC->APB2LPENR &= ~(mask); \
}
/**
* @brief Resets one or more peripheral on the APB2 bus.
*
* @param[in] mask APB2 peripherals mask
*
* @api
*/
#define rccResetAPB2(mask) { \
RCC->APB2RSTR |= (mask); \
RCC->APB2RSTR = 0; \
}
/**
* @brief Enables the clock of one or more peripheral on the AHB1 bus.
*
* @param[in] mask AHB1 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableAHB1(mask, lp) { \
RCC->AHB1ENR |= (mask); \
if (lp) \
RCC->AHB1LPENR |= (mask); \
}
/**
* @brief Disables the clock of one or more peripheral on the AHB1 bus.
*
* @param[in] mask AHB1 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableAHB1(mask, lp) { \
RCC->AHB1ENR &= ~(mask); \
if (lp) \
RCC->AHB1LPENR &= ~(mask); \
}
/**
* @brief Resets one or more peripheral on the AHB1 bus.
*
* @param[in] mask AHB1 peripherals mask
*
* @api
*/
#define rccResetAHB1(mask) { \
RCC->AHB1RSTR |= (mask); \
RCC->AHB1RSTR = 0; \
}
/**
* @brief Enables the clock of one or more peripheral on the AHB2 bus.
*
* @param[in] mask AHB2 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableAHB2(mask, lp) { \
RCC->AHB2ENR |= (mask); \
if (lp) \
RCC->AHB2LPENR |= (mask); \
}
/**
* @brief Disables the clock of one or more peripheral on the AHB2 bus.
*
* @param[in] mask AHB2 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableAHB2(mask, lp) { \
RCC->AHB2ENR &= ~(mask); \
if (lp) \
RCC->AHB2LPENR &= ~(mask); \
}
/**
* @brief Resets one or more peripheral on the AHB2 bus.
*
* @param[in] mask AHB2 peripherals mask
*
* @api
*/
#define rccResetAHB2(mask) { \
RCC->AHB2RSTR |= (mask); \
RCC->AHB2RSTR = 0; \
}
/**
* @brief Enables the clock of one or more peripheral on the AHB3 (FSMC) bus.
*
* @param[in] mask AHB3 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableAHB3(mask, lp) { \
RCC->AHB3ENR |= (mask); \
if (lp) \
RCC->AHB3LPENR |= (mask); \
}
/**
* @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus.
*
* @param[in] mask AHB3 peripherals mask
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableAHB3(mask, lp) { \
RCC->AHB3ENR &= ~(mask); \
if (lp) \
RCC->AHB3LPENR &= ~(mask); \
}
/**
* @brief Resets one or more peripheral on the AHB3 (FSMC) bus.
*
* @param[in] mask AHB3 peripherals mask
*
* @api
*/
#define rccResetAHB3(mask) { \
RCC->AHB3RSTR |= (mask); \
RCC->AHB3RSTR = 0; \
}
/** @} */
/**
* @brief ADC peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the ADC1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableADC1(lp) rccEnableAPB2(RCC_APB2ENR_ADC1EN, lp)
/**
* @brief Disables the ADC1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableADC1(lp) rccDisableAPB2(RCC_APB2ENR_ADC1EN, lp)
/**
* @brief Resets the ADC1 peripheral.
*
* @api
*/
#define rccResetADC1() rccResetAPB2(RCC_APB2RSTR_ADC1RST)
/**
* @brief Enables the ADC2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableADC2(lp) rccEnableAPB2(RCC_APB2ENR_ADC2EN, lp)
/**
* @brief Disables the ADC2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableADC2(lp) rccDisableAPB2(RCC_APB2ENR_ADC2EN, lp)
/**
* @brief Resets the ADC2 peripheral.
*
* @api
*/
#define rccResetADC2() rccResetAPB2(RCC_APB2RSTR_ADC2RST)
/**
* @brief Enables the ADC3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableADC3(lp) rccEnableAPB2(RCC_APB2ENR_ADC3EN, lp)
/**
* @brief Disables the ADC3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableADC3(lp) rccDisableAPB2(RCC_APB2ENR_ADC3EN, lp)
/**
* @brief Resets the ADC3 peripheral.
*
* @api
*/
#define rccResetADC3() rccResetAPB2(RCC_APB2RSTR_ADC3RST)
/** @} */
/**
* @brief DMA peripheral specific RCC operations
* @{
*/
/**
* @brief Enables the DMA1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp)
/**
* @brief Disables the DMA1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableDMA1(lp) rccDisableAHB1(RCC_AHB1ENR_DMA1EN, lp)
/**
* @brief Resets the DMA1 peripheral.
*
* @api
*/
#define rccResetDMA1() rccResetAHB1(RCC_AHB1RSTR_DMA1RST)
/**
* @brief Enables the DMA2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableDMA2(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2EN, lp)
/**
* @brief Disables the DMA2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableDMA2(lp) rccDisableAHB1(RCC_AHB1ENR_DMA2EN, lp)
/**
* @brief Resets the DMA2 peripheral.
*
* @api
*/
#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST)
/** @} */
/**
* @brief I2C peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the I2C1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableI2C1(lp) rccEnableAPB1(RCC_APB1ENR_I2C1EN, lp)
/**
* @brief Disables the I2C1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableI2C1(lp) rccDisableAPB1(RCC_APB1ENR_I2C1EN, lp)
/**
* @brief Resets the I2C1 peripheral.
*
* @api
*/
#define rccResetI2C1() rccResetAPB1(RCC_APB1RSTR_I2C1RST)
/**
* @brief Enables the I2C2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableI2C2(lp) rccEnableAPB1(RCC_APB1ENR_I2C2EN, lp)
/**
* @brief Disables the I2C2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableI2C2(lp) rccDisableAPB1(RCC_APB1ENR_I2C2EN, lp)
/**
* @brief Resets the I2C2 peripheral.
*
* @api
*/
#define rccResetI2C2() rccResetAPB1(RCC_APB1RSTR_I2C2RST)
/**
* @brief Enables the I2C3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableI2C3(lp) rccEnableAPB1(RCC_APB1ENR_I2C3EN, lp)
/**
* @brief Disables the I2C3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableI2C3(lp) rccDisableAPB1(RCC_APB1ENR_I2C3EN, lp)
/**
* @brief Resets the I2C3 peripheral.
*
* @api
*/
#define rccResetI2C3() rccResetAPB1(RCC_APB1RSTR_I2C3RST)
/** @} */
/**
* @brief SPI peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the SPI1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp)
/**
* @brief Disables the SPI1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableSPI1(lp) rccDisableAPB2(RCC_APB2ENR_SPI1EN, lp)
/**
* @brief Resets the SPI1 peripheral.
*
* @api
*/
#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST)
/**
* @brief Enables the SPI2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableSPI2(lp) rccEnableAPB1(RCC_APB1ENR_SPI2EN, lp)
/**
* @brief Disables the SPI2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableSPI2(lp) rccDisableAPB1(RCC_APB1ENR_SPI2EN, lp)
/**
* @brief Resets the SPI2 peripheral.
*
* @api
*/
#define rccResetSPI2() rccResetAPB1(RCC_APB1RSTR_SPI2RST)
/**
* @brief Enables the SPI3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableSPI3(lp) rccEnableAPB1(RCC_APB1ENR_SPI3EN, lp)
/**
* @brief Disables the SPI3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableSPI3(lp) rccDisableAPB1(RCC_APB1ENR_SPI3EN, lp)
/**
* @brief Resets the SPI3 peripheral.
*
* @api
*/
#define rccResetSPI3() rccResetAPB1(RCC_APB1RSTR_SPI3RST)
/** @} */
/**
* @brief TIM peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the TIM1 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp)
/**
* @brief Disables the TIM1 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableTIM1(lp) rccDisableAPB2(RCC_APB2ENR_TIM1EN, lp)
/**
* @brief Resets the TIM1 peripheral.
*
* @api
*/
#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST)
/**
* @brief Enables the TIM2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableTIM2(lp) rccEnableAPB1(RCC_APB1ENR_TIM2EN, lp)
/**
* @brief Disables the TIM2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableTIM2(lp) rccDisableAPB1(RCC_APB1ENR_TIM2EN, lp)
/**
* @brief Resets the TIM2 peripheral.
*
* @api
*/
#define rccResetTIM2() rccResetAPB1(RCC_APB1RSTR_TIM2RST)
/**
* @brief Enables the TIM3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableTIM3(lp) rccEnableAPB1(RCC_APB1ENR_TIM3EN, lp)
/**
* @brief Disables the TIM3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableTIM3(lp) rccDisableAPB1(RCC_APB1ENR_TIM3EN, lp)
/**
* @brief Resets the TIM3 peripheral.
*
* @api
*/
#define rccResetTIM3() rccResetAPB1(RCC_APB1RSTR_TIM3RST)
/**
* @brief Enables the TIM4 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableTIM4(lp) rccEnableAPB1(RCC_APB1ENR_TIM4EN, lp)
/**
* @brief Disables the TIM4 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableTIM4(lp) rccDisableAPB1(RCC_APB1ENR_TIM4EN, lp)
/**
* @brief Resets the TIM4 peripheral.
*
* @api
*/
#define rccResetTIM4() rccResetAPB1(RCC_APB1RSTR_TIM4RST)
/**
* @brief Enables the TIM5 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableTIM5(lp) rccEnableAPB1(RCC_APB1ENR_TIM5EN, lp)
/**
* @brief Disables the TIM5 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableTIM5(lp) rccDisableAPB1(RCC_APB1ENR_TIM5EN, lp)
/**
* @brief Resets the TIM5 peripheral.
*
* @api
*/
#define rccResetTIM5() rccResetAPB1(RCC_APB1RSTR_TIM5RST)
/**
* @brief Enables the TIM8 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp)
/**
* @brief Disables the TIM8 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableTIM8(lp) rccDisableAPB2(RCC_APB2ENR_TIM8EN, lp)
/**
* @brief Resets the TIM8 peripheral.
*
* @api
*/
#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST)
/** @} */
/**
* @brief USART/UART peripherals specific RCC operations
* @{
*/
/**
* @brief Enables the USART1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp)
/**
* @brief Disables the USART1 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableUSART1(lp) rccDisableAPB2(RCC_APB2ENR_USART1EN, lp)
/**
* @brief Resets the USART1 peripheral.
*
* @api
*/
#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST)
/**
* @brief Enables the USART2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableUSART2(lp) rccEnableAPB1(RCC_APB1ENR_USART2EN, lp)
/**
* @brief Disables the USART2 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableUSART2(lp) rccDisableAPB1(RCC_APB1ENR_USART2EN, lp)
/**
* @brief Resets the USART2 peripheral.
*
* @api
*/
#define rccResetUSART2() rccResetAPB1(RCC_APB1RSTR_USART2RST)
/**
* @brief Enables the USART3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableUSART3(lp) rccEnableAPB1(RCC_APB1ENR_USART3EN, lp)
/**
* @brief Disables the USART3 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableUSART3(lp) rccDisableAPB1(RCC_APB1ENR_USART3EN, lp)
/**
* @brief Resets the USART3 peripheral.
*
* @api
*/
#define rccResetUSART3() rccResetAPB1(RCC_APB1RSTR_USART3RST)
/**
* @brief Enables the USART6 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableUSART6(lp) rccEnableAPB2(RCC_APB2ENR_USART6EN, lp)
/**
* @brief Disables the USART6 peripheral clock.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableUSART6(lp) rccDisableAPB2(RCC_APB2ENR_USART6EN, lp)
/**
* @brief Enables the UART4 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableUART4(lp) rccEnableAPB1(RCC_APB1ENR_UART4EN, lp)
/**
* @brief Disables the UART4 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableUART4(lp) rccDisableAPB1(RCC_APB1ENR_UART4EN, lp)
/**
* @brief Resets the UART4 peripheral.
*
* @api
*/
#define rccResetUART4() rccResetAPB1(RCC_APB1RSTR_UART4RST)
/**
* @brief Enables the UART5 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccEnableUART5(lp) rccEnableAPB1(RCC_APB1ENR_UART5EN, lp)
/**
* @brief Disables the UART5 peripheral clock.
* @note The @p lp parameter is ignored in this family.
*
* @param[in] lp low power enable flag
*
* @api
*/
#define rccDisableUART5(lp) rccDisableAPB1(RCC_APB1ENR_UART5EN, lp)
/**
* @brief Resets the UART5 peripheral.
*
* @api
*/
#define rccResetUART5() rccResetAPB1(RCC_APB1RSTR_UART5RST)
/**
* @brief Resets the USART6 peripheral.
*
* @api
*/
#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST)
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* _STM32_RCC_ */
/** @} */

View File

@ -94,6 +94,11 @@ void stm32_clock_init(void) {
/* PWR clock enable.*/
RCC->APB1ENR = RCC_APB1ENR_PWREN;
/* PWR initialization.*/
PWR->CR = STM32_VOS;
while (PWR->CSR & PWR_CSR_VOSRDY)
; /* Waits until power regulator is stable. */
/* Initial clocks setup and wait for HSI stabilization, the MSI clock is
always enabled because it is the fallback clock when PLL the fails.*/
RCC->CR |= RCC_CR_HSION;

View File

@ -56,24 +56,24 @@
* @{
*/
/**
* @brief Maximum HSE clock frequency.
* @brief Maximum HSE clock frequency.
*/
#define STM32_HSECLK_MAX 26000000
/**
* @brief Minimum HSE clock frequency.
* @brief Minimum HSE clock frequency.
*/
#define STM32_HSECLK_MIN 1000000
/**
* @brief Maximum LSE clock frequency.
* @brief Maximum LSE clock frequency.
*/
#define STM32_LSECLK_MAX 1000000
/**
* @brief Minimum LSE clock frequency.
* @brief Minimum LSE clock frequency.
*/
#define STM32_LSECLK_MIN 1000
#define STM32_LSECLK_MIN 32768
/**
* @brief Maximum PLLs input clock frequency.
@ -126,7 +126,7 @@
* @{
*/
#define STM32_HSICLK 16000000 /**< High speed internal clock. */
#define STM32_LSICLK 38000 /**< Low speed internal clock. */
#define STM32_LSICLK 32000 /**< Low speed internal clock. */
/** @} */
/**
@ -204,9 +204,9 @@
#define STM32_MCO1SEL_HSE (2 << 21) /**< HSE clock on MCO1 pin. */
#define STM32_MCO1SEL_PLL (3 << 21) /**< PLL clock on MCO1 pin. */
#define STM32_I2CSRC_MASK (1 << 23) /**< I2CSRC mask. */
#define STM32_I2CSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */
#define STM32_I2CSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */
#define STM32_I2SSRC_MASK (1 << 23) /**< I2CSRC mask. */
#define STM32_I2SSRC_PLLI2S (0 << 23) /**< I2SSRC is PLLI2S. */
#define STM32_I2SSRC_CKIN (1 << 23) /**< I2S_CKIN is PLLI2S. */
#define STM32_MCO1PRE_MASK (7 << 24) /**< MCO1PRE mask. */
#define STM32_MCO1PRE_DIV1 (0 << 24) /**< MCO1 divided by 1. */
@ -732,7 +732,7 @@
* @brief I2S clock source.
*/
#if !defined(STM32_I2SSRC) || defined(__DOXYGEN__)
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#endif
/**
@ -836,7 +836,7 @@
#error "HSI not enabled, required by STM32_MCO2SEL"
#endif
#if (STM32_I2SSRC == STM32_I2CSRC_PLLI2S) && \
#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \
(STM32_PLLSRC == STM32_PLLSRC_HSI)
#error "HSI not enabled, required by STM32_I2SSRC"
#endif
@ -876,7 +876,7 @@
#error "HSE not enabled, required by STM32_MCO2SEL"
#endif
#if (STM32_I2SSRC == STM32_I2CSRC_PLLI2S) && \
#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) && \
(STM32_PLLSRC == STM32_PLLSRC_HSE)
#error "HSE not enabled, required by STM32_I2SSRC"
#endif
@ -1126,7 +1126,7 @@
/*
* PLLI2S enable check.
*/
#if (STM32_I2CSRC == STM32_I2CSRC_PLLI2S) || defined(__DOXYGEN__)
#if (STM32_I2SSRC == STM32_I2SSRC_PLLI2S) || defined(__DOXYGEN__)
/**
* @brief PLL activation flag.
*/

View File

@ -176,82 +176,34 @@
#include "nvic.h"
/* The following declarations are there just for Doxygen documentation, the
real declarations are inside the sub-headers.*/
#if defined(__DOXYGEN__)
/**
* @brief Stack and memory alignment enforcement.
* @note In this architecture the stack alignment is enforced to 64 bits,
* 32 bits alignment is supported by hardware but deprecated by ARM,
* the implementation choice is to not offer the option.
*/
#if defined(__DOXYGEN__)
/* Dummy declaration, for Doxygen only.*/
typedef uint64_t stkalign_t;
#else
typedef uint64_t stkalign_t __attribute__ ((aligned (8)));
#endif
#if defined(__DOXYGEN__)
/**
* @brief Interrupt saved context.
* @details This structure represents the stack frame saved during a
* preemption-capable interrupt handler.
* @note It is implemented to match the Cortex-Mx exception context.
*/
struct extctx {
/* Dummy definition, just for Doxygen.*/
};
struct extctx {};
/**
* @brief System saved context.
* @details This structure represents the inner stack frame during a context
* switching.
*/
struct intctx {
/* Dummy definition, just for Doxygen.*/
};
#endif
struct intctx {};
/**
* @brief Platform dependent part of the @p Thread structure.
* @details In this port the structure just holds a pointer to the @p intctx
* structure representing the stack pointer at context switch time.
*/
struct context {
struct intctx *r13;
};
/**
* @brief Platform dependent part of the @p chThdCreateI() API.
* @details This code usually setup the context switching frame represented
* by an @p intctx structure.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
wsize - \
sizeof(struct intctx)); \
tp->p_ctx.r13->r4 = pf; \
tp->p_ctx.r13->r5 = arg; \
tp->p_ctx.r13->lr = _port_thread_start; \
}
/**
* @brief Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
* @brief Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
sizeof(struct extctx) + \
(n) + (PORT_INT_REQUIRED_STACK))
/**
* @brief Static working area allocation.
* @details This macro is used to allocate a static thread working area
* aligned as both position and size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)]
#endif /* defined(__DOXYGEN__) */
#endif /* _FROM_ASM_ */

View File

@ -41,10 +41,61 @@
*/
#define CORTEX_PRIORITY_PENDSV 0
/*===========================================================================*/
/* Port macros. */
/*===========================================================================*/
/*===========================================================================*/
/* Port configurable parameters. */
/*===========================================================================*/
/**
* @brief Stack size for the system idle thread.
* @details This size depends on the idle thread implementation, usually
* the idle thread should take no more space than those reserved
* by @p PORT_INT_REQUIRED_STACK.
* @note In this port it is set to 16 because the idle thread does have
* a stack frame when compiling without optimizations. You may
* reduce this value to zero when compiling with optimizations.
*/
#if !defined(PORT_IDLE_THREAD_STACK_SIZE)
#define PORT_IDLE_THREAD_STACK_SIZE 16
#endif
/**
* @brief Per-thread stack overhead for interrupts servicing.
* @details This constant is used in the calculation of the correct working
* area size.
* This value can be zero on those architecture where there is a
* separate interrupt stack and the stack space between @p intctx and
* @p extctx is known to be zero.
* @note In this port it is conservatively set to 16 because the function
* @p chSchDoReschedule() can have a stack frame, expecially with
* compiler optimizations disabled.
*/
#if !defined(PORT_INT_REQUIRED_STACK)
#define PORT_INT_REQUIRED_STACK 16
#endif
/**
* @brief Enables the use of the WFI instruction in the idle thread loop.
*/
#if !defined(CORTEX_ENABLE_WFI_IDLE)
#define CORTEX_ENABLE_WFI_IDLE FALSE
#endif
/**
* @brief SYSTICK handler priority.
* @note The default SYSTICK handler priority is calculated as the priority
* level in the middle of the numeric priorities range.
*/
#if !defined(CORTEX_PRIORITY_SYSTICK)
#define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1)
#elif !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK)
/* If it is externally redefined then better perform a validity check on it.*/
#error "invalid priority level specified for CORTEX_PRIORITY_SYSTICK"
#endif
/**
* @brief Alternate preemption method.
* @details Activating this option will make the Kernel use the PendSV
@ -101,7 +152,12 @@
*/
typedef void *regarm_t;
/* The documentation of the following declarations is in chconf.h in order
to not have duplicated structure names into the documentation.*/
#if !defined(__DOXYGEN__)
typedef uint64_t stkalign_t __attribute__ ((aligned (8)));
struct extctx {
regarm_t r0;
regarm_t r1;
@ -124,7 +180,51 @@ struct intctx {
regarm_t r7;
regarm_t lr;
};
#endif
#endif /* !defined(__DOXYGEN__) */
/**
* @brief Platform dependent part of the @p Thread structure.
* @details In this port the structure just holds a pointer to the @p intctx
* structure representing the stack pointer at context switch time.
*/
struct context {
struct intctx *r13;
};
/**
* @brief Platform dependent part of the @p chThdCreateI() API.
* @details This code usually setup the context switching frame represented
* by an @p intctx structure.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
wsize - \
sizeof(struct intctx)); \
tp->p_ctx.r13->r4 = pf; \
tp->p_ctx.r13->r5 = arg; \
tp->p_ctx.r13->lr = _port_thread_start; \
}
/**
* @brief Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
* @brief Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
sizeof(struct extctx) + \
(n) + (PORT_INT_REQUIRED_STACK))
/**
* @brief Static working area allocation.
* @details This macro is used to allocate a static thread working area
* aligned as both position and size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)]
/**
* @brief IRQ prologue code.

View File

@ -38,10 +38,61 @@
*/
#define CORTEX_BASEPRI_DISABLED 0
/*===========================================================================*/
/* Port macros. */
/*===========================================================================*/
/*===========================================================================*/
/* Port configurable parameters. */
/*===========================================================================*/
/**
* @brief Stack size for the system idle thread.
* @details This size depends on the idle thread implementation, usually
* the idle thread should take no more space than those reserved
* by @p PORT_INT_REQUIRED_STACK.
* @note In this port it is set to 16 because the idle thread does have
* a stack frame when compiling without optimizations. You may
* reduce this value to zero when compiling with optimizations.
*/
#if !defined(PORT_IDLE_THREAD_STACK_SIZE)
#define PORT_IDLE_THREAD_STACK_SIZE 16
#endif
/**
* @brief Per-thread stack overhead for interrupts servicing.
* @details This constant is used in the calculation of the correct working
* area size.
* This value can be zero on those architecture where there is a
* separate interrupt stack and the stack space between @p intctx and
* @p extctx is known to be zero.
* @note In this port it is conservatively set to 16 because the function
* @p chSchDoReschedule() can have a stack frame, expecially with
* compiler optimizations disabled.
*/
#if !defined(PORT_INT_REQUIRED_STACK)
#define PORT_INT_REQUIRED_STACK 16
#endif
/**
* @brief Enables the use of the WFI instruction in the idle thread loop.
*/
#if !defined(CORTEX_ENABLE_WFI_IDLE)
#define CORTEX_ENABLE_WFI_IDLE FALSE
#endif
/**
* @brief SYSTICK handler priority.
* @note The default SYSTICK handler priority is calculated as the priority
* level in the middle of the numeric priorities range.
*/
#if !defined(CORTEX_PRIORITY_SYSTICK)
#define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1)
#elif !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK)
/* If it is externally redefined then better perform a validity check on it.*/
#error "invalid priority level specified for CORTEX_PRIORITY_SYSTICK"
#endif
/**
* @brief Simplified priority handling flag.
* @details Activating this option will make the Kernel work in compact mode.
@ -156,7 +207,12 @@
*/
typedef void *regarm_t;
/* The documentation of the following declarations is in chconf.h in order
to not have duplicated structure names into the documentation.*/
#if !defined(__DOXYGEN__)
typedef uint64_t stkalign_t __attribute__ ((aligned (8)));
struct extctx {
regarm_t r0;
regarm_t r1;
@ -166,7 +222,7 @@ struct extctx {
regarm_t lr_thd;
regarm_t pc;
regarm_t xpsr;
#if CORTEX_USE_FPU || defined(__DOXYGEN__)
#if CORTEX_USE_FPU
regarm_t s0;
regarm_t s1;
regarm_t s2;
@ -189,7 +245,7 @@ struct extctx {
};
struct intctx {
#if CORTEX_USE_FPU || defined(__DOXYGEN__)
#if CORTEX_USE_FPU
regarm_t s16;
regarm_t s17;
regarm_t s18;
@ -217,7 +273,51 @@ struct intctx {
regarm_t r11;
regarm_t lr;
};
#endif
#endif /* !defined(__DOXYGEN__) */
/**
* @brief Platform dependent part of the @p Thread structure.
* @details In this port the structure just holds a pointer to the @p intctx
* structure representing the stack pointer at context switch time.
*/
struct context {
struct intctx *r13;
};
/**
* @brief Platform dependent part of the @p chThdCreateI() API.
* @details This code usually setup the context switching frame represented
* by an @p intctx structure.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
wsize - \
sizeof(struct intctx)); \
tp->p_ctx.r13->r4 = pf; \
tp->p_ctx.r13->r5 = arg; \
tp->p_ctx.r13->lr = _port_thread_start; \
}
/**
* @brief Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
* @brief Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
sizeof(struct extctx) + \
(n) + (PORT_INT_REQUIRED_STACK))
/**
* @brief Static working area allocation.
* @details This macro is used to allocate a static thread working area
* aligned as both position and size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)]
/**
* @brief IRQ prologue code.

View File

@ -77,9 +77,12 @@
- FIX: Fixed PWM with TIM1 and TIM8 broken in STM32 HAL (bug 3458947).
- FIX: Fixed SYSCFG clock not started in STM32L1/F4 HALs (bug 3449139).
- FIX: Fixed wrong definitions in STM32L-Discovery board file (bug 3449076).
- NEW: Updated STM32F2xx support by inheriting the work done on the STM32F4xx,
the whole thing is untested because lack of hardware.
- NEW: Files nvic.c and nvic.h moved under ./os/ports/common/ARMCMx, removed
the duplicated instances under the GCC, IAR and Keil ports. Function names
prefixes changed from "NVIC" to "nvic" because style conventions.
- NEW: Added voltage regulator initialization to the STM32F4xx HAL.
- NEW: Modified the STM32F4-Discovery demo to put critical kernel data
structures and stacks in the CCM RAM instead normal RAM. It is done using
a special .ld file that can be customized to decide how to allocate data

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -59,7 +59,7 @@
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2CSRC_CKIN
#define STM32_I2SSRC STM32_I2SSRC_CKIN
#define STM32_PLLI2SN_VALUE 192
#define STM32_PLLI2SR_VALUE 5

View File

@ -6,33 +6,31 @@ X = In progress, some work done.
N = Decided against.
Current Pipeline (2.3.x):
* Improved Makefile system.
* USB driver enhancements.
* USB and USB_SERIAL APIs reclassification.
* Incorporate the USB bus attach/detach handling in usbStart()/usbStop().
* Fix zero size packets handling in USB_SERIAL driver.
? USB double buffering support for STM32 implementation.
X Evaluate using DMA channels for buffer copy.
X I2C device driver class support and at least one implementation.
X Evaluate a modified I2C API where the synchronous mode is default and the
callback mode optional.
- Software I2C implementation using a GPT instance for timings.
* STM32F2xx/STM32F4xx support (adapt and re-verify all drivers).
* New STM32 DMA helper driver abstracting differences between
STM32F2xx/STM32F4xx and other sub-families.
* Specific ADC driver for STM32F2xx/STM32F4xx.
- STM32F2xx support.
- MMC_SPI driver revision and speedup.
- FatFs 0.9x integration.
- FPU support in CM4 port.
- STM32F2xx support.
- Nios II support.
- LPC17xx support.
- NUC120 support.
- Static memory allocation hook macros in kernel code.
? Revision of scheduling strategy for threads at equal priority.
- MAC driver for STM32F107, STM32F2xx, STM32F4xx.
- Update C++ wrapper.
Within 2.x.x
- USB driver model revision.
? USB double buffering support for STM32 implementation.
X Evaluate using DMA channels for buffer copy.
X File System infrastructure.
X Implement the "transmission end" serial driver event on those platforms
supporting the feature, so far only done in STM32 driver.
- Revision of scheduling strategy for threads at equal priority.
- Add a chSysIntegrityCheck() API.
- Add a CH_THREAD macro for threads declaration in order to hide
compiler-specific optimizations for thread functions. All demos will have
to be updated.
@ -40,7 +38,6 @@ X Implement the "transmission end" serial driver event on those platforms
with different subsystems and not just the kernel.
- Reduce number of demos globally, add demos to a repository or on web site.
Required in order to reduce support effort.
- MAC driver for STM32F107.
- FatFs wrapper.
- New device driver models: Clock, Systick, RTC, WDG, DAC, Power Monitor.
- Add UART4 support to the STM32 UART driver (CL line only, HD has a nasty
@ -59,7 +56,6 @@ X Transactional flash file system implementation.
- Official segmented interrupts support and abstraction in CMx port.
- MAC driver revision in order to support copy-less operations, this will
require changes to lwIP or a new TCP/IP stack however.
- Update C++ wrapper (Heap, Pools, Mailboxes and any new feature).
- Threads Pools manager in the library.
- Dedicated TCP/IP stack.
? Evaluate if change thread functions to return void is worthwhile.
@ -78,4 +74,3 @@ Ideas for 3.x.x:
Side projects:
X ChibiOS Wizard, UML modeling and ChibiOS applications code and
documentation generator.
- Visual debugger/monitor interfaced through OpenOCD.