Page 1 of 1

Preallocating ram

Posted: Sun Oct 15, 2017 2:54 am
by droidwarrior
Hi all,

Having lot of trouble understanding how to preallocate ram for ISR routines no using classes.
Please someone enlight me.


Regards,

Re: Preallocating ram

Posted: Sun Oct 15, 2017 6:57 am
by Roberthh
You can preallocate a buffer outside the ISR and declare it that global, like this example below with a circular buffer:

Code: Select all

BUFFERSIZE = const(128)
_data = bytearray(BUFFERSIZE)
_index_put = 0
_index_get = 0

def my_isr(pin):
    global _data, _index_put
    .....
    _data[_index_put] = whatever_you captured_in_the_ISR
    _index_put = (_index_put + 1) % BUFFERSIZE
_data, being global, is also accessible outside the ISR. If you put that in a separate file and maybe also define a function for retrieving values from it, using it looks like using a class.

Re: Preallocating ram

Posted: Sun Oct 15, 2017 8:36 pm
by droidwarrior
Hi, thanks for your reply.

BUFFERSIZE = const(128)
_data = bytearray(BUFFERSIZE)

* You declared a bytearray to make the variable mutable and to make it contiguos and reuse the same ram positions everytime you write?


def my_isr(pin):
global _data, _index_put

* For what i see, for use the bytearray declared top, one has to include it as a global in every function whether they are ISR o regular code functions. Right?


Regards,

Re: Preallocating ram

Posted: Mon Oct 16, 2017 5:17 am
by Roberthh
A regular function within the same module does not have to declare _data as global, because when it's not local, the global name space will be searched for. But it does not hurt to declare it global. An ISR has no known global name space, therefore _data (and other global symbols) must be declared as global. This is just a simple circular buffer example with a global buffer and a variable. The buffer has not to be static, just the name you use as the handle must be static. As far as I recall, the ISR mechanism has changed, at least for the ESP series, in that the actual interrupt just registers your ISR function to be scheduled as soon as possible as regular Python function. These scheduled Pseudo-ISR ares different in that they can allocate memory if needed. This is much more convenient when writing code, since also intrinsic memory allocation is needed, e.g. for floating point operations. On the downside, this mechanism increases the interrupt latency.

There is an optimisation for pointing the ISR to _data, by supplying it as a function argument (thanks to Damien for the hint), like:

Code: Select all

BUFFERSIZE = const(128)
_data = bytearray(BUFFERSIZE)
_index_put = 0
_index_get = 0

def my_isr(pin, data = _data):
    global _index_put
    .....
    data[_index_put] = whatever_you captured_in_the_ISR
    _index_put = (_index_put + 1) % BUFFERSIZE
Doing that the local symbol data is linked to the global symbol _data already at compile time. That works for _data, but not for _index_put.

P.S.: In my first submit there was a typo. Within the ISR it must be written _data[] = ... . The _ letter was missing. Fixed.

Re: Preallocating ram

Posted: Mon Oct 16, 2017 7:11 am
by pythoncoder
Roberthh wrote:
Mon Oct 16, 2017 5:17 am
...As far as I recall, the ISR mechanism has changed, at least for the ESP series, in that the actual interrupt just registers your ISR function to be scheduled as soon as possible as regular Python function....
As I understand it ESP8266 interrupts are still hard interrupts (like the Pyboard).

@droidwarrior The latency of the ESP8266 is much higher than the Pyboard (on the order of 600μs max) because of the underlying RTOS, but the handlers are still subject to the same rules. Soft interrupts are handled by machine.schedule: see the recently revised http://docs.micropython.org/en/latest/p ... rules.html. The latency of soft IRQ's is higher still (on the order of single digits of ms) because they will not be scheduled when a garbage collection is in progress.