avatartwo / avatar2

Python core of avatar²
Apache License 2.0
518 stars 98 forks source link

avatar2/handbook/0x03_memory.md/Avatar² Peripheral Emulation Ranges #108

Closed zhao-dddw closed 2 years ago

zhao-dddw commented 2 years ago

Hi, can i get a complete example?

from avatar2 import *

class HelloWorldPeripheral(AvatarPeripheral):

    def hw_read(self, offset, size):         
        ret = self.hello_world[:size]
        self.hello_world = self.hello_world[size:] + self.hello_world[:size]

        # Convert the return value to an integer (py2/py3-compatible)
        # Python >3.2 could just call int.from_bytes(ret, byteorder='little')
        s2fmt = {1: 'B', 2: 'H', 4: 'I', 8: 'Q')
        ret = struct.unpack('<' + s2fmt[size], ret)[0]

        return ret

    def nop_write(self, offset, size, value):
        return True    

    def __init__(self, name, address, size, **kwargs):
        AvatarPeripheral.__init__(self, name, address, size)

        self.hello_world=b'Hello World'

        self.read_handler[0:size] = self.hw_read 
        self.write_handler[0:size] = self.nop_write

[...]        

hw = avatar.add_memory_range(0x40004c00, 0x100, name='hello_world',
                             emulate=HelloWorldPeripheral, permissions='rw-')       

I want a working example, because I don't understand some functions very well, I hope I can refer to it. Thank you so much!

aurelf commented 2 years ago

Hi, that's a good point. We could make this a complete example. In the mean time, did you look at the examples repository ? Probably this can help.

https://github.com/avatartwo/avatar2-examples

mariusmue commented 2 years ago

Besides this, you can also find examples implementation for the nucleo_usart or max32-uart in the avatar2 pyperipheral directory.

Hope this helps!

zhao-dddw commented 2 years ago

Hi, that's a good point. We could make this a complete example. In the mean time, did you look at the examples repository ? Probably this can help.

https://github.com/avatartwo/avatar2-examples

Thank you for your reply. I have seen the examples repository, but I still don't understand it. I will take a closer look. Thank you again for your reply.

zhao-dddw commented 2 years ago

Besides this, you can also find examples implementation for the nucleo_usart or max32-uart in the avatar2 pyperipheral directory.

Hope this helps!

Ok, I'll take a closer look, thanks for your reply and suggestion. : )

zhao-dddw commented 2 years ago

Besides this, you can also find examples implementation for the nucleo_usart or max32-uart in the avatar2 pyperipheral directory.

Hope this helps!

Hi, when i run

from avatar2 import *
import struct

from avatar_peripheral import AvatarPeripheral

class HelloWorldPeripheral(AvatarPeripheral):

    def hw_read(self, offset, size):
        ret = self.hello_world[:size]
        self.hello_world = self.hello_world[size:] + self.hello_world[:size]

        # Convert the return value to an integer (py2/py3-compatible)
        # Python >3.2 could just call int.from_bytes(ret, byteorder='little')
        s2fmt = {1: 'B', 2: 'H', 4: 'I', 8: 'Q'}
        ret = struct.unpack('<' + s2fmt[size], ret)[0]

        return ret

    def nop_write(self, offset, size, value):
        return True

    def __init__(self, name, address, size, **kwargs):
        AvatarPeripheral.__init__(self, name, address, size)

        self.hello_world=b'Hello World'

        self.read_handler[0:size] = self.hw_read
        self.write_handler[0:size] = self.nop_write

avatar = Avatar(arch=ARM,output_directory='./tmp1/avatar')

qemu = avatar.add_target(QemuTarget)

hw = avatar.add_memory_range(0x40004c00, 0x100, name='hello_world',
                                                    emulate=HelloWorldPeripheral, permissions='rw-')
avatar.init_targets()

it will have this problem

