From 2ab27d3c01ce51a26587e6aaafcef23b2dda4afe Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 19 Nov 2009 19:03:18 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1315 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/io/adc.c | 21 ++++-- os/io/adc.h | 4 +- os/io/platforms/STM32/adc_lld.c | 122 +++++++++++++++++++++----------- os/io/platforms/STM32/adc_lld.h | 29 ++++++-- os/io/platforms/STM32/spi_lld.c | 28 +++++--- os/io/platforms/STM32/spi_lld.h | 22 ++++-- os/io/templates/adc_lld.c | 30 ++++---- os/io/templates/adc_lld.h | 22 ++++-- os/io/templates/spi_lld.c | 8 +++ readme.txt | 5 ++ 10 files changed, 199 insertions(+), 92 deletions(-) diff --git a/os/io/adc.c b/os/io/adc.c index ac003bc31..2fc64f561 100644 --- a/os/io/adc.c +++ b/os/io/adc.c @@ -42,9 +42,12 @@ void adcInit(void) { */ void adcObjectInit(ADCDriver *adcp) { - adcp->ad_state = ADC_STOP; - adcp->ad_config = NULL; + adcp->ad_state = ADC_STOP; + adcp->ad_config = NULL; adcp->ad_callback = NULL; + adcp->ad_samples = NULL; + adcp->ad_depth = 0; + adcp->ad_grpp = NULL; chSemInit(&adcp->ad_sem, 0); } @@ -119,7 +122,7 @@ void adcStop(ADCDriver *adcp) { */ bool_t adcStartConversion(ADCDriver *adcp, ADCConversionGroup *grpp, - void *samples, + adcsample_t *samples, size_t depth, adccallback_t callback) { @@ -137,7 +140,10 @@ bool_t adcStartConversion(ADCDriver *adcp, return TRUE; } adcp->ad_callback = callback; - adc_lld_start_conversion(adcp, grpp, samples, depth); + adcp->ad_samples = samples; + adcp->ad_depth = depth; + adcp->ad_grpp = grpp; + adc_lld_start_conversion(adcp); adcp->ad_state = ADC_RUNNING; chSysUnlock(); return FALSE; @@ -157,8 +163,11 @@ void adcStopConversion(ADCDriver *adcp) { (adcp->ad_state == ADC_RUNNING), "adcStopConversion(), #1", "invalid state"); - adc_lld_stop_conversion(adcp); - adcp->ad_state = ADC_READY; + if (adcp->ad_state == ADC_RUNNING) { + adc_lld_stop_conversion(adcp); + adcp->ad_grpp = NULL; + adcp->ad_state = ADC_READY; + } chSysUnlock(); } diff --git a/os/io/adc.h b/os/io/adc.h index 9fcaba508..9c505f66d 100644 --- a/os/io/adc.h +++ b/os/io/adc.h @@ -38,7 +38,7 @@ typedef enum { ADC_UNINIT = 0, /**< @brief Not initialized. */ ADC_STOP = 1, /**< @brief Stopped. */ ADC_READY = 2, /**< @brief Ready. */ - ADC_RUNNING = 3 /**< @brief Conversion complete.*/ + ADC_RUNNING = 3 /**< @brief Conversion running. */ } adcstate_t; #include "adc_lld.h" @@ -52,7 +52,7 @@ extern "C" { void adcStop(ADCDriver *adcp); bool_t adcStartConversion(ADCDriver *adcp, ADCConversionGroup *grpp, - void *samples, + adcsample_t *samples, size_t depth, adccallback_t callback); void adcStopConversion(ADCDriver *adcp); diff --git a/os/io/platforms/STM32/adc_lld.c b/os/io/platforms/STM32/adc_lld.c index 9a482c045..9cc123e36 100644 --- a/os/io/platforms/STM32/adc_lld.c +++ b/os/io/platforms/STM32/adc_lld.c @@ -29,11 +29,19 @@ #include #include +/*===========================================================================*/ +/* Low Level Driver exported variables. */ +/*===========================================================================*/ + #if USE_STM32_ADC1 || defined(__DOXYGEN__) /** @brief ADC1 driver identifier.*/ ADCDriver ADCD1; #endif +/*===========================================================================*/ +/* Low Level Driver local variables. */ +/*===========================================================================*/ + /*===========================================================================*/ /* Low Level Driver local functions. */ /*===========================================================================*/ @@ -47,13 +55,43 @@ ADCDriver ADCD1; * @brief ADC1 DMA interrupt handler (channel 1). */ CH_IRQ_HANDLER(Vector6C) { + uint32_t isr; CH_IRQ_PROLOGUE(); - if ((DMA1->ISR & DMA_ISR_TEIF1) != 0) + isr = DMA1->ISR; + if ((isr & DMA_ISR_HTIF1) != 0) { + /* Half transfer processing.*/ + if (ADCD1.ad_callback != NULL) { + /* Invokes the callback passing the 1st half of the buffer.*/ + ADCD1.ad_callback(ADCD1.ad_samples, ADCD1.ad_depth / 2); + } + } + if ((isr & DMA_ISR_TCIF1) != 0) { + /* Transfer complete processing.*/ + if (!ADCD1.ad_grpp->acg_circular) { + /* End conversion.*/ + adc_lld_stop_conversion(&ADCD1); + ADCD1.ad_grpp = NULL; + ADCD1.ad_state = ADC_READY; + chSemResetI(&ADCD1.ad_sem, 0); + } + /* Callback handling.*/ + if (ADCD1.ad_callback != NULL) { + if (ADCD1.ad_depth > 1) { + /* Invokes the callback passing the 2nd half of the buffer.*/ + size_t half = ADCD1.ad_depth / 2; + ADCD1.ad_callback(ADCD1.ad_samples + half, half); + } + else { + /* Invokes the callback passing the while buffer.*/ + ADCD1.ad_callback(ADCD1.ad_samples, ADCD1.ad_depth); + } + } + } + if ((isr & DMA_ISR_TEIF1) != 0) { + /* DMA error processing.*/ STM32_ADC1_DMA_ERROR_HOOK(); - else { - /* */ } DMA1->IFCR |= DMA_IFCR_CGIF1 | DMA_IFCR_CTCIF1 | DMA_IFCR_CHTIF1 | DMA_IFCR_CTEIF1; @@ -72,10 +110,28 @@ CH_IRQ_HANDLER(Vector6C) { void adc_lld_init(void) { #if USE_STM32_ADC1 + /* Driver initialization.*/ adcObjectInit(&ADCD1); ADCD1.ad_adc = ADC1; ADCD1.ad_dma = DMA1_Channel1; ADCD1.ad_dmaprio = STM32_ADC1_DMA_PRIORITY << 12; + + /* Temporary activation.*/ + ADC1->CR1 = 0; + ADC1->CR2 = ADC_CR2_ADON; + + /* Reset calibration just to be safe.*/ + ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL; + while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0) + ; + + /* Calibration.*/ + ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL; + while ((ADC1->CR2 & ADC_CR2_CAL) != 0) + ; + + /* Return the ADC in low power mode.*/ + ADC1->CR2 = 0; #endif } @@ -90,8 +146,8 @@ void adc_lld_start(ADCDriver *adcp) { if (adcp->ad_state == ADC_STOP) { #if USE_STM32_ADC1 if (&ADCD1 == adcp) { + dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/ NVICEnableVector(DMA1_Channel1_IRQn, STM32_ADC1_IRQ_PRIORITY); - dmaEnable(DMA1_ID); DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_ADCPRE) | adcp->ad_config->ac_prescaler;*/ @@ -99,19 +155,10 @@ void adc_lld_start(ADCDriver *adcp) { } #endif - /* ADC activation.*/ - adcp->ad_adc->CR1 = 0; + /* ADC activation, the calibration procedure has already been performed + during initialization.*/ + adcp->ad_adc->CR1 = ADC_CR1_SCAN; adcp->ad_adc->CR2 = ADC_CR2_ADON; - - /* Reset calibration just to be safe.*/ - adcp->ad_adc->CR2 |= ADC_CR2_RSTCAL; - while ((adcp->ad_adc->CR2 & ADC_CR2_RSTCAL) != 0) - ; - - /* Calibration.*/ - adcp->ad_adc->CR2 |= ADC_CR2_CAL; - while ((adcp->ad_adc->CR2 & ADC_CR2_CAL) != 0) - ; } } @@ -130,7 +177,6 @@ void adc_lld_stop(ADCDriver *adcp) { ADC1->CR2 = 0; NVICDisableVector(DMA1_Channel1_IRQn); dmaDisable(DMA1_ID); -/* RCC->CFGR &= ~RCC_CFGR_ADCPRE;*/ RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN; } #endif @@ -141,35 +187,27 @@ void adc_lld_stop(ADCDriver *adcp) { * @brief Starts an ADC conversion. * * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. */ -void adc_lld_start_conversion(ADCDriver *adcp, - ADCConversionGroup *grpp, - void *samples, - size_t depth) { +void adc_lld_start_conversion(ADCDriver *adcp) { + uint32_t ccr, n; + ADCConversionGroup *grpp = adcp->ad_grpp; /* DMA setup.*/ - adcp->ad_dma->CMAR = (uint32_t)samples; - if (depth > 1) { - adcp->ad_dma->CNDTR = (uint32_t)grpp->acg_num_channels * (uint32_t)depth; - adcp->ad_dma->CCR = adcp->ad_dmaprio | - DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0 | DMA_CCR1_MINC | - DMA_CCR1_TCIE | DMA_CCR1_TEIE | DMA_CCR1_HTIE; - } - else { - adcp->ad_dma->CNDTR = (uint32_t)grpp->acg_num_channels; - adcp->ad_dma->CCR = adcp->ad_dmaprio | - DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0 | DMA_CCR1_MINC | - DMA_CCR1_TCIE | DMA_CCR1_TEIE; + adcp->ad_dma->CMAR = (uint32_t)adcp->ad_samples; + ccr = adcp->ad_dmaprio | DMA_CCR1_EN | DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0 | + DMA_CCR1_MINC | DMA_CCR1_TCIE | DMA_CCR1_TEIE; + if (grpp->acg_circular) + ccr |= DMA_CCR1_CIRC; + if (adcp->ad_depth > 1) { + /* If the buffer depth is greater than one then the half transfer interrupt + interrupt is enabled in order to allows streaming processing.*/ + ccr |= DMA_CCR1_HTIE; + n = (uint32_t)grpp->acg_num_channels * (uint32_t)adcp->ad_depth; } + else + n = (uint32_t)grpp->acg_num_channels; + adcp->ad_dma->CNDTR = n; + adcp->ad_dma->CCR = ccr; /* ADC setup.*/ adcp->ad_adc->SMPR1 = grpp->acg_smpr1; diff --git a/os/io/platforms/STM32/adc_lld.h b/os/io/platforms/STM32/adc_lld.h index 7c3249741..8b16e1aa3 100644 --- a/os/io/platforms/STM32/adc_lld.h +++ b/os/io/platforms/STM32/adc_lld.h @@ -63,6 +63,8 @@ /** * @brief ADC1 DMA error hook. + * @note The default action for DMA errors is a system halt because DMA error + * can only happen because programming errors. */ #if !defined(STM32_ADC1_DMA_ERROR_HOOK) || defined(__DOXYGEN__) #define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt() @@ -99,6 +101,11 @@ typedef void (*adccallback_t)(adcsample_t *buffer, size_t n); * operation. */ typedef struct { + /** + * @brief Enables the circular buffer mode for the group. + */ + bool_t acg_circular; + /* End of the mandatory fields.*/ /** * @brief Number of the analog channels belonging to the conversion group. */ @@ -140,6 +147,7 @@ typedef struct { /** * @brief Driver configuration structure. + * @note It could be empty on some architectures. */ typedef struct { /* * <---------- @@ -164,13 +172,25 @@ typedef struct { */ const ADCConfig *ad_config; /** - * @brief Semaphore for completion synchronization. + * @brief Synchronization semaphore. */ Semaphore ad_sem; /** * @brief Current callback function or @p NULL. */ adccallback_t ad_callback; + /** + * @brief Current samples buffer pointer or @p NULL. + */ + adcsample_t *ad_samples; + /** + * @brief Current samples buffer depth or @p 0. + */ + size_t ad_depth; + /** + * @brief Current conversion group pointer or @p NULL. + */ + ADCConversionGroup *ad_grpp; /* End of the mandatory fields.*/ /** * @brief Pointer to the ADCx registers block. @@ -190,20 +210,19 @@ typedef struct { /* External declarations. */ /*===========================================================================*/ +/** @cond never*/ #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, - ADCConversionGroup *grpp, - void *samples, - size_t depth); + void adc_lld_start_conversion(ADCDriver *adcp); void adc_lld_stop_conversion(ADCDriver *adcp); #ifdef __cplusplus } #endif +/** @endcond*/ #endif /* _ADC_LLD_H_ */ diff --git a/os/io/platforms/STM32/spi_lld.c b/os/io/platforms/STM32/spi_lld.c index 598e0fd5b..769b797e8 100644 --- a/os/io/platforms/STM32/spi_lld.c +++ b/os/io/platforms/STM32/spi_lld.c @@ -34,11 +34,19 @@ SPIDriver SPID1; #endif +/*===========================================================================*/ +/* Low Level Driver exported variables. */ +/*===========================================================================*/ + #if USE_STM32_SPI2 || defined(__DOXYGEN__) /** @brief SPI2 driver identifier.*/ SPIDriver SPID2; #endif +/*===========================================================================*/ +/* Low Level Driver local variables. */ +/*===========================================================================*/ + static uint16_t dummyrx; static uint16_t dummytx; @@ -107,8 +115,9 @@ CH_IRQ_HANDLER(Vector70) { CH_IRQ_PROLOGUE(); spi_stop(&SPID1); - if ((DMA1->ISR & DMA_ISR_TEIF2) != 0) - chEvtBroadcastI(&SPID1.spd_dmaerror); + if ((DMA1->ISR & DMA_ISR_TEIF2) != 0) { + STM32_SPI1_DMA_ERROR_HOOK(); + } DMA1->IFCR |= DMA_IFCR_CGIF2 | DMA_IFCR_CTCIF2 | DMA_IFCR_CHTIF2 | DMA_IFCR_CTEIF2; @@ -122,7 +131,7 @@ CH_IRQ_HANDLER(Vector74) { CH_IRQ_PROLOGUE(); - chEvtBroadcastI(&SPID1.spd_dmaerror); + STM32_SPI1_DMA_ERROR_HOOK(); DMA1->IFCR |= DMA_IFCR_CGIF3 | DMA_IFCR_CTCIF3 | DMA_IFCR_CHTIF3 | DMA_IFCR_CTEIF3; @@ -139,8 +148,9 @@ CH_IRQ_HANDLER(Vector78) { CH_IRQ_PROLOGUE(); spi_stop(&SPID2); - if ((DMA1->ISR & DMA_ISR_TEIF4) != 0) - chEvtBroadcastI(&SPID2.spd_dmaerror); + if ((DMA1->ISR & DMA_ISR_TEIF4) != 0) { + STM32_SPI2_DMA_ERROR_HOOK(); + } DMA1->IFCR |= DMA_IFCR_CGIF4 | DMA_IFCR_CTCIF4 | DMA_IFCR_CHTIF4 | DMA_IFCR_CTEIF4; @@ -154,7 +164,7 @@ CH_IRQ_HANDLER(Vector7C) { CH_IRQ_PROLOGUE(); - chEvtBroadcastI(&SPID2.spd_dmaerror); + STM32_SPI2_DMA_ERROR_HOOK(); DMA1->IFCR |= DMA_IFCR_CGIF5 | DMA_IFCR_CTCIF5 | DMA_IFCR_CHTIF5 | DMA_IFCR_CTEIF5; @@ -180,7 +190,6 @@ void spi_lld_init(void) { SPID1.spd_dmarx = DMA1_Channel2; SPID1.spd_dmatx = DMA1_Channel3; SPID1.spd_dmaprio = STM32_SPI1_DMA_PRIORITY << 12; - chEvtInit(&SPID1.spd_dmaerror); GPIOA->CRL = (GPIOA->CRL & 0x000FFFFF) | 0xB4B00000; #endif @@ -191,7 +200,6 @@ void spi_lld_init(void) { SPID2.spd_dmarx = DMA1_Channel4; SPID2.spd_dmatx = DMA1_Channel5; SPID2.spd_dmaprio = STM32_SPI2_DMA_PRIORITY << 12; - chEvtInit(&SPID2.spd_dmaerror); GPIOB->CRH = (GPIOB->CRH & 0x000FFFFF) | 0xB4B00000; #endif } @@ -207,7 +215,7 @@ void spi_lld_start(SPIDriver *spip) { if (spip->spd_state == SPI_STOP) { #if USE_STM32_SPI1 if (&SPID1 == spip) { - dmaEnable(DMA1_ID); + dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/ NVICEnableVector(DMA1_Channel2_IRQn, STM32_SPI1_IRQ_PRIORITY); NVICEnableVector(DMA1_Channel3_IRQn, STM32_SPI1_IRQ_PRIORITY); RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; @@ -215,7 +223,7 @@ void spi_lld_start(SPIDriver *spip) { #endif #if USE_STM32_SPI2 if (&SPID2 == spip) { - dmaEnable(DMA1_ID); + dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/ NVICEnableVector(DMA1_Channel4_IRQn, STM32_SPI2_IRQ_PRIORITY); NVICEnableVector(DMA1_Channel5_IRQn, STM32_SPI2_IRQ_PRIORITY); RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; diff --git a/os/io/platforms/STM32/spi_lld.h b/os/io/platforms/STM32/spi_lld.h index 2918eaa6c..1cba01b42 100644 --- a/os/io/platforms/STM32/spi_lld.h +++ b/os/io/platforms/STM32/spi_lld.h @@ -93,6 +93,24 @@ #define STM32_SPI2_IRQ_PRIORITY 0x60 #endif +/** + * @brief SPI1 DMA error hook. + * @note The default action for DMA errors is a system halt because DMA error + * can only happen because programming errors. + */ +#if !defined(STM32_SPI1_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI1_DMA_ERROR_HOOK() chSysHalt() +#endif + +/** + * @brief SPI2 DMA error hook. + * @note The default action for DMA errors is a system halt because DMA error + * can only happen because programming errors. + */ +#if !defined(STM32_SPI2_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI2_DMA_ERROR_HOOK() chSysHalt() +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -158,10 +176,6 @@ typedef struct { * @brief DMA priority bit mask. */ uint32_t spd_dmaprio; - /** - * @brief DMA error event. - */ - EventSource spd_dmaerror; } SPIDriver; /*===========================================================================*/ diff --git a/os/io/templates/adc_lld.c b/os/io/templates/adc_lld.c index d45817778..31fd64691 100644 --- a/os/io/templates/adc_lld.c +++ b/os/io/templates/adc_lld.c @@ -27,6 +27,14 @@ #include #include +/*===========================================================================*/ +/* Low Level Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Low Level Driver local variables. */ +/*===========================================================================*/ + /*===========================================================================*/ /* Low Level Driver local functions. */ /*===========================================================================*/ @@ -49,7 +57,7 @@ void adc_lld_init(void) { /** * @brief Configures and activates the ADC peripheral. * - * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] adcp pointer to the @p ADCDriver object */ void adc_lld_start(ADCDriver *adcp) { @@ -62,7 +70,7 @@ void adc_lld_start(ADCDriver *adcp) { /** * @brief Deactivates the ADC peripheral. * - * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] adcp pointer to the @p ADCDriver object */ void adc_lld_stop(ADCDriver *adcp) { @@ -71,28 +79,16 @@ void adc_lld_stop(ADCDriver *adcp) { /** * @brief Starts an ADC conversion. * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @note The buffer is organized as a matrix of M*N elements where M is the - * channels number configured into the conversion group and N is the - * buffer depth. The samples are sequentially written into the buffer - * with no gaps. + * @param[in] adcp pointer to the @p ADCDriver object */ -void adc_lld_start_conversion(ADCDriver *adcp, - ADCConversionGroup *grpp, - void *samples, - size_t depth) { +void adc_lld_start_conversion(ADCDriver *adcp) { } /** * @brief Stops an ongoing conversion. * - * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] adcp pointer to the @p ADCDriver object */ void adc_lld_stop_conversion(ADCDriver *adcp) { diff --git a/os/io/templates/adc_lld.h b/os/io/templates/adc_lld.h index 23e06f89e..cb790aec7 100644 --- a/os/io/templates/adc_lld.h +++ b/os/io/templates/adc_lld.h @@ -70,6 +70,7 @@ typedef struct { /** * @brief Driver configuration structure. + * @note It could be empty on some architectures. */ typedef struct { @@ -88,13 +89,25 @@ typedef struct { */ const ADCConfig *ad_config; /** - * @brief Semaphore for completion synchronization. + * @brief Synchronization semaphore. */ - Semaphore ac_sem; + Semaphore ad_sem; /** * @brief Current callback function or @p NULL. */ adccallback_t ad_callback; + /** + * @brief Current samples buffer pointer or @p NULL. + */ + adcsample_t *ad_samples; + /** + * @brief Current samples buffer depth or @p 0. + */ + size_t ad_depth; + /** + * @brief Current conversion group pointer or @p NULL. + */ + ADCConversionGroup *ad_grpp; /* End of the mandatory fields.*/ } ADCDriver; @@ -108,10 +121,7 @@ extern "C" { void adc_lld_init(void); void adc_lld_start(ADCDriver *adcp); void adc_lld_stop(ADCDriver *adcp); - void adc_lld_start_conversion(ADCDriver *adcp, - ADCConversionGroup *grpp, - void *samples, - size_t depth); + void adc_lld_start_conversion(ADCDriver *adcp); void adc_lld_stop_conversion(ADCDriver *adcp); #ifdef __cplusplus } diff --git a/os/io/templates/spi_lld.c b/os/io/templates/spi_lld.c index 501352037..8e9a14b6a 100644 --- a/os/io/templates/spi_lld.c +++ b/os/io/templates/spi_lld.c @@ -27,6 +27,14 @@ #include #include +/*===========================================================================*/ +/* Low Level Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Low Level Driver local variables. */ +/*===========================================================================*/ + /*===========================================================================*/ /* Low Level Driver local functions. */ /*===========================================================================*/ diff --git a/readme.txt b/readme.txt index 2921ff6f2..9342e152f 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,13 @@ ***************************************************************************** *** 1.3.5 *** +- NEW: STM32 ADC driver implementation with DMA support. +- CHANGE: In the STM32 drivers now the DMA errors are handled by hook macros + rather than by events. The default action is to halt the system but users + are able to override this and define custom handling. - CHANGE: In the Cortex-M3 port, modified the NVICEnableVector() function to make it clear pending interrupts. +- CHANGE: Minor changes to the ADC driver model. *** 1.3.4 *** - FIX: Fixed bug in STM32 PAL port driver (bug 2897636).