git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3381 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
40c7a8982a
commit
4a3e3fc01e
|
@ -34,8 +34,9 @@
|
|||
* @if LATEX_PDF
|
||||
* @dot
|
||||
digraph example {
|
||||
size="5, 7";
|
||||
rankdir="LR";
|
||||
size="5, 7";
|
||||
|
||||
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
|
||||
edge [fontname=Helvetica, fontsize=8];
|
||||
|
||||
|
@ -43,6 +44,7 @@
|
|||
uninit [label="ADC_UNINIT", style="bold"];
|
||||
ready [label="ADC_READY\nClock Enabled"];
|
||||
active [label="ADC_ACTIVE\nConverting"];
|
||||
error [label="ADC_ERROR\nError"];
|
||||
complete [label="ADC_COMPLETE\nComplete"];
|
||||
|
||||
uninit -> stop [label="\n adcInit()", constraint=false];
|
||||
|
@ -53,15 +55,19 @@
|
|||
ready -> active [label="\nadcStartConversion() (async)\nadcConvert() (sync)"];
|
||||
active -> ready [label="\nadcStopConversion()\nsync return"];
|
||||
active -> active [label="\nasync callback (half buffer)\nasync callback (full buffer circular)\n>acg_endcb<"];
|
||||
active -> complete [label="\nasync callback (full buffer)\n>acg_endcb<"];
|
||||
active -> complete [label="\n\nasync callback (full buffer)\n>end_cb<"];
|
||||
active -> error [label="\n\nasync callback (error)\n>error_cb<"];
|
||||
complete -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
|
||||
complete -> ready [label="\ncallback return"];
|
||||
error -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
|
||||
error -> ready [label="\ncallback return"];
|
||||
}
|
||||
* @enddot
|
||||
* @else
|
||||
* @dot
|
||||
digraph example {
|
||||
rankdir="LR";
|
||||
|
||||
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
|
||||
edge [fontname=Helvetica, fontsize=8];
|
||||
|
||||
|
@ -69,6 +75,7 @@
|
|||
uninit [label="ADC_UNINIT", style="bold"];
|
||||
ready [label="ADC_READY\nClock Enabled"];
|
||||
active [label="ADC_ACTIVE\nConverting"];
|
||||
error [label="ADC_ERROR\nError"];
|
||||
complete [label="ADC_COMPLETE\nComplete"];
|
||||
|
||||
uninit -> stop [label="\n adcInit()", constraint=false];
|
||||
|
@ -79,9 +86,12 @@
|
|||
ready -> active [label="\nadcStartConversion() (async)\nadcConvert() (sync)"];
|
||||
active -> ready [label="\nadcStopConversion()\nsync return"];
|
||||
active -> active [label="\nasync callback (half buffer)\nasync callback (full buffer circular)\n>acg_endcb<"];
|
||||
active -> complete [label="\nasync callback (full buffer)\n>acg_endcb<"];
|
||||
active -> complete [label="\n\nasync callback (full buffer)\n>end_cb<"];
|
||||
active -> error [label="\n\nasync callback (error)\n>error_cb<"];
|
||||
complete -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
|
||||
complete -> ready [label="\ncallback return"];
|
||||
error -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
|
||||
error -> ready [label="\ncallback return"];
|
||||
}
|
||||
* @enddot
|
||||
* @endif
|
||||
|
|
|
@ -80,7 +80,8 @@ typedef enum {
|
|||
ADC_STOP = 1, /**< Stopped. */
|
||||
ADC_READY = 2, /**< Ready. */
|
||||
ADC_ACTIVE = 3, /**< Converting. */
|
||||
ADC_COMPLETE = 4 /**< Conversion complete. */
|
||||
ADC_COMPLETE = 4, /**< Conversion complete. */
|
||||
ADC_ERROR = 5 /**< Conversion complete. */
|
||||
} adcstate_t;
|
||||
|
||||
#include "adc_lld.h"
|
||||
|
@ -144,10 +145,30 @@ typedef enum {
|
|||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wakes up the waiting thread with a timeout message.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _adc_timeout_isr(adcp) { \
|
||||
if ((adcp)->thread != NULL) { \
|
||||
Thread *tp; \
|
||||
chSysLockFromIsr(); \
|
||||
tp = (adcp)->thread; \
|
||||
(adcp)->thread = NULL; \
|
||||
tp->p_u.rdymsg = RDY_TIMEOUT; \
|
||||
chSchReadyI(tp); \
|
||||
chSysUnlockFromIsr(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else /* !ADC_USE_WAIT */
|
||||
#define _adc_reset_i(adcp)
|
||||
#define _adc_reset_s(adcp)
|
||||
#define _adc_wakeup_isr(adcp)
|
||||
#define _adc_timeout_isr(adcp)
|
||||
#endif /* !ADC_USE_WAIT */
|
||||
|
||||
/**
|
||||
|
@ -220,6 +241,32 @@ typedef enum {
|
|||
_adc_wakeup_isr(adcp); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common ISR code, error event.
|
||||
* @details This code handles the portable part of the ISR code:
|
||||
* - Callback invocation.
|
||||
* - Waiting thread timeout signaling, if any.
|
||||
* - Driver state transitions.
|
||||
* .
|
||||
* @note This macro is meant to be used in the low level drivers
|
||||
* implementation only.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _adc_isr_error_code(adcp, err) { \
|
||||
adc_lld_stop_conversion(adcp); \
|
||||
if ((adcp)->grpp->error_cb != NULL) { \
|
||||
(adcp)->state = ADC_ERROR; \
|
||||
(adcp)->grpp->error_cb(adcp, err); \
|
||||
if ((adcp)->state == ADC_ERROR) \
|
||||
(adcp)->state = ADC_READY; \
|
||||
} \
|
||||
(adcp)->grpp = NULL; \
|
||||
_adc_timeout_isr(adcp); \
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -57,20 +57,20 @@ ADCDriver ADCD1;
|
|||
static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
|
||||
|
||||
/* DMA errors handling.*/
|
||||
#if defined(STM32_ADC_DMA_ERROR_HOOK)
|
||||
if ((flags & STM32_DMA_ISR_TEIF) != 0) {
|
||||
STM32_ADC_DMA_ERROR_HOOK(spip);
|
||||
/* 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
|
||||
(void)flags;
|
||||
#endif
|
||||
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);
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ void adc_lld_start(ADCDriver *adcp) {
|
|||
|
||||
/* ADC setup, the calibration procedure has already been performed
|
||||
during initialization.*/
|
||||
adcp->adc->CR1 = ADC_CR1_SCAN;
|
||||
adcp->adc->CR1 = 0;
|
||||
adcp->adc->CR2 = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,15 +108,6 @@
|
|||
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC 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_ADC_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
|
||||
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
@ -147,6 +138,15 @@ typedef uint16_t adcsample_t;
|
|||
*/
|
||||
typedef uint16_t adc_channels_num_t;
|
||||
|
||||
/**
|
||||
* @brief Possible ADC failure causes.
|
||||
* @note Error codes are architecture dependent and should not relied
|
||||
* upon.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_ERR_DMAFAILURE = 0 /**< DMA operations failure. */
|
||||
} adcerror_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an ADC driver.
|
||||
*/
|
||||
|
@ -162,6 +162,14 @@ typedef struct ADCDriver ADCDriver;
|
|||
*/
|
||||
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
|
||||
|
@ -183,6 +191,10 @@ typedef struct {
|
|||
* @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.
|
||||
|
|
|
@ -57,20 +57,20 @@ ADCDriver ADCD1;
|
|||
static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
|
||||
|
||||
/* DMA errors handling.*/
|
||||
#if defined(STM32_ADC_DMA_ERROR_HOOK)
|
||||
if ((flags & STM32_DMA_ISR_TEIF) != 0) {
|
||||
STM32_ADC_DMA_ERROR_HOOK(spip);
|
||||
/* 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
|
||||
(void)flags;
|
||||
#endif
|
||||
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);
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,29 @@ static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
|
|||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief ADC1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(UART5_IRQHandler) {
|
||||
uint32_t sr;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
sr = ADC1->SR;
|
||||
ADC1->SR = 0;
|
||||
if (sr & ADC_SR_OVR) {
|
||||
/* ADC overflow condition, this could happen only if the DMA is unable
|
||||
to read data fast enough.*/
|
||||
_adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW);
|
||||
}
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
@ -145,6 +168,7 @@ void adc_lld_stop(ADCDriver *adcp) {
|
|||
if (adcp->state == ADC_READY) {
|
||||
#if STM32_ADC_USE_ADC1
|
||||
if (&ADCD1 == adcp) {
|
||||
ADC1->CR1 = 0;
|
||||
ADC1->CR2 = 0;
|
||||
dmaStreamRelease(adcp->dmastp);
|
||||
rccDisableADC1(FALSE);
|
||||
|
@ -182,7 +206,7 @@ void adc_lld_start_conversion(ADCDriver *adcp) {
|
|||
|
||||
/* ADC setup.*/
|
||||
adcp->adc->SR = 0;
|
||||
adcp->adc->CR1 = grpp->cr1 | ADC_CR1_SCAN;
|
||||
adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN;
|
||||
adcp->adc->SMPR1 = grpp->smpr1; /* Writing SMPRx requires ADON=0. */
|
||||
adcp->adc->SMPR2 = grpp->smpr2;
|
||||
adcp->adc->SMPR3 = grpp->smpr3;
|
||||
|
@ -211,6 +235,7 @@ void adc_lld_start_conversion(ADCDriver *adcp) {
|
|||
void adc_lld_stop_conversion(ADCDriver *adcp) {
|
||||
|
||||
dmaStreamDisable(adcp->dmastp);
|
||||
adcp->adc->CR1 = 0;
|
||||
adcp->adc->CR2 = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,8 +39,7 @@
|
|||
* @name Triggers selection
|
||||
* @{
|
||||
*/
|
||||
#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @brief Trigger source. */
|
||||
#define ADC_CR2_EXTSEL_SWSTART (7 << 17) /**< @brief Software trigger. */
|
||||
#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -136,15 +135,6 @@
|
|||
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC 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_ADC_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
|
||||
#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt()
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
@ -175,6 +165,16 @@ typedef uint16_t adcsample_t;
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -190,6 +190,14 @@ typedef struct ADCDriver ADCDriver;
|
|||
*/
|
||||
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
|
||||
|
@ -211,6 +219,10 @@ typedef struct {
|
|||
* @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.
|
||||
|
|
|
@ -162,6 +162,8 @@ void adcStartConversion(ADCDriver *adcp,
|
|||
/**
|
||||
* @brief Starts an ADC conversion.
|
||||
* @details Starts an asynchronous conversion operation.
|
||||
* @post The callbacks associated to the conversion group will be invoked
|
||||
* on buffer fill and error events.
|
||||
* @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
|
||||
|
@ -185,7 +187,8 @@ void adcStartConversionI(ADCDriver *adcp,
|
|||
((depth == 1) || ((depth & 1) == 0)),
|
||||
"adcStartConversionI");
|
||||
chDbgAssert((adcp->state == ADC_READY) ||
|
||||
(adcp->state == ADC_COMPLETE),
|
||||
(adcp->state == ADC_COMPLETE) ||
|
||||
(adcp->state == ADC_ERROR),
|
||||
"adcStartConversionI(), #1", "not ready");
|
||||
|
||||
adcp->samples = samples;
|
||||
|
@ -268,6 +271,8 @@ void adcStopConversionI(ADCDriver *adcp) {
|
|||
* @retval RDY_RESET The conversion has been stopped using
|
||||
* @p acdStopConversion() or @p acdStopConversionI(),
|
||||
* the result buffer may contain incorrect data.
|
||||
* @retval RDY_TIMEOUT The conversion has been stopped because an hardware
|
||||
* error.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
|
|
@ -95,7 +95,12 @@
|
|||
(backported to 2.2.4).
|
||||
- FIX: Fixed timeout problem in the lwIP interface layer (bug 3302420)
|
||||
(backported to 2.2.4).
|
||||
- NEW: STM32L1xx sub-family support, all STM32 drivers adapted and retested
|
||||
- NEW: STM32L ADC driver implementation.
|
||||
(TODO: To be tested.)
|
||||
- NEW: Improved ADC driver model, now it is possible to handle error
|
||||
conditions during the conversion process.
|
||||
(TODO: Modify existing STM32 ADC implementation).
|
||||
- NEW: STM32L1xx sub-family support, all STM32 drivers adapted and re-tested
|
||||
on the new platform except ADC that will need a specific implementation.
|
||||
- NEW: Added new API chThdExitS() in order to allow atomic operations on
|
||||
thead exit (backported to 2.2.8).
|
||||
|
|
|
@ -41,6 +41,12 @@ static void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
|
|||
}
|
||||
}
|
||||
|
||||
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) {
|
||||
|
||||
(void)adcp;
|
||||
(void)err;
|
||||
}
|
||||
|
||||
/*
|
||||
* ADC conversion group.
|
||||
* Mode: Streaming, continuous, 16 samples of 8 channels, SW triggered.
|
||||
|
@ -50,6 +56,7 @@ static const ADCConversionGroup adcgrpcfg = {
|
|||
TRUE,
|
||||
ADC_GRP1_NUM_CHANNELS,
|
||||
adccallback,
|
||||
adcerrorcallback,
|
||||
0,
|
||||
ADC_CR2_TSVREFE,
|
||||
0,
|
||||
|
|
|
@ -41,6 +41,12 @@ static void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
|
|||
}
|
||||
}
|
||||
|
||||
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) {
|
||||
|
||||
(void)adcp;
|
||||
(void)err;
|
||||
}
|
||||
|
||||
/*
|
||||
* ADC conversion group.
|
||||
* Mode: Streaming, continuous, 16 samples of 8 channels, SW triggered.
|
||||
|
@ -50,6 +56,7 @@ static const ADCConversionGroup adcgrpcfg = {
|
|||
TRUE,
|
||||
ADC_GRP1_NUM_CHANNELS,
|
||||
adccallback,
|
||||
adcerrorcallback,
|
||||
0, 0, /* CR1, CR2 */
|
||||
0, 0, 0, /* SMPR1...SMPR3 */
|
||||
ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS),
|
||||
|
|
Loading…
Reference in New Issue