Open ThomasAtBBTF opened 4 years ago
The SWD pins are intentionally protected on startup, as debugging is very difficult without them. There isn't really an interface for releasing them either (I'm not sure why they're even available on your first startup). But you could try removing them from the protected list and rebuilding circuitpython. I'm not sure where the list is for Atmel-SAMD but @tannewt should be able to help you out tomorrow.
Thank you for the explanation. I have one more observation:
Thomas
Hi Thomas, It looks like you've hit a bug in the pin reset code. For SAMD it is here: https://github.com/adafruit/circuitpython/blob/master/ports/atmel-samd/common-hal/microcontroller/Pin.c#L81
Are you hitting the RuntimeError after your code works once? Is it a "pin in use" error? All pins should be reset before all VM runs using the function in the link above. Since the SWD pins are a special case, it is likely that it needs to be fixed.
Hi, after a pressing reset and the code starts to work (so: "after my code works once") I am not getting the error ever again until I power on the device once again.
Your answer leads me to another question / request: In my project the ItsyBitsy is a controller for peripherals and does "powermanagement" for an Arm-Board (NanoPi Air). The ItsyBitsy can (among other things) turn the power on and off for the Arm-Board. This (and the behaviour of CP) creates with a problem for updating the CP-Code on the ItsyBitsy. Because when I update files on the CIRCUITPY drive, the VM's seem to reset and the power for the ARM-board id cut off.
It would be helpful if you could add to microcontroller/supervisor a "value" like "don't touch the pins on next VM run.
Thomas
Hi Scott, I tried to create some simple code, so that you can reproduce the problem. But not so easy!!!!! I took a new (never used) itsybitsy and loaded my code into it. (In order to strip it down to a minimal repro code.) But it turns out when no pins are connected to any peripherals the bug does not occur.
Then I reread the code piece you referenced... Line 81 says: // Configure SWD. SWDIO will be automatically switched on PA31 when a signal is input on SWCLK ! I have connected the status line of a simple bluetooth module (JDY-32). This alone may lead to the problem. Maybe over the weekend, I will investigate this further.
I still think you should "offer" a force "deinit" and leave your boot and debug code as it is. This forced deinit will almost never be called. And certainly not hinder your boot code debug experience. As any forced deinit will only happen after code.py (or maybe boot.by) started to execute.
Also I want to reiterate my request from my post above to have an additional runmode for microcontroller.on_next_reset(run_mode) which leaves the pins as they are on autoloading a new code.py !!!!!! Maybe it is not "next reset" ... So maybe something similar in supervisor like: supervisor.on_next_reload(xxx)
Thomas
The pin reset is deliberate so that the state of the hardware is the same every time the code runs. Why do you want to control the power pin from CircuitPython but not have it reset and start the same as the first run?
Because the ARM-Linux should run continuously as long a possible. And changes to the code of the itsybitsy should not shut the down the Linux system.
I can very well understand your argument, that "the hardware" should be the same every time the code runs. And this is very positive for most, if not all of the users. But: you introduced exceptions already by offering "microcontroller.on_next_reset(run_mode)" I think such an obscure and really not "dangerous" / rarely used (and not many bytes consuming) function would do no harm for the normal users.
@ThomasAtBBTF Why not just disconnect the power control pin when you are iterating on the circuitpython code? In "normal" operating mode the CircuitPython vm won't reset and therefore won't reset the pin.
If you are designing a custom board you can exempt pins from reset but I'd rather not allow that from Python. The "never_reset" concept is only for use under-the-hood.
Ok, I can live with that. But what about the two "unusable" pins? If you don't want to change the code there, how about to get a reference to the allocated pin objects in microcontroller. So they become usable.
As I am not an native english speaker, can you please elaborate what you mean with: "concept is only for use under-the-hood"
The two SWD pins should be usable. If they aren't it is because there is a bug. It is complex because when reset, the pins should be in SWD configuration. I'm not sure what you mean by a pin reference.
I meant that the concept of never_reset
is meant for use in C code ("under the hood of Python") only. Thanks for requesting clarification. I'm happy to elaborate.
@tannewt I'm guessing you mean that the two SWD pins should be usable by SWD, right? As in, under normal operation, they should not be accessible as GPIO pins, ever. Or should they be SWD pins only on reset, and then become accessible as GPIO pins for code.py? Asking because I want to make sure my STM32 port is aligning to this as well!
@hierophect the default "reset" state of the pins should be SWD. If user code uses them then they won't be until they are deinit
or the VM finishes and resets them.
Thank you too! So again my problem:
Neither microprocessor.reboot() nor supervisor.reload() is chaingeing this.
I understand, that this is a complex case!
But when these pin are in use, someone / some part of the underlying code uses them and does not set them free when booting after power on. If they are in use somewhere there is a reference(/instance?) to the pin object either in python or in the c code or in the SAMD. Could this instance to the object be shared? like microprocessor.cpu which is the sole object of microprocessor.Processor.
@ThomasAtBBTF thank you for the clear recap of the issue. I don't believe the issue is any user code. My guess is that the state of the pins on start up varies with reset as you are seeing. It'll take some debugging to sort out what state the pins are in when you are seeing them as in use.
I don't think this is a good first issue. It looks like a complex thing that needs a lot of knowledge to debug properly. Should we remove the label?
I am using all pins on the ItsyBitsy M4 and would need more... So I tried to do this: BTSelect = digitalio.DigitalInOut(microcontroller.pin.PA30) And was very happy that I can also use PA30 & PA31 (the SWCLK & SWDIO pins on the "other end" of the ItsyBitsy)
But now when I am using them after powering on a runtime error happens on the first boot. If I the do a reset all works fine!
Is there a way to "Deinit" all pins at startup of a script? Can I somehow deinit a pin even thou I hold no reference to the pin?
Thomas
Note: this happens on CP4 and also the same on CP Beta 5.