184 lines
4.2 KiB
C
184 lines
4.2 KiB
C
|
/**************************************************************************//**
|
||
|
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*
|
||
|
* Change Logs:
|
||
|
* Date Author Notes
|
||
|
* 2022-3-16 Wayne First version
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
#include <rtconfig.h>
|
||
|
#include <rtdevice.h>
|
||
|
#include "NuMicro.h"
|
||
|
|
||
|
#if defined(BSP_USING_EADC)
|
||
|
|
||
|
/* Private define ---------------------------------------------------------------*/
|
||
|
enum
|
||
|
{
|
||
|
EADC_START = -1,
|
||
|
#if defined(BSP_USING_EADC0)
|
||
|
EADC0_IDX,
|
||
|
#endif
|
||
|
#if defined(BSP_USING_EADC1)
|
||
|
EADC1_IDX,
|
||
|
#endif
|
||
|
#if defined(BSP_USING_EADC2)
|
||
|
EADC2_IDX,
|
||
|
#endif
|
||
|
EADC_CNT
|
||
|
};
|
||
|
|
||
|
/* Private Typedef --------------------------------------------------------------*/
|
||
|
struct nu_eadc
|
||
|
{
|
||
|
struct rt_adc_device dev;
|
||
|
char *name;
|
||
|
EADC_T *base;
|
||
|
uint32_t chn_msk;
|
||
|
uint32_t max_chn_num;
|
||
|
};
|
||
|
typedef struct nu_eadc *nu_eadc_t;
|
||
|
|
||
|
/* Private functions ------------------------------------------------------------*/
|
||
|
static rt_err_t nu_eadc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled);
|
||
|
static rt_err_t nu_get_eadc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value);
|
||
|
static rt_err_t nu_get_eadc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value);
|
||
|
|
||
|
/* Public functions ------------------------------------------------------------*/
|
||
|
int rt_hw_eadc_init(void);
|
||
|
|
||
|
/* Private variables ------------------------------------------------------------*/
|
||
|
|
||
|
static struct nu_eadc nu_eadc_arr [] =
|
||
|
{
|
||
|
#if defined(BSP_USING_EADC0)
|
||
|
{
|
||
|
.name = "eadc0",
|
||
|
.base = EADC0,
|
||
|
.chn_msk = 0,
|
||
|
.max_chn_num = 16,
|
||
|
},
|
||
|
#endif
|
||
|
#if defined(BSP_USING_EADC1)
|
||
|
{
|
||
|
.name = "eadc1",
|
||
|
.base = EADC1,
|
||
|
.chn_msk = 0,
|
||
|
.max_chn_num = 16,
|
||
|
},
|
||
|
#endif
|
||
|
#if defined(BSP_USING_EADC2)
|
||
|
{
|
||
|
.name = "eadc2",
|
||
|
.base = EADC2,
|
||
|
.chn_msk = 0,
|
||
|
.max_chn_num = 16,
|
||
|
},
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
static const struct rt_adc_ops nu_adc_ops =
|
||
|
{
|
||
|
nu_eadc_enabled,
|
||
|
nu_get_eadc_value,
|
||
|
};
|
||
|
typedef struct rt_adc_ops *rt_adc_ops_t;
|
||
|
|
||
|
|
||
|
/* nu_adc_enabled - Enable ADC clock and wait for ready */
|
||
|
static rt_err_t nu_eadc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
|
||
|
{
|
||
|
nu_eadc_t psNuEADC = (nu_eadc_t)device;
|
||
|
|
||
|
RT_ASSERT(device);
|
||
|
|
||
|
if (channel >= psNuEADC->max_chn_num)
|
||
|
return -(RT_EINVAL);
|
||
|
|
||
|
if (enabled)
|
||
|
{
|
||
|
if (psNuEADC->chn_msk == 0)
|
||
|
{
|
||
|
EADC_Open(psNuEADC->base, EADC_CTL_DIFFEN_SINGLE_END);
|
||
|
}
|
||
|
|
||
|
psNuEADC->chn_msk |= (0x1 << channel);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
psNuEADC->chn_msk &= ~(0x1 << channel);
|
||
|
|
||
|
if (psNuEADC->chn_msk == 0)
|
||
|
{
|
||
|
EADC_Close(psNuEADC->base);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
static rt_err_t nu_get_eadc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
|
||
|
{
|
||
|
nu_eadc_t psNuEADC = (nu_eadc_t)device;
|
||
|
rt_err_t ret = RT_ERROR;
|
||
|
|
||
|
RT_ASSERT(device);
|
||
|
RT_ASSERT(value);
|
||
|
|
||
|
if (channel >= psNuEADC->max_chn_num)
|
||
|
{
|
||
|
*value = 0xFFFFFFFF;
|
||
|
ret = RT_EINVAL;
|
||
|
goto exit_nu_get_eadc_value;
|
||
|
}
|
||
|
|
||
|
if ((psNuEADC->chn_msk & (1 << channel)) == 0)
|
||
|
{
|
||
|
*value = 0xFFFFFFFF;
|
||
|
ret = RT_EBUSY;
|
||
|
goto exit_nu_get_eadc_value;
|
||
|
}
|
||
|
|
||
|
EADC_ConfigSampleModule(psNuEADC->base, 0, EADC_SOFTWARE_TRIGGER, channel);
|
||
|
|
||
|
EADC_CLR_INT_FLAG(psNuEADC->base, EADC_STATUS2_ADIF0_Msk);
|
||
|
|
||
|
EADC_ENABLE_INT(psNuEADC->base, BIT0);
|
||
|
|
||
|
EADC_ENABLE_SAMPLE_MODULE_INT(psNuEADC->base, 0, BIT0);
|
||
|
|
||
|
EADC_START_CONV(psNuEADC->base, BIT0);
|
||
|
|
||
|
while (EADC_GET_INT_FLAG(psNuEADC->base, BIT0) == 0);
|
||
|
|
||
|
EADC_DISABLE_INT(psNuEADC->base, BIT0);
|
||
|
|
||
|
*value = EADC_GET_CONV_DATA(psNuEADC->base, 0);
|
||
|
|
||
|
ret = RT_EOK;
|
||
|
|
||
|
exit_nu_get_eadc_value:
|
||
|
|
||
|
return -(ret);
|
||
|
}
|
||
|
|
||
|
int rt_hw_eadc_init(void)
|
||
|
{
|
||
|
int i;
|
||
|
rt_err_t result;
|
||
|
|
||
|
for (i = (EADC_START + 1); i < EADC_CNT; i++)
|
||
|
{
|
||
|
result = rt_hw_adc_register(&nu_eadc_arr[i].dev, nu_eadc_arr[i].name, &nu_adc_ops, NULL);
|
||
|
RT_ASSERT(result == RT_EOK);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
INIT_BOARD_EXPORT(rt_hw_eadc_init);
|
||
|
|
||
|
#endif //#if defined(BSP_USING_EADC)
|