mirror of https://github.com/RT-Thread/rt-thread
bsp: k230: support adc
Signed-off-by: Chen Wang <unicorn_wang@outlook.com>
This commit is contained in:
parent
01ca3911ec
commit
fe506d5157
|
@ -1490,6 +1490,7 @@ CONFIG_PKG_ZLIB_VER="latest"
|
||||||
#
|
#
|
||||||
# Drivers Configuration
|
# Drivers Configuration
|
||||||
#
|
#
|
||||||
|
# CONFIG_BSP_USING_ADC is not set
|
||||||
CONFIG_BSP_USING_HARDLOCK=y
|
CONFIG_BSP_USING_HARDLOCK=y
|
||||||
CONFIG_BSP_USING_SDIO=y
|
CONFIG_BSP_USING_SDIO=y
|
||||||
CONFIG_BSP_USING_SDIO0=y
|
CONFIG_BSP_USING_SDIO0=y
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
menu "Drivers Configuration"
|
menu "Drivers Configuration"
|
||||||
|
|
||||||
|
config BSP_USING_ADC
|
||||||
|
bool "Enable ADC"
|
||||||
|
select RT_USING_ADC
|
||||||
|
default n
|
||||||
|
|
||||||
config BSP_USING_HARDLOCK
|
config BSP_USING_HARDLOCK
|
||||||
bool "Enable Hard-Lock"
|
bool "Enable Hard-Lock"
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# RT-Thread building script for component
|
||||||
|
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = Glob('*.c')
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
group = DefineGroup('ADC', src, depend = ['BSP_USING_ADC'], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
Return('group')
|
|
@ -0,0 +1,162 @@
|
||||||
|
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2025 RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <drivers/adc.h>
|
||||||
|
#include <ioremap.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
#include <riscv_io.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "drv_adc.h"
|
||||||
|
|
||||||
|
struct k230_adc adc_dev;
|
||||||
|
|
||||||
|
static int k230_adc_hw_init(struct k230_adc_regs *adc_regs)
|
||||||
|
{
|
||||||
|
rt_uint32_t reg;
|
||||||
|
|
||||||
|
reg = readl(&adc_regs->trim_reg);
|
||||||
|
reg &= (~(0x1));
|
||||||
|
writel(reg, &adc_regs->trim_reg);
|
||||||
|
|
||||||
|
reg = readl(&adc_regs->trim_reg);
|
||||||
|
reg |= 0x1;
|
||||||
|
writel(reg, &adc_regs->trim_reg);
|
||||||
|
|
||||||
|
reg = readl(&adc_regs->trim_reg);
|
||||||
|
reg |= (0x1 << 20);
|
||||||
|
writel(reg, &adc_regs->trim_reg);
|
||||||
|
|
||||||
|
/* delay 150us */
|
||||||
|
rt_hw_us_delay(150);
|
||||||
|
|
||||||
|
reg &= ~(0x1 << 20);
|
||||||
|
writel(reg, &adc_regs->trim_reg);
|
||||||
|
|
||||||
|
writel(0x0, &adc_regs->mode_reg);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int k230_adc_init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
adc_dev.adc_regs = (struct k230_adc_regs*)rt_ioremap((void *)ADC_BASE_ADDR, ADC_IO_SIZE);
|
||||||
|
|
||||||
|
for (i = 0; i < ADC_MAX_DMA_CHN; i++)
|
||||||
|
{
|
||||||
|
adc_dev.chn[i].chn_num = i;
|
||||||
|
adc_dev.chn[i].enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
k230_adc_hw_init(adc_dev.adc_regs);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int k_adc_drv_enabled(struct k230_adc_regs *adc_regs)
|
||||||
|
{
|
||||||
|
rt_uint32_t reg;
|
||||||
|
|
||||||
|
reg = readl(&adc_regs->trim_reg);
|
||||||
|
reg |= 0x1;
|
||||||
|
writel(reg, &adc_regs->trim_reg);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int k_adc_drv_disabled(struct k230_adc_regs *adc_regs)
|
||||||
|
{
|
||||||
|
rt_uint32_t reg;
|
||||||
|
|
||||||
|
reg = readl(&adc_regs->trim_reg);
|
||||||
|
reg = reg & (~(0x1));
|
||||||
|
writel(reg, &adc_regs->trim_reg);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_err_t k230_adc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
|
||||||
|
{
|
||||||
|
if (channel >= ADC_MAX_CHANNEL)
|
||||||
|
return -RT_ERROR;
|
||||||
|
|
||||||
|
struct k230_adc *kd_adc = rt_container_of(device, struct k230_adc, dev);
|
||||||
|
|
||||||
|
kd_adc->chn[channel].enabled = 1;
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
kd_adc->chn[channel].enabled = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kd_adc->chn[channel].enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_err_t k230_get_adc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
|
||||||
|
{
|
||||||
|
if (channel >= ADC_MAX_CHANNEL)
|
||||||
|
return -RT_ERROR;
|
||||||
|
|
||||||
|
struct k230_adc *kd_adc = rt_container_of(device, struct k230_adc, dev);
|
||||||
|
|
||||||
|
if (!kd_adc->chn[channel].enabled)
|
||||||
|
return -RT_ERROR;
|
||||||
|
|
||||||
|
writel(channel | 0x10, &kd_adc->adc_regs->cfg_reg);
|
||||||
|
while ((readl(&kd_adc->adc_regs->cfg_reg) & 0x10000) == 0);
|
||||||
|
*value = readl(&kd_adc->adc_regs->data_reg[channel]);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rt_adc_ops k230_adc_ops =
|
||||||
|
{
|
||||||
|
.enabled = k230_adc_enabled,
|
||||||
|
.convert = k230_get_adc_value,
|
||||||
|
};
|
||||||
|
|
||||||
|
int rt_hw_adc_init(void)
|
||||||
|
{
|
||||||
|
k230_adc_init();
|
||||||
|
|
||||||
|
rt_hw_adc_register(&adc_dev.dev, K230_ADC_NAME, &k230_adc_ops, NULL);
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
INIT_BOARD_EXPORT(rt_hw_adc_init);
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2025 RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DRV_ADC__
|
||||||
|
#define __DRV_ADC__
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
#define K230_ADC_NAME "adc"
|
||||||
|
|
||||||
|
#define ADC_MAX_CHANNEL 6
|
||||||
|
#define ADC_MAX_DMA_CHN 3
|
||||||
|
|
||||||
|
struct k230_adc_regs
|
||||||
|
{
|
||||||
|
rt_uint32_t trim_reg; /**< 0x00 */
|
||||||
|
rt_uint32_t cfg_reg; /**< 0x04 */
|
||||||
|
rt_uint32_t mode_reg; /**< 0x08 */
|
||||||
|
rt_uint32_t thsd_reg; /**< 0x0c */
|
||||||
|
rt_uint32_t dma_intr_reg; /**< 0x10 */
|
||||||
|
rt_uint32_t data_reg[ADC_MAX_CHANNEL]; /**< 0x14~0x28 */
|
||||||
|
rt_uint32_t data_dma[ADC_MAX_DMA_CHN]; /**< 0x2c~0x34 */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct k230_adc_chan
|
||||||
|
{
|
||||||
|
rt_uint32_t chn_num;
|
||||||
|
rt_int8_t enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct k230_adc
|
||||||
|
{
|
||||||
|
struct rt_adc_device dev;
|
||||||
|
struct k230_adc_regs *adc_regs;
|
||||||
|
struct k230_adc_chan chn[ADC_MAX_CHANNEL];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*__DRV_ADC__*/
|
|
@ -6,6 +6,9 @@ if GetDepend('RT_UTEST_USING_ALL_CASES') or GetDepend('BSP_UTEST_DRIVERS'):
|
||||||
src += ['test_gpio.c']
|
src += ['test_gpio.c']
|
||||||
src += ['test_gpio_irq.c']
|
src += ['test_gpio_irq.c']
|
||||||
|
|
||||||
|
if GetDepend('BSP_USING_ADC'):
|
||||||
|
src += ['test_adc.c']
|
||||||
|
|
||||||
if GetDepend('BSP_USING_TIMERS'):
|
if GetDepend('BSP_USING_TIMERS'):
|
||||||
src += ['test_timer.c']
|
src += ['test_timer.c']
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/* Copyright 2020 Canaan Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "../interdrv/adc/drv_adc.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 测试 ADC 驱动的读操作
|
||||||
|
* 1. 查找 ADC 设备。
|
||||||
|
* 2. 启用 ADC 设备。
|
||||||
|
* 3. 启用每个 ADC 通道并读取其值。
|
||||||
|
* 4. 验证读取的值在预期范围内。
|
||||||
|
* 5. 禁用每个 ADC 通道并验证读取值为 0。
|
||||||
|
*
|
||||||
|
* 本测试基于 01Studio 开发板,该开发板自带排针,并引出 SoC 的以下 4 个 ADC 通道
|
||||||
|
* 板级排针编号 | SoC 的 ADC 通道编号 | 输入电压范围
|
||||||
|
* -------------+---------------------+-------------
|
||||||
|
* 32 | ADC0 | (0 ~ 3.6V)
|
||||||
|
* 36 | ADC1 | (0 ~ 3.6V)
|
||||||
|
* 38 | ADC2 | (0 ~ 1.8V)
|
||||||
|
* 40 | ADC3 | (0 ~ 1.8V)
|
||||||
|
* SoC 的 ADC 通道默认只支持最大 1.8V 的输入电压,对于 ADC0 和 ADC1 通道,开发板
|
||||||
|
* 通过增加功放将最大支持电压提升到 3.6V(而且同样采用了分压机制,导致实际 ADC
|
||||||
|
* 通道的输入电压只有板级排针电压的一半)。
|
||||||
|
*
|
||||||
|
* 测试时注意连接输入的最大电压不要超过额定值,否则可能会损坏 ADC 通道。
|
||||||
|
*
|
||||||
|
* 另外注意这个adc 只有 12bit,所以读取的值范围是 0 ~ 4095
|
||||||
|
*
|
||||||
|
* 具体测试最大 1.8V 的 ADC 通道(譬如 38/40)时,可以自己通过两个 10K 欧姆的电
|
||||||
|
* 阻将模拟输入从 3.3V 分压(将可调电阻调制最大时万用表实测 A 点电压为 1.69V 左右):
|
||||||
|
* +----------+ +---------------+
|
||||||
|
* 3.3V ----| 10K 欧姆 |----| 可调 10K 欧姆 |---- 接地
|
||||||
|
* +----------+ +---------------+
|
||||||
|
* A
|
||||||
|
* |
|
||||||
|
* ADC2/ADC3
|
||||||
|
*
|
||||||
|
* 具体测试最大 3.6V 的 ADC 通道(譬如 32/36)时,可以直接引入 3.3V。
|
||||||
|
* +---------------+
|
||||||
|
* 3.3V --------------------| 可调 10K 欧姆 |---- 接地
|
||||||
|
* +---------------+
|
||||||
|
* A
|
||||||
|
* |
|
||||||
|
* ADC0/ADC1
|
||||||
|
*/
|
||||||
|
static void test_read(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
rt_err_t ret = RT_EOK;
|
||||||
|
rt_uint32_t value, vol;
|
||||||
|
rt_adc_device_t adc_dev;
|
||||||
|
|
||||||
|
adc_dev = (rt_adc_device_t)rt_device_find(K230_ADC_NAME);
|
||||||
|
uassert_not_null(adc_dev);
|
||||||
|
|
||||||
|
ret = rt_adc_enable(adc_dev, 0);
|
||||||
|
uassert_int_equal(ret, RT_EOK);
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
ret = rt_adc_enable(adc_dev, i);
|
||||||
|
uassert_int_equal(ret, RT_EOK);
|
||||||
|
|
||||||
|
value = rt_adc_read(adc_dev, i);
|
||||||
|
/* 转换为对应电压值,对应 12 位 ADC 最大值 4095, 内部基准最大电压值 1.8V,数据精度乘以 100 保留 2 位小数 */
|
||||||
|
vol = value * 180 / 4095;
|
||||||
|
if (i == 0 || i == 1)
|
||||||
|
vol = vol * 2; /* ADC0/ADC1 分压后实际电压是输入电压的二分之一 */
|
||||||
|
|
||||||
|
LOG_I("ADC chan[%d] read value: %d, calculated voltage is: %d.%02dV\n",
|
||||||
|
i, value, vol / 100, vol % 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ADC_MAX_CHANNEL; i++)
|
||||||
|
{
|
||||||
|
ret = rt_adc_disable(adc_dev, i);
|
||||||
|
uassert_int_equal(ret, RT_EOK);
|
||||||
|
|
||||||
|
value = rt_adc_read(adc_dev, i);
|
||||||
|
uassert_int_equal(value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t utest_tc_init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t utest_tc_cleanup(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testcase(void)
|
||||||
|
{
|
||||||
|
UTEST_UNIT_RUN(test_read);
|
||||||
|
}
|
||||||
|
UTEST_TC_EXPORT(testcase, "adc", utest_tc_init, utest_tc_cleanup, 100);
|
Loading…
Reference in New Issue