bsp: k230: support adc

Signed-off-by: Chen Wang <unicorn_wang@outlook.com>
This commit is contained in:
Chen Wang 2025-06-09 10:27:09 +08:00 committed by Rbb666
parent 01ca3911ec
commit fe506d5157
7 changed files with 365 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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);

View File

@ -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__*/

View File

@ -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']

View File

@ -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);