1102 lines
38 KiB
C
1102 lines
38 KiB
C
|
/**
|
||
|
******************************************************************************
|
||
|
* @file ald_adc.c
|
||
|
* @brief This file provides firmware functions to manage the following
|
||
|
* functionalities of the Analog to Digital Convertor (ADC)
|
||
|
* peripheral:
|
||
|
* + Initialization functions
|
||
|
* ++ Initialization and Configuration of ADC
|
||
|
* + Operation functions
|
||
|
* ++ Start, stop, get result of conversions of normal
|
||
|
* group, using 3 possible modes: polling, interruption or DMA.
|
||
|
* + Control functions
|
||
|
* ++ Channels configuration on normal group
|
||
|
* ++ Channels configuration on insert group
|
||
|
* ++ Analog Watchdog configuration
|
||
|
* + State functions
|
||
|
* ++ ADC state machine management
|
||
|
* ++ Interrupts and flags management
|
||
|
*
|
||
|
* @version V1.0
|
||
|
* @date 06 Mar. 2023
|
||
|
* @author AE Team.
|
||
|
* @note
|
||
|
* Change Logs:
|
||
|
* Date Author Notes
|
||
|
* 06 Mar. 2023 Lisq The first version
|
||
|
*
|
||
|
* Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*
|
||
|
* 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
|
||
|
*
|
||
|
* 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.
|
||
|
**********************************************************************************
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "ald_adc.h"
|
||
|
|
||
|
/** @addtogroup ES32VF2264_ALD
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @defgroup ADC ADC
|
||
|
* @brief ADC module driver
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @addtogroup ADC_Private_Functions
|
||
|
* @{
|
||
|
*/
|
||
|
static void adc_dma_normal_conv_cplt(void *arg);
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/** @defgroup ADC_Public_Functions ADC Public Functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @defgroup ADC_Public_Functions_Group1 Initialization functions
|
||
|
* @brief Initialization and Configuration functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @brief Initializes the ADC peripheral and normal group according to
|
||
|
* parameters specified in structure "adc_handle_t".
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_init(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_DATA_ALIGN_TYPE(hperh->init.align));
|
||
|
assert_param(IS_FUNC_STATE(hperh->init.scan));
|
||
|
assert_param(IS_ADC_CLK_DIV_TYPE(hperh->init.div));
|
||
|
assert_param(IS_ADC_NEG_REF_VOLTAGE_TYPE(hperh->init.n_ref));
|
||
|
assert_param(IS_POS_REF_VOLTAGE_TYPE(hperh->init.p_ref));
|
||
|
assert_param(IS_ADC_CONV_BIT_TYPE(hperh->init.data_bit));
|
||
|
assert_param(IS_ADC_NCH_NR_TYPE(hperh->init.nch_nr));
|
||
|
assert_param(IS_ADC_DISC_NR_TYPE(hperh->init.disc_nr));
|
||
|
assert_param(IS_FUNC_STATE(hperh->init.cont));
|
||
|
assert_param(IS_ADC_NCHESEL_MODE_TYPE(hperh->init.nche_sel));
|
||
|
|
||
|
if (hperh->state == ALD_ADC_STATE_RESET ) {
|
||
|
hperh->error_code = ALD_ADC_ERROR_NONE;
|
||
|
hperh->lock = UNLOCK;
|
||
|
}
|
||
|
|
||
|
ALD_ADC_DISABLE(hperh);
|
||
|
ald_adc_reset(hperh);
|
||
|
hperh->state = ALD_ADC_STATE_BUSY;
|
||
|
MODIFY_REG(hperh->perh->CON1, ADC_CON1_ALIGN_MSK, hperh->init.align << ADC_CON1_ALIGN_POS);
|
||
|
MODIFY_REG(hperh->perh->CON0, ADC_CON0_RSEL_MSK, hperh->init.data_bit << ADC_CON0_RSEL_POSS);
|
||
|
|
||
|
/* Enable discontinuous mode only if continuous mode is disable */
|
||
|
if (hperh->init.disc == ALD_ADC_NCH_DISC_EN) {
|
||
|
hperh->init.scan = ENABLE;
|
||
|
hperh->init.cont = DISABLE;
|
||
|
SET_BIT(hperh->perh->CON0, ADC_CON0_NCHDCEN_MSK);
|
||
|
MODIFY_REG(hperh->perh->CON0, ADC_CON0_ETRGN_MSK, hperh->init.disc_nr << ADC_CON0_ETRGN_POSS);
|
||
|
}
|
||
|
else if (hperh->init.disc == ALD_ADC_ICH_DISC_EN) {
|
||
|
hperh->init.scan = ENABLE;
|
||
|
hperh->init.cont = DISABLE;
|
||
|
SET_BIT(hperh->perh->CON0, ADC_CON0_ICHDCEN_MSK);
|
||
|
MODIFY_REG(hperh->perh->CON0, ADC_CON0_ETRGN_MSK, hperh->init.disc_nr << ADC_CON0_ETRGN_POSS);
|
||
|
}
|
||
|
else {
|
||
|
CLEAR_BIT(hperh->perh->CON0, ADC_CON0_NCHDCEN_MSK);
|
||
|
CLEAR_BIT(hperh->perh->CON0, ADC_CON0_ICHDCEN_MSK);
|
||
|
}
|
||
|
|
||
|
if ((hperh->init.scan == ENABLE) || (hperh->init.disc == ALD_ADC_NCH_DISC_EN))
|
||
|
MODIFY_REG(hperh->perh->CHSL, ADC_CHSL_NSL_MSK, hperh->init.nch_nr << ADC_CHSL_NSL_POSS);
|
||
|
|
||
|
MODIFY_REG(hperh->perh->CON1, ADC_CON1_CM_MSK, hperh->init.cont << ADC_CON1_CM_POS);
|
||
|
MODIFY_REG(hperh->perh->CON0, ADC_CON0_SCANEN_MSK, hperh->init.scan << ADC_CON0_SCANEN_POS);
|
||
|
|
||
|
WRITE_REG(hperh->perh->CCR, 0x0);
|
||
|
MODIFY_REG(hperh->perh->CCR, ADC_CCR_PWRMODSEL_MSK, DISABLE << ADC_CCR_PWRMODSEL_POS);
|
||
|
MODIFY_REG(hperh->perh->CCR, ADC_CCR_VREFEN_MSK, ENABLE << ADC_CCR_VREFEN_POS);
|
||
|
MODIFY_REG(hperh->perh->CCR, ADC_CCR_IREFEN_MSK, ENABLE << ADC_CCR_IREFEN_POS);
|
||
|
MODIFY_REG(hperh->perh->CCR, ADC_CCR_VRNSEL_MSK, hperh->init.n_ref << ADC_CCR_VRNSEL_POS);
|
||
|
MODIFY_REG(hperh->perh->CCR, ADC_CCR_VRPSEL_MSK, hperh->init.p_ref << ADC_CCR_VRPSEL_POS);
|
||
|
MODIFY_REG(hperh->perh->CCR, ADC_CCR_POSDIV_MSK, hperh->init.div << ADC_CCR_POSDIV_POSS);
|
||
|
MODIFY_REG(hperh->perh->CON1, ADC_CON1_NCHESEL_MSK, hperh->init.nche_sel << ADC_CON1_NCHESEL_POS);
|
||
|
ALD_ADC_ENABLE(hperh);
|
||
|
|
||
|
hperh->error_code = ALD_ADC_ERROR_NONE;
|
||
|
hperh->state = ALD_ADC_STATE_READY;
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Deinitialize the ADC peripheral registers to their default reset
|
||
|
* values.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_reset(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
ALD_ADC_DISABLE(hperh);
|
||
|
WRITE_REG(hperh->perh->CLR, 0x30F);
|
||
|
WRITE_REG(hperh->perh->CON0, 0x0);
|
||
|
WRITE_REG(hperh->perh->CON1, 0x0);
|
||
|
WRITE_REG(hperh->perh->CCR, 0x0);
|
||
|
WRITE_REG(hperh->perh->WDTH, 0xFFF);
|
||
|
WRITE_REG(hperh->perh->WDTL, 0x0);
|
||
|
WRITE_REG(hperh->perh->NCHOFF, 0x0);
|
||
|
WRITE_REG(hperh->perh->ICHOFF1, 0x0);
|
||
|
WRITE_REG(hperh->perh->ICHOFF2, 0x0);
|
||
|
WRITE_REG(hperh->perh->ICHOFF3, 0x0);
|
||
|
WRITE_REG(hperh->perh->ICHOFF4, 0x0);
|
||
|
WRITE_REG(hperh->perh->ICHS, 0x0);
|
||
|
WRITE_REG(hperh->perh->NCHS1, 0x0);
|
||
|
WRITE_REG(hperh->perh->NCHS2, 0x0);
|
||
|
WRITE_REG(hperh->perh->NCHS3, 0x0);
|
||
|
WRITE_REG(hperh->perh->NCHS4, 0x0);
|
||
|
WRITE_REG(hperh->perh->SMPT1, 0x0);
|
||
|
WRITE_REG(hperh->perh->SMPT2, 0x0);
|
||
|
WRITE_REG(hperh->perh->SMPT3, 0x0);
|
||
|
WRITE_REG(hperh->perh->CHSL, 0x0);
|
||
|
|
||
|
hperh->state = ALD_ADC_STATE_RESET;
|
||
|
hperh->error_code = ALD_ADC_ERROR_NONE;
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/** @defgroup ADC_Public_Functions_Group2 IO operation functions
|
||
|
* @brief Input and Output operation functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @brief Enables ADC, starts conversion of normal group.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_normal_start(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
ALD_ADC_ENABLE(hperh);
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_NCH | ALD_ADC_FLAG_NCHS);
|
||
|
SET_BIT(hperh->perh->CON1, ADC_CON1_NCHTRG_MSK);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Stop ADC conversion of normal group (and insert channels in
|
||
|
* case of auto_injection mode), disable ADC peripheral.
|
||
|
* @note: ADC peripheral disable is forcing stop of potential
|
||
|
* conversion on insert group. If insert group is under use, it
|
||
|
* should be preliminarily stopped using ald_adc_insert_stop function.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_normal_stop(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
ALD_ADC_DISABLE(hperh);
|
||
|
hperh->state = ALD_ADC_STATE_READY;
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Wait for normal group conversion to be completed.
|
||
|
* @note This function cannot be used in a particular setup: ADC configured in DMA mode.
|
||
|
* In this case, DMA resets the flag EOC and polling cannot be performed on each conversion.
|
||
|
* @note When use this function,you should be pay attention to the hperh->init.reocs_mode,
|
||
|
* if it is ADC_REOCS_MODE_ALL, it means the function will wait all normal rank conversion finished.
|
||
|
* if it is ADC_REOCS_MODE_ONE, it means the funcion will wait every normal rank conversion finished.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param timeout: Timeout value in millisecond.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_normal_poll_for_conversion(ald_adc_handle_t *hperh, uint32_t timeout)
|
||
|
{
|
||
|
uint32_t _tick;
|
||
|
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
_tick = ald_get_tick();
|
||
|
while (!(READ_BIT(hperh->perh->STAT, ADC_STAT_NCHE_MSK))) {
|
||
|
if (timeout != ALD_MAX_DELAY ) {
|
||
|
if ((timeout == 0) || ((ald_get_tick() - _tick) > timeout)) {
|
||
|
hperh->state = ALD_ADC_STATE_TIMEOUT;
|
||
|
return ALD_TIMEOUT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_NCHS | ALD_ADC_FLAG_NCH);
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Poll for conversion event.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param event_type: the ADC event type.
|
||
|
* This parameter can be one of the following values:
|
||
|
* ADC_awd_event: ADC Analog watchdog event.
|
||
|
* @param timeout: Timeout value in millisecond.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_poll_for_event(ald_adc_handle_t *hperh, ald_adc_event_type_t event_type, uint32_t timeout)
|
||
|
{
|
||
|
uint32_t _tick;
|
||
|
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_EVENT_TYPE(event_type));
|
||
|
|
||
|
_tick = ald_get_tick();
|
||
|
while (ald_adc_get_flag_status(hperh, (ald_adc_flag_t)event_type) == RESET) {
|
||
|
if (timeout != ALD_MAX_DELAY ) {
|
||
|
if ((timeout == 0) || ((ald_get_tick() - _tick) > timeout)) {
|
||
|
hperh->state = ALD_ADC_STATE_TIMEOUT;
|
||
|
return ALD_TIMEOUT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CLEAR_BIT(hperh->state, ALD_ADC_STATE_BUSY_WDG);
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Enables ADC, starts conversion of normal group with interruption.
|
||
|
* Interruptions enabled in this function:
|
||
|
* - REOC (end of conversion of normal group)
|
||
|
* Each of these interruptions has its dedicated callback function.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_normal_start_by_it(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
SET_BIT(hperh->state, ALD_ADC_STATE_BUSY_N);
|
||
|
ALD_ADC_ENABLE(hperh);
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_NCH);
|
||
|
ald_adc_interrupt_config(hperh, ALD_ADC_IT_NCH, ENABLE);
|
||
|
SET_BIT(hperh->perh->CON1, ADC_CON1_NCHTRG_MSK);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Stop ADC conversion of normal group (and insert group in
|
||
|
* case of auto_injection mode), disable interrution of
|
||
|
* end-of-conversion, disable ADC peripheral.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_normal_stop_by_it(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
ALD_ADC_DISABLE(hperh);
|
||
|
ald_adc_interrupt_config(hperh, ALD_ADC_IT_NCH, DISABLE);
|
||
|
CLEAR_BIT(hperh->state, ALD_ADC_STATE_BUSY_N);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Enables ADC, starts conversion of normal group and transfers result
|
||
|
* through DMA.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param buf: The destination Buffer address.
|
||
|
* @param size: The length of data to be transferred from ADC peripheral to memory.
|
||
|
* @param channel: The DMA channel
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_start_by_dma(ald_adc_handle_t *hperh, uint16_t *buf, uint16_t size, uint8_t channel)
|
||
|
{
|
||
|
if ((buf == NULL) || (size == 0))
|
||
|
return ALD_ERROR;
|
||
|
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
SET_BIT(hperh->state, ALD_ADC_STATE_BUSY_N);
|
||
|
|
||
|
if (hperh->hdma.perh == NULL)
|
||
|
hperh->hdma.perh = DMA;
|
||
|
|
||
|
SET_BIT(hperh->perh->CON1, ADC_CON1_DMA_MSK);
|
||
|
|
||
|
ald_dma_interrupt_config(channel, ALD_DMA_IT_FLAG_TC, ENABLE);
|
||
|
hperh->hdma.cplt_tc_cbk = adc_dma_normal_conv_cplt;
|
||
|
hperh->hdma.cplt_tc_arg = hperh;
|
||
|
ald_dma_config_struct(&hperh->hdma.config);
|
||
|
hperh->hdma.config.src = (void *)&hperh->perh->NCHDR;
|
||
|
hperh->hdma.config.dst = (void *)buf;
|
||
|
hperh->hdma.config.size = size;
|
||
|
hperh->hdma.config.src_data_width = ALD_DMA_DATA_SIZE_HALFWORD;
|
||
|
hperh->hdma.config.dst_data_width = ALD_DMA_DATA_SIZE_HALFWORD;
|
||
|
hperh->hdma.config.src_inc = ALD_DMA_DATA_INC_DISABLE;
|
||
|
hperh->hdma.config.dst_inc = ALD_DMA_DATA_INC_ENABLE;
|
||
|
hperh->hdma.config.msel = ALD_DMA_MSEL_ADC;
|
||
|
hperh->hdma.config.msigsel = ALD_DMA_MSIGSEL_ADC;
|
||
|
hperh->hdma.config.circle_mode = ENABLE;
|
||
|
hperh->hdma.config.channel = channel;
|
||
|
ald_dma_config_basic(&hperh->hdma);
|
||
|
|
||
|
ALD_ADC_ENABLE(hperh);
|
||
|
SET_BIT(hperh->perh->CON1, ADC_CON1_NCHTRG_MSK);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Stop ADC conversion of normal group (and insert group in
|
||
|
* case of auto_insert mode), disable ADC DMA transfer, disable
|
||
|
* ADC peripheral.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param channel: The DMA channel
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_stop_by_dma(ald_adc_handle_t *hperh, uint8_t channel)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
ALD_ADC_DISABLE(hperh);
|
||
|
CLEAR_BIT(hperh->perh->CON1, ADC_CON1_DMA_MSK);
|
||
|
ald_dma_channel_config(channel, DISABLE);
|
||
|
CLEAR_BIT(hperh->state, ALD_ADC_STATE_BUSY_N);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief DMA transfer complete callback.
|
||
|
* @param arg: argument of the call back.
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void adc_dma_timer_trigger_cplt(void *arg)
|
||
|
{
|
||
|
ald_adc_timer_config_t *hperh = (ald_adc_timer_config_t *)arg;
|
||
|
|
||
|
ald_timer_base_stop(&hperh->h_timer);
|
||
|
CLEAR_BIT(hperh->h_adc.perh->CON1, ADC_CON1_DMA_MSK);
|
||
|
ALD_ADC_DISABLE(&hperh->h_adc);
|
||
|
ald_dma_channel_config(hperh->dma_ch, DISABLE);
|
||
|
CLEAR_BIT(hperh->h_adc.state, ALD_ADC_STATE_BUSY_N);
|
||
|
|
||
|
if (hperh->h_adc.normal_cplt_cbk)
|
||
|
hperh->h_adc.normal_cplt_cbk(&hperh->h_adc);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Config timer trigger adc insert channel conversion.
|
||
|
* @param config: Pointer to a adc_timer_config_t structure that
|
||
|
* contains the configuration information for the specified function.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_timer_trigger_insert(ald_adc_timer_config_t *config)
|
||
|
{
|
||
|
config->h_pis.perh = PIS;
|
||
|
config->h_pis.init.producer_clk = ALD_PIS_CLK_PCLK;
|
||
|
config->h_pis.init.producer_edge = ALD_PIS_EDGE_NONE;
|
||
|
config->h_pis.init.consumer_clk = ALD_PIS_CLK_PCLK;
|
||
|
|
||
|
if (config->p_timer == AD16C4T)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER0_UPDATA;
|
||
|
else if (config->p_timer == GP16C4T0)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER5_UPDATA;
|
||
|
else if (config->p_timer == GP16C4T1)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER6_UPDATA;
|
||
|
else if (config->p_timer == GP16C4T2)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER7_UPDATA;
|
||
|
else
|
||
|
return ALD_ERROR;
|
||
|
|
||
|
config->h_pis.init.consumer_trig = ALD_PIS_CH5_ADC0_INSERT;
|
||
|
|
||
|
ald_pis_create(&config->h_pis);
|
||
|
|
||
|
/* Initialize TIMER */
|
||
|
config->h_timer.perh = config->p_timer;
|
||
|
config->h_timer.init.prescaler = 0;
|
||
|
config->h_timer.init.mode = ALD_TIMER_CNT_MODE_UP;
|
||
|
config->h_timer.init.period = ((ald_cmu_get_pclk_clock() / 1000000) * config->time);
|
||
|
config->h_timer.init.clk_div = ALD_TIMER_CLOCK_DIV1;
|
||
|
config->h_timer.init.re_cnt = 0;
|
||
|
ald_timer_base_init(&config->h_timer);
|
||
|
|
||
|
config->h_adc.perh = config->p_adc;
|
||
|
config->h_adc.init.align = ALD_ADC_DATAALIGN_RIGHT;
|
||
|
config->h_adc.init.scan = DISABLE;
|
||
|
config->h_adc.init.cont = DISABLE;
|
||
|
config->h_adc.init.ich_nr = ALD_ADC_ICH_NR_1;
|
||
|
config->h_adc.init.disc = ALD_ADC_ALL_DISABLE;
|
||
|
config->h_adc.init.disc_nr = ALD_ADC_DISC_NR_1;
|
||
|
config->h_adc.init.data_bit = ALD_ADC_CONV_BIT_12;
|
||
|
config->h_adc.init.div = ALD_ADC_CKDIV_128;
|
||
|
config->h_adc.init.nche_sel = ALD_ADC_NCHESEL_MODE_ONE;
|
||
|
config->h_adc.init.n_ref = config->n_ref;
|
||
|
config->h_adc.init.p_ref = config->p_ref;
|
||
|
config->h_adc.normal_cplt_cbk = config->cplt_cbk;
|
||
|
config->h_adc.insert_cplt_cbk = NULL;
|
||
|
config->h_adc.wdg_cbk = NULL;
|
||
|
config->h_adc.error_cbk = NULL;
|
||
|
config->h_adc.ovr_cbk = NULL;
|
||
|
ald_adc_init(&config->h_adc);
|
||
|
|
||
|
config->h_adc.perh->CON1 |= 0x00100000; /* rising edge trigger insert channel convert */
|
||
|
config->i_config.ch = config->adc_ch;
|
||
|
config->i_config.idx = ALD_ADC_ICH_IDX_1;
|
||
|
config->i_config.samp = ALD_ADC_SAMPLETIME_4;
|
||
|
config->i_config.nr = ALD_ADC_ICH_NR_1;
|
||
|
config->i_config.auto_m = DISABLE;
|
||
|
ald_adc_insert_channel_config(&config->h_adc, &config->i_config);
|
||
|
|
||
|
ALD_ADC_ENABLE(&config->h_adc);
|
||
|
ald_timer_base_start(&config->h_timer);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Config Timer trigger adc function
|
||
|
* @param config: Pointer to a adc_timer_config_t structure that
|
||
|
* contains the configuration information for the specified function.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_timer_trigger_adc_by_dma(ald_adc_timer_config_t *config)
|
||
|
{
|
||
|
config->h_pis.perh = PIS;
|
||
|
config->h_pis.init.producer_clk = ALD_PIS_CLK_PCLK;
|
||
|
config->h_pis.init.producer_edge = ALD_PIS_EDGE_NONE;
|
||
|
config->h_pis.init.consumer_clk = ALD_PIS_CLK_PCLK;
|
||
|
|
||
|
if (config->p_timer == AD16C4T)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER0_UPDATA;
|
||
|
else if (config->p_timer == GP16C4T0)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER5_UPDATA;
|
||
|
else if (config->p_timer == GP16C4T1)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER6_UPDATA;
|
||
|
else if (config->p_timer == GP16C4T2)
|
||
|
config->h_pis.init.producer_src = ALD_PIS_TIMER7_UPDATA;
|
||
|
else
|
||
|
return ALD_ERROR;
|
||
|
|
||
|
config->h_pis.init.consumer_trig = ALD_PIS_CH4_ADC0_NORMAL;
|
||
|
|
||
|
ald_pis_create(&config->h_pis);
|
||
|
|
||
|
/* Initialize TIMER */
|
||
|
config->h_timer.perh = config->p_timer;
|
||
|
config->h_timer.init.prescaler = 0;
|
||
|
config->h_timer.init.mode = ALD_TIMER_CNT_MODE_UP;
|
||
|
config->h_timer.init.period = ((ald_cmu_get_pclk_clock() / 1000000) * config->time);
|
||
|
config->h_timer.init.clk_div = ALD_TIMER_CLOCK_DIV1;
|
||
|
config->h_timer.init.re_cnt = 0;
|
||
|
ald_timer_base_init(&config->h_timer);
|
||
|
|
||
|
config->h_adc.perh = config->p_adc;
|
||
|
config->h_adc.init.align = ALD_ADC_DATAALIGN_RIGHT;
|
||
|
config->h_adc.init.scan = DISABLE;
|
||
|
config->h_adc.init.cont = DISABLE;
|
||
|
config->h_adc.init.nch_nr = ALD_ADC_NCH_NR_1;
|
||
|
config->h_adc.init.disc = ALD_ADC_ALL_DISABLE;
|
||
|
config->h_adc.init.disc_nr = ALD_ADC_DISC_NR_1;
|
||
|
config->h_adc.init.data_bit = ALD_ADC_CONV_BIT_12;
|
||
|
config->h_adc.init.div = ALD_ADC_CKDIV_128;
|
||
|
config->h_adc.init.nche_sel = ALD_ADC_NCHESEL_MODE_ONE;
|
||
|
config->h_adc.init.n_ref = config->n_ref;
|
||
|
config->h_adc.init.p_ref = config->p_ref;
|
||
|
config->h_adc.normal_cplt_cbk = config->cplt_cbk;
|
||
|
config->h_adc.insert_cplt_cbk = NULL;
|
||
|
config->h_adc.wdg_cbk = NULL;
|
||
|
config->h_adc.error_cbk = NULL;
|
||
|
config->h_adc.ovr_cbk = NULL;
|
||
|
ald_adc_init(&config->h_adc);
|
||
|
|
||
|
config->h_adc.perh->CON1 |= 0x10000000;
|
||
|
config->config.ch = config->adc_ch;
|
||
|
config->config.idx = ALD_ADC_NCH_IDX_1;
|
||
|
config->config.samp = ALD_ADC_SAMPLETIME_4;
|
||
|
ald_adc_normal_channel_config(&config->h_adc, &config->config);
|
||
|
|
||
|
config->h_dma.cplt_tc_cbk = adc_dma_timer_trigger_cplt;
|
||
|
config->h_dma.cplt_tc_arg = config;
|
||
|
|
||
|
ald_dma_config_struct(&config->h_dma.config);
|
||
|
config->h_dma.perh = DMA;
|
||
|
config->h_dma.config.src = (void *)&config->h_adc.perh->NCHDR;
|
||
|
config->h_dma.config.dst = (void *)config->buf;
|
||
|
config->h_dma.config.size = config->size;
|
||
|
config->h_dma.config.src_data_width = ALD_DMA_DATA_SIZE_HALFWORD;
|
||
|
config->h_dma.config.dst_data_width = ALD_DMA_DATA_SIZE_HALFWORD;
|
||
|
config->h_dma.config.src_inc = ALD_DMA_DATA_INC_DISABLE;
|
||
|
config->h_dma.config.dst_inc = ALD_DMA_DATA_INC_ENABLE;
|
||
|
config->h_dma.config.msel = ALD_DMA_MSEL_ADC;
|
||
|
config->h_dma.config.msigsel = ALD_DMA_MSIGSEL_ADC;
|
||
|
config->h_dma.config.channel = config->dma_ch;
|
||
|
ald_dma_config_basic(&config->h_dma);
|
||
|
ald_dma_interrupt_config(config->dma_ch, ALD_DMA_IT_FLAG_TC, ENABLE);
|
||
|
|
||
|
SET_BIT(config->h_adc.perh->CON1, ADC_CON1_DMA_MSK);
|
||
|
ALD_ADC_ENABLE(&config->h_adc);
|
||
|
ald_timer_base_start(&config->h_timer);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get ADC normal group conversion result.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval ADC group normal conversion data
|
||
|
*/
|
||
|
uint32_t ald_adc_normal_get_value(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
return hperh->perh->NCHDR;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Enables ADC, starts conversion of insert group.
|
||
|
* Interruptions enabled in this function: None.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_insert_start(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
ALD_ADC_ENABLE(hperh);
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_ICH);
|
||
|
|
||
|
if (!(READ_BIT(hperh->perh->CON0, ADC_CON0_IAUTO_MSK)))
|
||
|
SET_BIT(hperh->perh->CON1, ADC_CON1_ICHTRG_MSK);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Stop conversion of insert channels. Disable ADC peripheral if
|
||
|
* no normal conversion is on going.
|
||
|
* @note If ADC must be disabled and if conversion is on going on
|
||
|
* normal group, function ald_adc_normal_stop must be used to stop both
|
||
|
* insert and normal groups, and disable the ADC.
|
||
|
* @note If insert group mode auto-injection is enabled,
|
||
|
* function ald_adc_normal_stop must be used.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_insert_stop(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
ALD_ADC_DISABLE(hperh);
|
||
|
hperh->state = ALD_ADC_STATE_READY;
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Wait for insert group conversion to be completed.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param timeout: Timeout value in millisecond.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_insert_poll_for_conversion(ald_adc_handle_t *hperh, uint32_t timeout)
|
||
|
{
|
||
|
uint32_t _tick;
|
||
|
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
_tick = ald_get_tick();
|
||
|
|
||
|
while (!(READ_BIT(hperh->perh->STAT, ADC_STAT_ICHE_MSK))) {
|
||
|
if (timeout != ALD_MAX_DELAY) {
|
||
|
if ((timeout == 0) || ((ald_get_tick() - _tick) > timeout)) {
|
||
|
hperh->state |= ALD_ADC_STATE_TIMEOUT;
|
||
|
return ALD_TIMEOUT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_ICHS | ALD_ADC_FLAG_ICH);
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Enables ADC, starts conversion of insert group with interruption.
|
||
|
* - JEOC (end of conversion of insert group)
|
||
|
* Each of these interruptions has its dedicated callback function.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval Status, see @ref ald_status_t..
|
||
|
*/
|
||
|
ald_status_t ald_adc_insert_start_by_it(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
SET_BIT(hperh->state, ALD_ADC_STATE_BUSY_I);
|
||
|
ALD_ADC_ENABLE(hperh);
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_ICHS | ALD_ADC_FLAG_ICH);
|
||
|
ald_adc_interrupt_config(hperh, ALD_ADC_IT_ICH, ENABLE);
|
||
|
|
||
|
if (!(READ_BIT(hperh->perh->CON0, ADC_CON0_IAUTO_MSK)))
|
||
|
SET_BIT(hperh->perh->CON1, ADC_CON1_ICHTRG_MSK);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Stop conversion of insert channels, disable interruption of
|
||
|
* end-of-conversion. Disable ADC peripheral if no normal conversion
|
||
|
* is on going.
|
||
|
* @note If ADC must be disabled and if conversion is on going on
|
||
|
* normal group, function ald_adc_normal_stop must be used to stop both
|
||
|
* insert and normal groups, and disable the ADC.
|
||
|
* @note If insert group mode auto-injection is enabled,
|
||
|
* function ald_adc_normal_stop must be used.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval None
|
||
|
*/
|
||
|
ald_status_t ald_adc_insert_stop_by_it(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
CLEAR_BIT(hperh->state, ALD_ADC_STATE_BUSY_I);
|
||
|
ALD_ADC_DISABLE(hperh);
|
||
|
ald_adc_interrupt_config(hperh, ALD_ADC_IT_ICH, DISABLE);
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get ADC insert group conversion result.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param idx: Index of converted ADC insert channel.
|
||
|
* @retval ADC group insert conversion data
|
||
|
*/
|
||
|
uint32_t ald_adc_insert_get_value(ald_adc_handle_t *hperh, ald_adc_ich_idx_t idx)
|
||
|
{
|
||
|
uint32_t tmp;
|
||
|
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_ICH_IDX_TYPE(idx));
|
||
|
|
||
|
switch (idx) {
|
||
|
case ALD_ADC_ICH_IDX_1:
|
||
|
tmp = hperh->perh->ICHDR1;
|
||
|
break;
|
||
|
case ALD_ADC_ICH_IDX_2:
|
||
|
tmp = hperh->perh->ICHDR2;
|
||
|
break;
|
||
|
case ALD_ADC_ICH_IDX_3:
|
||
|
tmp = hperh->perh->ICHDR3;
|
||
|
break;
|
||
|
case ALD_ADC_ICH_IDX_4:
|
||
|
tmp = hperh->perh->ICHDR4;
|
||
|
break;
|
||
|
default:
|
||
|
tmp = hperh->perh->ICHDR1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Handles ADC interrupt request
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval None
|
||
|
*/
|
||
|
void ald_adc_irq_handler(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
|
||
|
if (ald_adc_get_it_status(hperh, ALD_ADC_IT_NCH) && ald_adc_get_flag_status(hperh, ALD_ADC_FLAG_NCH)) {
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_NCH | ALD_ADC_FLAG_NCHS);
|
||
|
CLEAR_BIT(hperh->state, ALD_ADC_STATE_BUSY_N);
|
||
|
|
||
|
if (hperh->normal_cplt_cbk)
|
||
|
hperh->normal_cplt_cbk(hperh);
|
||
|
}
|
||
|
|
||
|
if (ald_adc_get_it_status(hperh, ALD_ADC_IT_ICH) && ald_adc_get_flag_status(hperh, ALD_ADC_FLAG_ICH)) {
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_ICH | ALD_ADC_FLAG_ICHS);
|
||
|
CLEAR_BIT(hperh->state, ALD_ADC_STATE_BUSY_I);
|
||
|
|
||
|
if (hperh->insert_cplt_cbk)
|
||
|
hperh->insert_cplt_cbk(hperh);
|
||
|
}
|
||
|
|
||
|
if (ald_adc_get_it_status(hperh, ALD_ADC_IT_AWD) && ald_adc_get_flag_status(hperh, ALD_ADC_FLAG_AWD)) {
|
||
|
CLEAR_BIT(hperh->state, ALD_ADC_STATE_BUSY_WDG);
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_AWD);
|
||
|
|
||
|
if (hperh->wdg_cbk)
|
||
|
hperh->wdg_cbk(hperh);
|
||
|
}
|
||
|
|
||
|
if (ald_adc_get_it_status(hperh, ALD_ADC_IT_OVR) && ald_adc_get_flag_status(hperh, ALD_ADC_FLAG_OVR)) {
|
||
|
WRITE_REG(hperh->perh->CLR, ALD_ADC_FLAG_OVR);
|
||
|
hperh->error_code |= ALD_ADC_ERROR_OVR;
|
||
|
hperh->state |= ALD_ADC_STATE_ERROR;
|
||
|
|
||
|
if (hperh->ovr_cbk)
|
||
|
hperh->ovr_cbk(hperh);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/** @defgroup ADC_Public_Functions_Group3 Peripheral Control functions
|
||
|
* @brief Peripheral Control functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @brief Configures the the selected channel to be linked to the normal
|
||
|
* group.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param config: Structure of ADC channel for normal group.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_normal_channel_config(ald_adc_handle_t *hperh, ald_adc_nch_conf_t *config)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_CHANNELS_TYPE(config->ch));
|
||
|
assert_param(IS_ADC_NCH_IDX_TYPE(config->idx));
|
||
|
assert_param(IS_ADC_SAMPLING_TIMES_TYPE(config->samp));
|
||
|
|
||
|
if (config->idx <= ALD_ADC_NCH_IDX_4 ) {
|
||
|
hperh->perh->NCHS1 &= ~(0x1f << (uint32_t)((config->idx - 1) << 3));
|
||
|
hperh->perh->NCHS1 |= (config->ch << (uint32_t)((config->idx - 1) << 3));
|
||
|
}
|
||
|
else if (config->idx <= ALD_ADC_NCH_IDX_8) {
|
||
|
hperh->perh->NCHS2 &= ~(0x1f << (uint32_t)((config->idx - 5) << 3));
|
||
|
hperh->perh->NCHS2 |= (config->ch << (uint32_t)((config->idx - 5) << 3));
|
||
|
}
|
||
|
else if (config->idx <= ALD_ADC_NCH_IDX_12) {
|
||
|
hperh->perh->NCHS3 &= ~(0x1f << (uint32_t)((config->idx - 9) << 3));
|
||
|
hperh->perh->NCHS3 |= (config->ch << (uint32_t)((config->idx - 9) << 3));
|
||
|
}
|
||
|
else {
|
||
|
hperh->perh->NCHS4 &= ~(0x1f << (uint32_t)((config->idx - 13) << 3));
|
||
|
hperh->perh->NCHS4 |= (config->ch << (uint32_t)((config->idx - 13) << 3));
|
||
|
}
|
||
|
|
||
|
if (config->ch < ALD_ADC_CHANNEL_8) {
|
||
|
hperh->perh->SMPT1 &= ~(0xf << (uint32_t)(config->ch << 2));
|
||
|
hperh->perh->SMPT1 |= config->samp << (uint32_t)(config->ch << 2);
|
||
|
}
|
||
|
else if (config->ch < ALD_ADC_CHANNEL_16) {
|
||
|
hperh->perh->SMPT2 &= ~(0xf << (uint32_t)((config->ch - ALD_ADC_CHANNEL_8) << 2));
|
||
|
hperh->perh->SMPT2 |= config->samp << (uint32_t)((config->ch - ALD_ADC_CHANNEL_8) << 2);
|
||
|
}
|
||
|
else {
|
||
|
hperh->perh->SMPT3 &= ~(0xf << (uint32_t)((config->ch - ALD_ADC_CHANNEL_16) << 2));
|
||
|
hperh->perh->SMPT3 |= config->samp << (uint32_t)((config->ch - ALD_ADC_CHANNEL_16) << 2);
|
||
|
}
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configures the the selected channel to be linked to the insert
|
||
|
* group.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param config: Structure of ADC channel for insert group.
|
||
|
* @retval Status, see @ref ald_status_t.
|
||
|
*/
|
||
|
ald_status_t ald_adc_insert_channel_config(ald_adc_handle_t *hperh, ald_adc_ich_conf_t *config)
|
||
|
{
|
||
|
ald_status_t tmp_status = ALD_OK;
|
||
|
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_CHANNELS_TYPE(config->ch));
|
||
|
assert_param(IS_ADC_ICH_IDX_TYPE(config->idx));
|
||
|
assert_param(IS_ADC_SAMPLING_TIMES_TYPE(config->samp));
|
||
|
assert_param(IS_ADC_IST_OFFSET_TYPE(config->offset));
|
||
|
assert_param(IS_ADC_ICH_NR_TYPE(config->nr));
|
||
|
assert_param(IS_FUNC_STATE(config->auto_m));
|
||
|
|
||
|
MODIFY_REG(hperh->perh->CHSL, ADC_CHSL_ISL_MSK, config->nr << ADC_CHSL_ISL_POSS);
|
||
|
hperh->perh->ICHS &= ~(0x1f << (uint32_t)((config->idx - 1) << 3));
|
||
|
hperh->perh->ICHS |= config->ch << (uint32_t)((config->idx - 1) << 3);
|
||
|
|
||
|
if (config->auto_m == ENABLE)
|
||
|
SET_BIT(hperh->perh->CON0, ADC_CON0_IAUTO_MSK);
|
||
|
else
|
||
|
CLEAR_BIT(hperh->perh->CON0, ADC_CON0_IAUTO_MSK);
|
||
|
|
||
|
if (hperh->init.disc == ALD_ADC_ICH_DISC_EN) {
|
||
|
if (config->auto_m == DISABLE) {
|
||
|
SET_BIT(hperh->perh->CON0, ADC_CON0_ICHDCEN_MSK);
|
||
|
}
|
||
|
else {
|
||
|
hperh->state |= ALD_ADC_STATE_ERROR;
|
||
|
hperh->error_code |= ALD_ADC_ERROR_INTERNAL;
|
||
|
tmp_status = ALD_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (config->ch < 8) {
|
||
|
hperh->perh->SMPT1 &= ~(0x0f << (uint32_t)(config->ch << 2));
|
||
|
hperh->perh->SMPT1 |= config->samp << (uint32_t)(config->ch << 2);
|
||
|
}
|
||
|
else if (config->ch < 16) {
|
||
|
hperh->perh->SMPT2 &= ~(0x0f << (uint32_t)((config->ch - 8) << 2));
|
||
|
hperh->perh->SMPT2 |= config->samp << (uint32_t)((config->ch - 8) << 2);
|
||
|
}
|
||
|
else {
|
||
|
hperh->perh->SMPT3 &= ~(0x0f << (uint32_t)((config->ch - 16) << 2));
|
||
|
hperh->perh->SMPT3 |= config->samp << (uint32_t)((config->ch - 16) << 2);
|
||
|
}
|
||
|
|
||
|
switch (config->idx) {
|
||
|
case ALD_ADC_ICH_IDX_1:
|
||
|
hperh->perh->ICHOFF1 = config->offset;
|
||
|
break;
|
||
|
case ALD_ADC_ICH_IDX_2:
|
||
|
hperh->perh->ICHOFF2 = config->offset;
|
||
|
break;
|
||
|
case ALD_ADC_ICH_IDX_3:
|
||
|
hperh->perh->ICHOFF3 = config->offset;
|
||
|
break;
|
||
|
case ALD_ADC_ICH_IDX_4:
|
||
|
hperh->perh->ICHOFF4 = config->offset;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return tmp_status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configures the analog watchdog.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @param config: Structure of ADC analog watchdog configuration
|
||
|
* @retval ALD status
|
||
|
*/
|
||
|
ald_status_t ald_adc_analog_wdg_config(ald_adc_handle_t *hperh, ald_adc_analog_wdg_conf_t *config)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_ANALOG_WTD_MODE_TYPE(config->mode));
|
||
|
assert_param(IS_FUNC_STATE(config->interrupt));
|
||
|
assert_param(IS_HTR_TYPE(config->high_thrd));
|
||
|
assert_param(IS_LTR_TYPE(config->low_thrd));
|
||
|
|
||
|
if ((config->mode == ALD_ADC_ANAWTD_SING_NM)
|
||
|
|| (config->mode == ALD_ADC_ANAWTD_SING_IST)
|
||
|
|| (config->mode == ALD_ADC_ANAWTD_SING_NMIST))
|
||
|
assert_param(IS_ADC_CHANNELS_TYPE(config->ch));
|
||
|
|
||
|
if (config->interrupt == DISABLE)
|
||
|
ald_adc_interrupt_config(hperh, ALD_ADC_IT_AWD, DISABLE);
|
||
|
else
|
||
|
ald_adc_interrupt_config(hperh, ALD_ADC_IT_AWD, ENABLE);
|
||
|
|
||
|
CLEAR_BIT(hperh->perh->CON0, ADC_CON0_ICHWDTEN_MSK);
|
||
|
CLEAR_BIT(hperh->perh->CON0, ADC_CON0_NCHWDEN_MSK);
|
||
|
CLEAR_BIT(hperh->perh->CON0, ADC_CON0_AWDSGL_MSK);
|
||
|
hperh->perh->CON0 |= config->mode;
|
||
|
|
||
|
if (READ_BIT(hperh->perh->CON0, ADC_CON0_AWDSGL_MSK))
|
||
|
MODIFY_REG(hperh->perh->CON0, ADC_CON0_AWDCH_MSK, config->ch << ADC_CON0_AWDCH_POSS);
|
||
|
|
||
|
WRITE_REG(hperh->perh->WDTL, config->low_thrd);
|
||
|
WRITE_REG(hperh->perh->WDTH, config->high_thrd);
|
||
|
SET_BIT(hperh->state, ALD_ADC_STATE_BUSY_WDG);
|
||
|
|
||
|
return ALD_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Enables or disables the specified ADC interrupts.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure.
|
||
|
* @param it: Specifies the ADC interrupt sources to be enabled or disabled.
|
||
|
* This parameter can be one of the @ref adc_it_t.
|
||
|
* @param state: New status
|
||
|
* - ENABLE
|
||
|
* - DISABLE
|
||
|
* @retval None
|
||
|
*/
|
||
|
void ald_adc_interrupt_config(ald_adc_handle_t *hperh, ald_adc_it_t it, type_func_t state)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_IT_TYPE(it));
|
||
|
assert_param(IS_FUNC_STATE(state));
|
||
|
|
||
|
if (state == ENABLE)
|
||
|
SET_BIT(hperh->perh->CON0, it);
|
||
|
else
|
||
|
CLEAR_BIT(hperh->perh->CON0, it);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Checks whether the specified ADC interrupt has occurred or not.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure.
|
||
|
* @param it: Specifies the ADC interrupt source to check.
|
||
|
* This parameter can be one of the @ref adc_it_t.
|
||
|
* @retval Status
|
||
|
* - SET
|
||
|
* - RESET
|
||
|
*/
|
||
|
it_status_t ald_adc_get_it_status(ald_adc_handle_t *hperh, ald_adc_it_t it)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_IT_TYPE(it));
|
||
|
|
||
|
if (READ_BIT(hperh->perh->CON0, it))
|
||
|
return SET;
|
||
|
|
||
|
return RESET;
|
||
|
}
|
||
|
|
||
|
/** @brief Check whether the specified ADC flag is set or not.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure.
|
||
|
* @param flag: specifies the flag to check.
|
||
|
* This parameter can be one of the @ref adc_flag_t.
|
||
|
* @retval Status
|
||
|
* - SET
|
||
|
* - RESET
|
||
|
*/
|
||
|
flag_status_t ald_adc_get_flag_status(ald_adc_handle_t *hperh, ald_adc_flag_t flag)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_FLAGS_TYPE(flag));
|
||
|
|
||
|
if (READ_BIT(hperh->perh->STAT, flag))
|
||
|
return SET;
|
||
|
|
||
|
return RESET;
|
||
|
}
|
||
|
|
||
|
/** @brief Clear the specified ADC pending flags.
|
||
|
* @param hperh: Pointer to a adc_handle_t structure.
|
||
|
* @param flag: specifies the flag to check.
|
||
|
* This parameter can be one of the @ref adc_flag_t.
|
||
|
* @retval None
|
||
|
*/
|
||
|
void ald_adc_clear_flag_status(ald_adc_handle_t *hperh, ald_adc_flag_t flag)
|
||
|
{
|
||
|
assert_param(IS_ADC_TYPE(hperh->perh));
|
||
|
assert_param(IS_ADC_FLAGS_TYPE(flag));
|
||
|
|
||
|
WRITE_REG(hperh->perh->CLR, flag);
|
||
|
return;
|
||
|
}
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/** @defgroup ADC_Public_Functions_Group4 Peripheral State functions
|
||
|
* @brief Peripheral State functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @brief return the ADC state
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval state
|
||
|
*/
|
||
|
uint32_t ald_adc_get_state(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
return hperh->state;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Return the ADC error code
|
||
|
* @param hperh: Pointer to a adc_handle_t structure that contains
|
||
|
* the configuration information for the specified ADC module.
|
||
|
* @retval ADC Error Code
|
||
|
*/
|
||
|
uint32_t ald_adc_get_error(ald_adc_handle_t *hperh)
|
||
|
{
|
||
|
return hperh->error_code;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*@}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
*@}
|
||
|
*/
|
||
|
|
||
|
/** @defgroup ADC_Private_Functions ADC Private Functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @brief DMA transfer complete callback.
|
||
|
* @param arg: argument of the call back.
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void adc_dma_normal_conv_cplt(void *arg)
|
||
|
{
|
||
|
ald_adc_handle_t *hperh = (ald_adc_handle_t *)arg;
|
||
|
|
||
|
CLEAR_BIT(hperh->perh->CON1, ADC_CON1_DMA_MSK);
|
||
|
|
||
|
if (hperh->normal_cplt_cbk)
|
||
|
hperh->normal_cplt_cbk(hperh);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*@}
|
||
|
*/
|
||
|
/**
|
||
|
*@}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
*@}
|
||
|
*/
|