2025-10-10 16:07:00 +08:00

421 lines
10 KiB
C

// Copyright 2022-2023 Beken
//
// 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 <os/os.h>
#include <os/mem.h>
#include "sdmadc_hal.h"
#include "sys_driver.h"
#include <driver/int.h>
#include <driver/gpio.h>
#include "gpio_driver.h"
#include "sdmadc_driver.h"
typedef struct {
sdmadc_hal_t hal;
uint16_t chan_init_bits;
} adc_driver_t;
typedef struct {
beken_semaphore_t sdmadc_read_sema;
beken_mutex_t sdmadc_mutex;
} sdmadc_dev_t;
typedef struct {
int16_t *buf;
/* The size is in unit of uint16_t */
volatile uint16_t size;
volatile uint16_t sample_cnt;
} sdmadc_buf_t;
static bool s_sdmadc_driver_is_init = false;
static sdmadc_dev_t s_sdmadc_dev = {0};
static sdmadc_buf_t s_sdmadc_buf = {0};
static sdmadc_config_t s_sdmadc_config = {0};
sdmadc_calibrate_val sdmadc_val = {
#if (CONFIG_SOC_BK7236XX) || (CONFIG_SOC_BK7239XX)|| (CONFIG_SOC_BK7286XX)
24695, 31618 /* 1Volt:-8072, 2Volt:-1149 +32768 offset*/
#else
/*TBD*/
#endif
};
static void sdmadc_isr(void);
bk_err_t bk_sdmadc_set_cfg(sdmadc_config_t * config);
bk_err_t bk_sdmadc_driver_init(void)
{
int ret;
if (s_sdmadc_driver_is_init) {
return BK_OK;
}
if (s_sdmadc_buf.buf) {
os_free(s_sdmadc_buf.buf);
}
s_sdmadc_buf.size = CONFIG_SDMADC_BUF_SIZE;
s_sdmadc_buf.buf = (int16_t*)os_zalloc(CONFIG_SDMADC_BUF_SIZE << 1);
if (!s_sdmadc_buf.buf) {
return BK_ERR_NO_MEM;
}
if (!s_sdmadc_dev.sdmadc_mutex) {
ret = rtos_init_mutex(&s_sdmadc_dev.sdmadc_mutex);
if (kNoErr != ret) {
os_free(s_sdmadc_buf.buf);
return BK_FAIL;
}
}
if (!s_sdmadc_dev.sdmadc_read_sema) {
ret = rtos_init_semaphore(&(s_sdmadc_dev.sdmadc_read_sema), 1);
if (BK_OK != ret) {
os_free(s_sdmadc_buf.buf);
rtos_deinit_mutex(&s_sdmadc_dev.sdmadc_mutex);
return BK_FAIL;
}
}
bk_int_isr_register(INT_SRC_SDMADC, sdmadc_isr, NULL);
s_sdmadc_driver_is_init = true;
return BK_OK;
}
bk_err_t bk_sdmadc_driver_deinit(void)
{
if (!s_sdmadc_driver_is_init)
return BK_OK;
bk_int_isr_unregister(INT_SRC_SDMADC);
if (s_sdmadc_dev.sdmadc_mutex)
rtos_deinit_mutex(&s_sdmadc_dev.sdmadc_mutex);
if (s_sdmadc_dev.sdmadc_read_sema)
rtos_deinit_semaphore(&(s_sdmadc_dev.sdmadc_read_sema));
os_free(s_sdmadc_buf.buf);
s_sdmadc_buf.buf = NULL;
s_sdmadc_buf.size = 0;
os_memset(&s_sdmadc_dev, 0, sizeof(s_sdmadc_dev));
os_memset(&s_sdmadc_config, 0, sizeof(s_sdmadc_config));
s_sdmadc_driver_is_init = false;
return BK_OK;
}
bk_err_t bk_sdmadc_init()
{
if(!s_sdmadc_driver_is_init)
return BK_FAIL;
sdmadc_hal_enable_efuse_cken();
sdmadc_hal_enable_sample();
sys_hal_set_sdmadc_config();
return BK_OK;
}
bk_err_t bk_sdmadc_deinit()
{
sdmadc_hal_disable_sample();
return BK_OK;
}
bk_err_t bk_sdmadc_acquire()
{
return rtos_lock_mutex(&s_sdmadc_dev.sdmadc_mutex);
}
bk_err_t bk_sdmadc_release()
{
return rtos_unlock_mutex(&s_sdmadc_dev.sdmadc_mutex);
}
static void sdmadc_init_gpio(sdmadc_chan_t chan)
{
if (sdmadc_hal_is_analog_channel(chan))
return;
sdmadc_gpio_map_t sdmadc_map_table[] = SDMADC_DEV_MAP;
sdmadc_gpio_map_t *sdmadc_map = &sdmadc_map_table[chan];
gpio_dev_map(sdmadc_map->gpio_id, sdmadc_map->gpio_dev);
bk_gpio_disable_pull(sdmadc_map->gpio_id);
bk_gpio_disable_input(sdmadc_map->gpio_id);
bk_gpio_disable_output(sdmadc_map->gpio_id);
}
bk_err_t bk_sdmadc_start()
{
BK_LOG_ON_ERR(bk_sdmadc_acquire());
os_memset(s_sdmadc_buf.buf, 0, sizeof(s_sdmadc_buf.buf[0])*s_sdmadc_buf.size);
s_sdmadc_buf.sample_cnt = 0;
sdmadc_hal_disable_soft_rst();
sdmadc_hal_enable_int();
return BK_OK;
}
bk_err_t bk_sdmadc_stop()
{
sdmadc_hal_disable_int();
sdmadc_hal_enable_soft_rst();
s_sdmadc_buf.size = CONFIG_SDMADC_BUF_SIZE;
return bk_sdmadc_release();
}
bk_err_t bk_sdmadc_read_average(int16_t* average, uint32_t size)
{
if (size > s_sdmadc_buf.size) {
os_printf("size %d too big\r\n",size);
return BK_FAIL;
} else {
s_sdmadc_buf.size = size;
}
int32_t sum = 0;
bk_sdmadc_start();
rtos_get_semaphore(&(s_sdmadc_dev.sdmadc_read_sema),1000000);
for(int i = 1; i < s_sdmadc_buf.sample_cnt; ++i){
sum += s_sdmadc_buf.buf[i];
}
*average = sum/(s_sdmadc_buf.sample_cnt-1);
return BK_OK;
}
bk_err_t bk_sdmadc_single_read(int16_t* average, uint16_t channel)
{
int32_t sum = 0;
s_sdmadc_config.samp_mode = 0x1;
s_sdmadc_config.samp_numb = 0x3;
s_sdmadc_config.samp_chan = channel;
s_sdmadc_config.comp_bpss = 0x1;
s_sdmadc_config.cic2_bpss = 0x1;
s_sdmadc_config.cic2_gain = 0x2d;
s_sdmadc_config.int_enable = 0x1;
s_sdmadc_config.cali_offset = 0x0;
s_sdmadc_config.cali_gains = 0x1000;
bk_sdmadc_set_cfg(&s_sdmadc_config);
bk_sdmadc_start();
rtos_get_semaphore(&(s_sdmadc_dev.sdmadc_read_sema),1000000);
for(int i = 1; i < s_sdmadc_buf.sample_cnt; ++i){
sum += s_sdmadc_buf.buf[i];
}
*average = sum/(s_sdmadc_buf.sample_cnt-1);
return BK_OK;
}
bk_err_t bk_sdmadc_continuous_read(int16_t* average, uint32_t size, uint16_t channel)
{
if (size > s_sdmadc_buf.size) {
os_printf("size %d too big\r\n",size);
return BK_FAIL;
} else {
s_sdmadc_buf.size = size;
}
int32_t sum = 0;
s_sdmadc_config.samp_mode = 0x0;
s_sdmadc_config.samp_numb = 0x0;
s_sdmadc_config.samp_chan = channel;
s_sdmadc_config.comp_bpss = 0x1;
s_sdmadc_config.cic2_bpss = 0x1;
s_sdmadc_config.cic2_gain = 0x2d;
s_sdmadc_config.int_enable = 0x8;
s_sdmadc_config.cali_offset = 0x0;
s_sdmadc_config.cali_gains = 0x1000;
bk_sdmadc_set_cfg(&s_sdmadc_config);
bk_sdmadc_start();
rtos_get_semaphore(&(s_sdmadc_dev.sdmadc_read_sema),1000000);
for(int i = 1; i < s_sdmadc_buf.sample_cnt; ++i){
sum += s_sdmadc_buf.buf[i];
}
*average = sum/(s_sdmadc_buf.sample_cnt-1);
return BK_OK;
}
bk_err_t bk_sdmadc_set_channel(uint32_t channel)
{
sdmadc_hal_set_sample_channel(channel);
return BK_OK;
}
bk_err_t bk_sdmadc_set_sample_mode(sdmadc_mode_t mode)
{
sdmadc_hal_set_sample_mode(mode);
return BK_OK;
}
bk_err_t bk_sdmadc_set_cfg(sdmadc_config_t *config)
{
sdmadc_hal_set_sample_mode(config->samp_mode);
sdmadc_hal_set_sample_numb(config->samp_numb);
sdmadc_hal_set_sample_channel(config->samp_chan);
sdmadc_init_gpio(config->samp_chan);
sdmadc_hal_set_comp_bypass(config->comp_bpss);
sdmadc_hal_set_cic2_bypass(config->cic2_bpss);
sdmadc_hal_set_cic2_gains(config->cic2_gain);
sdmadc_hal_set_intr_enable(config->int_enable);
sdmadc_hal_set_cali_offset(config->cali_offset);
sdmadc_hal_set_cali_gain(config->cali_gains);
return BK_OK;
}
bk_err_t bk_sdmadc_read_raw(int16_t* buf, uint32_t size)
{
int32_t sum = 0;
if (size > s_sdmadc_buf.size) {
os_printf("size %d too big\r\n",size);
return BK_FAIL;
} else {
s_sdmadc_buf.size = size;
}
bk_sdmadc_start();
rtos_get_semaphore(&(s_sdmadc_dev.sdmadc_read_sema),1000000);
for(int i = 0; i < s_sdmadc_buf.sample_cnt;i++){
sum += s_sdmadc_buf.buf[i];
}
os_memcpy(buf, s_sdmadc_buf.buf, (size<<1));
return BK_OK;
}
float bk_sdmadc_calculate_voltage(int16_t adc_val)
{
float practic_voltage;
/* (adc_val - low) / (practic_voltage - 1Volt) = (high - low) / 1Volt */
/* practic_voltage = (adc_val - low) / (high - low) + 1Volt */
practic_voltage = (float)(adc_val - sdmadc_val.low + CFG_SDMADC_OFFSET);
practic_voltage = (practic_voltage / (float)(sdmadc_val.high - sdmadc_val.low)) + 1;
return practic_voltage;
}
bk_err_t bk_sdmadc_set_calibrate_val(uint16_t value, SDMADC_MODE mode)
{
bk_err_t result = BK_OK;
uint32_t irq_level;
irq_level = rtos_enter_critical();
if (SDMADC_CALIBRATE_LOW == mode)
{
sdmadc_val.low = value;
}
else if (SDMADC_CALIBRATE_HIGH == mode)
{
sdmadc_val.high = value;
}
else
{
result = BK_FAIL;
}
rtos_exit_critical(irq_level);
return result;
}
static void sdmadc_isr()
{
uint32_t stat = sdmadc_hal_get_sample_status();
if (s_sdmadc_config.samp_mode == SDMADC_SINGLE_STEP_MODE) {
while (smdadc_hal_is_fifo_empty_int_triggered()) {
s_sdmadc_buf.buf[s_sdmadc_buf.sample_cnt++] = sdmadc_hal_get_sample_data();
}
bk_sdmadc_stop();
rtos_set_semaphore(&(s_sdmadc_dev.sdmadc_read_sema));
} else if(s_sdmadc_config.samp_mode == SDMADC_CONTINUOUS_MODE) {
while ((smdadc_hal_is_fifo_empty_int_triggered()) &&
(s_sdmadc_buf.sample_cnt < s_sdmadc_buf.size)) {
if (s_sdmadc_buf.sample_cnt < s_sdmadc_buf.size) {
s_sdmadc_buf.buf[s_sdmadc_buf.sample_cnt++] = sdmadc_hal_get_sample_data();
}
if (s_sdmadc_buf.sample_cnt == s_sdmadc_buf.size) {
bk_sdmadc_stop();
rtos_set_semaphore(&(s_sdmadc_dev.sdmadc_read_sema));
}
}
}
sdmadc_hal_clear_interrupt_status(stat);
}
void bk_sdmadc_read_for_ate(uint32_t saradc_num, uint16_t *saradc_buf)
{
uint32_t i = 0;
int irq_level=0;
BK_LOG_ON_ERR(sdmadc_hal_disable_int());
//need check saradc fifo empty
//os_printf("saradc_hal_is_fifo_empty=%x\r\n",saradc_hal_is_fifo_empty());
//os_printf("sardata_start\r\n");
irq_level = rtos_enter_critical();
for(i = 0; i < saradc_num; i++)
{
if(smdadc_hal_is_fifo_empty_int_triggered())
{
saradc_buf[i] = sdmadc_hal_get_sample_data();
//saradc_buf[i] = *((volatile unsigned long *) (BASEADDR_SADC+0x4*4));
}
else
{
i--;
continue;
}
}
rtos_exit_critical(irq_level);
}
void test_sdmadc_for_ate(sdmadc_chan_t channel, sdmadc_mode_t mode,
uint32_t cic2_bpss, uint32_t cic2_gain,
uint32_t int_enable, uint32_t cali_gains,
uint32_t usCount, uint16_t *pDataBuffer)
{
sdmadc_config_t config = {0};
BK_LOG_ON_ERR(bk_sdmadc_driver_init());
BK_LOG_ON_ERR(bk_sdmadc_init());
config.samp_chan = channel;
config.samp_mode = mode;
config.samp_numb = 0x0;
config.comp_bpss = 0x1;
config.cic2_bpss = cic2_bpss;
config.cic2_gain = cic2_gain;
config.int_enable = int_enable;
config.cali_offset = 0x0;
config.cali_gains = cali_gains;
BK_LOG_ON_ERR(bk_sdmadc_set_cfg(&config));
BK_LOG_ON_ERR(bk_sdmadc_start());
bk_sdmadc_read_for_ate(usCount, pDataBuffer);
BK_LOG_ON_ERR(bk_sdmadc_stop());
BK_LOG_ON_ERR(bk_sdmadc_deinit(channel));
}