Hi Sintech,
sintech wrote:On ARM CPU I can do some ASM nop and we have ARM_DWT_CYCCNT to count elapsed cycles.
Are there any alternatives to them on ESP32?
The CCOUNT special register on Xtensa gives you the CPU cycle count (at the current CPU clock speed). You can read it from C code via the "RSR" (read special register) macro:
Code: Select all
uint32_t ccount;
RSR(CCOUNT, ccount);
There is also ets_delay_us(), which is a ROM function that will give you microsecond-level busy-waiting delays.
Bear in mind that because esp-idf is a preemptive multitasking environment, high-priority tasks and interrupts may prevent you getting cycle-accurate delays of this kind. Placing the WiFi & IP stacks on one core and disabling interrupts on the other core (which runs the task with your bit-banging code) will help, but there's a better solution which I'll explain in a moment.
sintech wrote:
You also mention that gpio_set_level are slow on current ESP32 revision. Maybe there any workaround to change gpio level directly?
Once the GPIO is configured, you can write directly to the GPIO W1TS & W1TC ("set" and "clear") registers in the same way gpio_set_level does:
https://github.com/espressif/esp-idf/bl ... pio.c#L162
The registers themselves (available in "struct" and bare register form) are here:
https://github.com/espressif/esp-idf/bl ... ruct.h#L59
https://github.com/espressif/esp-idf/bl ... _reg.h#L34
There is one thing to keep in mind, the current chip revision's
ECO document section 3.3 describes a problem when writing to the same register address repeatedly (ie one CPU cycle after the next), some writes are lost. If you're writing at microsecond-ish intervals, this won't be a problem - but if trying to bit-bang at close to the peripheral bus clock rate (80MHz) then you'll need to either add some "nops" in between each register write, or use the alternative register base address given in the ECO document. The next silicon revision will not have this limitation.
(This is the same "chip bug" Sprite mentioned, although it turns esp-idf hasn't been updated to use the "slower/fixed" addresses yet - it's using the faster/may-lose-writes addresses.)
sintech wrote:I would like to send some serial stream of pulses to gpio with 1 to 8 microsecond delay between them.
Good news! ESP32 has a bunch of dedicated hardware that means you don't need to bit-bang these signals at all.
I suggest taking a look at the RMT ("remote control") peripheral. It's documented in the hardware Technical Reference Manual, and there is also a
driver with a documented API. It can generate arbitrary pulse signals of this kind, without needing to bit-bang with the CPU. By using the GPIO Matrix, the RMT peripheral channels can be mapped to any pin (this is true for nearly all ESP32 peripherals.)
The I2S hardware may also be suitable, although it's more complex hardware and the documentation/driver are still forthcoming. If the pulses are very simple, the LEDC (LED controller) pulse generation hardware may be suitable.
Angus