WIP
This commit is contained in:
@@ -89,17 +89,26 @@ As usual the Arduino HAL makes this all really easy and hides a bunch of complex
|
|||||||
|
|
||||||
All of the ADC hardware is controlled by writing values to the ADC hardware registers. Once these are changed, the ADC hardware sees the change and starts acting on the request.
|
All of the ADC hardware is controlled by writing values to the ADC hardware registers. Once these are changed, the ADC hardware sees the change and starts acting on the request.
|
||||||
|
|
||||||
The hardware registers are all memory mapped in to various regions above `0x5000_0000`. These memory addresses are memory mapped in from the low power mode peripherals in the address controller, and are part of the shared instruction/data bus. Basically, when something requests data from those memory regions, the memory address controller redirects the request out to the appropriate peripheral on behalf of whoever is requesting that memory. The peripheral in question then manages the requested item, which is usually stored in a hardware register inside the peripheral. Memory mapped registers are a really common way of controlling peripherals and reduces the complexity of connections between components in the package.
|
The ESP32 hardware peripheral registers are all memory mapped in to various regions above `0x5000_0000`. These memory addresses are memory mapped in from the low power mode peripherals in the address controller, and are part of the shared instruction/data bus. Basically, when something requests data from those memory regions, the memory address controller redirects the request out to the appropriate peripheral on behalf of whoever is requesting that memory. The peripheral in question then manages the requested item, which is usually stored in a hardware register inside the peripheral. Memory mapped registers are a really common way of controlling peripherals and reduces the complexity of connections between components in the package.
|
||||||
|
|
||||||
There are some other registers that I'm not mentioning here, that allow you to do things like set monitors and thresholds on the ADC when it's being driven by the digital controller, that will fire interrpts when they are exceeded. If you really want to dig deep, grab a copy of the ESP32-S3 technical reference manual.
|
### Driving and Arbitrating the ADC
|
||||||
|
|
||||||
### Driving the ADC : RTC, Digital, and PWDET
|
|
||||||
|
|
||||||
There are three ways to drive the ADC : using the real time clock driver, the digital driver, or the PWDET driver. ADC1 can use the digital or RTC driver, selected by the user. ADC2 can use the digital, RTC, or PWDET driver, but the mode is controlled by the arbiter hardware device.
|
There are three ways to drive the ADC : using the real time clock driver, the digital driver, or the PWDET driver. ADC1 can use the digital or RTC driver, selected by the user. ADC2 can use the digital, RTC, or PWDET driver, but the mode is controlled by the arbiter hardware device.
|
||||||
|
|
||||||
The PWDET driver is the one I know the least about, but I'm sure you can do some nifty stuff with it. Basically it's used only internally to monitor RF power, looks like it's used by the WiFi controller somehow.
|
* The PWDET driver is the one I know the least about, but I'm sure you can do some nifty stuff with it. Basically it's used only internally to monitor RF power, looks like it's used by the WiFi controller somehow.
|
||||||
|
* The RTC driver is connected to the system real time clock (using a configurable clock divider) and the ULP.
|
||||||
|
* The digital driver is driven either by its own clock (`APB_CLK`) or by the `PLL_240M_CLK` using a configurable clock divider and needs the CPU and ULP to be awake.
|
||||||
|
|
||||||
### RTC ADC operation
|
ADC1 can be driven on demand by choosing either the RTC or the Digital modes of operation, and firing off a sampling event. ADC2, however, is controlled by the ADC2 Arbiter hardware, which acts as a scheduler for the device. It is the job of the arbiter to ensure there are no hardware conflicts accessing the ADC2 resource. The arbiter is aware of the priority of each ADC2 consumer, and has two modes of operation:
|
||||||
|
|
||||||
|
* Fair arbitration. In this mode, cyclic priority arbitration is used. Essentially this means that customer A is at the front of the line; they got served first; they go to the back of the line, and the next customer gets served. This ensures all requestors get access and nobody can monopolize the resource.
|
||||||
|
* Fixed priority arbitration. In this mode, the RTC, the digital controller, and the PWDET controller are all given priority values (via `APB_SARADC_ADC_ARB_*_PRIORITY` registers), and higher priority customers will pre-empt lower priority customers, even if that lower priority customer is in the middle of an operation. When a lower priority customer is pre-empted, bitflags are set on its output data is set to indicate that the sample was either interrupted or not started.
|
||||||
|
|
||||||
|
The arbiter can actually be masked off with the `GRANT` and `FORCE` flags of the `APB_SARADC_APB_ADC_ARB_CTRL_REG` register, to completely take arbitration logic of the loop, using ADC2 in a similar way to how ADC1 is used. I have to imagine that doing so will make your ESP32-S3's wifi .... very unhappy.
|
||||||
|
|
||||||
|
### RTC ADC Controller
|
||||||
|
|
||||||
|
The RTC ADC controller is a simplistic and low power controller for the ADC units that take a single reading and generate an interrupt when they are done.
|
||||||
|
|
||||||
#### Hardware Registers
|
#### Hardware Registers
|
||||||
|
|
||||||
@@ -132,7 +141,10 @@ The RTC operation looks like this:
|
|||||||
* ADC RTC controller has some logic wired in that uses bits from the `SENS_SAR_MEAS1_CTRL2_REG` to determine who can turn it on and when.
|
* ADC RTC controller has some logic wired in that uses bits from the `SENS_SAR_MEAS1_CTRL2_REG` to determine who can turn it on and when.
|
||||||
* When `SENS_MEAS1_START_FORCE = 0`, the ULP is allowed to start the ADC RTC Reader.
|
* When `SENS_MEAS1_START_FORCE = 0`, the ULP is allowed to start the ADC RTC Reader.
|
||||||
* When the `SENS_SAR1_DIG_FORCE` bit of `SENS_SAR_MEAS1_MUX_REG` is unset, the output of the ADC RTC Reader is used for the SAR ADC operation
|
* When the `SENS_SAR1_DIG_FORCE` bit of `SENS_SAR_MEAS1_MUX_REG` is unset, the output of the ADC RTC Reader is used for the SAR ADC operation
|
||||||
* The ADC performs a SAR operation, sets the value in the low word of `SEND_SAR_MEAS1_CTRL2_REG`, and sets the `SENS_MEAS1_DONE_SAR` when the operation is complete and the data is ready
|
* The ADC performs a SAR operation
|
||||||
|
* sets the value in the low word of `SEND_SAR_MEAS1_CTRL2_REG`
|
||||||
|
* sets the `SENS_MEAS1_DONE_SAR` when the operation is complete and the data is ready
|
||||||
|
* fires an interrupt if `SENS_SAR_READERx_CTRL_REG` enables it
|
||||||
|
|
||||||
Since the RTC ADC controller is designed for one-time conversion operations, historically, the RTC pathway is how the HAL drives the ADC for one-shot `analogRead` events. But it varies slightly from the way that the default system timer pathway works.
|
Since the RTC ADC controller is designed for one-time conversion operations, historically, the RTC pathway is how the HAL drives the ADC for one-shot `analogRead` events. But it varies slightly from the way that the default system timer pathway works.
|
||||||
|
|
||||||
@@ -140,13 +152,63 @@ Since the RTC ADC controller is designed for one-time conversion operations, his
|
|||||||
* HAL sets the `SENS_MEAS1_START_FORCE` bit of `SENS_SAR_MEAS1_CTRL2_REG` to `1`, which configures the ADC to allow software start requests via the `SENS_MEAS1_START` bit
|
* HAL sets the `SENS_MEAS1_START_FORCE` bit of `SENS_SAR_MEAS1_CTRL2_REG` to `1`, which configures the ADC to allow software start requests via the `SENS_MEAS1_START` bit
|
||||||
* HAL sets the `SENS_MEAS1_START` bit of `SENS_SAR_MEAS1_CTRL2_REG` to `1`, which forces the RTC ADC to fire
|
* HAL sets the `SENS_MEAS1_START` bit of `SENS_SAR_MEAS1_CTRL2_REG` to `1`, which forces the RTC ADC to fire
|
||||||
* When the `SENS_SAR1_DIG_FORCE` bit of `SENS_SAR_MEAS1_MUX_REG` is unset, the output of the ADC RTC Reader is used for the SAR ADC operation
|
* When the `SENS_SAR1_DIG_FORCE` bit of `SENS_SAR_MEAS1_MUX_REG` is unset, the output of the ADC RTC Reader is used for the SAR ADC operation
|
||||||
* The ADC performs a SAR operation, sets the value in the low word of `SEND_SAR_MEAS1_CTRL2_REG`, and sets the `SENS_MEAS1_DONE_SAR` when the operation is complete and the data is ready
|
* The ADC performs a SAR operation
|
||||||
|
* sets the value in the low word of `SEND_SAR_MEAS1_CTRL2_REG`
|
||||||
|
* sets the `SENS_MEAS1_DONE_SAR` when the operation is complete and the data is ready
|
||||||
|
* fires an interrupt if `SENS_SAR_READERx_CTRL_REG` enables it
|
||||||
|
|
||||||
|
When an RTC operation is pre-empted by the arbiter on ADC2, the top two bits of `SENS_MEAS2_DATA_SAR` indicate this. `00` is a complete operation, `01` is a sample that did not start, `10` is a sample that did not complete.
|
||||||
|
|
||||||
####
|
### Digital ADC Controller
|
||||||
|
|
||||||
|
The digital ADC controller is a higher power controller for the ADC that can do quite a bit more stuff. Specifically, it can do things like firing on a timer (separate from the system clock), continuously polling the ADC and updating with new values, and setting a threshold for the ADC values and firing an interrupt when the value is outside that threshold.
|
||||||
|
|
||||||
|
#### Hardware Registers
|
||||||
|
|
||||||
|
The ADC RTC hardware registers are mapped into memory between `0x6004_0000` and `0x6004_0FFF`.
|
||||||
|
|
||||||
|
| ADC | Register | Address | Purpose |
|
||||||
|
|-------|------------------------------------|---------------|-----------------------------------------------|
|
||||||
|
| ADC1 | `APB_SARADC_CTRL_REG` | `0x6004_0000` | Configuration register for DIG ADC controller |
|
||||||
|
| ADC2 | `APB_SARADC_CTRL2_REG` | `0x6004_0004` | Configuration register for DIG ADC controller |
|
||||||
|
| ADC2* | `APB_SARADC_FILTER_CTRL1_REG` | `0x6004_0008` | Configuration register 1 for SAR ADC filter |
|
||||||
|
| ADC1 | `APB_SARADC_APB_ADC_ARB_CTRL_REG` | `0x6004_0038` | Configuration register for SAR ADC2 arbiter |
|
||||||
|
| ADC1 | `APB_SARADC_FILTER_CTRL0_REG` | `0x6004_003C` | Configuration register 0 for SAR ADC filter |
|
||||||
|
| ADC1 | `APB_SARADC_THRES0_CTRL_REG` | `0x6004_0044` | Sampling threshold control register 0 |
|
||||||
|
| ADC2* | `APB_SARADC_THRES1_CTRL_REG` | `0x6004_0048` | Sampling threshold control register 1 |
|
||||||
|
| ADC1 | `APB_SARADC_THRES_CTRL_REG` | `0x6004_0058` | Threshold monitor enable register |
|
||||||
|
| ADC1 | `APB_SARADC_DMA_CONF_REG` | `0x6004_006C` | DMA configuration register for SAR ADC |
|
||||||
|
| ADC1 | `APB_SARADC_APB_ADC_CLKM_CONF_REG` | `0x6004_0070` | Configure SAR ADC clock |
|
||||||
|
|
||||||
|
* : I'm guessing somewhat here. The TRM didn't make it clear if these registers were for ADC1 or ADC2, they just numbered them 0 or 1.
|
||||||
|
|
||||||
|
#### Digital ADC Operation
|
||||||
|
|
||||||
|
The operation of the digital ADC is, on the surface, very similar to the RTC mode.
|
||||||
|
|
||||||
|
* User calls `analogContinuous` or `analogContinuousRead`
|
||||||
|
* HAL sets `SENS_SAR1_DIG_FORCE` bit of `SENS_SAR_MEAS1_MUX_REG` to 1, which tells the ADC1 mux to use the input from the digital reader
|
||||||
|
* HAL configures the Digital ADC registers
|
||||||
|
* HAL sets the configuration for the continuous digital operation in `APB_SARADC_CTRLx_REG`
|
||||||
|
* HAL sets DMA configuration in `APB_SARADC_DMA_CONF_REG`
|
||||||
|
* HAL sets the `SENS_MEAS1_START_FORCE` bit of `SENS_SAR_MEAS1_CTRL2_REG` to `1`, which configures the ADC to allow software start requests via the `SENS_MEAS1_START` bit
|
||||||
|
* HAL sets the `SENS_MEAS1_START` bit of `SENS_SAR_MEAS1_CTRL2_REG` to `1`, which forces the RTC ADC to fire
|
||||||
|
* The ADC performs a SAR operation
|
||||||
|
* sets the value in the DMA data
|
||||||
|
* sets the `SENS_MEAS1_DONE_SAR` when the operation is complete and the data is ready
|
||||||
|
* fires an interrupt if `SENS_SAR_READERx_CTRL_REG` enables it
|
||||||
|
|
||||||
|
That's for the most simple case of the digital ADC controller operating on ADC1.
|
||||||
|
|
||||||
|
There are several features that are supported by the digital controller, and they don't appear to map into the `analogContinuous*` functions:
|
||||||
|
|
||||||
|
* Scanning multiple channels. The ESP32-S3 digital ADC can scan up to 10 channels at a time, with different attenuation levels on each channel.
|
||||||
|
* Thresholding. The ESP32-S3 digital ADC can generate an interrupt when the analog value is outside of a given threshold by setting threshold parameters in `APB_SARADC_THRESx_CTRL_REG` and `APB_SARADC_THRES`.
|
||||||
|
* Filtering. The digital ADC automatically filters, but there are some extra filtering parameters you can set in `APB_SARADC_FILTER_CTRLx_REG`.
|
||||||
|
* Mode control. From the architecture diagram above we can see that the digital ADC has two finite state machines connected to two digital readers. The digital ADC controller can sample a single reader, both readers can be sampled simultaneously, or it can flip-flop between FSMs/readers on even/odd requests.
|
||||||
|
* Timers. You can set a timer and, after that given amount of time has elapsed, a sampling operation is performed and the output is stored via DMA somewhere.
|
||||||
|
|
||||||
|
When a digital operation is pre-empted by the arbiter on ADC2, the ` {sar_sel, ch_sel}` bits in the DMA data indicate this. `1110` is a sample that did not start, `1111` is a sample that did not complete, and the data is valid when those two bits equal the channel number.
|
||||||
|
|
||||||
## Measuring Capacitance
|
## Measuring Capacitance
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user