MicroPython

Sat, 20 Feb 2021 14:28:14 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 20 Feb 2021 14:28:14 +0100
changeset 8122
eb85ced7844c
parent 8121
9a2aa5353a32
child 8123
b93ae18a4395

MicroPython
- added support for "Raspberry Pi Pico" (i.e. RP2040 based boards)

docs/changelog file | annotate | diff | comparison | revisions
eric6.epj file | annotate | diff | comparison | revisions
eric6/MicroPython/MicroPythonDevices.py file | annotate | diff | comparison | revisions
eric6/MicroPython/RP2040Devices.py file | annotate | diff | comparison | revisions
--- a/docs/changelog	Sat Feb 20 14:25:06 2021 +0100
+++ b/docs/changelog	Sat Feb 20 14:28:14 2021 +0100
@@ -8,14 +8,15 @@
 - Debugger
   -- added capability to delete environment variables for the debugged script
      by adding a '-' to the variable name in the start dialog
-- Debug Viewer:
+- Debug Viewer
   -- changed code to show project relative paths in the breakpoint viewer
 - File Browser
   -- added capability to show/hide hidden files (i.e. those starting with '.')
   -- added capability to create new files/directories and delete them
 - Mercurial Interface
   -- added support for Mercurial 5.7
-- MicroPython:
+- MicroPython
+  -- added support for "Raspberry Pi Pico" (i.e. RP2040 based boards)
   -- extended the list of supported (recognized) CircuitPython boards
   -- added capability to manually configure devices not yet known by eric6
   -- added a generic dialog for flashing UF2 capable devices (with device
--- a/eric6.epj	Sat Feb 20 14:25:06 2021 +0100
+++ b/eric6.epj	Sat Feb 20 14:28:14 2021 +0100
@@ -250,10 +250,12 @@
       "eric6/IconEditor/IconSizeDialog.py",
       "eric6/IconEditor/__init__.py",
       "eric6/IconEditor/cursors/__init__.py",
+      "eric6/MicroPython/AddEditDevicesDialog.py",
       "eric6/MicroPython/CircuitPythonDevices.py",
       "eric6/MicroPython/EspBackupRestoreFirmwareDialog.py",
       "eric6/MicroPython/EspDevices.py",
       "eric6/MicroPython/EspFirmwareSelectionDialog.py",
+      "eric6/MicroPython/GenericMicroPythonDevices.py",
       "eric6/MicroPython/IgnoredDevicesDialog.py",
       "eric6/MicroPython/MicroPythonCommandsInterface.py",
       "eric6/MicroPython/MicroPythonDevices.py",
@@ -266,6 +268,8 @@
       "eric6/MicroPython/MicroPythonWidget.py",
       "eric6/MicroPython/MicrobitDevices.py",
       "eric6/MicroPython/PyBoardDevices.py",
+      "eric6/MicroPython/UF2FlashDialog.py",
+      "eric6/MicroPython/UnknownDevicesDialog.py",
       "eric6/MicroPython/__init__.py",
       "eric6/MultiProject/AddProjectDialog.py",
       "eric6/MultiProject/MultiProject.py",
@@ -1623,10 +1627,7 @@
       "scripts/uninstall-debugclients.py",
       "scripts/uninstall.py",
       "setup.py",
-      "eric6/MicroPython/AddEditDevicesDialog.py",
-      "eric6/MicroPython/UnknownDevicesDialog.py",
-      "eric6/MicroPython/GenericMicroPythonDevices.py",
-      "eric6/MicroPython/UF2FlashDialog.py"
+      "eric6/MicroPython/RP2040Devices.py"
     ],
     "FORMS": [
       "eric6/CondaInterface/CondaExecDialog.ui",
@@ -1669,12 +1670,15 @@
       "eric6/HexEdit/HexEditReplaceWidget.ui",
       "eric6/HexEdit/HexEditSearchWidget.ui",
       "eric6/IconEditor/IconSizeDialog.ui",
+      "eric6/MicroPython/AddEditDevicesDialog.ui",
       "eric6/MicroPython/EspBackupRestoreFirmwareDialog.ui",
       "eric6/MicroPython/EspFirmwareSelectionDialog.ui",
       "eric6/MicroPython/IgnoredDevicesDialog.ui",
       "eric6/MicroPython/MicroPythonFileManagerWidget.ui",
       "eric6/MicroPython/MicroPythonProgressInfoDialog.ui",
       "eric6/MicroPython/MicroPythonWidget.ui",
+      "eric6/MicroPython/UF2FlashDialog.ui",
+      "eric6/MicroPython/UnknownDevicesDialog.ui",
       "eric6/MultiProject/AddProjectDialog.ui",
       "eric6/MultiProject/PropertiesDialog.ui",
       "eric6/Network/IRC/IrcChannelEditDialog.ui",
@@ -2071,10 +2075,7 @@
       "eric6/WebBrowser/VirusTotal/VirusTotalWhoisDialog.ui",
       "eric6/WebBrowser/WebBrowserClearPrivateDataDialog.ui",
       "eric6/WebBrowser/WebBrowserLanguagesDialog.ui",
-      "eric6/WebBrowser/ZoomManager/ZoomValuesDialog.ui",
-      "eric6/MicroPython/AddEditDevicesDialog.ui",
-      "eric6/MicroPython/UnknownDevicesDialog.ui",
-      "eric6/MicroPython/UF2FlashDialog.ui"
+      "eric6/WebBrowser/ZoomManager/ZoomValuesDialog.ui"
     ],
     "RESOURCES": [],
     "INTERFACES": [],
