Перейти к содержанию
Материалы раздела

ULP

Модуль ulp управляет ULP FSM-сопроцессором ESP32. Он может выполнять измерения и обращаться к RTC_SLOW_MEM, пока основные процессоры находятся в глубоком сне. Инструкции и ячейки памяти имеют ширину 32 бита, а четыре регистра ULP — 16 бит. Методы valueat и value работают с младшими 16 битами ячейки памяти.

ulp.load(filename [, load_address])

Загружает скомпилированную бинарную программу ULP в зарезервированную область RTC_SLOW_MEM.

  • filename — путь к бинарному файлу ULP;
  • load_address — смещение загрузки в 32-битных словах, по умолчанию 0.

Файл должен иметь корректный формат ULP, содержать непустую секцию инструкций, иметь размер, кратный четырём байтам, и помещаться в зарезервированную память.

ulp.load("/examples/ulp/adc-ch4.ulp")

ulp.settimer(period1_us [, period2_us, period3_us, period4_us])

Настраивает четыре периода запуска ULP в микросекундах. Первый период используется после ulp.run; затем программа ULP может выбрать один из остальных регистров инструкцией сна. Неуказанные периоды устанавливаются в 0.

-- Запускать ULP каждые 100 мс по первому периоду.
ulp.settimer(100000)

ulp.run([entry_point])

Запускает последнюю успешно загруженную программу и включает таймер ULP. entry_point — точка входа в 32-битных словах, по умолчанию 0. Она должна попадать в секцию инструкций этой программы; при ненулевом load_address точку входа нужно передать явно.

ulp.run()

ulp.stop()

Отключает таймер ULP и предотвращает следующие периодические запуски. Уже выполняющаяся программа должна самостоятельно дойти до инструкции HALT.

ulp.stop()

ulp.enableadc(channel [, resolution, vref, max_value])

Настраивает канал внутреннего ADC1 для ULP и включает доступ ULP к АЦП.

  • channeladc.ADC_CH0adc.ADC_CH7 или соответствующий GPIO (pio.GPIO32pio.GPIO39);
  • resolution — разрешение от 9 до 12 бит, по умолчанию 12;
  • vref — для внутреннего АЦП должно быть nil или 0;
  • max_value — ожидаемое максимальное входное напряжение в милливольтах, от 0 до 3900. Значение определяет ослабление входа; 0 выбирает значение по умолчанию 3900 мВ.
-- GPIO32 соответствует каналу ADC1_CH4.
ulp.enableadc(pio.GPIO32, 12, 0, 1100)

Доступ к переменным ULP

ulp.valueat и объект, возвращённый ulp.assign, принимают абсолютные адреса основной системы, а не смещения в словах. Адрес должен быть выровнен по четырём байтам и находиться в области RTC_SLOW_MEM, зарезервированной для ULP.

Компоновщик ULP обычно показывает символы как смещения от начала этой области. Для ESP32 к такому смещению нужно прибавить базовый адрес 0x50000000: например, смещению 0x70 соответствует адрес 0x50000070.

При чтении возвращаются только младшие 16 бит 32-битного слова. При записи сохраняется value & 0xffff; старшие 16 бит очищаются. Используйте адреса символов из файла компоновки именно вашей ULP-программы — адреса из примеров нельзя переносить в другую программу без проверки.

value = ulp.valueat(address)

ulp.valueat(address, value)

Читает значение по адресу или записывает новое.

ulp.load("/examples/ulp/adc-ch4.ulp")

-- Адреса должны совпадать с символами собранной ULP-программы.
ulp.valueat(0x50000070, 0)
ulp.valueat(0x50000074, 2000)

ulp.run()

local last_result = ulp.valueat(0x5000007c)
print(last_result)

variable = ulp.assign(address)

Создаёт Lua-объект, привязанный к адресу переменной ULP. Это позволяет один раз указать адрес и затем работать с ним через методы value и address.

ulp.load("/examples/ulp/adc-ch4.ulp")

local low_threshold = ulp.assign(0x50000070)
local high_threshold = ulp.assign(0x50000074)
local last_result = ulp.assign(0x5000007c)

low_threshold:value(0)
high_threshold:value(2000)

ulp.run()
print(last_result:value())

value = variable:value()

variable:value(value)

Читает или записывает младшие 16 бит слова по назначенному адресу.

address = variable:address()

variable:address(address)

Возвращает назначенный адрес или привязывает объект к другому допустимому адресу RTC_SLOW_MEM.