Skip to content

esp32/machine_rtc: ESP32 machine.RTC().usermem() returning a bytearray. #7133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions docs/library/machine.RTC.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,82 @@ Methods
- ``wake`` specifies the sleep mode from where this interrupt can wake
up the system.

.. method:: RTC.memory([data])

Stores ``data`` (byte literal) into RTC memory, which is kept stored in deep sleep mode of the ESP8266 or ESP32.
The data is stored together with a magic word to detect that the RTC memory is valid.
An uninitialized or cleared RTC memory has no magic word and will deliver ``b''``.
Without ``data`` the method delivers the RTC memory content.
In the ESP8266 are max. 492 bytes and in the ESP32 are max. 2048 Bytes storeable by this method.

Example::

import machine
rtc = machine.RTC()
writedata = b'test'
rtc.memory(writedata) # this command writes writedata into the RTC memory
readdata = rtc.memory() # this command puts the RTC memory into readdata
print(readdata)

Availability: ESP8266, ESP32

.. method:: RTC.usermem()

This is similar to the RTC.memory() above, but returns a bytearray object whose data
gets stored directly in the user memory area.

**The bytearray uses the same memory area as** ``RTC.memory()``, so a little care is required when using both methods.

Advantages over ``RTC.memory()``:

- quick access to the entire available RTC slow memory user area
- Python access to details of the memory area, e.g. by using ``uctypes.sizeof()``
and ``uctypes.addressof()``
- data loggers and similar applications don't need to copy the entire (up to 3.5k)
memory area

The data is stored together with a magic word to detect that the RTC memory is valid.
An uninitialized or cleared RTC memory has no magic word; the bytearray returned
by ``RTC.usermem()`` will contain binary zeroes.

Example::

from machine import RTC
import uctypes

RESERVED = 64 # leave a little space for RTC.memory()

STRUCT = {
"data1": 0 | uctypes.UINT32,
"data2": 0 | uctypes.UINT32,
}

# get the RTC memory area
rtc_mem = RTC().usermem()

data = uctypes.struct(uctypes.addressof(rtc_mem) + RESERVED, STRUCT)
print(data.data1) # get data1 out of RTC memory
data.data1 = 4712 # set data1 in RTC memory

Availability: ESP32

Constants
---------

.. data:: RTC.ALARM0

irq trigger source


Compile-time options
--------------------

These can be set e.g. in ``ports/esp32/boards/XXX/mpconfigboard.h``

``#define MICROPY_HW_RTC_USER_MEM_MAX 2048``

sets the entire size of the user memory. This can be increased up to ~3500 bytes on the ESP32.

A value of 0 (zero) disables ``RTC.memory()`` as well as ``RTC.usermem()``


18 changes: 16 additions & 2 deletions ports/esp32/machine_rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *ar
return mp_const_none;
}
}
STATIC mp_obj_t machine_rtc_datetime(size_t n_args, const mp_obj_t *args) {
STATIC mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
return machine_rtc_datetime_helper(n_args, args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, machine_rtc_datetime);
Expand All @@ -152,7 +152,20 @@ STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) {
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init);

#if MICROPY_HW_RTC_USER_MEM_MAX > 0
STATIC mp_obj_t machine_rtc_memory(size_t n_args, const mp_obj_t *args) {
/*
* both RTC().usermem() and RTC().memory() refer to the same area in memory.
* RTC().memory() is here for backward compatibility.
*/

// returns a bytearray referencing the whole user memory.
STATIC mp_obj_t machine_rtc_usermem(mp_obj_t self_in) {
// mp_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bytearray_by_ref(MICROPY_HW_RTC_USER_MEM_MAX, (void *)rtc_user_mem_data);
}
MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_usermem_obj, machine_rtc_usermem);


STATIC mp_obj_t machine_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// read RTC memory
uint8_t rtcram[MICROPY_HW_RTC_USER_MEM_MAX];
Expand All @@ -179,6 +192,7 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) },
#if MICROPY_HW_RTC_USER_MEM_MAX > 0
{ MP_ROM_QSTR(MP_QSTR_memory), MP_ROM_PTR(&machine_rtc_memory_obj) },
{ MP_ROM_QSTR(MP_QSTR_usermem), MP_ROM_PTR(&machine_rtc_usermem_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
Expand Down