add, use coproc_manager
This commit is contained in:
parent
5e5d1800b6
commit
dc16588575
5 changed files with 74 additions and 40 deletions
17
py/coproc_manager.py
Normal file
17
py/coproc_manager.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import minielf
|
||||||
|
|
||||||
|
class Program:
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.elf = minielf.ELFFile(open(filename, "rb"))
|
||||||
|
code_header = self.elf.get_header_by_type(minielf.PT_LOAD)
|
||||||
|
self.code = bytes(self.elf.pread(code_header.p_offset, code_header.p_filesz))
|
||||||
|
self.symtab = self.elf.get_section_by_name('.symtab')
|
||||||
|
|
||||||
|
def get_code(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_symbol(self, name):
|
||||||
|
r = self.symtab.get_first_symbol_by_name(name)
|
||||||
|
if r is None:
|
||||||
|
raise ValueError(f"{repr(name)} not found")
|
||||||
|
return r
|
||||||
|
|
@ -1,26 +1,28 @@
|
||||||
import time
|
import time
|
||||||
import struct
|
import struct
|
||||||
from coproc import *
|
from coproc import *
|
||||||
from minidump import e, h, en
|
from coproc_manager import Program
|
||||||
|
|
||||||
def storele32(cm, off, x):
|
|
||||||
print(off, ":=", x)
|
program = Program("/a.out-stripped")
|
||||||
cm[off:off+4] = struct.pack("<l", x)
|
shared_mem = program.get_symbol('shared_mem').entry.st_value
|
||||||
def storele16(cm, off, x):
|
print(f"{shared_mem=}")
|
||||||
print(off, ":=", x)
|
|
||||||
cm[off:off+2] = struct.pack("<h", x)
|
|
||||||
binary = e._readat(h.p_offset, h.p_filesz)
|
|
||||||
cm = CoprocMemory(0x50000000, 8176)
|
cm = CoprocMemory(0x50000000, 8176)
|
||||||
off = en.st_value
|
c = Coproc(program.code)
|
||||||
print(f"value at {off}, adjusted offset is {off}")
|
print(f"{shared_mem=}")
|
||||||
c = Coproc(binary)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
run(c)
|
run(c)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
cm[off] = 10
|
cm[shared_mem] = 10
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
cm[off] = 20
|
cm[shared_mem] = 20
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
finally:
|
finally:
|
||||||
|
print("about to halt")
|
||||||
|
time.sleep(.2)
|
||||||
halt(c)
|
halt(c)
|
||||||
|
print("returned from halt")
|
||||||
|
time.sleep(.2)
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,13 @@ a_out = open("a.out-stripped", "rb")
|
||||||
e = ELFFile(a_out)
|
e = ELFFile(a_out)
|
||||||
s = e.get_section(1)
|
s = e.get_section(1)
|
||||||
s = e.get_section_by_name('.symtab')
|
s = e.get_section_by_name('.symtab')
|
||||||
sy = s.get_symbol_by_name('shared_mem')[0]
|
print(s)
|
||||||
|
sy = s.get_first_symbol_by_name('shared_mem')
|
||||||
en = sy.entry
|
en = sy.entry
|
||||||
for h in e.iter_headers():
|
for h in e.iter_headers():
|
||||||
if h.p_type == PT_LOAD:
|
if h.p_type == PT_LOAD:
|
||||||
print(f"@{h.p_vaddr:04x}: Load {h.p_filesz} bytes starting at {h.p_offset}")
|
print(f"@{h.p_vaddr:04x}: Load {h.p_filesz} bytes starting at {h.p_offset}")
|
||||||
content = e._readat(h.p_offset, 16)
|
content = e.pread(h.p_offset, 16)
|
||||||
print(" ".join(f"{b:02x}" for b in content))
|
print(" ".join(f"{b:02x}" for b in content))
|
||||||
|
|
||||||
print(f"shared_mem @ 0x{en.st_value:04x} 0x{en.st_size:04x} bytes")
|
print(f"shared_mem @ 0x{en.st_value:04x} 0x{en.st_size:04x} bytes")
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ class Section:
|
||||||
self._header = sh
|
self._header = sh
|
||||||
|
|
||||||
def readat(self, offset, sz):
|
def readat(self, offset, sz):
|
||||||
return self._elffile._readat(offset + self._header.sh_offset, sz)
|
return self._elffile.pread(offset + self._header.sh_offset, sz)
|
||||||
def constructat(self, offset, cls):
|
def constructat(self, offset, cls):
|
||||||
return self._elffile._constructat(offset + self._header.sh_offset, cls)
|
return self._elffile.construct_at(offset + self._header.sh_offset, cls)
|
||||||
|
|
||||||
class StringTable(Section):
|
class StringTable(Section):
|
||||||
def symbolat(self, offset):
|
def symbolat(self, offset):
|
||||||
|
|
@ -42,6 +42,15 @@ class StringTable(Section):
|
||||||
result += c
|
result += c
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def symbolat_matches(self, offset, name):
|
||||||
|
stream = self._elffile.stream
|
||||||
|
stream.seek(self._header.sh_offset + offset)
|
||||||
|
name1 = stream.read(len(name))
|
||||||
|
if name1 != name: return False
|
||||||
|
nul = stream.read(1)
|
||||||
|
if nul != b'\0': return False
|
||||||
|
return True
|
||||||
|
|
||||||
_SymbolTableEntry = namedtuple('_SymbolTableEntry',
|
_SymbolTableEntry = namedtuple('_SymbolTableEntry',
|
||||||
['st_name', 'st_value', 'st_size', 'set_info', 'st_other', 'st_shndx'])
|
['st_name', 'st_value', 'st_size', 'set_info', 'st_other', 'st_shndx'])
|
||||||
|
|
||||||
|
|
@ -54,17 +63,22 @@ class Symbol:
|
||||||
self.entry = entry
|
self.entry = entry
|
||||||
|
|
||||||
class SymbolTable(Section):
|
class SymbolTable(Section):
|
||||||
|
def __init__(self, ef, sh):
|
||||||
|
super().__init__(ef, sh)
|
||||||
|
self.strtab = None
|
||||||
|
|
||||||
def iter_symbols(self):
|
def iter_symbols(self):
|
||||||
for i in range(0, self._header.sh_size, SymbolTableEntry.calcsize()):
|
for i in range(0, self._header.sh_size, SymbolTableEntry.calcsize()):
|
||||||
yield self.constructat(i, SymbolTableEntry)
|
yield self.constructat(i, SymbolTableEntry)
|
||||||
|
|
||||||
def get_symbol_by_name(self, name):
|
def get_first_symbol_by_name(self, name):
|
||||||
if not isinstance(name, bytes): name = name.encode()
|
if not isinstance(name, bytes): name = name.encode()
|
||||||
strs = self._elffile.get_section_by_name('.strtab')
|
if self.strtab is None:
|
||||||
|
self.strtab = self._elffile.get_section_by_name('.strtab')
|
||||||
|
strtab = self.strtab
|
||||||
for sy in self.iter_symbols():
|
for sy in self.iter_symbols():
|
||||||
name2 = strs.symbolat(sy.st_name)
|
if strtab.symbolat_matches(sy.st_name, name):
|
||||||
if name == name2:
|
return Symbol(name, sy)
|
||||||
return [Symbol(name, sy)]
|
|
||||||
|
|
||||||
|
|
||||||
section_constructors = {
|
section_constructors = {
|
||||||
|
|
@ -84,13 +98,13 @@ class ELFFile:
|
||||||
def __init__(self, stream):
|
def __init__(self, stream):
|
||||||
self.stream = stream
|
self.stream = stream
|
||||||
self._buffer = ()
|
self._buffer = ()
|
||||||
if self._readat(0, 4) != b'\177ELF':
|
if self.pread(0, 4) != b'\177ELF':
|
||||||
raise ValueError("Not an ELF file")
|
raise ValueError("Not an ELF file")
|
||||||
if self._readat(4, 3) != b'\1\1\1':
|
if self.pread(4, 3) != b'\1\1\1':
|
||||||
raise ValueError("Incompatible ELF file")
|
raise ValueError("Incompatible ELF file")
|
||||||
self._header = self._constructat(0, ElfHeader32)
|
self._header = self.construct_at(0, ElfHeader32)
|
||||||
|
|
||||||
def _readat(self, offset, sz):
|
def pread(self, offset, sz):
|
||||||
if len(self._buffer) < sz:
|
if len(self._buffer) < sz:
|
||||||
self._buffer = bytearray(sz)
|
self._buffer = bytearray(sz)
|
||||||
self._view = memoryview(self._buffer)
|
self._view = memoryview(self._buffer)
|
||||||
|
|
@ -99,21 +113,16 @@ class ELFFile:
|
||||||
self.stream.readinto(mv)
|
self.stream.readinto(mv)
|
||||||
return mv
|
return mv
|
||||||
|
|
||||||
def _decodeat(self, offset, fmt):
|
def construct_at(self, offset, cls):
|
||||||
sz = struct.calcsize(fmt)
|
|
||||||
mb = self._readat(offset, sz)
|
|
||||||
return struct.unpack(fmt, mv)
|
|
||||||
|
|
||||||
def _constructat(self, offset, cls):
|
|
||||||
sz = cls.calcsize()
|
sz = cls.calcsize()
|
||||||
mb = self._readat(offset, sz)
|
mb = self.pread(offset, sz)
|
||||||
return cls.frombuffer(mb)
|
return cls.frombuffer(mb)
|
||||||
|
|
||||||
def get_section(self, index):
|
def get_section(self, index):
|
||||||
if not (0 <= index < self._header.e_shnum):
|
if not (0 <= index < self._header.e_shnum):
|
||||||
raise IndexError("Invalid section number")
|
raise IndexError("Invalid section number")
|
||||||
offset = self._header.e_shoff + index * self._header.e_shentsize
|
offset = self._header.e_shoff + index * self._header.e_shentsize
|
||||||
sh = self._constructat(offset, SectionHeader32)
|
sh = self.construct_at(offset, SectionHeader32)
|
||||||
constructor = section_constructors.get(sh.sh_type, Section)
|
constructor = section_constructors.get(sh.sh_type, Section)
|
||||||
return constructor(self, sh)
|
return constructor(self, sh)
|
||||||
|
|
||||||
|
|
@ -126,16 +135,20 @@ class ELFFile:
|
||||||
idx = self.get_section(self._header.e_shstrndx)
|
idx = self.get_section(self._header.e_shstrndx)
|
||||||
for sec in self.iter_sections():
|
for sec in self.iter_sections():
|
||||||
off = sec._header.sh_name
|
off = sec._header.sh_name
|
||||||
name2 = idx.symbolat(off)
|
if idx.symbolat_matches(sec._header.sh_name, name):
|
||||||
if name == name2:
|
|
||||||
return sec
|
return sec
|
||||||
|
|
||||||
def get_header(self, index):
|
def get_header(self, index):
|
||||||
if not (0 <= index < self._header.e_phnum):
|
if not (0 <= index < self._header.e_phnum):
|
||||||
raise IndexError("Invalid header number")
|
raise IndexError("Invalid header number")
|
||||||
offset = self._header.e_phoff + index * self._header.e_phentsize
|
offset = self._header.e_phoff + index * self._header.e_phentsize
|
||||||
return self._constructat(offset, HeaderTableEntry)
|
return self.construct_at(offset, HeaderTableEntry)
|
||||||
|
|
||||||
def iter_headers(self):
|
def iter_headers(self):
|
||||||
for i in range(self._header.e_phnum):
|
for i in range(self._header.e_phnum):
|
||||||
yield self.get_header(i)
|
yield self.get_header(i)
|
||||||
|
|
||||||
|
def get_header_by_type(self, p_type):
|
||||||
|
for h in self.iter_headers():
|
||||||
|
if h.p_type == p_type:
|
||||||
|
return h
|
||||||
|
|
|
||||||
7
ulp.c
7
ulp.c
|
|
@ -15,17 +15,18 @@ EXPORT uint16_t shared_mem_len = 1024;
|
||||||
#undef ULP_RISCV_CYCLES_PER_MS
|
#undef ULP_RISCV_CYCLES_PER_MS
|
||||||
#define ULP_RISCV_CYCLES_PER_MS (int)(1000*ULP_RISCV_CYCLES_PER_US)
|
#define ULP_RISCV_CYCLES_PER_MS (int)(1000*ULP_RISCV_CYCLES_PER_US)
|
||||||
|
|
||||||
|
#define GPIO (GPIO_NUM_3)
|
||||||
int main (void) {
|
int main (void) {
|
||||||
shared_mem[0] = 10;
|
shared_mem[0] = 10;
|
||||||
shared_mem_len = 1024;
|
shared_mem_len = 1024;
|
||||||
|
|
||||||
bool gpio_level = true;
|
bool gpio_level = true;
|
||||||
|
|
||||||
ulp_riscv_gpio_init(GPIO_NUM_21);
|
ulp_riscv_gpio_init(GPIO);
|
||||||
ulp_riscv_gpio_output_enable(GPIO_NUM_21);
|
ulp_riscv_gpio_output_enable(GPIO);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
ulp_riscv_gpio_output_level(GPIO_NUM_21, gpio_level);
|
ulp_riscv_gpio_output_level(GPIO, gpio_level);
|
||||||
ulp_riscv_delay_cycles(shared_mem[0] * 10 * ULP_RISCV_CYCLES_PER_MS);
|
ulp_riscv_delay_cycles(shared_mem[0] * 10 * ULP_RISCV_CYCLES_PER_MS);
|
||||||
gpio_level = !gpio_level;
|
gpio_level = !gpio_level;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue