High speed GPIO operations

star_7
Posts: 3
Joined: Sat Dec 10, 2016 3:28 pm

High speed GPIO operations

Postby star_7 » Mon Dec 12, 2016 6:01 am

I have a question is about the main operation of the clock.The default clock frequency is how much?
while(1) {
gpio_set_level(BLINK_GPIO, 0);
gpio_set_level(BLINK_GPIO, 1);
}
I wrote above, the BLINK_GPIO output frequency only 3Mhz,If the clock is 240 Mhz,I/O output frequency why so low?

Frederir
Posts: 3
Joined: Sun Feb 14, 2016 9:07 pm

Re: Confirmations about ESP32 peripherals

Postby Frederir » Mon Dec 12, 2016 8:44 am

I wrote above, the BLINK_GPIO output frequency only 3Mhz,If the clock is 240 Mhz,I/O output frequency why so low?
May be because the C function gpio_set_level get translated in multiple assembly instructions by the C compiler ?


F.

ESP_Sprite
Posts: 9766
Joined: Thu Nov 26, 2015 4:08 am

Re: Confirmations about ESP32 peripherals

Postby ESP_Sprite » Tue Dec 13, 2016 4:31 am

It's mostly because GPIO_SET_LEVEL is somewhat inefficient if you're generating MHz-scale signals, plus because iirc we use the APB bus to control GPIO because of a chip bug (which is going to be fixed in the next rev), causing GPIO to be slower than it can be in general.

sintech
Posts: 27
Joined: Wed Dec 14, 2016 2:54 pm

Re: Confirmations about ESP32 peripherals

Postby sintech » Wed Dec 14, 2016 3:35 pm

Can you please suggest how do bit banging on gpio at microsecond resolution on esp32?
I would like to send some serial stream of pulses to gpio with 1 to 8 microsecond delay between them.
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?

You also mention that gpio_set_level are slow on current ESP32 revision. Maybe there any workaround to change gpio level directly?

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: Confirmations about ESP32 peripherals

Postby ESP_Angus » Wed Dec 14, 2016 10:11 pm

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

User avatar
rudi ;-)
Posts: 1729
Joined: Fri Nov 13, 2015 3:25 pm

Re: High speed GPIO operations

Postby rudi ;-) » Wed Dec 14, 2016 10:40 pm

in some situation i use asm for "counting"
and make a function in c code like this:
( i use it for other esp's too )

Code: Select all

static inline unsigned get_ccount(void)
{
        unsigned r;
        asm volatile ("rsr %0, ccount" : "=r"(r));
        return r;
}
and use return value in a wait while,
or perhabs, you have a try CCOMPARE SRs with setting a Value there and use the IRQ
( 4.4.6 Timer interrupt option ) old ISA book

@Angus
txs ;-) "special register macro" - have not seen this in the past ;-)


best wishes
rudi ;-)
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

sintech
Posts: 27
Joined: Wed Dec 14, 2016 2:54 pm

Re: High speed GPIO operations

Postby sintech » Thu Dec 15, 2016 1:55 pm

Thanks a lot for answers.

ESP_Angus, you mention use of RMT for sending stream of pulses.
I have read manual chapter about RMT and found that I need to allocate memory for pulses description.
According to manual, maximum memory block that I can have for one tx channel is 512x32 bytes, which would be 32 bit per 1 byte of my data. Total amount of data that I need to send are 13000 bytes, so we need to allocate 416k of RAM for this purpose which is not possible.
But as I read from manual, RMT in wraparound mode can generate interrupt after sending configured count of entries. And on this interrupt I should refill the buffer with fresh data before it came to an end of transmission.
I think the speed of CPU and APB bus will be enough to keep the buffer full and avoid interruptions of continuous stream of pulses.

A couple of words about my project: it is a floppy drive simulator for the Apple II clone computer. So I have to generate MFM encoded pulses on GPIO to emulate output from floppy drive. My current sources for Teensy 3.1 dev board https://github.com/sintech/AGAT/tree/ma ... c/agatdisk

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: High speed GPIO operations

Postby ESP_Angus » Thu Dec 15, 2016 10:41 pm

sintech wrote: But as I read from manual, RMT in wraparound mode can generate interrupt after sending configured count of entries. And on this interrupt I should refill the buffer with fresh data before it came to an end of transmission.
I think the speed of CPU and APB bus will be enough to keep the buffer full and avoid interruptions of continuous stream of pulses.
I agree, I think this is the best approach for what you need.
sintech wrote: A couple of words about my project: it is a floppy drive simulator for the Apple II clone computer. So I have to generate MFM encoded pulses on GPIO to emulate output from floppy drive. My current sources for Teensy 3.1 dev board https://github.com/sintech/AGAT/tree/ma ... c/agatdisk
Very cool. :) I look forward to seeing how this goes!

ESP_Sprite
Posts: 9766
Joined: Thu Nov 26, 2015 4:08 am

Re: High speed GPIO operations

Postby ESP_Sprite » Fri Dec 16, 2016 1:43 am

I think in general the RMT could benefit from a streaming mode. If I have some time, I can see if I can implement it.

sintech
Posts: 27
Joined: Wed Dec 14, 2016 2:54 pm

Re: High speed GPIO operations

Postby sintech » Thu Jan 05, 2017 11:01 am

When experimenting with launching tasks on APP core I have observed that "ets_delay_us" function produces much shorter delays when used in tasks working on APP core, while it is pretty accurate on PRO core. Is it an expected behaviour?
At the same time counting cycles via "CCOUNT" register produce the same results on both cores.

Who is online

Users browsing this forum: ESP_Sprite and 120 guests