From 10f6cb780ace63113fd8a4f5f59426414aa7bf1e Mon Sep 17 00:00:00 2001 From: jzlv Date: Fri, 3 Nov 2023 10:04:19 +0800 Subject: [PATCH] [fix][adc] disable single mode --- drivers/lhal/src/bflb_adc.c | 134 +++++++++++++----- examples/peripherals/adc/adc_dma/main.c | 5 +- examples/peripherals/adc/adc_int/main.c | 61 ++++---- examples/peripherals/adc/adc_poll/main.c | 55 ++++--- .../peripherals/adc/adc_poll_diff_mode/main.c | 2 + examples/peripherals/adc/adc_vbat/main.c | 3 + 6 files changed, 165 insertions(+), 95 deletions(-) diff --git a/drivers/lhal/src/bflb_adc.c b/drivers/lhal/src/bflb_adc.c index 309619d4e..70fff474a 100644 --- a/drivers/lhal/src/bflb_adc.c +++ b/drivers/lhal/src/bflb_adc.c @@ -12,8 +12,9 @@ volatile float coe = 1.0f; volatile uint32_t tsen_offset; volatile int adc_reference_channel = -1; volatile int32_t adc_reference_channel_millivolt = -1; +volatile uint32_t gnd_offset = 0; -void bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *config) +void __bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *config) { uint32_t regval; uint32_t reg_base; @@ -47,23 +48,6 @@ void bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *co regval &= ~AON_GPADC_SOFT_RST; putreg32(regval, reg_base + AON_GPADC_REG_CMD_OFFSET); - /* disable int and clear status */ - regval = getreg32(ADC_GPIP_BASE + GPIP_GPADC_CONFIG_OFFSET); - regval |= (GPIP_GPADC_FIFO_UNDERRUN_MASK | GPIP_GPADC_FIFO_OVERRUN_MASK | GPIP_GPADC_RDY_MASK | - GPIP_GPADC_FIFO_UNDERRUN_CLR | GPIP_GPADC_FIFO_OVERRUN_CLR | GPIP_GPADC_RDY_CLR); - -#if defined(BL702) || defined(BL702L) - regval |= (GPIP_GPADC_FIFO_RDY_MASK | GPIP_GPADC_FIFO_RDY); -#endif - regval |= GPIP_GPADC_FIFO_CLR; - regval &= ~GPIP_GPADC_FIFO_THL_MASK; - regval &= ~GPIP_GPADC_DMA_EN; - putreg32(regval, ADC_GPIP_BASE + GPIP_GPADC_CONFIG_OFFSET); - - bflb_adc_start_conversion(dev); - bflb_mtimer_delay_ms(1); - bflb_adc_stop_conversion(dev); - regval = 0; regval |= (2 << AON_GPADC_V18_SEL_SHIFT); /* V18 select 1.82V */ regval |= (1 << AON_GPADC_V11_SEL_SHIFT); /* V11 select 1.1V */ @@ -93,12 +77,22 @@ void bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *co __asm volatile("nop"); __asm volatile("nop"); + /* CONFIG2 setting + * + * gpadc_dly_sel = 0x02 + * pga bit enable + * pga1 gain = pga2 gain = 1 + * pgadc_pga_os_cal = 8 + * gpadc_chop_mode = 2 + * gpadc_pga_vcm = 1 + * + */ regval = 0; regval |= (2 << AON_GPADC_DLY_SEL_SHIFT); regval |= (2 << AON_GPADC_CHOP_MODE_SHIFT); /* Vref AZ and PGA chop on */ regval |= (1 << AON_GPADC_PGA1_GAIN_SHIFT); /* gain 1 */ #if defined(BL702L) - regval &= ~AON_GPADC_PGA2_GAIN_MASK; /* gain 2 */ + regval &= ~AON_GPADC_PGA2_GAIN_MASK; /* gain 2 */ #else regval |= (1 << AON_GPADC_PGA2_GAIN_SHIFT); /* gain 2 */ #endif @@ -159,38 +153,91 @@ void bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *co tsen_offset = bflb_efuse_get_adc_tsen_trim(); /* read from efuse */ } -void bflb_adc_deinit(struct bflb_device_s *dev) +void bflb_adc_init(struct bflb_device_s *dev, const struct bflb_adc_config_s *config) { uint32_t regval; uint32_t reg_base; + uint32_t gnd_val = 0; reg_base = dev->reg_base; - /* adc disable */ + __bflb_adc_init(dev, config); + + regval = getreg32(reg_base + AON_GPADC_REG_CONFIG1_OFFSET); + regval |= AON_GPADC_CONT_CONV_EN; + regval &= ~AON_GPADC_SCAN_EN; + putreg32(regval, reg_base + AON_GPADC_REG_CONFIG1_OFFSET); + regval = getreg32(reg_base + AON_GPADC_REG_CMD_OFFSET); - regval &= ~AON_GPADC_GLOBAL_EN; + regval &= ~AON_GPADC_NEG_GND; putreg32(regval, reg_base + AON_GPADC_REG_CMD_OFFSET); - /* adc reset */ regval = getreg32(reg_base + AON_GPADC_REG_CMD_OFFSET); - regval |= AON_GPADC_SOFT_RST; + regval &= ~AON_GPADC_POS_SEL_MASK; + regval &= ~AON_GPADC_NEG_SEL_MASK; + regval |= (ADC_CHANNEL_GND << AON_GPADC_POS_SEL_SHIFT); + regval |= (ADC_CHANNEL_GND << AON_GPADC_NEG_SEL_SHIFT); putreg32(regval, reg_base + AON_GPADC_REG_CMD_OFFSET); - __asm volatile("nop"); - __asm volatile("nop"); - __asm volatile("nop"); - __asm volatile("nop"); - __asm volatile("nop"); - __asm volatile("nop"); - __asm volatile("nop"); - __asm volatile("nop"); + bflb_adc_start_conversion(dev); + + for (uint16_t i = 0; i < 10; i++) { + regval = getreg32(ADC_GPIP_BASE + GPIP_GPADC_CONFIG_OFFSET); + regval |= GPIP_GPADC_FIFO_CLR; + putreg32(regval, ADC_GPIP_BASE + GPIP_GPADC_CONFIG_OFFSET); + + while (bflb_adc_get_count(dev) == 0) {} + + regval = bflb_adc_read_raw(dev); + + if (i > 4) { + gnd_val += (regval & 0xffff); + } + } + + bflb_adc_stop_conversion(dev); + bflb_mtimer_delay_ms(10); + + if (gnd_val > 0) { + gnd_offset = gnd_val / 5; + } else { + gnd_offset = 0; + } + + /* restore config from user */ + regval = getreg32(reg_base + AON_GPADC_REG_CONFIG1_OFFSET); + if (config->continuous_conv_mode) { + regval |= AON_GPADC_CONT_CONV_EN; + } else { + regval &= ~AON_GPADC_CONT_CONV_EN; + } + if (config->scan_conv_mode) { + regval |= AON_GPADC_SCAN_EN; + } + putreg32(regval, reg_base + AON_GPADC_REG_CONFIG1_OFFSET); regval = getreg32(reg_base + AON_GPADC_REG_CMD_OFFSET); - regval &= ~AON_GPADC_SOFT_RST; + if (config->differential_mode) { + regval &= ~AON_GPADC_NEG_GND; + } else { + regval |= AON_GPADC_NEG_GND; + } putreg32(regval, reg_base + AON_GPADC_REG_CMD_OFFSET); - putreg32(0, reg_base + AON_GPADC_REG_CONFIG1_OFFSET); - putreg32(0, reg_base + AON_GPADC_REG_CONFIG2_OFFSET); + regval = getreg32(ADC_GPIP_BASE + GPIP_GPADC_CONFIG_OFFSET); + regval |= GPIP_GPADC_FIFO_CLR; + putreg32(regval, ADC_GPIP_BASE + GPIP_GPADC_CONFIG_OFFSET); +} + +void bflb_adc_deinit(struct bflb_device_s *dev) +{ + uint32_t reg_base; + + reg_base = dev->reg_base; + + putreg32(0xf78, reg_base + AON_GPADC_REG_CMD_OFFSET); + putreg32(0xc0002, reg_base + AON_GPADC_REG_CONFIG1_OFFSET); + putreg32(0x19100, reg_base + AON_GPADC_REG_CONFIG2_OFFSET); } void bflb_adc_link_rxdma(struct bflb_device_s *dev, bool enable) @@ -504,6 +551,9 @@ void bflb_adc_parse_result(struct bflb_device_s *dev, uint32_t *buffer, struct b if (conv_result > 4095) { conv_result = 4095; } + if (conv_result > gnd_offset) { + conv_result -= gnd_offset; + } result[i].value = conv_result; result[i].millivolt = (int32_t)result[i].value * ref / 4096; } else if (resolution == ADC_RESOLUTION_14B) { @@ -511,6 +561,9 @@ void bflb_adc_parse_result(struct bflb_device_s *dev, uint32_t *buffer, struct b if (conv_result > 16383) { conv_result = 16383; } + if (conv_result > gnd_offset) { + conv_result -= gnd_offset; + } result[i].value = conv_result; result[i].millivolt = (int32_t)result[i].value * ref / 16384; } else if (resolution == ADC_RESOLUTION_16B) { @@ -518,13 +571,20 @@ void bflb_adc_parse_result(struct bflb_device_s *dev, uint32_t *buffer, struct b if (conv_result > 65535) { conv_result = 65535; } + if (conv_result > gnd_offset) { + conv_result -= gnd_offset; + } result[i].value = conv_result; result[i].millivolt = (int32_t)result[i].value * ref / 65536; } else { } if ((adc_reference_channel != -1) && ((buffer[i] >> 21) != adc_reference_channel)) { - result[i].millivolt = result[i].millivolt * adc_reference_channel_millivolt / chan_vref; + if (chan_vref) { + result[i].millivolt = result[i].millivolt * adc_reference_channel_millivolt / chan_vref; + } else { + result[i].millivolt = 0; + } } } } else { @@ -691,4 +751,4 @@ void bflb_adc_vbat_disable(struct bflb_device_s *dev) regval = getreg32(reg_base + AON_GPADC_REG_CONFIG2_OFFSET); regval &= ~AON_GPADC_VBAT_EN; putreg32(regval, reg_base + AON_GPADC_REG_CONFIG2_OFFSET); -} \ No newline at end of file +} diff --git a/examples/peripherals/adc/adc_dma/main.c b/examples/peripherals/adc/adc_dma/main.c index 2531b14d3..9ebe33724 100644 --- a/examples/peripherals/adc/adc_dma/main.c +++ b/examples/peripherals/adc/adc_dma/main.c @@ -104,7 +104,7 @@ int main(void) struct bflb_adc_config_s cfg; cfg.clk_div = ADC_CLK_DIV_32; cfg.scan_conv_mode = true; - cfg.continuous_conv_mode = true; + cfg.continuous_conv_mode = true; /* do not support single mode */ cfg.differential_mode = false; cfg.resolution = ADC_RESOLUTION_16B; cfg.vref = ADC_VREF_3P2V; @@ -132,6 +132,7 @@ int main(void) struct bflb_dma_channel_lli_transfer_s transfers[1]; + dma_tc_flag0 = 0; memset(raw_data, 0, sizeof(raw_data)); transfers[0].src_addr = (uint32_t)DMA_ADDR_ADC_RDR; @@ -156,6 +157,8 @@ int main(void) printf("pos chan %d,%d mv \r\n", result[j].pos_chan, result[j].millivolt); } + bflb_adc_deinit(adc); + while (1) { } } diff --git a/examples/peripherals/adc/adc_int/main.c b/examples/peripherals/adc/adc_int/main.c index 47aa65c10..50422d76d 100644 --- a/examples/peripherals/adc/adc_int/main.c +++ b/examples/peripherals/adc/adc_int/main.c @@ -16,20 +16,18 @@ struct bflb_device_s *adc; #define TEST_ADC_CHANNEL_9 1 #define TEST_ADC_CHANNEL_10 1 -#define TEST_ADC_CHANNELS (TEST_ADC_CHANNEL_0 + \ - TEST_ADC_CHANNEL_1 + \ - TEST_ADC_CHANNEL_2 + \ - TEST_ADC_CHANNEL_3 + \ - TEST_ADC_CHANNEL_4 + \ - TEST_ADC_CHANNEL_5 + \ - TEST_ADC_CHANNEL_6 + \ - TEST_ADC_CHANNEL_7 + \ - TEST_ADC_CHANNEL_8 + \ - TEST_ADC_CHANNEL_9 + \ +#define TEST_ADC_CHANNELS (TEST_ADC_CHANNEL_0 + \ + TEST_ADC_CHANNEL_1 + \ + TEST_ADC_CHANNEL_2 + \ + TEST_ADC_CHANNEL_3 + \ + TEST_ADC_CHANNEL_4 + \ + TEST_ADC_CHANNEL_5 + \ + TEST_ADC_CHANNEL_6 + \ + TEST_ADC_CHANNEL_7 + \ + TEST_ADC_CHANNEL_8 + \ + TEST_ADC_CHANNEL_9 + \ TEST_ADC_CHANNEL_10) -#define TEST_COUNT 10 - struct bflb_adc_channel_s chan[] = { #if TEST_ADC_CHANNEL_0 { .pos_chan = ADC_CHANNEL_0, @@ -77,7 +75,10 @@ struct bflb_adc_channel_s chan[] = { #endif }; -volatile uint32_t raw_data[TEST_ADC_CHANNELS]; +#define TEST_COUNT 10 + +uint32_t raw_data[TEST_ADC_CHANNELS * TEST_COUNT]; + volatile uint8_t read_count = 0; void adc_isr(int irq, void *arg) @@ -89,13 +90,18 @@ void adc_isr(int irq, void *arg) for (size_t i = 0; i < count; i++) { raw_data[read_count] = bflb_adc_read_raw(adc); read_count++; + + if (read_count == TEST_ADC_CHANNELS * TEST_COUNT) { + bflb_adc_stop_conversion(adc); + bflb_adc_rxint_mask(adc, true); + } } } } int main(void) { - struct bflb_adc_result_s result[TEST_ADC_CHANNELS]; + struct bflb_adc_result_s result[TEST_ADC_CHANNELS * TEST_COUNT]; board_init(); board_adc_gpio_init(); @@ -106,7 +112,7 @@ int main(void) struct bflb_adc_config_s cfg; cfg.clk_div = ADC_CLK_DIV_32; cfg.scan_conv_mode = true; - cfg.continuous_conv_mode = false; + cfg.continuous_conv_mode = true; /* do not support single mode */ cfg.differential_mode = false; cfg.resolution = ADC_RESOLUTION_16B; cfg.vref = ADC_VREF_3P2V; @@ -117,25 +123,22 @@ int main(void) bflb_irq_attach(adc->irq_num, adc_isr, NULL); bflb_irq_enable(adc->irq_num); - for (size_t i = 0; i < TEST_COUNT; i++) { - read_count = 0; - bflb_adc_start_conversion(adc); + read_count = 0; + bflb_adc_start_conversion(adc); - while (read_count < TEST_ADC_CHANNELS) { - bflb_mtimer_delay_ms(1); - } + while (read_count < (TEST_ADC_CHANNELS * TEST_COUNT)) { + bflb_mtimer_delay_ms(1); + } - bflb_adc_parse_result(adc, raw_data, result, TEST_ADC_CHANNELS); + bflb_adc_parse_result(adc, raw_data, result, TEST_ADC_CHANNELS * TEST_COUNT); - for (size_t j = 0; j < TEST_ADC_CHANNELS; j++) { - printf("raw data:%08x\r\n", raw_data[j]); - printf("pos chan %d,%d mv \r\n", result[j].pos_chan, result[j].millivolt); - } - - bflb_adc_stop_conversion(adc); - bflb_mtimer_delay_ms(100); + for (size_t j = 0; j < TEST_ADC_CHANNELS * TEST_COUNT; j++) { + printf("raw data:%08x\r\n", raw_data[j]); + printf("pos chan %d,%d mv \r\n", result[j].pos_chan, result[j].millivolt); } + bflb_adc_deinit(adc); + while (1) { } } diff --git a/examples/peripherals/adc/adc_poll/main.c b/examples/peripherals/adc/adc_poll/main.c index a55b51b93..dba9e1b98 100644 --- a/examples/peripherals/adc/adc_poll/main.c +++ b/examples/peripherals/adc/adc_poll/main.c @@ -16,20 +16,18 @@ struct bflb_device_s *adc; #define TEST_ADC_CHANNEL_9 1 #define TEST_ADC_CHANNEL_10 1 -#define TEST_ADC_CHANNELS (TEST_ADC_CHANNEL_0 + \ - TEST_ADC_CHANNEL_1 + \ - TEST_ADC_CHANNEL_2 + \ - TEST_ADC_CHANNEL_3 + \ - TEST_ADC_CHANNEL_4 + \ - TEST_ADC_CHANNEL_5 + \ - TEST_ADC_CHANNEL_6 + \ - TEST_ADC_CHANNEL_7 + \ - TEST_ADC_CHANNEL_8 + \ - TEST_ADC_CHANNEL_9 + \ +#define TEST_ADC_CHANNELS (TEST_ADC_CHANNEL_0 + \ + TEST_ADC_CHANNEL_1 + \ + TEST_ADC_CHANNEL_2 + \ + TEST_ADC_CHANNEL_3 + \ + TEST_ADC_CHANNEL_4 + \ + TEST_ADC_CHANNEL_5 + \ + TEST_ADC_CHANNEL_6 + \ + TEST_ADC_CHANNEL_7 + \ + TEST_ADC_CHANNEL_8 + \ + TEST_ADC_CHANNEL_9 + \ TEST_ADC_CHANNEL_10) -#define TEST_COUNT 10 - struct bflb_adc_channel_s chan[] = { #if TEST_ADC_CHANNEL_0 { .pos_chan = ADC_CHANNEL_0, @@ -77,11 +75,13 @@ struct bflb_adc_channel_s chan[] = { #endif }; -uint32_t raw_data[TEST_ADC_CHANNELS]; +#define TEST_COUNT 10 + +uint32_t raw_data[TEST_ADC_CHANNELS * TEST_COUNT]; int main(void) { - struct bflb_adc_result_s result[TEST_ADC_CHANNELS]; + struct bflb_adc_result_s result[TEST_ADC_CHANNELS * TEST_COUNT]; board_init(); board_adc_gpio_init(); @@ -92,7 +92,7 @@ int main(void) struct bflb_adc_config_s cfg; cfg.clk_div = ADC_CLK_DIV_32; cfg.scan_conv_mode = true; - cfg.continuous_conv_mode = false; + cfg.continuous_conv_mode = true; /* do not support single mode */ cfg.differential_mode = false; cfg.resolution = ADC_RESOLUTION_16B; cfg.vref = ADC_VREF_3P2V; @@ -100,28 +100,27 @@ int main(void) bflb_adc_init(adc, &cfg); bflb_adc_channel_config(adc, chan, TEST_ADC_CHANNELS); - for (uint32_t i = 0; i < TEST_COUNT; i++) { - bflb_adc_start_conversion(adc); + bflb_adc_start_conversion(adc); - while (bflb_adc_get_count(adc) < TEST_ADC_CHANNELS) { + for (uint16_t i = 0; i < TEST_ADC_CHANNELS * TEST_COUNT; i++) { + while (bflb_adc_get_count(adc) == 0) { bflb_mtimer_delay_ms(1); } - for (size_t j = 0; j < TEST_ADC_CHANNELS; j++) { - raw_data[j] = bflb_adc_read_raw(adc); - } + raw_data[i] = bflb_adc_read_raw(adc); + } - bflb_adc_parse_result(adc, raw_data, result, TEST_ADC_CHANNELS); + bflb_adc_stop_conversion(adc); - for (size_t j = 0; j < TEST_ADC_CHANNELS; j++) { - printf("raw data:%08x\r\n", raw_data[j]); - printf("pos chan %d,%d mv \r\n", result[j].pos_chan, result[j].millivolt); - } + bflb_adc_parse_result(adc, raw_data, result, TEST_ADC_CHANNELS * TEST_COUNT); - bflb_adc_stop_conversion(adc); - bflb_mtimer_delay_ms(100); + for (uint16_t j = 0; j < TEST_ADC_CHANNELS * TEST_COUNT; j++) { + printf("raw data:%08x\r\n", raw_data[j]); + printf("pos chan %d,%d mv \r\n", result[j].pos_chan, result[j].millivolt); } + bflb_adc_deinit(adc); + while (1) { } } diff --git a/examples/peripherals/adc/adc_poll_diff_mode/main.c b/examples/peripherals/adc/adc_poll_diff_mode/main.c index b8f253a1f..d35fa61ff 100644 --- a/examples/peripherals/adc/adc_poll_diff_mode/main.c +++ b/examples/peripherals/adc/adc_poll_diff_mode/main.c @@ -53,6 +53,8 @@ int main(void) bflb_mtimer_delay_ms(100); } + bflb_adc_deinit(adc); + while (1) { } } diff --git a/examples/peripherals/adc/adc_vbat/main.c b/examples/peripherals/adc/adc_vbat/main.c index 05de8bb90..e8bb29952 100644 --- a/examples/peripherals/adc/adc_vbat/main.c +++ b/examples/peripherals/adc/adc_vbat/main.c @@ -29,6 +29,7 @@ int main(void) bflb_adc_vbat_enable(adc); struct bflb_adc_result_s result; + for (uint16_t i = 0; i < 10; i++) { bflb_adc_start_conversion(adc); while (bflb_adc_get_count(adc) == 0) { @@ -42,6 +43,8 @@ int main(void) bflb_mtimer_delay_ms(500); } + + bflb_adc_deinit(adc); while (1) { } }