Improved DAC driver, updated STM32 DACv1.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16315 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
f77d00b0c9
commit
665b0d48b4
|
@ -1,379 +1,385 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hal_dac.h
|
||||
* @brief DAC Driver macros and structures.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HAL_DAC_H
|
||||
#define HAL_DAC_H
|
||||
|
||||
#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name DAC configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define DAC_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define DAC_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Driver state machine possible states.
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_UNINIT = 0, /**< Not initialized. */
|
||||
DAC_STOP = 1, /**< Stopped. */
|
||||
DAC_READY = 2, /**< Ready. */
|
||||
DAC_ACTIVE = 3, /**< Exchanging data. */
|
||||
DAC_COMPLETE = 4, /**< Asynchronous operation complete. */
|
||||
DAC_ERROR = 5 /**< Error. */
|
||||
} dacstate_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver.
|
||||
*/
|
||||
typedef struct hal_dac_driver DACDriver;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver configuration.
|
||||
*/
|
||||
typedef struct hal_dac_config DACConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of a DAC conversion group.
|
||||
*/
|
||||
typedef struct hal_dac_conversion_group DACConversionGroup;
|
||||
|
||||
/* Including the low level driver header, it exports information required
|
||||
for completing types.*/
|
||||
#include "hal_dac_lld.h"
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
*/
|
||||
typedef void (*daccallback_t)(DACDriver *dacp);
|
||||
|
||||
/**
|
||||
* @brief DAC error callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
* @param[in] err DAC error code
|
||||
*/
|
||||
typedef void (*dacerrorcallback_t)(DACDriver *dacp, dacerror_t err);
|
||||
|
||||
/**
|
||||
* @brief DAC Conversion group structure.
|
||||
*/
|
||||
struct hal_dac_conversion_group {
|
||||
/**
|
||||
* @brief Number of DAC channels.
|
||||
*/
|
||||
uint32_t num_channels;
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
daccallback_t end_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
dacerrorcallback_t error_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
dac_lld_conversion_group_fields;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
struct hal_dac_config {
|
||||
/* End of the mandatory fields.*/
|
||||
dac_lld_config_fields;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing a DAC driver.
|
||||
*/
|
||||
struct hal_dac_driver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
dacstate_t state;
|
||||
/**
|
||||
* @brief Conversion group.
|
||||
*/
|
||||
const DACConversionGroup *grpp;
|
||||
/**
|
||||
* @brief Samples buffer pointer.
|
||||
*/
|
||||
dacsample_t *samples;
|
||||
/**
|
||||
* @brief Samples buffer size.
|
||||
*/
|
||||
size_t depth;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const DACConfig *config;
|
||||
#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
thread_reference_t thread;
|
||||
#endif /* DAC_USE_WAIT */
|
||||
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
mutex_t mutex;
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(DAC_DRIVER_EXT_FIELDS)
|
||||
DAC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
dac_lld_driver_fields;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Low level driver helper macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Buffer state.
|
||||
* @note This function is meant to be called from the DAC callback only.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @return The buffer state.
|
||||
* @retval false if the driver filled/sent the first half of the
|
||||
* buffer.
|
||||
* @retval true if the driver filled/sent the second half of the
|
||||
* buffer.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dacIsBufferComplete(dacp) ((bool)((dacp)->state == DAC_COMPLETE))
|
||||
|
||||
#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waits for operation completion.
|
||||
* @details This function waits for the driver to complete the current
|
||||
* operation.
|
||||
* @pre An operation must be running while the function is invoked.
|
||||
* @note No more than one thread can wait on a DAC driver using
|
||||
* this function.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_wait_s(dacp) osalThreadSuspendS(&(dacp)->thread)
|
||||
|
||||
/**
|
||||
* @brief Resumes a thread waiting for a conversion completion.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_reset_i(dacp) osalThreadResumeI(&(dacp)->thread, MSG_RESET)
|
||||
|
||||
/**
|
||||
* @brief Resumes a thread waiting for a conversion completion.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_reset_s(dacp) osalThreadResumeS(&(dacp)->thread, MSG_RESET)
|
||||
|
||||
/**
|
||||
* @brief Wakes up the waiting thread.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_wakeup_isr(dacp) { \
|
||||
osalSysLockFromISR(); \
|
||||
osalThreadResumeI(&(dacp)->thread, MSG_OK); \
|
||||
osalSysUnlockFromISR(); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wakes up the waiting thread with a timeout message.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_timeout_isr(dacp) { \
|
||||
osalSysLockFromISR(); \
|
||||
osalThreadResumeI(&(dacp)->thread, MSG_TIMEOUT); \
|
||||
osalSysUnlockFromISR(); \
|
||||
}
|
||||
|
||||
#else /* !DAC_USE_WAIT */
|
||||
#define _dac_wait_s(dacp)
|
||||
#define _dac_reset_i(dacp)
|
||||
#define _dac_reset_s(dacp)
|
||||
#define _dac_wakeup_isr(dacp)
|
||||
#define _dac_timeout_isr(dacp)
|
||||
#endif /* !DAC_USE_WAIT */
|
||||
|
||||
/**
|
||||
* @brief Common ISR code, half buffer event.
|
||||
* @details This code handles the portable part of the ISR code:
|
||||
* - Callback invocation.
|
||||
* .
|
||||
* @note This macro is meant to be used in the low level drivers
|
||||
* implementation only.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_isr_half_code(dacp) { \
|
||||
if ((dacp)->grpp->end_cb != NULL) { \
|
||||
(dacp)->grpp->end_cb(dacp); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common ISR code, full buffer event.
|
||||
* @details This code handles the portable part of the ISR code:
|
||||
* - Callback invocation.
|
||||
* - Driver state transitions.
|
||||
* .
|
||||
* @note This macro is meant to be used in the low level drivers
|
||||
* implementation only.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_isr_full_code(dacp) { \
|
||||
if ((dacp)->grpp->end_cb) { \
|
||||
(dacp)->state = DAC_COMPLETE; \
|
||||
(dacp)->grpp->end_cb(dacp); \
|
||||
if ((dacp)->state == DAC_COMPLETE) \
|
||||
(dacp)->state = DAC_ACTIVE; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @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] dacp pointer to the @p DACDriver object
|
||||
* @param[in] err platform dependent error code
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_isr_error_code(dacp, err) { \
|
||||
dac_lld_stop_conversion(dacp); \
|
||||
if ((dacp)->grpp->error_cb != NULL) { \
|
||||
(dacp)->state = DAC_ERROR; \
|
||||
(dacp)->grpp->error_cb(dacp, err); \
|
||||
if ((dacp)->state == DAC_ERROR) \
|
||||
(dacp)->state = DAC_READY; \
|
||||
} \
|
||||
(dacp)->grpp = NULL; \
|
||||
_dac_timeout_isr(dacp); \
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dacInit(void);
|
||||
void dacObjectInit(DACDriver *dacp);
|
||||
msg_t dacStart(DACDriver *dacp, const DACConfig *config);
|
||||
void dacStop(DACDriver *dacp);
|
||||
void dacPutChannelX(DACDriver *dacp,
|
||||
dacchannel_t channel,
|
||||
dacsample_t sample);
|
||||
void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp,
|
||||
dacsample_t *samples, size_t depth);
|
||||
void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp,
|
||||
dacsample_t *samples, size_t depth);
|
||||
void dacStopConversion(DACDriver *dacp);
|
||||
void dacStopConversionI(DACDriver *dacp);
|
||||
#if DAC_USE_WAIT
|
||||
msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp,
|
||||
dacsample_t *samples, size_t depth);
|
||||
#endif
|
||||
#if DAC_USE_MUTUAL_EXCLUSION
|
||||
void dacAcquireBus(DACDriver *dacp);
|
||||
void dacReleaseBus(DACDriver *dacp);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_DAC == TRUE */
|
||||
|
||||
#endif /* HAL_DAC_H */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hal_dac.h
|
||||
* @brief DAC Driver macros and structures.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HAL_DAC_H
|
||||
#define HAL_DAC_H
|
||||
|
||||
#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name DAC configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Support for thread synchronization API.
|
||||
*/
|
||||
#if !defined(DAC_USE_SYNCHRONIZATION) || defined(__DOXYGEN__)
|
||||
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define DAC_USE_SYNCHRONIZATION FALSE
|
||||
#else
|
||||
#define DAC_USE_SYNCHRONIZATION DAC_USE_WAIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define DAC_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Driver state machine possible states.
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_UNINIT = 0, /**< Not initialized. */
|
||||
DAC_STOP = 1, /**< Stopped. */
|
||||
DAC_READY = 2, /**< Ready. */
|
||||
DAC_ACTIVE = 3, /**< Exchanging data. */
|
||||
DAC_COMPLETE = 4, /**< Asynchronous operation complete. */
|
||||
DAC_ERROR = 5 /**< Error. */
|
||||
} dacstate_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver.
|
||||
*/
|
||||
typedef struct hal_dac_driver DACDriver;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver configuration.
|
||||
*/
|
||||
typedef struct hal_dac_config DACConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of a DAC conversion group.
|
||||
*/
|
||||
typedef struct hal_dac_conversion_group DACConversionGroup;
|
||||
|
||||
/* Including the low level driver header, it exports information required
|
||||
for completing types.*/
|
||||
#include "hal_dac_lld.h"
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
*/
|
||||
typedef void (*daccallback_t)(DACDriver *dacp);
|
||||
|
||||
/**
|
||||
* @brief DAC error callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
* @param[in] err DAC error code
|
||||
*/
|
||||
typedef void (*dacerrorcallback_t)(DACDriver *dacp, dacerror_t err);
|
||||
|
||||
/**
|
||||
* @brief DAC Conversion group structure.
|
||||
*/
|
||||
struct hal_dac_conversion_group {
|
||||
/**
|
||||
* @brief Number of DAC channels.
|
||||
*/
|
||||
uint32_t num_channels;
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
daccallback_t end_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
dacerrorcallback_t error_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
dac_lld_conversion_group_fields;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
struct hal_dac_config {
|
||||
/* End of the mandatory fields.*/
|
||||
dac_lld_config_fields;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing a DAC driver.
|
||||
*/
|
||||
struct hal_dac_driver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
dacstate_t state;
|
||||
/**
|
||||
* @brief Conversion group.
|
||||
*/
|
||||
const DACConversionGroup *grpp;
|
||||
/**
|
||||
* @brief Samples buffer pointer.
|
||||
*/
|
||||
dacsample_t *samples;
|
||||
/**
|
||||
* @brief Samples buffer size.
|
||||
*/
|
||||
size_t depth;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const DACConfig *config;
|
||||
#if (DAC_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
thread_reference_t thread;
|
||||
#endif /* DAC_USE_SYNCHRONIZATION */
|
||||
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
mutex_t mutex;
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(DAC_DRIVER_EXT_FIELDS)
|
||||
DAC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
dac_lld_driver_fields;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Low level driver helper macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Buffer state.
|
||||
* @note This function is meant to be called from the DAC callback only.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @return The buffer state.
|
||||
* @retval false if the driver filled/sent the first half of the
|
||||
* buffer.
|
||||
* @retval true if the driver filled/sent the second half of the
|
||||
* buffer.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dacIsBufferComplete(dacp) ((bool)((dacp)->state == DAC_COMPLETE))
|
||||
|
||||
#if (DAC_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waits for operation completion.
|
||||
* @details This function waits for the driver to complete the current
|
||||
* operation.
|
||||
* @pre An operation must be running while the function is invoked.
|
||||
* @note No more than one thread can wait on a DAC driver using
|
||||
* this function.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_wait_s(dacp) osalThreadSuspendS(&(dacp)->thread)
|
||||
|
||||
/**
|
||||
* @brief Resumes a thread waiting for a conversion completion.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_reset_i(dacp) osalThreadResumeI(&(dacp)->thread, MSG_RESET)
|
||||
|
||||
/**
|
||||
* @brief Resumes a thread waiting for a conversion completion.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_reset_s(dacp) osalThreadResumeS(&(dacp)->thread, MSG_RESET)
|
||||
|
||||
/**
|
||||
* @brief Wakes up the waiting thread.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_wakeup_isr(dacp) { \
|
||||
osalSysLockFromISR(); \
|
||||
osalThreadResumeI(&(dacp)->thread, MSG_OK); \
|
||||
osalSysUnlockFromISR(); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wakes up the waiting thread with a timeout message.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_timeout_isr(dacp) { \
|
||||
osalSysLockFromISR(); \
|
||||
osalThreadResumeI(&(dacp)->thread, MSG_TIMEOUT); \
|
||||
osalSysUnlockFromISR(); \
|
||||
}
|
||||
|
||||
#else /* !DAC_USE_SYNCHRONIZATION */
|
||||
#define _dac_wait_s(dacp)
|
||||
#define _dac_reset_i(dacp)
|
||||
#define _dac_reset_s(dacp)
|
||||
#define _dac_wakeup_isr(dacp)
|
||||
#define _dac_timeout_isr(dacp)
|
||||
#endif /* !DAC_USE_SYNCHRONIZATION */
|
||||
|
||||
/**
|
||||
* @brief Common ISR code, half buffer event.
|
||||
* @details This code handles the portable part of the ISR code:
|
||||
* - Callback invocation.
|
||||
* .
|
||||
* @note This macro is meant to be used in the low level drivers
|
||||
* implementation only.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_isr_half_code(dacp) { \
|
||||
if ((dacp)->grpp->end_cb != NULL) { \
|
||||
(dacp)->grpp->end_cb(dacp); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common ISR code, full buffer event.
|
||||
* @details This code handles the portable part of the ISR code:
|
||||
* - Callback invocation.
|
||||
* - Driver state transitions.
|
||||
* .
|
||||
* @note This macro is meant to be used in the low level drivers
|
||||
* implementation only.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_isr_full_code(dacp) { \
|
||||
if ((dacp)->grpp->end_cb) { \
|
||||
(dacp)->state = DAC_COMPLETE; \
|
||||
(dacp)->grpp->end_cb(dacp); \
|
||||
if ((dacp)->state == DAC_COMPLETE) \
|
||||
(dacp)->state = DAC_ACTIVE; \
|
||||
} \
|
||||
_dac_wakeup_isr(dacp); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common ISR code, error event.
|
||||
* @details This code handles the portable part of the ISR code:
|
||||
* - Callback invocation.
|
||||
* - Waiting thread timeout signalling, if any.
|
||||
* - Driver state transitions.
|
||||
* .
|
||||
* @note This macro is meant to be used in the low level drivers
|
||||
* implementation only.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] err platform dependent error code
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define _dac_isr_error_code(dacp, err) { \
|
||||
dac_lld_stop_conversion(dacp); \
|
||||
if ((dacp)->grpp->error_cb != NULL) { \
|
||||
(dacp)->state = DAC_ERROR; \
|
||||
(dacp)->grpp->error_cb(dacp, err); \
|
||||
if ((dacp)->state == DAC_ERROR) \
|
||||
(dacp)->state = DAC_READY; \
|
||||
} \
|
||||
(dacp)->grpp = NULL; \
|
||||
_dac_timeout_isr(dacp); \
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dacInit(void);
|
||||
void dacObjectInit(DACDriver *dacp);
|
||||
msg_t dacStart(DACDriver *dacp, const DACConfig *config);
|
||||
void dacStop(DACDriver *dacp);
|
||||
void dacPutChannelX(DACDriver *dacp,
|
||||
dacchannel_t channel,
|
||||
dacsample_t sample);
|
||||
void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp,
|
||||
dacsample_t *samples, size_t depth);
|
||||
void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp,
|
||||
dacsample_t *samples, size_t depth);
|
||||
void dacStopConversion(DACDriver *dacp);
|
||||
void dacStopConversionI(DACDriver *dacp);
|
||||
#if DAC_USE_SYNCHRONIZATION
|
||||
msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp,
|
||||
dacsample_t *samples, size_t depth);
|
||||
msg_t dacSynchronizeS(DACDriver *dacp, sysinterval_t timeout);
|
||||
msg_t dacSynchronize(DACDriver *dacp, sysinterval_t timeout);
|
||||
#endif /* DAC_USE_SYNCHRONIZATION */
|
||||
#if DAC_USE_MUTUAL_EXCLUSION
|
||||
void dacAcquireBus(DACDriver *dacp);
|
||||
void dacReleaseBus(DACDriver *dacp);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_DAC == TRUE */
|
||||
|
||||
#endif /* HAL_DAC_H */
|
||||
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,365 +1,422 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hal_dac.c
|
||||
* @brief DAC Driver code.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DAC Driver initialization.
|
||||
* @note This function is implicitly invoked by @p halInit(), there is
|
||||
* no need to explicitly initialize the driver.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dacInit(void) {
|
||||
|
||||
dac_lld_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the standard part of a @p DACDriver structure.
|
||||
*
|
||||
* @param[out] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dacObjectInit(DACDriver *dacp) {
|
||||
|
||||
dacp->state = DAC_STOP;
|
||||
dacp->config = NULL;
|
||||
#if DAC_USE_WAIT
|
||||
dacp->thread = NULL;
|
||||
#endif
|
||||
#if DAC_USE_MUTUAL_EXCLUSION
|
||||
osalMutexObjectInit(&dacp->mutex);
|
||||
#endif
|
||||
#if defined(DAC_DRIVER_EXT_INIT_HOOK)
|
||||
DAC_DRIVER_EXT_INIT_HOOK(dacp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] config pointer to the @p DACConfig object, it can be
|
||||
* @p NULL if the low level driver implementation
|
||||
* supports a default configuration
|
||||
* @return The operation status.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t dacStart(DACDriver *dacp, const DACConfig *config) {
|
||||
msg_t msg;
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
|
||||
"invalid state");
|
||||
|
||||
dacp->config = config;
|
||||
|
||||
#if defined(DAC_LLD_ENHANCED_API)
|
||||
msg = dac_lld_start(dacp);
|
||||
#else
|
||||
dac_lld_start(dacp);
|
||||
msg = HAL_RET_SUCCESS;
|
||||
#endif
|
||||
if (msg == HAL_RET_SUCCESS) {
|
||||
dacp->state = DAC_READY;
|
||||
}
|
||||
else {
|
||||
dacp->state = DAC_STOP;
|
||||
}
|
||||
|
||||
osalSysUnlock();
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the DAC peripheral.
|
||||
* @note Deactivating the peripheral also enforces a release of the slave
|
||||
* select line.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacStop(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
|
||||
"invalid state");
|
||||
|
||||
dac_lld_stop(dacp);
|
||||
dacp->config = NULL;
|
||||
dacp->state = DAC_STOP;
|
||||
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Outputs a value directly on a DAC channel.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] channel DAC channel number
|
||||
* @param[in] sample value to be output
|
||||
*
|
||||
* @xclass
|
||||
*/
|
||||
void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) {
|
||||
|
||||
osalDbgCheck(channel < (dacchannel_t)DAC_MAX_CHANNELS);
|
||||
osalDbgAssert(dacp->state == DAC_READY, "invalid state");
|
||||
|
||||
dac_lld_put_channel(dacp, channel, sample);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a DAC conversion.
|
||||
* @details Starts an asynchronous conversion operation.
|
||||
* @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] dacp pointer to the @p DACDriver object
|
||||
* @param[in] grpp pointer to a @p DACConversionGroup object
|
||||
* @param[in] samples pointer to the samples buffer
|
||||
* @param[in] depth buffer depth (matrix rows number). The buffer depth
|
||||
* must be one or an even number.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacStartConversion(DACDriver *dacp,
|
||||
const DACConversionGroup *grpp,
|
||||
dacsample_t *samples,
|
||||
size_t depth) {
|
||||
|
||||
osalSysLock();
|
||||
dacStartConversionI(dacp, grpp, samples, depth);
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a DAC 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
|
||||
* with no gaps.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] grpp pointer to a @p DACConversionGroup object
|
||||
* @param[in] samples pointer to the samples buffer
|
||||
* @param[in] depth buffer depth (matrix rows number). The buffer depth
|
||||
* must be one or an even number.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
void dacStartConversionI(DACDriver *dacp,
|
||||
const DACConversionGroup *grpp,
|
||||
dacsample_t *samples,
|
||||
size_t depth) {
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
|
||||
((depth == 1U) || ((depth & 1U) == 0U)));
|
||||
osalDbgAssert((dacp->state == DAC_READY) ||
|
||||
(dacp->state == DAC_COMPLETE) ||
|
||||
(dacp->state == DAC_ERROR),
|
||||
"not ready");
|
||||
|
||||
dacp->samples = samples;
|
||||
dacp->depth = depth;
|
||||
dacp->grpp = grpp;
|
||||
dacp->state = DAC_ACTIVE;
|
||||
dac_lld_start_conversion(dacp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing conversion.
|
||||
* @details This function stops the currently ongoing conversion and returns
|
||||
* the driver in the @p DAC_READY state. If there was no conversion
|
||||
* being processed then the function does nothing.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacStopConversion(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert((dacp->state == DAC_READY) ||
|
||||
(dacp->state == DAC_ACTIVE),
|
||||
"invalid state");
|
||||
|
||||
if (dacp->state != DAC_READY) {
|
||||
dac_lld_stop_conversion(dacp);
|
||||
dacp->grpp = NULL;
|
||||
dacp->state = DAC_READY;
|
||||
_dac_reset_s(dacp);
|
||||
}
|
||||
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing conversion.
|
||||
* @details This function stops the currently ongoing conversion and returns
|
||||
* the driver in the @p DAC_READY state. If there was no conversion
|
||||
* being processed then the function does nothing.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
void dacStopConversionI(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck(dacp != NULL);
|
||||
osalDbgAssert((dacp->state == DAC_READY) ||
|
||||
(dacp->state == DAC_ACTIVE) ||
|
||||
(dacp->state == DAC_COMPLETE),
|
||||
"invalid state");
|
||||
|
||||
if (dacp->state != DAC_READY) {
|
||||
dac_lld_stop_conversion(dacp);
|
||||
dacp->grpp = NULL;
|
||||
dacp->state = DAC_READY;
|
||||
_dac_reset_i(dacp);
|
||||
}
|
||||
}
|
||||
|
||||
#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Performs a DAC conversion.
|
||||
* @details Performs a synchronous conversion operation.
|
||||
* @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] dacp pointer to the @p DACDriver object
|
||||
* @param[in] grpp pointer to a @p DACConversionGroup 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.
|
||||
* @return The operation result.
|
||||
* @retval MSG_OK Conversion finished.
|
||||
* @retval MSG_RESET The conversion has been stopped using
|
||||
* @p acdStopConversion() or @p acdStopConversionI(),
|
||||
* the result buffer may contain incorrect data.
|
||||
* @retval MSG_TIMEOUT The conversion has been stopped because an hardware
|
||||
* error.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t dacConvert(DACDriver *dacp,
|
||||
const DACConversionGroup *grpp,
|
||||
dacsample_t *samples,
|
||||
size_t depth) {
|
||||
msg_t msg;
|
||||
|
||||
osalSysLock();
|
||||
|
||||
dacStartConversionI(dacp, grpp, samples, depth);
|
||||
msg = osalThreadSuspendS(&dacp->thread);
|
||||
|
||||
osalSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
#endif /* DAC_USE_WAIT == TRUE */
|
||||
|
||||
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Gains exclusive access to the DAC bus.
|
||||
* @details This function tries to gain ownership to the DAC bus, if the bus
|
||||
* is already being used then the invoking thread is queued.
|
||||
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
|
||||
* must be enabled.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacAcquireBus(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalMutexLock(&dacp->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases exclusive access to the DAC bus.
|
||||
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
|
||||
* must be enabled.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacReleaseBus(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalMutexUnlock(&dacp->mutex);
|
||||
}
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION == TRUE */
|
||||
|
||||
#endif /* HAL_USE_DAC == TRUE */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hal_dac.c
|
||||
* @brief DAC Driver code.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DAC Driver initialization.
|
||||
* @note This function is implicitly invoked by @p halInit(), there is
|
||||
* no need to explicitly initialize the driver.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dacInit(void) {
|
||||
|
||||
dac_lld_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the standard part of a @p DACDriver structure.
|
||||
*
|
||||
* @param[out] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dacObjectInit(DACDriver *dacp) {
|
||||
|
||||
dacp->state = DAC_STOP;
|
||||
dacp->config = NULL;
|
||||
#if DAC_USE_WAIT
|
||||
dacp->thread = NULL;
|
||||
#endif
|
||||
#if DAC_USE_MUTUAL_EXCLUSION
|
||||
osalMutexObjectInit(&dacp->mutex);
|
||||
#endif
|
||||
#if defined(DAC_DRIVER_EXT_INIT_HOOK)
|
||||
DAC_DRIVER_EXT_INIT_HOOK(dacp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] config pointer to the @p DACConfig object, it can be
|
||||
* @p NULL if the low level driver implementation
|
||||
* supports a default configuration
|
||||
* @return The operation status.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t dacStart(DACDriver *dacp, const DACConfig *config) {
|
||||
msg_t msg;
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
|
||||
"invalid state");
|
||||
|
||||
dacp->config = config;
|
||||
|
||||
#if defined(DAC_LLD_ENHANCED_API)
|
||||
msg = dac_lld_start(dacp);
|
||||
#else
|
||||
dac_lld_start(dacp);
|
||||
msg = HAL_RET_SUCCESS;
|
||||
#endif
|
||||
if (msg == HAL_RET_SUCCESS) {
|
||||
dacp->state = DAC_READY;
|
||||
}
|
||||
else {
|
||||
dacp->state = DAC_STOP;
|
||||
}
|
||||
|
||||
osalSysUnlock();
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the DAC peripheral.
|
||||
* @note Deactivating the peripheral also enforces a release of the slave
|
||||
* select line.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacStop(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
|
||||
"invalid state");
|
||||
|
||||
dac_lld_stop(dacp);
|
||||
dacp->config = NULL;
|
||||
dacp->state = DAC_STOP;
|
||||
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Outputs a value directly on a DAC channel.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] channel DAC channel number
|
||||
* @param[in] sample value to be output
|
||||
*
|
||||
* @xclass
|
||||
*/
|
||||
void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) {
|
||||
|
||||
osalDbgCheck(channel < (dacchannel_t)DAC_MAX_CHANNELS);
|
||||
osalDbgAssert(dacp->state == DAC_READY || dacp->state == DAC_ACTIVE,
|
||||
"invalid state");
|
||||
|
||||
dac_lld_put_channel(dacp, channel, sample);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a DAC conversion.
|
||||
* @details Starts an asynchronous conversion operation.
|
||||
* @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] dacp pointer to the @p DACDriver object
|
||||
* @param[in] grpp pointer to a @p DACConversionGroup object
|
||||
* @param[in] samples pointer to the samples buffer
|
||||
* @param[in] depth buffer depth (matrix rows number). The buffer depth
|
||||
* must be one or an even number.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacStartConversion(DACDriver *dacp,
|
||||
const DACConversionGroup *grpp,
|
||||
dacsample_t *samples,
|
||||
size_t depth) {
|
||||
|
||||
osalSysLock();
|
||||
dacStartConversionI(dacp, grpp, samples, depth);
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a DAC conversion.
|
||||
* @details Starts an asynchronous conversion operation.
|
||||
* @post The callbacks associated to the conversion group will be invoked
|
||||
* on buffer complete 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 organised in the buffer
|
||||
* with no gaps.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] grpp pointer to a @p DACConversionGroup object
|
||||
* @param[in] samples pointer to the samples buffer
|
||||
* @param[in] depth buffer depth (matrix rows number). The buffer depth
|
||||
* must be one or an even number.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
void dacStartConversionI(DACDriver *dacp,
|
||||
const DACConversionGroup *grpp,
|
||||
dacsample_t *samples,
|
||||
size_t depth) {
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
|
||||
((depth == 1U) || ((depth & 1U) == 0U)));
|
||||
osalDbgAssert((dacp->state == DAC_READY) ||
|
||||
(dacp->state == DAC_COMPLETE) ||
|
||||
(dacp->state == DAC_ERROR),
|
||||
"not ready");
|
||||
|
||||
dacp->samples = samples;
|
||||
dacp->depth = depth;
|
||||
dacp->grpp = grpp;
|
||||
dacp->state = DAC_ACTIVE;
|
||||
dac_lld_start_conversion(dacp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing conversion.
|
||||
* @details This function stops the currently ongoing conversion and returns
|
||||
* the driver in the @p DAC_READY state. If there was no conversion
|
||||
* being processed then the function does nothing.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacStopConversion(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalSysLock();
|
||||
|
||||
osalDbgAssert((dacp->state == DAC_READY) ||
|
||||
(dacp->state == DAC_ACTIVE),
|
||||
"invalid state");
|
||||
|
||||
if (dacp->state != DAC_READY) {
|
||||
dac_lld_stop_conversion(dacp);
|
||||
dacp->grpp = NULL;
|
||||
dacp->state = DAC_READY;
|
||||
_dac_reset_s(dacp);
|
||||
}
|
||||
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing conversion.
|
||||
* @details This function stops the currently ongoing conversion and returns
|
||||
* the driver in the @p DAC_READY state. If there was no conversion
|
||||
* being processed then the function does nothing.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
void dacStopConversionI(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck(dacp != NULL);
|
||||
osalDbgAssert((dacp->state == DAC_READY) ||
|
||||
(dacp->state == DAC_ACTIVE) ||
|
||||
(dacp->state == DAC_COMPLETE),
|
||||
"invalid state");
|
||||
|
||||
if (dacp->state != DAC_READY) {
|
||||
dac_lld_stop_conversion(dacp);
|
||||
dacp->grpp = NULL;
|
||||
dacp->state = DAC_READY;
|
||||
_dac_reset_i(dacp);
|
||||
}
|
||||
}
|
||||
|
||||
#if (DAC_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Performs a DAC conversion.
|
||||
* @details Performs a synchronous conversion operation.
|
||||
* @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 organised in the buffer
|
||||
* with no gaps.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] grpp pointer to a @p DACConversionGroup object
|
||||
* @param[in] samples pointer to the samples buffer
|
||||
* @param[in] depth buffer depth (matrix rows number). The buffer depth
|
||||
* must be one or an even number.
|
||||
*
|
||||
* @return The operation result.
|
||||
* @retval MSG_OK Conversion finished.
|
||||
* @retval MSG_RESET The conversion has been stopped using
|
||||
* @p dacStopConversion() or @p dacStopConversionI().
|
||||
* @retval MSG_TIMEOUT The conversion has been stopped because an hardware
|
||||
* error.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t dacConvert(DACDriver *dacp,
|
||||
const DACConversionGroup *grpp,
|
||||
dacsample_t *samples,
|
||||
size_t depth) {
|
||||
msg_t msg;
|
||||
|
||||
osalSysLock();
|
||||
|
||||
dacStartConversionI(dacp, grpp, samples, depth);
|
||||
msg = osalThreadSuspendS(&dacp->thread);
|
||||
|
||||
osalSysUnlock();
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Synchronize to a conversion completion.
|
||||
* @note This function can only be called by a single thread at time.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] timeout wait timeout
|
||||
*
|
||||
* @return The wait result.
|
||||
* @retval MSG_OK if operation completed without errors.
|
||||
* @retval MSG_TIMEOUT if synchronization request timed out.
|
||||
* @retval MSG_RESET if the conversion has been stopped.
|
||||
*
|
||||
* @sclass
|
||||
*/
|
||||
msg_t dacSynchronizeS(DACDriver *dacp, sysinterval_t timeout) {
|
||||
msg_t msg;
|
||||
|
||||
osalDbgCheckClassS();
|
||||
osalDbgCheck(dacp != NULL);
|
||||
osalDbgAssert((dacp->state == DAC_ACTIVE) || (dacp->state == DAC_READY),
|
||||
"invalid state");
|
||||
|
||||
if (dacp->state == DAC_ACTIVE) {
|
||||
msg = osalThreadSuspendTimeoutS(&dacp->thread, timeout);
|
||||
}
|
||||
else {
|
||||
msg = MSG_OK;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Synchronize to a conversion completion.
|
||||
* @note This function can only be called by a single thread at time.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] timeout wait timeout
|
||||
*
|
||||
* @return The wait result.
|
||||
* @retval MSG_OK if operation completed without errors.
|
||||
* @retval MSG_TIMEOUT if synchronization request timed out.
|
||||
* @retval MSG_RESET if the conversion has been stopped.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t dacSynchronize(DACDriver *dacp, sysinterval_t timeout) {
|
||||
msg_t msg;
|
||||
|
||||
osalSysLock();
|
||||
msg = dacSynchronizeS(dacp, timeout);
|
||||
osalSysUnlock();
|
||||
|
||||
return msg;
|
||||
}
|
||||
#endif /* DAC_USE_SYNCHRONIZATION == TRUE */
|
||||
|
||||
#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Gains exclusive access to the DAC bus.
|
||||
* @details This function tries to gain ownership to the DAC bus, if the bus
|
||||
* is already being used then the invoking thread is queued.
|
||||
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
|
||||
* must be enabled.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacAcquireBus(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalMutexLock(&dacp->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases exclusive access to the DAC bus.
|
||||
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
|
||||
* must be enabled.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void dacReleaseBus(DACDriver *dacp) {
|
||||
|
||||
osalDbgCheck(dacp != NULL);
|
||||
|
||||
osalMutexUnlock(&dacp->mutex);
|
||||
}
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION == TRUE */
|
||||
|
||||
#endif /* HAL_USE_DAC == TRUE */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
*****************************************************************************
|
||||
|
||||
*** Next ***
|
||||
- NEW: Improved DAC driver, updated STM32 DACv1.
|
||||
- NEW: STM32 RTCv2 and RTCv3 modified to not use shadow registers.
|
||||
- NEW: Enhanced STM32F7xx MPU configuration in mcuconf.h.
|
||||
- NEW: I2C slave support in HAL high level driver.
|
||||
|
|
Loading…
Reference in New Issue