Skip to content

Commit

Permalink
[fix][adc] disable single mode
Browse files Browse the repository at this point in the history
  • Loading branch information
sakumisue committed Nov 3, 2023
1 parent ff68f62 commit 10f6cb7
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 95 deletions.
134 changes: 97 additions & 37 deletions drivers/lhal/src/bflb_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -504,27 +551,40 @@ 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) {
conv_result = (uint32_t)(((buffer[i] & 0xffff) >> 2) / coe);
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) {
conv_result = (uint32_t)((buffer[i] & 0xffff) / coe);
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 {
Expand Down Expand Up @@ -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);
}
}
5 changes: 4 additions & 1 deletion examples/peripherals/adc/adc_dma/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
}
}
61 changes: 32 additions & 29 deletions examples/peripherals/adc/adc_int/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -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();
Expand All @@ -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;
Expand All @@ -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) {
}
}
Loading

0 comments on commit 10f6cb7

Please sign in to comment.