These are chat archives for esp8266/Arduino

2nd
Aug 2016
sticilface
@sticilface
Aug 02 2016 17:17

question for esp8266 boffins! PROGMEM what section should it end up in... i've got 3 strings in print

Serial.printf_P( PSTR("hello-pgm")); 
Serial.print("hello-not");
Serial.print( F("hello-F()"));

"hello-pgm" and "hello-F()" both end up in section .irom0.text:
"hello-not" ends up in section .rodata:

as

#define PROGMEM     ICACHE_RODATA_ATTR

should it not all be in .rodata.. I'm not entirely sure which sections are in RAM or not...

Michael Miller
@Makuna
Aug 02 2016 17:34
Rodata is still ram on esp8266, it's usually ram on most platforms. Irom0 section is flash on the esp8266, thus saving ram. Most code also resides in flash and is retrieved and cached in ram when run; but code can be marked so it stays on ram for faster access (like ISRs or timing critical code )
Hagai Shatz
@hagai-shatz
Aug 02 2016 17:55
Question - with all sort of other things running on the ESP (WiFi, AsyncServer, etc.), is there a way to execute a short HSPI communication every 500ns?
sticilface
@sticilface
Aug 02 2016 17:58
@Makuna cheers for clearing that up
Me No Dev
@me-no-dev
Aug 02 2016 18:03
@hagai-shatz every 500ns?
I doubt you can do anything even every 2-3us
Hagai Shatz
@hagai-shatz
Aug 02 2016 18:04
Sorry, 500us.
Michael Miller
@Makuna
Aug 02 2016 18:04
Also, while RAM can be accessed by 8 bits, flash must be read by 32 bits at atime, thus the requirement of using the progmem macros and wrappers. For AVR it's a completely different access method.
Me No Dev
@me-no-dev
Aug 02 2016 18:04
sure thing ;) totally doable
Hagai Shatz
@hagai-shatz
Aug 02 2016 18:05
How?
Me No Dev
@me-no-dev
Aug 02 2016 18:05
timer0 or timer1
or Ticker
Michael Miller
@Makuna
Aug 02 2016 18:06
@hagai-shatz how accurate do you need that 500us to be?
Hagai Shatz
@hagai-shatz
Aug 02 2016 18:08
20% tolerance will be okay.
About 2000 executions per second.
@me-no-dev - but what if something else is handled in interrupt and it take time to finish? Does the AsyncServer is interrupt based?
Some SPIFFS calls takes >10ms to execute.
Me No Dev
@me-no-dev
Aug 02 2016 18:15
@hagai-shatz using timer1 and it's regular ISR will not interrupt the network (that I have tested). Using NMI interrupt will, but I did not see any issues with that. I have not tested timer0 and Ticker, but Ticker should behave the same.
Hagai Shatz
@hagai-shatz
Aug 02 2016 18:19
Can you point me to some examples please?
As for Ticker, I use it and it is not reliable even in 20ms intervals. It looks like when the ESP is busy with AsyncWebServer handlers it does not tick.
Me No Dev
@me-no-dev
Aug 02 2016 18:23
analogWrite is an example with timer1, though it looks way more complicated than it is
gimme a minute to finish something and I'll try to put one up
Michael Miller
@Makuna
Aug 02 2016 18:42
Same with the servo library, it uses both timer0 and timer1, but abstracts them thus making it look more complex than it is.
Me No Dev
@me-no-dev
Aug 02 2016 18:55
@Makuna is ccompare running with higher prio than the network?
Michael Miller
@Makuna
Aug 02 2016 19:24
Its been a year since I researched it and I have forgotten most of what I have learned; but I thought there was a way to set the level.
TIMERINT[0..NCCOMPARE-1]
Interrupt number for each comparator
Me No Dev
@me-no-dev
Aug 02 2016 19:34
@hagai-shatz here is the code
Michael Miller
@Makuna
Aug 02 2016 19:34
Its a strange interrupt, INTCLEAR doesn't work with it.
Me No Dev
@me-no-dev
Aug 02 2016 19:34
#define TIMER_PERIOD 500 //us

