#5647·tinygo

esp32c6: machine.InitADC() hangs indefinitely in readADC1()

Author: m-antiCreated Sep 2, 2026Updated Sep 10, 2026

Description

When attempting to read from the ADC on an ESP32-C6 (board ESP32-C6-DevKitC-1), the program gets stuck inside machine.InitADC() and never returns.

Minimal Reproducible Example

package main

import (
	"machine"
	"time"
)

func main() {  
	time.Sleep(time.Second)
	
	println("Init ADC...")
	machine.InitADC()       // Hangs here
	println("Init done")
	
	sensor := machine.ADC{Pin: machine.ADC0}
	sensor.Configure(machine.ADCConfig{})

	for {
		val := sensor.Get()
		println(val)
		time.Sleep(time.Millisecond * 500)
	}
}

Expected Behavior

machine.InitADC() initializes the ADC peripheral, prints "Init done", and proceeds to read values in the main loop.

Actual Behavior

The program prints "Init ADC..." and halts indefinitely.

Suspected Cause

Debugging indicates that InitADC() calls adcSelfCalibrate(), which invokes readADC1(). Inside readADC1(), the execution enters a busy-wait loop waiting for the hardware:

func readADC1() uint32 {
	esp.APB_SARADC.SetINT_CLR_APB_SARADC1_DONE_INT_CLR(1)
	esp.APB_SARADC.SetONETIME_SAMPLE_SARADC_ONETIME_START(0)
	esp.APB_SARADC.SetONETIME_SAMPLE_SARADC_ONETIME_START(1)
	
	// Execution hangs here because APB_SARADC1_DONE_INT_RAW is never set to 1
	for esp.APB_SARADC.GetINT_RAW_APB_SARADC1_DONE_INT_RAW() == 0 {
	}
	
	raw := esp.APB_SARADC.GetSAR1DATA_STATUS_APB_SARADC1_DATA() & 0xfff
	esp.APB_SARADC.SetONETIME_SAMPLE_SARADC_ONETIME_START(0)
	return uint32(raw)
}

It appears the hardware register setup for the ESP32-C6 target lacks necessary clock/power gating initialization or configuration bits required to trigger the one-time sample completion.

Environment Details

  • Board: ESP32-C6-DevKitC-1
  • Architecture: RISC-V esp32c6 (chip rev: 0.2)
  • TinyGo Version: 0.42.0 linux/amd64
  • Compiled & flashed with: tinygo flash -target xiao-esp32c6 -port /dev/ttyACM0 -monitor adc.go