root@avatar2-exp:~# python3 hello_world.py 
2022-07-05 13:44:28,842 | avatar.INFO | Initialized Avatar. Output directory is ./tmp1/avatar
2022-07-05 13:44:28,844 | avatar.targets.QemuTarget0.WARNING | No cpu_model specified - are you sure?
Traceback (most recent call last):
  File "hello_world.py", line 36, in <module>
    avatar.init_targets()
  File "/usr/local/lib/python3.8/dist-packages/avatar2-1.4.7-py3.8.egg/avatar2/avatar2.py", line 233, in init_targets
    t[1].init()
  File "/usr/local/lib/python3.8/dist-packages/avatar2-1.4.7-py3.8.egg/avatar2/watchmen.py", line 78, in watchtrigger
    ret = func(self, *args, **kwargs)
  File "/usr/local/lib/python3.8/dist-packages/avatar2-1.4.7-py3.8.egg/avatar2/targets/qemu_target.py", line 263, in init
    file_name=self.qemu_config_file, config=self.generate_qemu_config()
  File "/usr/local/lib/python3.8/dist-packages/avatar2-1.4.7-py3.8.egg/avatar2/targets/qemu_target.py", line 174, in generate_qemu_config
    conf_dict = self.avatar.generate_config()
  File "/usr/local/lib/python3.8/dist-packages/avatar2-1.4.7-py3.8.egg/avatar2/avatar2.py", line 153, in generate_config
    conf_dict["memory_mapping"].append(mr.data.dictify())
  File "/usr/local/lib/python3.8/dist-packages/avatar2-1.4.7-py3.8.egg/avatar2/memory_range.py", line 65, in dictify
    raise Exception(
Exception: Unsupported type <class '__main__.HelloWorldPeripheral'> for dictifying python_peripheral for mem_range at 0x40004c00

Did I write something wrong?Can you take a look at it.Thanks!

zhao-dddw commented 2 years ago

@mariusmue

zhao-dddw commented 2 years ago

@aurelf

rawsample commented 2 years ago

Hello @zhao-dddw , I'm going to look at it but i need to finish other tasks before.

zhao-dddw commented 2 years ago

@rawsample Ok, you go to work first.

rawsample commented 2 years ago

Could you try replacing the import with from avatar2.peripherals.avatar_peripheral import AvatarPeripheral? My guess is that HelloWorldPeripheral doesn't inherit from the correct AvatarPeripheral class and therefore fail the check on the expected_types

zhao-dddw commented 2 years ago

@rawsample When i try replacing the import, it works normally. I think your guess is correct, Thank you for your answer.

2022-07-12 03:33:09,533 | avatar.INFO | Initialized Avatar. Output directory is ./tmp1/avatar
2022-07-12 03:33:09,535 | avatar.targets.QemuTarget0.WARNING | No cpu_model specified - are you sure?
2022-07-12 03:33:09,540 | avatar.targets.QemuTarget0.INFO | QEMU process running
2022-07-12 03:33:09,753 | avatar.targets.QemuTarget0.INFO | State changed to TargetStates.STOPPED
2022-07-12 03:33:09,754 | avatar.INFO | Received state update of target QemuTarget0 to TargetStates.STOPPED
2022-07-12 03:33:09,769 | avatar.targets.QemuTarget0.QMPProtocol.INFO | b'{"return": {}, "id": 0}\r\n'
2022-07-12 03:33:09,771 | avatar.targets.QemuTarget0.INFO | Connected to remote target
2022-07-12 03:33:09,774 | avatar.targets.QemuTarget0.RemoteMemoryProtocol.INFO | Successfully connected rmp
2022-07-12 03:33:10,275 | avatar.targets.QemuTarget0.RemoteMemoryProtocol.WARNING | Tried to close/unlink non existent rx_queue
2022-07-12 03:33:10,275 | avatar.targets.QemuTarget0.RemoteMemoryProtocol.WARNING | Tried to close/unlink non existent tx_queue
mariusmue commented 2 years ago

Can we maybe update the handbook to reflect this pitfall?

rawsample commented 2 years ago

Changes added in 974c6b35c7d3a17621b117a56247bcffa511ba66

zhao-dddw commented 2 years ago

@rawsample Excuse me, do you have the source code of this binary file? I tried to compile it, but it couldn't run. https://github.com/avatartwo/avatar2/tree/main/tests/pyperipheral image

rawsample commented 2 years ago

I'm afraid not, maybe @mariusmue has? Be aware in the case you recompile it, you may need to update the different addresses used in test_pyperipheral.py.

zhao-dddw commented 2 years ago

@mariusmue Hi,do you have the source code of this binary file. image

zhao-dddw commented 2 years ago

@rawsample Ok,thank you for your advice.

mariusmue commented 2 years ago

Hi, sorry for the delay.

The source code should be:

#include "mbed.h"

//------------------------------------
// Hyperterminal configuration
// 9600 bauds, 8-bit data, no parity
//------------------------------------

Serial pc(SERIAL_TX, SERIAL_RX);

DigitalOut myled(LED1);

int main()
{
    int i = 1;
    pc.printf("Hello World !\n");
    while(1) {
        wait(1);
        pc.printf("This program runs since %d seconds.\n", i++);
        myled = !myled;
    }
}

The example was build with mbed-os2, also known as libmbed. In comparison to more recent version of mbedOS, that version linked everything into a monoloithic application. If I recall correctly, I either built this example using the mbed online compiler, or using the linux mbed toolchain.

Hope that helps!

zhao-dddw commented 2 years ago

@mariusmue Thank you for your answer.But I have one more question, do the other two bin files have any specific purpose? rcc_dump.bin sram_dump.bin Sorry to bother you again.

mariusmue commented 2 years ago

No worries! Yes, these are dumps of the memory regions of the device in the right state. They are defined here in the according script.

The "right state" here, means that there was a breakpoint set on the device on the entry of the main-loop (which matches the entry-address for the qemu object.

This allows to emulate the firmware without the need of having the physical device to transfer the state from at this point.