@@ -2287,9 +2288,9 @@
       "linux/eric6_browser.desktop",
       "linux/eric6_browser.desktop.in",
       "others/default.e4k",
+      "others/default.ekj",
       "others/default_Mac.e4k",
-      "others/pylint.rc",
-      "others/default.ekj"
+      "others/pylint.rc"
     ],
     "TRANSLATIONS": [
       "eric6/i18n/eric6_cs.qm",
@@ -2387,38 +2388,22 @@
     "PROJECTTYPESPECIFICDATA": {},
     "CHECKERSPARMS": {
       "Pep8Checker": {
-        "EnabledCheckerCategories": "C, D, E, M, N, W",
-        "ExcludeFiles": "*/ThirdParty/*, */coverage/*, */Ui_*.py, */Examples/*, */*_rc.py,*/pycodestyle.py,*/pyflakes/checker.py,*/mccabe.py,*/eradicate.py",
-        "ExcludeMessages": "C101,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W504",
-        "IncludeMessages": "",
-        "RepeatMessages": true,
-        "FixCodes": "",
-        "NoFixCodes": "E501",
-        "FixIssues": false,
-        "ShowIgnored": false,
-        "MaxLineLength": 79,
-        "MaxDocLineLength": 79,
+        "AnnotationsChecker": {
+          "MaximumComplexity": 3,
+          "MinimumCoverage": 75
+        },
         "BlankLines": [
           2,
           1
         ],
-        "HangClosing": false,
-        "DocstringType": "eric",
-        "MaxCodeComplexity": 10,
-        "LineComplexity": 25,
-        "LineComplexityScore": 10,
-        "ValidEncodings": "latin-1, utf-8",
-        "CopyrightMinFileSize": 0,
-        "CopyrightAuthor": "",
-        "FutureChecker": "",
         "BuiltinsChecker": {
-          "str": [
+          "bytes": [
             "unicode"
           ],
           "chr": [
             "unichr"
           ],
-          "bytes": [
+          "str": [
             "unicode"
           ]
         },
@@ -2440,11 +2425,26 @@
             "- "
           ]
         },
-        "AnnotationsChecker": {
-          "MinimumCoverage": 75,
-          "MaximumComplexity": 3
-        },
+        "CopyrightAuthor": "",
+        "CopyrightMinFileSize": 0,
+        "DocstringType": "eric",
+        "EnabledCheckerCategories": "C, D, E, M, N, W",
+        "ExcludeFiles": "*/ThirdParty/*, */coverage/*, */Ui_*.py, */Examples/*, */*_rc.py,*/pycodestyle.py,*/pyflakes/checker.py,*/mccabe.py,*/eradicate.py",
+        "ExcludeMessages": "C101,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W504",
+        "FixCodes": "",
+        "FixIssues": false,
+        "FutureChecker": "",
+        "HangClosing": false,
+        "IncludeMessages": "",
+        "LineComplexity": 25,
+        "LineComplexityScore": 10,
+        "MaxCodeComplexity": 10,
+        "MaxDocLineLength": 79,
+        "MaxLineLength": 79,
+        "NoFixCodes": "E501",
+        "RepeatMessages": true,
         "SecurityChecker": {
+          "CheckTypedException": false,
           "HardcodedTmpDirectories": [
             "/tmp",
             "/var/tmp",
@@ -2468,12 +2468,13 @@
           ],
           "WeakKeySizeDsaHigh": "1024",
           "WeakKeySizeDsaMedium": "2048",
-          "WeakKeySizeRsaHigh": "1024",
-          "WeakKeySizeRsaMedium": "2048",
           "WeakKeySizeEcHigh": "160",
           "WeakKeySizeEcMedium": "224",
-          "CheckTypedException": false
-        }
+          "WeakKeySizeRsaHigh": "1024",
+          "WeakKeySizeRsaMedium": "2048"
+        },
+        "ShowIgnored": false,
+        "ValidEncodings": "latin-1, utf-8"
       },
       "SyntaxChecker": {
         "ExcludeFiles": "*/coverage/*, */ThirdParty/*, */Examples/*"
--- a/eric6/MicroPython/MicroPythonDevices.py	Sat Feb 20 14:25:06 2021 +0100
+++ b/eric6/MicroPython/MicroPythonDevices.py	Sat Feb 20 14:28:14 2021 +0100
@@ -137,7 +137,16 @@
         "port_description": "",
     },
     
-    # TODO: add RP2040 boards (VID: 0x2e8a, PID: 0x0005)
+    "rp2040": {
+        "ids": [
+            (0x2E8A, 0x0005),       # Raspberry Pi Pico
+        ],
+        "description": QCoreApplication.translate(
+            "MicroPythonDevice", "RP2040 based"),
+        "icon": "rp2040Device",
+        "port_description": "",
+    },
+    
     "generic": {
         # only manually configured devices use this
         "ids": [],
@@ -290,7 +299,9 @@
     elif deviceType == "pyboard":
         from .PyBoardDevices import PyBoardDevice
         return PyBoardDevice(microPythonWidget, deviceType)
-    # TODO: add RP2040 boards (VID: 0x2e8a, PID: 0x0005)
+    elif deviceType == "rp2040":
+        from .RP2040Devices import RP2040Device
+        return RP2040Device(microPythonWidget, deviceType)
     elif deviceType == "generic":
         from .GenericMicroPythonDevices import GenericMicroPythonDevice
         return GenericMicroPythonDevice(microPythonWidget, deviceType,
@@ -494,7 +505,7 @@
         commands = [c.encode("utf-8)") + b'\r' for c in commandsList]
         commands.append(b'\r')
         commands.append(b'\x04')
-        rawOff = [b'\x02']
+        rawOff = [b'\x02', b'\x02']
         commandSequence = rawOn + newLine + commands + rawOff
         self.microPython.commandsInterface().executeAsync(commandSequence)
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/MicroPython/RP2040Devices.py	Sat Feb 20 14:28:14 2021 +0100
@@ -0,0 +1,184 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the device interface class for RP2040 based boards
+(e.g. Raspberry Pi Pico).
+"""
+
+from PyQt5.QtCore import pyqtSlot
+
+from .MicroPythonDevices import MicroPythonDevice
+from .MicroPythonWidget import HAS_QTCHART
+
+import Preferences
+
+
+class RP2040Device(MicroPythonDevice):
+    """
+    Class implementing the device for RP2040 based boards.
+    """
+    def __init__(self, microPythonWidget, deviceType, parent=None):
+        """
+        Constructor
+        
+        @param microPythonWidget reference to the main MicroPython widget
+        @type MicroPythonWidget
+        @param deviceType device type assigned to this device interface
+        @type str
+        @param parent reference to the parent object
+        @type QObject
+        """
+        super(RP2040Device, self).__init__(
+            microPythonWidget, deviceType, parent)
+    
+    def setButtons(self):
+        """
+        Public method to enable the supported action buttons.
+        """
+        super(RP2040Device, self).setButtons()
+        self.microPython.setActionButtons(
+            run=True, repl=True, files=True, chart=HAS_QTCHART)
+    
+    def forceInterrupt(self):
+        """
+        Public method to determine the need for an interrupt when opening the
+        serial connection.
+        
+        @return flag indicating an interrupt is needed
+        @rtype bool
+        """
+        return False
+    
+    def deviceName(self):
+        """
+        Public method to get the name of the device.
+        
+        @return name of the device
+        @rtype str
+        """
+        return self.tr("RP2040")
+    
+    def canStartRepl(self):
+        """
+        Public method to determine, if a REPL can be started.
+        
+        @return tuple containing a flag indicating it is safe to start a REPL
+            and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return True, ""
+    
+    def canStartPlotter(self):
+        """
+        Public method to determine, if a Plotter can be started.
+        
+        @return tuple containing a flag indicating it is safe to start a
+            Plotter and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return True, ""
+    
+    def canRunScript(self):
+        """
+        Public method to determine, if a script can be executed.
+        
+        @return tuple containing a flag indicating it is safe to start a
+            Plotter and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return True, ""
+    
+    def runScript(self, script):
+        """
+        Public method to run the given Python script.
+        
+        @param script script to be executed
+        @type str
+        """
+        pythonScript = script.split("\n")
+        self.sendCommands(pythonScript)
+    
+    def canStartFileManager(self):
+        """
+        Public method to determine, if a File Manager can be started.
+        
+        @return tuple containing a flag indicating it is safe to start a
+            File Manager and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return True, ""
+    
+    def addDeviceMenuEntries(self, menu):
+        """
+        Public method to add device specific entries to the given menu.
+        
+        @param menu reference to the context menu
+        @type QMenu
+        """
+        connected = self.microPython.isConnected()
+        
+        act = menu.addAction(self.tr("Activate Bootloader"),
+                             self.__activateBootloader)
+        act.setEnabled(connected)
+        act = menu.addAction(self.tr("Flash Firmware"), self.__flashPython)
+        act.setEnabled(not connected)
+    
+    def hasFlashMenuEntry(self):
+        """
+        Public method to check, if the device has its own flash menu entry.
+        
+        @return flag indicating a specific flash menu entry
+        @rtype bool
+        """
+        return True
+    
+    @pyqtSlot()
+    def __flashPython(self):
+        """
+        Private slot to flash a MicroPython firmware to the device.
+        """
+        from .UF2FlashDialog import UF2FlashDialog
+        dlg = UF2FlashDialog(boardType="rp2040")
+        dlg.exec()
+    
+    def __activateBootloader(self):
+        """
+        Private method to switch the board into 'bootloader' mode.
+        """
+        if self.microPython.isConnected():
+            self.microPython.commandsInterface().execute([
+                "import machine",
+                "machine.bootloader()",
+            ])
+            # simulate pressing the disconnect button
+            self.microPython.on_connectButton_clicked()
+    
+    def getDocumentationUrl(self):
+        """
+        Public method to get the device documentation URL.
+        
+        @return documentation URL of the device
+        @rtype str
+        """
+        return Preferences.getMicroPython("MicroPythonDocuUrl")
+    
+    def getDownloadMenuEntries(self):
+        """
+        Public method to retrieve the entries for the downloads menu.
+        
+        @return list of tuples with menu text and URL to be opened for each
+            entry
+        @rtype list of tuple of (str, str)
+        """
+        return [
+            (self.tr("MicroPython Firmware"),
+             Preferences.getMicroPython("MicroPythonFirmwareUrl")),
+            ("<separator>", ""),
+            (self.tr("CircuitPython Firmware"),
+             Preferences.getMicroPython("CircuitPythonFirmwareUrl")),
+            (self.tr("CircuitPython Libraries"),
+             Preferences.getMicroPython("CircuitPythonLibrariesUrl"))
+        ]

eric ide

mercurial