Rahix / tbot

Automation/Testing tool for Embedded Linux Development
https://tbot.tools
GNU General Public License v3.0
84 stars 21 forks source link

Weird power cycle recursion #97

Closed retpolanne closed 1 year ago

retpolanne commented 1 year ago

Hey!

I'm trying to test u-boot using tbot. I followed the documentation and created, on my config, a generic Board for running picocom connection and handling power cycling:

class OrangePi(
    connector.ConsoleConnector,
    board.PowerControl,
    board.Board
):
    baudrate = 115200
    serial_port = "/dev/ttyUSB0"

    def poweron(self):
        with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
            ub.exec0("reset")

    def poweroff(self):
        pass

    def connect(self, mach):
        return mach.open_channel("picocom", "-b", str(self.baudrate), self.serial_port)

And a UBootShell for handling just u-boot stuff:

class OrangePiUBoot(
    board.Connector,
    board.UBootAutobootIntercept,
    board.UBootShell
):
    prompt = "=> "

They are both registered:

def register_machines(ctx):
    ctx.register(OrangePi, tbot.role.Board)
    ctx.register(OrangePiUBoot, tbot.role.BoardUBoot)

My testcase should just run dhcp for now:

import tbot

@tbot.testcase
def test_uboot_dhcp() -> None:
    with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
        ub.exec0("dhcp")

However, when I run that, I see a lot of parallel powerons running:

newbot -c config.orange_pi_test_config tc.interactive.test_uboot_dhcp
tbot starting ...
├─Calling test_uboot_dhcp ...
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
RecursionError: maximum recursion depth exceeded while calling a Python object

Then it fails with max recursion depth.

Am I missing something? The only way I know that I can powercycle on u-boot is by resetting, so I did it according to the documentation (poweron handles the reset while poweroff just passes).

retpolanne commented 1 year ago

Attached pdb, seem that the loop is on the ctx request:

╰→ newbot -c config.orange_pi_test_config tc.interactive.test_uboot_dhcp
tbot starting ...
├─Calling test_uboot_dhcp ...
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
> /home/retpolanne/Dev/orange-pi-one-plus-image/config/orange_pi_test_config.py(14)poweron()
-> with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
(Pdb) l
  9        baudrate = 115200
 10        serial_port = "/dev/ttyUSB0"
 11     
 12        def poweron(self):
 13            import pdb; pdb.set_trace()
 14  ->        with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
 15                ub.exec0("reset")
 16     
 17        def poweroff(self):
 18            pass
 19     
(Pdb) n
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
> /home/retpolanne/Dev/orange-pi-one-plus-image/config/orange_pi_test_config.py(14)poweron()
-> with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
(Pdb) n
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
> /home/retpolanne/Dev/orange-pi-one-plus-image/config/orange_pi_test_config.py(14)poweron()
-> with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
(Pdb) n
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
> /home/retpolanne/Dev/orange-pi-one-plus-image/config/orange_pi_test_config.py(14)poweron()
-> with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
(Pdb) n
│   ├─[local] picocom -b 115200 /dev/ttyUSB0
│   ├─POWERON (orange-pi)
> /home/retpolanne/Dev/orange-pi-one-plus-image/config/orange_pi_test_config.py(14)poweron()
-> with tbot.ctx.request(tbot.role.BoardUBoot) as ub:
retpolanne commented 1 year ago

I understood what I did wrong: poweron runs before connect and it seems that if I try to run this with BoardUBoot role I get to this loop. I wonder how am I able to send a reset to u-boot after picocom connects.

retpolanne commented 1 year ago

Fixed it :)

I moved the PowerControl to the OrangePiUBoot class and then added this to poweron:

    def poweron(self):
    ¦   time.sleep(1)
    ¦   self.ch.sendline("reset")

Plays well with autoboot btw!