void onTimer(){
  //do your thing
  // NO YIELD OR DELAY
}

void setup() {
  timer1_attachInterrupt(&onTimer);
  timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
  timer1_write(TIMER_PERIOD * 5);
}

void loop() {

}
@Makuna I digged myself a bit as well working on the ESP31B but forgot it all the same as you
Michael Miller
@Makuna
Aug 02 2016 19:47
timer0 does not support scaling, it runs at instruction count speed always and doesn't auto reset. So you set the timer by calling timer0_write(count) giving it the instruction count to trigger on, once it fires you have to call write again to get it to fire again. To calculate the trigger count, call timer0_read() and add your count to it and pass this to write.
Me No Dev
@me-no-dev
Aug 02 2016 19:49
count per microsecond depend on cpu speed and it's either 80 or 160
Michael Miller
@Makuna
Aug 02 2016 19:53

Use something like this and avoid constants so you don't care about 80, 160.

    uint32_t usToTicks(uint32_t us) const
    {
        return (clockCyclesPerMicrosecond() * us);     // converts microseconds to tick
    }
    uint32_t ticksToUs(uint32_t ticks) const
    {
        return (ticks / clockCyclesPerMicrosecond()); // converts from ticks back to microseconds
    }

This is what the servo timer stuff uses when using timer0.

Me No Dev
@me-no-dev
Aug 02 2016 20:03
static uint32_t ticksPeriod = 500;//still in us

void onTimer0(){
  uint32_t ticksAtEnter = timer0_read();
  //do your thing
  // NO YIELD OR DELAY
  timer0_write(ticksAtEnter + ticksPeriod);
}

void setup() {
  //convert period in us to ticks
  ticksPeriod *= clockCyclesPerMicrosecond();
  uint32_t ticksAtInit = timer0_read();
  timer0_attachInterrupt(&onTimer0);
  timer0_write(ticksAtInit + ticksPeriod);
}
@Makuna is this correct?
woops missed attachInterrupt
Hagai Shatz
@hagai-shatz
Aug 02 2016 20:27
@Makuna, @me-no-dev - thanks for the examples, will give it a go.
Are there more differences between timer0 and timer1?
Can I break some other functionality by using them? For example, unable to use the servo library?
Me No Dev
@me-no-dev
Aug 02 2016 20:31
above code does not run for timer0
I'm looking into why timer0_read is returning 0;
timer0 is used by the Servi lib
timer1 is used by analogWrite
so those will not work
Hagai Shatz
@hagai-shatz
Aug 02 2016 20:37
Not good. But since I'm not planning on using Servi lib for now, this might be okay. As long as the timer0_read() works! :smile:
Me No Dev
@me-no-dev
Aug 02 2016 20:47
ok I should have read @Makuna better and use ccount
also missed to init the interrupt
static uint32_t ticksPeriod = 500;//still in us

void onTimer0(){
  uint32_t ticksAtEnter = ESP.getCycleCount();
  //do your thing
  // NO YIELD OR DELAY
  timer0_write(ticksAtEnter + ticksPeriod);
}

void setup() {
  //convert period in us to ticks
  ticksPeriod *= clockCyclesPerMicrosecond();
  timer0_isr_init();
  timer0_attachInterrupt(&onTimer0);
  timer0_write(ESP.getCycleCount() + ticksPeriod);
}
both run with the same accuracy as far as I can tell
Hagai Shatz
@hagai-shatz
Aug 02 2016 20:58
Thanks
Michael Miller
@Makuna
Aug 02 2016 23:41
Last time I checked, timer0 was only used by servo library so in general it is open for use. Servo library can be told to use timer1 only also.
@me-no-dev esp.getcyclecount aND timer0_read should be the samething.