Перейти к основному содержимому

mp.memory — 60 функций

Функции *_at принимают абсолютный MCU-адрес; смещение в буфере вычисляется автоматически: buffer_offset = addr - region.start_address.

-- Flash начинается с 0x4000. Чтение 4 байт по адресу 0xF650:
local bytes = mp.memory.read_at("Flash", 0xF650, 4)
-- внутри читает смещение в буфере: 0xF650 - 0x4000 = 0xB650

Навигация по регионам

ФункцияВозвратОписание
get_regions()tableМассив имён регионов
current_region()stringИмя активного региона
region_count()intКоличество регионов
select_region(idx)voidПереключить регион по индексу (с 0)
select_region_by_name(n)boolПереключить регион по имени
get_region_info([r])table{index, name, size, start_address, end_address, cell_size}r это имя, индекс или опущен (активный)
region_size(r)intРазмер региона в байтах

Редактируемость

Вкладки по умолчанию read-only, как в GUI. Записи молча возвращают false, пока не включить writability.

ФункцияВозвратОписание
set_writable(r, b)ok, errr — имя или индекс; b — bool. Голый set_writable(b) (один bool) переключает все табы. set_writable(0) (число) → (false, "...")
set_writable_all(b)ok, errПрименить ко всем регионам
is_writable([r])boolr — имя, индекс или опущен (активный регион)

Чтение — по смещению

ФункцияВозвратОписание
read_byte(r, off)intОдин байт (-1 если вне диапазона)
read_range(r, start, len)tableМассив байт
read_bytes(r, off, n)tableМассив байт (alias-class с read_range)
read_hex(r, off, n)stringHex-строка, например "deadbeef"
read_string(r, off, maxLen)stringСырая строка (может содержать непечатное)
read_string_until_null(r, off, maxLen?)stringДо первого NUL (по умолчанию макс 256)
get_region_data(r)tableВесь регион как массив байт
get_all_data()tableВсе регионы подряд как массив байт

Чтение — по адресу

ФункцияВозвратОписание
read_at(r, addr, n)tableМассив байт начиная с MCU-адреса
read_byte_at(r, addr)intОдин байт по MCU-адресу
read_string_at(r, addr, maxLen)stringСырая строка по MCU-адресу
read_string_until_null_at(r, addr, maxLen?)stringДо первого NUL по абсолютному адресу (макс 256)

Запись — по смещению

ФункцияВозвратОписание
write_byte(r, off, v)boolОдин байт
write_range(r, off, bytes)boolМассив байт
write_hex(r, off, hexStr)boolБайты из hex-строки
write_string(r, off, text)boolСырая строка
fill(r, off, len, v)boolЗаливка константой
fill_pattern(r, off, len, pattern)boolЗаливка повторяющимся паттерном байт

Запись — по адресу

ФункцияВозвратОписание
write_at(r, addr, bytes)boolМассив байт по MCU-адресу
write_byte_at(r, addr, v)boolОдин байт по MCU-адресу
write_string_at(r, addr, text)boolСырая строка по MCU-адресу

Поиск

ФункцияВозвратОписание
find(r, hex, startOff?)intСмещение первого совпадения или -1
find_prev(r, hex, startOff?)intПоследнее совпадение до start, или -1
find_all(r, hex) / find_all(r, byte_table)tableМассив смещений в регионе. Для ASCII используйте byte-table или find_string
find_string(r, text, startOff?)intПервое ASCII-совпадение или -1
search_all(hex) / search_all(region, hex)table{region, offset, address, offset_hex, address_hex} на каждое совпадение. Без region — по всем регионам
search_string_all(text) / search_string_all(region, text)tableТо же + context_hex (совпавшие байты + 16 после)
search_patterns(patterns)tableБатч: {label, hits[], count}

Выделение и курсор

ФункцияВозвратОписание
set_selection(r, off, len)voidВыделить диапазон
get_selection(r)table{start, end, length, hex} или пустая
go_to(r, off)ok, errПереместить курсор на смещение
cursor_offset(r)intТекущее смещение курсора

Undo / redo

ФункцияВозвратОписание
undo(r)voidОткатить последнее
redo(r)voidПовторить
can_undo(r)bool
can_redo(r)bool

Закладки

ФункцияВозвратОписание
add_bookmark(r, off, comment) / add_bookmark(off, comment)ok, errДобавить закладку
get_bookmarks(r) / get_bookmarks() / list_bookmarks(...)tableМассив {offset, comment}
clear_bookmarks(r)voidУдалить все

Конвертация адресов

ФункцияВозвратОписание
addr_to_offset(r, addr)intMCU-адрес → смещение в буфере (-1 если ниже базы)
offset_to_addr(r, off)intСмещение в буфере → MCU-адрес

Буфер и экспорт

ФункцияВозвратОписание
clear()voidОчистить все буферы (через backend)
load_file() / show_load_dialog()voidОткрыть диалог импорта
load_file(path)ok, errПарсит файл, заполняет регионы по совпавшим адресам
save_file() / show_save_dialog()voidОткрыть диалог экспорта
save_file(path)ok, errЗаписать все регионы в <path> (формат по расширению)
export_region(r, path[, off, len])stringОшибка или пусто. Опц. off, len — слайс в байтах буфера; адрес в файле = start_address + off
export_all(path)stringЭкспорт всех регионов в один файл
compare(r1, r2)table{diffs[], diff_count, size1, size2, equal}

Имена регионов и cell_size — типичные ловушки

Три момента, на которых спотыкается каждый новый автор скрипта:

1. Имена регионов — не везде "Flash"

Каждый бэкенд использует свои — P_Flash, D_Flash, RAM_P (DSC), Code Flash, EEPROM, User Boot и т.д. Не хардкодьте, перечислите сначала:

for i, name in ipairs(mp.memory.get_regions()) do
mp.log.info(i .. ": " .. name)
end

При ошибочном имени read_byte / go_to / cursor_offset молча возвращают 0 / false / -1. Бэкенд логирует [QT-WARN] со списком актуальных имён — смотрите лог, если что-то «всегда возвращает 0».

2. Содержимое буфера сразу после set_target — НЕ чип

Большинство бэкендов префиллят регион байтами 0xFF на полный размер, поэтому region_size может уже вернуть реальный размер flash, а read_byte возвращает 0xFF — это не содержимое чипа, это dummy «erased flash» заглушка. Всегда вызывайте mp.backend.read() (или mp.file.load(path)) до выводов о содержимом чипа.

3. Word-addressed таргеты — DSC, dsPIC и подобные

Freescale / NXP DSC (MC56F8xxx) word-addressed: один адрес устройства указывает на 16-битную ячейку, но в буфере лежат байты, поэтому region.sizeв 2 раза больше числа адресуемых слов, а cell_size = 2.

Проверяйте cell_size и пересчитывайте на границе адрес ↔ смещение в буфере:

local info = mp.memory.get_region_info() -- например, P_Flash на MC56F8006
-- info.start_address = 0x800, size = 12288 (байт), cell_size = 2
-- → 6144 word-адресов от 0x800 до 0x37FF

-- byte_offset (Lua API) = (адрес_устройства - start_address) * cell_size
local addr = 0x900
local byte_offset = (addr - info.start_address) * info.cell_size -- 0x200
local lo = mp.memory.read_byte(info.name, byte_offset)
local hi = mp.memory.read_byte(info.name, byte_offset + 1)
local word = lo | (hi << 8)

_at-семейство (read_at, read_byte_at, write_at, write_byte_at, addr_to_offset, offset_to_addr) не умножает на cell_size — они трактуют address - start_address как байтовый offset в буфер. Для cell_size == 1 это совпадает; для DSC вы должны сами умножать на cell_size, либо работать сразу в байтовых offset через read_range / read_byte.

mp.memory.go_to(region, off) и cursor_offset(region) работают в байтах буфера, а не в word-адресах устройства — умножайте свой адрес на cell_size, если он пришёл из datasheet или HEX-файла.