Browse Source

first fork

yoneda 1 year ago
commit
ddf736a45e

File diff suppressed because it is too large
+ 92 - 0
README.md


+ 27 - 0
boards/pico-boot.json

@@ -0,0 +1,27 @@
+{
+  "name": "WizIO-PICO BOOT STAGE 2 HELPER",
+  "url": "https://github.com",
+  "build": {
+    "core": "pico",
+    "variant": "pico",    
+    "uploader": "pico-none",
+    "f_cpu": "133000000L",
+    "mcu": "RP2040"
+  },
+  "debug": {
+    "tools": {
+      "uart": {
+        "onboard": true,
+        "extra_cmds": [],
+        "load_cmd": [],
+        "server": {}
+      }
+    }
+  },  
+  "frameworks": ["boot2"],
+  "vendor": "WizIO",
+  "upload": {
+        "maximum_ram_size":  262144,
+        "maximum_size"    : 2097152
+  }
+}

+ 24 - 0
boards/pico-dap.json

@@ -0,0 +1,24 @@
+{
+  "name": "WizIO - Raspberry Pi Pico ( CMSIS-DAP )",
+  "url": "https://github.com",
+  "vendor": "Raspberry Pi",  
+  "frameworks": [ "baremetal", "arduino" ],
+
+  "build": {
+    "core"      : "RP2040",
+    "variant"   : "raspberry-pi-pico",    
+    "f_cpu"     : "125000000L",
+    "mcu"       : "RP2040"
+  },
+
+  "debug": {
+    "openocd_target" : "rp2040-core0.cfg",
+    "svd_path"       : "rp2040.svd"
+  },  
+
+  "upload": {
+    "maximum_ram_size" :  262144,
+    "maximum_size"     : 2097152, 
+    "protocol"         : "uf2"        
+  }
+}

+ 26 - 0
boards/raspberry-pi-pico-w.json

@@ -0,0 +1,26 @@
+{
+  "name": "WizIO - Raspberry Pi Pico WiFi ( PICOPROBE )",
+  "url": "https://github.com",
+  "vendor": "Raspberry Pi",  
+  "frameworks": [ "baremetal", "arduino" ],
+
+  "build": {
+      "core"          : "RP2040",
+      "variant"       : "raspberry-pi-pico-w",
+      "f_cpu"         : "125000000L",
+      "mcu"           : "RP2040",
+      "WIFI"          : true,      
+      "autogen_board" :"pico_w.h"    
+  },
+
+  "debug": {
+    "openocd_target" : "rp2040.cfg",
+    "svd_path"       : "rp2040.svd"
+  },  
+
+  "upload": {
+    "maximum_ram_size" :  262144,
+    "maximum_size"     : 2097152, 
+    "protocol"         : "uf2"        
+  }
+}

+ 24 - 0
boards/raspberry-pi-pico.json

@@ -0,0 +1,24 @@
+{
+  "name": "WizIO - Raspberry Pi Pico ( PICOPROBE )",
+  "url": "https://github.com",
+  "vendor": "Raspberry Pi",  
+  "frameworks": [ "baremetal", "arduino" ],
+
+  "build": {
+    "core"      : "RP2040",
+    "variant"   : "raspberry-pi-pico",    
+    "f_cpu"     : "125000000L",
+    "mcu"       : "RP2040"
+  },
+
+  "debug": {
+    "openocd_target" : "rp2040.cfg",
+    "svd_path"       : "rp2040.svd"
+  },  
+
+  "upload": {
+    "maximum_ram_size" :  262144,
+    "maximum_size"     : 2097152, 
+    "protocol"         : "uf2"        
+  }
+}

BIN
builder/__pycache__/wpioasm.cpython-39.pyc


BIN
builder/frameworks/__pycache__/common.cpython-39.pyc


BIN
builder/frameworks/__pycache__/pico.cpython-39.pyc


BIN
builder/frameworks/__pycache__/sdk-RP2040.cpython-39.pyc


BIN
builder/frameworks/__pycache__/uf2conv.cpython-39.pyc


+ 34 - 0
builder/frameworks/arduino-RP2040.py

@@ -0,0 +1,34 @@
+# WizIO 2022 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from os.path import join
+from SCons.Script import DefaultEnvironment, Builder
+from common import *
+
+def dev_init(env, platform):
+    env.platform = platform
+    env.framework_dir = env.PioPlatform().get_package_dir("framework-wizio-pico")
+    env.libs = []
+    dev_compiler(env, 'ARDUINO')
+    dev_create_template(env)
+    core = env.BoardConfig().get("build.core")
+    variant= env.BoardConfig().get("build.variant")
+    PLATFORM_DIR = join( env.framework_dir, platform )
+    env.Append(
+        CPPDEFINES = [ "ARDUINO=200" ],
+        CPPPATH = [
+            join(PLATFORM_DIR, platform),
+            join(PLATFORM_DIR, "cores", core),
+            join(PLATFORM_DIR, "variants", variant),
+        ],
+        LIBSOURCE_DIRS = [ join(PLATFORM_DIR, "libraries", core) ],
+        LIBPATH        = [ join(PLATFORM_DIR, "libraries", core) ],
+    )
+    dev_config_board(env)
+    OBJ_DIR = join( "$BUILD_DIR", platform, "arduino" )
+    env.BuildSources( join( OBJ_DIR, "arduino" ), join( PLATFORM_DIR, platform )  )
+    env.BuildSources( join( OBJ_DIR, "core" ),    join( PLATFORM_DIR, "cores", core ) )
+    env.BuildSources( join( OBJ_DIR, "variant" ), join( PLATFORM_DIR, "variants", variant )  )
+    dev_finalize(env)
+    

+ 14 - 0
builder/frameworks/arduino.py

@@ -0,0 +1,14 @@
+# WizIO 2021 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from __future__ import print_function
+from SCons.Script import DefaultEnvironment
+
+env = DefaultEnvironment()
+platform = "arduino"
+module = platform + "-" + env.BoardConfig().get("build.core")
+m = __import__(module)
+globals()[module] = m
+m.dev_init(env, platform)
+#print( env.Dump() )

+ 98 - 0
builder/frameworks/boot2-pico.py

@@ -0,0 +1,98 @@
+# WizIO 2021 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+import os
+from os.path import join
+from SCons.Script import DefaultEnvironment, Builder
+from common import *
+
+def dev_create_asm(target, source, env):
+    py = join(env.framework_dir, env.sdk, "boot_stage2", "pad_checksum")
+    dir = join(env["BUILD_DIR"], env["PROGNAME"])
+    env.Execute("python " + py + " -s 0xffffffff " + dir + ".bin " + dir + ".S")
+    f = open(dir + ".S", "a")
+    f.write('\n#include "../link.S')
+    f.close()
+
+def dev_compiler(env):
+    env.Replace(
+        BUILD_DIR = env.subst("$BUILD_DIR").replace("\\", "/"),
+        AR="arm-none-eabi-ar",
+        AS="arm-none-eabi-as",
+        CC="arm-none-eabi-gcc",
+        GDB="arm-none-eabi-gdb",
+        CXX="arm-none-eabi-g++",
+        OBJCOPY="arm-none-eabi-objcopy",
+        RANLIB="arm-none-eabi-ranlib",
+        SIZETOOL="arm-none-eabi-size",
+        ARFLAGS=["rc"],
+        SIZEPROGREGEXP=r"^(?:\.text|\.data|\.bootloader)\s+(\d+).*",
+        SIZEDATAREGEXP=r"^(?:\.data|\.bss|\.noinit)\s+(\d+).*",
+        SIZECHECKCMD="$SIZETOOL -A -d $SOURCES",
+        SIZEPRINTCMD='$SIZETOOL --mcu=$BOARD_MCU -C -d $SOURCES',
+        PROGSUFFIX=".elf",
+        PROGNAME = "BOOT-2"
+    )
+    env.cortex = ["-mcpu=cortex-m0plus", "-mthumb"]
+
+def dev_init(env, platform):
+    print( "RASPBERRYPI PI PICO RP2040 BOOT STAGE 2 COMPILER")
+    env.platform = platform
+    env.framework_dir = env.PioPlatform().get_package_dir("framework-wizio-pico")
+    env.libs = []
+    dev_compiler(env)
+    dev_create_template(env)
+    env.Append(
+        ASFLAGS=[ env.cortex, "-x", "assembler-with-cpp" ],
+        CPPDEFINES = [ "PICO_FLASH_SPI_CLKDIV=2"],
+        CPPPATH = [
+            join("$PROJECT_DIR", "include"),
+            join(env.framework_dir, env.sdk, "include"),
+            join(env.framework_dir, env.sdk, "boards"),
+            join(env.framework_dir, env.sdk, "boot_stage2", "asminclude"),
+        ],
+        CFLAGS = [
+            env.cortex,
+            "-Os",
+            "-fdata-sections",
+            "-ffunction-sections",
+            "-Wall",
+            "-Wfatal-errors",
+            "-Wstrict-prototypes",
+        ],
+        LINKFLAGS = [
+            env.cortex,
+            "-Os",
+            "-nostartfiles",
+            "-nostdlib",
+            "-Wall",
+            "-Wfatal-errors",
+            "--entry=_stage2_boot"
+        ],
+        LDSCRIPT_PATH = [ join(env.framework_dir, env.sdk, "boot_stage2", "boot_stage2.ld") ],
+        BUILDERS = dict(
+            ElfToBin = Builder(
+                action = env.VerboseAction(" ".join([
+                    "$OBJCOPY",
+                    "-O",
+                    "binary",
+                    "$SOURCES",
+                    "$TARGET",
+                ]), "Building $TARGET"),
+                suffix = ".bin"
+            )
+        ),
+        UPLOADCMD = dev_create_asm
+    )
+
+    libs = []
+    env.Append(LIBS = libs)
+
+# Select file, Clean, Upload, Get boot2.S from build folder
+
+    env.BuildSources(join("$BUILD_DIR", "BOOT2"), join(env.framework_dir, env.sdk, "boot_stage2"), src_filter="-<*> +<boot2_w25q080.S>") # is default
+    #env.BuildSources(join("$BUILD_DIR", "BOOT2"), join(env.framework_dir, env.sdk, "boot_stage2"), src_filter="-<*> +<boot2_w25x10cl.S>")
+    #env.BuildSources(join("$BUILD_DIR", "BOOT2"), join(env.framework_dir, env.sdk, "boot_stage2"), src_filter="-<*> +<boot2_is25lp080.S>")
+    #env.BuildSources(join("$BUILD_DIR", "BOOT2"), join(env.framework_dir, env.sdk, "boot_stage2"), src_filter="-<*> +<boot2_generic_03h.S>")
+    #env.BuildSources(join("$BUILD_DIR", "BOOT2"), join(env.framework_dir, env.sdk, "boot_stage2"), src_filter="-<*> +<boot2_usb_blinky.S>")

+ 14 - 0
builder/frameworks/boot2.py

@@ -0,0 +1,14 @@
+# WizIO 2021 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from __future__ import print_function
+from SCons.Script import DefaultEnvironment
+
+env = DefaultEnvironment()
+platform = "boot2"
+module = platform + "-" + env.BoardConfig().get("build.core")
+m = __import__(module)
+globals()[module] = m
+m.dev_init(env, platform)
+#print( env.Dump() )

+ 403 - 0
builder/frameworks/common.py

@@ -0,0 +1,403 @@
+# WizIO 2022 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from distutils.log import error
+import os
+from os.path import join
+from shutil import copyfile
+from colorama import Fore
+from pico import *
+from uf2conv import dev_uploader
+from SCons.Script import Builder
+
+bynary_type_info = []
+
+def do_copy(src, dst, name):
+    file_name = join(dst, name)
+    if False == os.path.isfile( file_name ):
+        copyfile( join(src, name), file_name )
+    return file_name
+
+def do_mkdir(path, name):
+    dir = join(path, name)
+    if False == os.path.isdir( dir ):
+        try:
+            os.mkdir(dir)
+        except OSError:
+            print ("[ERROR] Creation of the directory %s failed" % dir)
+            exit(1)
+    return dir
+
+def ini_file(env): # add defaut keys
+    ini = join( env.subst("$PROJECT_DIR"), 'platformio.ini' )
+    f = open(ini, "r")
+    txt = f.read()
+    f.close()
+    f = open(ini, "a+")
+    if 'monitor_port'  not in txt: f.write("\n;monitor_port = SELECT SERIAL PORT\n")
+    if 'monitor_speed' not in txt: f.write(";monitor_speed = 115200\n")    
+    if 'lib_deps'      not in txt: f.write("\n;lib_deps = \n")
+    if True == env.wifi:
+        if 'build_flags' not in txt: f.write("\n;build_flags = \n")
+    else:
+        if 'build_flags' not in txt: f.write("\nbuild_flags = -D PICO_CYW43_ARCH_POLL ; select wifi driver mode\n")
+    f.close()
+
+def dev_create_template(env):
+    ini_file(env)
+    src = join(env.PioPlatform().get_package_dir("framework-wizio-pico"), "templates")
+    dst = do_mkdir( env.subst("$PROJECT_DIR"), "include" )
+    do_copy(src, dst, "tusb_config.h")
+
+    if "freertos" in env.GetProjectOption("lib_deps", []) or "USE_FREERTOS" in env.get("CPPDEFINES"):
+        do_copy(src, dst, "FreeRTOSConfig.h")
+
+    if "VFS" in env.GetProjectOption("lib_deps", []) or "USE_VFS" in env.get("CPPDEFINES"):
+        do_copy(src, dst, "vfs_config.h")
+
+    if 'APPLICATION'== env.get("PROGNAME"):
+        if "fatfs" in env.GetProjectOption("lib_deps", []):
+            do_copy(src, dst, "ffconf.h")
+
+        dst = do_mkdir( env.subst("$PROJECT_DIR"), join("include", "pico") )
+        autogen_filename = join(dst, "config_autogen.h")
+        if False == os.path.isfile( autogen_filename ):
+            default_board = "pico.h"
+            autogen_board = env.BoardConfig().get("build.autogen_board", default_board )
+            f = open(autogen_filename, "w")
+            f.write("/* SELECT OTHER BOARD */\n")
+            f.write('#include "boards/{}"\n'.format(autogen_board))
+            f.close()
+
+        dst = join(env.subst("$PROJECT_DIR"), "src")
+        if False == os.path.isfile( join(dst, "main.cpp") ):
+            do_copy(src, dst, "main.c" )
+
+    if 'BOOT-2'== env.get("PROGNAME"):
+        dst = do_mkdir( env.subst("$PROJECT_DIR"), join("include", "pico") )
+        do_copy(src, dst, "config_autogen.h" )
+
+def dev_nano(env):
+    enable_nano = env.BoardConfig().get("build.nano", "enable") # no <sys/lock>
+    nano = []
+    if enable_nano == "enable":
+        nano = ["-specs=nano.specs", "-u", "_printf_float", "-u", "_scanf_float" ]
+    if len(nano) > 0: print('  * SPECS        :', nano[0][7:])
+    else:             print('  * SPECS        : default')
+    return nano
+
+def dev_compiler(env, application_name = 'APPLICATION'):
+    env["FRAMEWORK_DIR"] = env.framework_dir
+    env.sdk = env.BoardConfig().get("build.sdk", "SDK") # get/set default SDK
+    env.variant = env.BoardConfig().get("build.variant", 'raspberry-pi-pico')
+    env.wifi = env.BoardConfig().get("build.WIFI", False )
+    print()
+    print( Fore.BLUE + "%s RASPBERRYPI PI PICO RP2040 ( PICO - %s )" % (env.platform.upper(), env.sdk.upper()) )
+    env.Replace(
+        BUILD_DIR = env.subst("$BUILD_DIR").replace("\\", "/"),
+        AR="arm-none-eabi-ar",
+        AS="arm-none-eabi-as",
+        CC="arm-none-eabi-gcc",
+        GDB="arm-none-eabi-gdb",
+        CXX="arm-none-eabi-g++",
+        OBJCOPY="arm-none-eabi-objcopy",
+        RANLIB="arm-none-eabi-ranlib",
+        SIZETOOL="arm-none-eabi-size",
+        ARFLAGS=["rc"],
+        SIZEPROGREGEXP=r"^(?:\.text|\.data|\.boot2|\.rodata)\s+(\d+).*",
+        SIZEDATAREGEXP=r"^(?:\.data|\.bss|\.ram_vector_table)\s+(\d+).*",
+        SIZECHECKCMD="$SIZETOOL -A -d $SOURCES",
+        SIZEPRINTCMD='$SIZETOOL --mcu=$BOARD_MCU -C -d $SOURCES',
+        PROGSUFFIX=".elf",
+        PROGNAME = application_name
+    )
+    cortex = ["-march=armv6-m", "-mcpu=cortex-m0plus", "-mthumb"]
+    env.heap_size = env.BoardConfig().get("build.heap", "2048")
+    optimization = env.BoardConfig().get("build.optimization", "-Os")
+    stack_size = env.BoardConfig().get("build.stack", "2048")
+    print('  * OPTIMIZATION :', optimization)
+    if 'ARDUINO' == env.get("PROGNAME"):
+        if "freertos" in env.GetProjectOption("lib_deps", []) or "USE_FREERTOS" in env.get("CPPDEFINES"):
+            pass
+        else:
+            print('  * STACK        :', stack_size)
+            print('  * HEAP         : maximum')
+    else:
+        print('  * STACK        :', stack_size)
+        print('  * HEAP         :', env.heap_size)
+    #fix_old_new_stdio(env)
+    env.Append(
+        ASFLAGS=[ cortex, "-x", "assembler-with-cpp" ],
+        CPPPATH = [
+            join("$PROJECT_DIR", "src"),
+            join("$PROJECT_DIR", "lib"),
+            join("$PROJECT_DIR", "include"),
+            join( env.framework_dir, "wizio", "pico"),
+            join( env.framework_dir, "wizio", "newlib"),
+            join( env.framework_dir, env.sdk, "include"),
+            join( env.framework_dir, env.sdk, "cmsis", "include"), #
+        ],
+        CPPDEFINES = [
+            "NDEBUG",
+            "PICO_ON_DEVICE=1",
+            "PICO_HEAP_SIZE="  + env.heap_size,
+            "PICO_STACK_SIZE=" + stack_size,
+        ],
+        CCFLAGS = [
+            cortex,
+            optimization,
+            "-fdata-sections",
+            "-ffunction-sections",
+            "-Wall",
+            "-Wextra",
+            "-Wfatal-errors",
+            "-Wno-sign-compare",
+            "-Wno-type-limits",
+            "-Wno-unused-parameter",
+            "-Wno-unused-function",
+            "-Wno-unused-but-set-variable",
+            "-Wno-unused-variable",
+            "-Wno-unused-value",
+            "-Wno-strict-aliasing",
+            "-Wno-maybe-uninitialized"
+        ],
+        CFLAGS = [
+            cortex,
+            "-Wno-discarded-qualifiers",
+            "-Wno-ignored-qualifiers",
+            "-Wno-attributes", #
+        ],
+        CXXFLAGS = [
+            "-fno-rtti",
+            "-fno-exceptions",
+            "-fno-threadsafe-statics",
+            "-fno-non-call-exceptions",
+            "-fno-use-cxa-atexit",
+        ],
+        LINKFLAGS = [
+            cortex,
+            optimization,
+            "-nostartfiles",
+            "-Xlinker", "--gc-sections",
+            "-Wl,--gc-sections",
+            "--entry=_entry_point",
+            dev_nano(env)
+        ],
+        LIBSOURCE_DIRS = [ join(env.framework_dir, "library"),  ],
+        LIBPATH        = [ join(env.framework_dir, "library"), join("$PROJECT_DIR", "lib") ],
+        LIBS           = ['m', 'gcc'],
+        BUILDERS = dict(
+            ElfToBin = Builder(
+                action = env.VerboseAction(" ".join([
+                    "$OBJCOPY", "-O",  "binary",
+                    "$SOURCES", "$TARGET",
+                ]), "Building $TARGET"),
+                suffix = ".bin"
+            )
+        ),
+        UPLOADCMD = dev_uploader
+    )
+    if False == env.wifi:
+        env.Append( CPPDEFINES = [ "PICO_WIFI" ] )    
+
+def add_libraries(env): # is PIO LIB-s
+    if "freertos" in env.GetProjectOption("lib_deps", []) or "USE_FREERTOS" in env.get("CPPDEFINES"):
+        env.Append(  CPPPATH = [ join( env.framework_dir, "library", "freertos", "include" ), ]  )
+        print('  * RTOS         : FreeRTOS')
+        if "USE_FREERTOS" not in env.get("CPPDEFINES"):
+            env.Append(  CPPDEFINES = [ "USE_FREERTOS"] )
+
+    if "cmsis-dap" in env.GetProjectOption("lib_deps", []):
+        env.Append( CPPDEFINES = [ "DAP" ], )
+
+def add_boot(env):
+    boot = env.BoardConfig().get("build.boot", "w25q080") # get boot
+    if "w25q080" != boot and "$PROJECT_DIR" in boot:
+        boot = boot.replace('$PROJECT_DIR', env["PROJECT_DIR"]).replace("\\", "/")
+    bynary_type_info.append(boot)
+    env.BuildSources( join("$BUILD_DIR", env.platform, "wizio", "boot"), join(env.framework_dir, "boot", boot) )
+
+def add_bynary_type(env):
+    add_boot(env)
+    bynary_type = env.BoardConfig().get("build.bynary_type", 'default')
+    env.address = env.BoardConfig().get("build.address", "empty")
+    linker      = env.BoardConfig().get("build.linker", "empty")
+    if "empty" != linker and "$PROJECT_DIR" in linker:
+        linker = linker.replace('$PROJECT_DIR', env["PROJECT_DIR"]).replace("\\", "/")
+    if 'copy_to_ram' == bynary_type:
+        if "empty" == env.address: env.address = '0x10000000'
+        if "empty" == linker: linker = 'memmap_copy_to_ram.ld'
+        env.Append(  CPPDEFINES = ['PICO_COPY_TO_RAM'] )
+    elif 'no_flash' == bynary_type:
+        if "empty" == env.address: env.address = '0x20000000'
+        if "empty" == linker: linker = 'memmap_no_flash.ld'
+        env.Append(  CPPDEFINES = ['PICO_NO_FLASH'] )
+    elif 'blocked_ram' == bynary_type:
+        print('TODO: blocked_ram is not supported yet')
+        exit(0)
+        if "empty" == env.address: env.address = ''
+        if "empty" == linker: linker = ''
+        env.Append( CPPDEFINES = ['PICO_USE_BLOCKED_RAM'] )
+    else: #default
+        if "empty" == env.address: env.address = '0x10000000'
+        if "empty" == linker: linker = 'memmap_default.ld'
+    env.Append( LDSCRIPT_PATH = join(env.framework_dir, env.sdk, "pico", "pico_standard_link", linker) )
+    bynary_type_info.append(linker)
+    bynary_type_info.append(env.address)
+    print('  * BINARY TYPE  :' , bynary_type, bynary_type_info  )
+    add_libraries(env)
+
+def dev_finalize(env):
+# WIZIO
+    env.BuildSources( join("$BUILD_DIR", env.platform, "wizio"), join(env.framework_dir, "wizio") )
+# SDK
+    add_bynary_type(env)
+    add_sdk(env)
+    env.Append(LIBS = env.libs)
+    dev_add_modules(env)
+    print()
+
+def dev_config_board(env):
+    src = join(env.PioPlatform().get_package_dir("framework-wizio-pico"), "templates")
+    dst = do_mkdir( env.subst("$PROJECT_DIR"), "include" )
+
+    if False == env.wifi:
+        print("  * WIFI         : NO")
+        return
+    ### pico w board
+    else:
+        do_copy(src, dst, "lwipopts.h") # for user edit
+
+        env.Append(
+            CPPDEFINES = [ "PICO_W", 'CYW43_SPI_PIO', 'CYW43_USE_SPI' ],
+            CPPPATH = [
+                join( env.framework_dir, env.sdk, "lib", "lwip", "src", "include" ),
+                join( env.framework_dir, env.sdk, "lib", "cyw43-driver", "src" ),
+                join( env.framework_dir, env.sdk, "lib", "cyw43-driver", "firmware" ),
+            ],            
+        )
+
+        ### pico wifi support
+        env.BuildSources( 
+            join( "$BUILD_DIR", "wifi", "pico" ), 
+            join(env.framework_dir, env.sdk), 
+            [ "-<*>", "+<pico/pico_cyw43_arch>", "+<pico/pico_lwip>", ]
+        )
+
+        ### wifi spi driver & firmware
+        env.BuildSources( 
+            join( "$BUILD_DIR", "wifi" , "cyw43-driver" ), 
+            join( env.framework_dir, env.sdk, "lib", "cyw43-driver", "src" ), 
+            [ "+<*>", "-<cyw43_sdio.c>", ] # remove sdio driver  
+        )
+
+        ### LWIP: for add other files, use PRE:SCRIPT.PY
+        env.BuildSources( 
+            join( "$BUILD_DIR", env.platform, "lwip", "api" ),
+            join( env.framework_dir, env.sdk, "lib", "lwip", "src", "api" ), 
+        )
+        env.BuildSources( 
+            join( "$BUILD_DIR", env.platform, "lwip", "core" ),
+            join( env.framework_dir, env.sdk, "lib", "lwip", "src", "core" ), 
+            [ "+<*>",  "-<ipv6>", ] # remove ipv6
+        )
+        env.BuildSources( 
+            join( "$BUILD_DIR", env.platform, "lwip", "netif" ),
+            join( env.framework_dir, env.sdk, "lib", "lwip", "src", "netif" ), 
+            [ "-<*>", "+<ethernet.c>", ]
+        )        
+
+        ### wifi firmware object
+        """
+        BUILD_DIR = env.subst( "$BUILD_DIR" )
+        do_mkdir( BUILD_DIR, "wifi" )
+        do_mkdir( join( BUILD_DIR, "wifi" ), "firmware" )
+        WIFI_FIRMWARE_DIR = join( BUILD_DIR, "wifi", "firmware" )
+        WIFI_FIRMWARE_OBJ = join( WIFI_FIRMWARE_DIR, "wifi_firmware.o" ) 
+        WIFI_FIRMWARE_BIN = join( env.framework_dir, env.sdk, "lib", "cyw43-driver", "firmware", "43439A0-7.95.49.00.combined" )
+        old_name = WIFI_FIRMWARE_BIN
+        old_name = '_binary_' + old_name.replace('\\', '_').replace('/', '_').replace('.', '_').replace(':', '_').replace('-', '_')
+        cmd = [ "$OBJCOPY", "-I", "binary", "-O", "elf32-littlearm", "-B", "arm", "--readonly-text",
+                "--rename-section", ".data=.big_const,contents,alloc,load,readonly,data",
+                "--redefine-sym", old_name + "_start=fw_43439A0_7_95_49_00_start",
+                "--redefine-sym", old_name + "_end=fw_43439A0_7_95_49_00_end",
+                "--redefine-sym", old_name + "_size=fw_43439A0_7_95_49_00_size",
+                WIFI_FIRMWARE_BIN, # SOURCE BIN
+                WIFI_FIRMWARE_OBJ  # TARGET OBJ
+        ]
+        env.AddPreAction( 
+                join( "$BUILD_DIR", "wifi" , "cyw43-driver", "cyw43_bus_pio_spi.o" ), # TRIGER
+                env.VerboseAction(" ".join(cmd), "Compiling wifi/firmware/wifi_firmware.o") 
+        )       
+        print( "  * WIFI         : Compile Firmware Object" )
+        env.Append( LINKFLAGS = [ WIFI_FIRMWARE_OBJ ] )
+        return
+        """
+        ### use pre-compiled wifi_firmware.o
+        print( "  * WIFI         : Firmware Object" )
+        env.Append( LINKFLAGS = [ join( env.framework_dir, env.sdk, "lib", "cyw43-driver", "src", "wifi_firmware.o" ) ] ) 
+        return
+        ### use pre-compiled libwifi_firmware.a
+        print( "  * WIFI         : Firmware Library" )
+        env.Append( # AS LIB
+            LIBPATH = [ join( env.framework_dir, env.sdk, "lib", "cyw43-driver", "src" ) ], 
+            LIBS = ['wifi_firmware'] 
+        )
+        
+# EXPERIMENTAL FEATURE: LOAD MODULES
+
+'''
+### Add & Compile not compiled sources with main builder
+
+###[INI] custom_modules = 
+    $PROJECT_DIR/modules/MODULE_SCRYPT.py = parameters if need
+    $PROJECT_DIR/any_folder_with_py_scripts
+
+### example: MODULE_VERNO.py
+from os.path import join
+def module_init(env, parameter=''): # if parameter: string separated by space
+    name = "verno"
+    print( "  *", name.upper() ) # just info
+    path = join( env.framework_dir, "sdk", "middleware", name)
+    env.Append( CPPPATH = [ join( path, "inc" ) ] )    
+    env.BuildSources( join( "$BUILD_DIR", "modules", name ), join( path, "src" ) )
+'''
+
+from importlib.machinery import SourceFileLoader
+
+# private 
+def dev_load_module(filename, params, env):
+    name = 'module_' +  str( abs(hash( filename )) )
+    m = SourceFileLoader(name, filename).load_module() 
+    m.module_init( env, params )     
+
+# public: call it at builder end
+def dev_add_modules(env): 
+    #lines = env.BoardConfig().get("build.modules", "0")
+    lines = env.GetProjectOption("custom_modules", "0")
+    if '0' != lines: 
+        print("Project Modules:")  
+        for line in lines.split("\n"):
+            if line == '': continue
+            ### Cleaning the INI line
+            line = line.strip().replace("\r", "").replace("\t", "")
+            delim = '='  # for parameters
+            params = ''  # from ini line
+            if delim in line:
+                params = line[ line.index( delim ) + 1 : ].strip()  # remove delim and whitespaces
+                params = " ".join( params.split() )                 # remove double spaces, params are separated by a space   
+                line = line.partition( delim )[0].strip()           # remove delim and whitespaces
+            module_path = env.subst( line ).strip().replace("\\", "/")
+            ### Loading
+            if False == os.path.exists(module_path):
+                print("[ERROR] MODULE PATH NOT EXIST: %s" % module_path)
+                exit(0)
+            if True == os.path.isdir( module_path ):  # files in folder
+                for root, dirs, files in os.walk( module_path ):                       
+                    files = [ f for f in files if f.endswith(".py") ] # filter py files
+                    for file in files: 
+                        dev_load_module( join(root, file), params, env)
+            else: # single file
+                dev_load_module( module_path, params, env)
+   

+ 297 - 0
builder/frameworks/pico.py

@@ -0,0 +1,297 @@
+# WizIO 2022 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from os.path import join
+from SCons.Script import DefaultEnvironment, Builder
+from platformio.builder.tools.piolib import PlatformIOLibBuilder
+
+def add_ops(env):
+    if "PICO_STDIO_UART" in env.get("CPPDEFINES"):
+        env.Append( CPPDEFINES = [ "LIB_PICO_STDIO_UART"] )
+    if "LIB_PICO_STDIO_UART" in env.get("CPPDEFINES"):
+        env.Append( CPPDEFINES = [ "PICO_STDIO_UART"] )
+    if "PICO_STDIO_USB" in env.get("CPPDEFINES"):
+        env.Append( CPPDEFINES = [ "LIB_PICO_STDIO_USB"] )
+    if "LIB_PICO_STDIO_USB" in env.get("CPPDEFINES"):
+        env.Append( CPPDEFINES = [ "PICO_STDIO_USB"] )
+    if "PICO_STDIO_SEMIHOSTING" in env.get("CPPDEFINES"):
+        env.Append( CPPDEFINES = [ "LIB_PICO_STDIO_SEMIHOSTING"] )
+    if "LIB_PICO_STDIO_SEMIHOSTING" in env.get("CPPDEFINES"):
+        env.Append( CPPDEFINES = [ "PICO_STDIO_SEMIHOSTING"] )
+
+    tab = '  *'
+    OBJ_DIR = join( "$BUILD_DIR", env.platform, env.sdk, "pico" )
+    LIB_DIR  = join( env.framework_dir, env.sdk, "pico" )
+    if "PICO_DOUBLE_SUPPORT_ROM_V1" in env.get("CPPDEFINES"):
+        print(tab, 'PICO_DOUBLE_SUPPORT_ROM_V1')
+        env.BuildSources( join(OBJ_DIR, "pico_double"), join(LIB_DIR, "pico_double") )
+        env.Append( LINKFLAGS = [
+            "-Wl,-wrap,__aeabi_dadd",
+            "-Wl,-wrap,__aeabi_ddiv",
+            "-Wl,-wrap,__aeabi_dmul",
+            "-Wl,-wrap,__aeabi_drsub",
+            "-Wl,-wrap,__aeabi_dsub",
+            "-Wl,-wrap,__aeabi_cdcmpeq",
+            "-Wl,-wrap,__aeabi_cdrcmple",
+            "-Wl,-wrap,__aeabi_cdcmple",
+            "-Wl,-wrap,__aeabi_dcmpeq",
+            "-Wl,-wrap,__aeabi_dcmplt",
+            "-Wl,-wrap,__aeabi_dcmple",
+            "-Wl,-wrap,__aeabi_dcmpge",
+            "-Wl,-wrap,__aeabi_dcmpgt",
+            "-Wl,-wrap,__aeabi_dcmpun",
+            "-Wl,-wrap,__aeabi_i2d",
+            "-Wl,-wrap,__aeabi_l2d",
+            "-Wl,-wrap,__aeabi_ui2d",
+            "-Wl,-wrap,__aeabi_ul2d",
+            "-Wl,-wrap,__aeabi_d2iz",
+            "-Wl,-wrap,__aeabi_d2lz",
+            "-Wl,-wrap,__aeabi_d2uiz",
+            "-Wl,-wrap,__aeabi_d2ulz",
+            "-Wl,-wrap,__aeabi_d2f",
+            "-Wl,-wrap,sqrt",
+            "-Wl,-wrap,cos",
+            "-Wl,-wrap,sin",
+            "-Wl,-wrap,tan",
+            "-Wl,-wrap,atan2",
+            "-Wl,-wrap,exp",
+            "-Wl,-wrap,log",
+            "-Wl,-wrap,ldexp",
+            "-Wl,-wrap,copysign",
+            "-Wl,-wrap,trunc",
+            "-Wl,-wrap,floor",
+            "-Wl,-wrap,ceil",
+            "-Wl,-wrap,round",
+            "-Wl,-wrap,sincos",
+            "-Wl,-wrap,asin",
+            "-Wl,-wrap,acos",
+            "-Wl,-wrap,atan",
+            "-Wl,-wrap,sinh",
+            "-Wl,-wrap,cosh",
+            "-Wl,-wrap,tanh",
+            "-Wl,-wrap,asinh",
+            "-Wl,-wrap,acosh",
+            "-Wl,-wrap,atanh",
+            "-Wl,-wrap,exp2",
+            "-Wl,-wrap,log2",
+            "-Wl,-wrap,exp10",
+            "-Wl,-wrap,log10",
+            "-Wl,-wrap,pow",
+            "-Wl,-wrap,powint",
+            "-Wl,-wrap,hypot",
+            "-Wl,-wrap,cbrt",
+            "-Wl,-wrap,fmod",
+            "-Wl,-wrap,drem",
+            "-Wl,-wrap,remainder",
+            "-Wl,-wrap,remquo",
+            "-Wl,-wrap,expm1",
+            "-Wl,-wrap,log1p",
+            "-Wl,-wrap,fma",
+        ])
+
+    if "PICO_FLOAT_SUPPORT_ROM_V1" in env.get("CPPDEFINES"):
+        print(tab, 'PICO_FLOAT_SUPPORT_ROM_V1')
+        env.BuildSources( join(OBJ_DIR, "pico_float"), join(LIB_DIR, "pico_float") )
+        env.Append( LINKFLAGS = [
+            "-Wl,-wrap,__aeabi_fadd",
+            "-Wl,-wrap,__aeabi_fdiv",
+            "-Wl,-wrap,__aeabi_fmul",
+            "-Wl,-wrap,__aeabi_frsub",
+            "-Wl,-wrap,__aeabi_fsub",
+            "-Wl,-wrap,__aeabi_cfcmpeq",
+            "-Wl,-wrap,__aeabi_cfrcmple",
+            "-Wl,-wrap,__aeabi_cfcmple",
+            "-Wl,-wrap,__aeabi_fcmpeq",
+            "-Wl,-wrap,__aeabi_fcmplt",
+            "-Wl,-wrap,__aeabi_fcmple",
+            "-Wl,-wrap,__aeabi_fcmpge",
+            "-Wl,-wrap,__aeabi_fcmpgt",
+            "-Wl,-wrap,__aeabi_fcmpun",
+            "-Wl,-wrap,__aeabi_i2f",
+            "-Wl,-wrap,__aeabi_l2f",
+            "-Wl,-wrap,__aeabi_ui2f",
+            "-Wl,-wrap,__aeabi_ul2f",
+            "-Wl,-wrap,__aeabi_f2iz",
+            "-Wl,-wrap,__aeabi_f2lz",
+            "-Wl,-wrap,__aeabi_f2uiz",
+            "-Wl,-wrap,__aeabi_f2ulz",
+            "-Wl,-wrap,__aeabi_f2d",
+            "-Wl,-wrap,sqrtf",
+            "-Wl,-wrap,cosf",
+            "-Wl,-wrap,sinf",
+            "-Wl,-wrap,tanf",
+            "-Wl,-wrap,atan2f",
+            "-Wl,-wrap,expf",
+            "-Wl,-wrap,logf",
+            "-Wl,-wrap,ldexpf",
+            "-Wl,-wrap,copysignf",
+            "-Wl,-wrap,truncf",
+            "-Wl,-wrap,floorf",
+            "-Wl,-wrap,ceilf",
+            "-Wl,-wrap,roundf",
+            "-Wl,-wrap,sincosf",
+            "-Wl,-wrap,asinf",
+            "-Wl,-wrap,acosf",
+            "-Wl,-wrap,atanf",
+            "-Wl,-wrap,sinhf",
+            "-Wl,-wrap,coshf",
+            "-Wl,-wrap,tanhf",
+            "-Wl,-wrap,asinhf",
+            "-Wl,-wrap,acoshf",
+            "-Wl,-wrap,atanhf",
+            "-Wl,-wrap,exp2f",
+            "-Wl,-wrap,log2f",
+            "-Wl,-wrap,exp10f",
+            "-Wl,-wrap,log10f",
+            "-Wl,-wrap,powf",
+            "-Wl,-wrap,powintf",
+            "-Wl,-wrap,hypotf",
+            "-Wl,-wrap,cbrtf",
+            "-Wl,-wrap,fmodf",
+            "-Wl,-wrap,dremf",
+            "-Wl,-wrap,remainderf",
+            "-Wl,-wrap,remquof",
+            "-Wl,-wrap,expm1f",
+            "-Wl,-wrap,log1pf",
+            "-Wl,-wrap,fmaf",
+        ])
+
+    if "PICO_DIVIDER_HARDWARE" in env.get("CPPDEFINES"):
+        print(tab, 'PICO_DIVIDER_HARDWARE')
+        env.BuildSources( join(OBJ_DIR, "pico_divider"), join(LIB_DIR, "pico_divider") )
+        env.Append( LINKFLAGS = [
+            "-Wl,-wrap,__aeabi_idiv",
+            "-Wl,-wrap,__aeabi_idivmod",
+            "-Wl,-wrap,__aeabi_ldivmod",
+            "-Wl,-wrap,__aeabi_uidiv",
+            "-Wl,-wrap,__aeabi_uidivmod",
+            "-Wl,-wrap,__aeabi_uldivmod",
+        ])
+
+    if "PICO_INT64_OPS_PICO" in env.get("CPPDEFINES"):
+        print(tab, 'PICO_INT64_OPS_PICO')
+        env.BuildSources( join(OBJ_DIR, "pico_int64_ops"), join(LIB_DIR, "pico_int64_ops") )
+        env.Append( LINKFLAGS = [
+            "-Wl,-wrap,wrapper_func __aeabi_lmul",
+        ])
+
+    if "PICO_BIT_OPS_PICO" in env.get("CPPDEFINES"):
+        print(tab, 'PICO_BIT_OPS_PICO')
+        env.BuildSources( join(OBJ_DIR, "pico_bit_ops"), join(LIB_DIR, "pico_bit_ops") )
+        env.Append( LINKFLAGS = [
+            "-Wl,-wrap,__clzsi2",
+            "-Wl,-wrap,__clzsi2",
+            "-Wl,-wrap,__clzdi2",
+            "-Wl,-wrap,__ctzsi2",
+            "-Wl,-wrap,__ctzdi2",
+            "-Wl,-wrap,__popcountsi2",
+            "-Wl,-wrap,__popcountdi2",
+            #"-Wl,-wrap,__clz",
+            #"-Wl,-wrap,__clzl",
+            #"-Wl,-wrap,__clzsi2",
+            #"-Wl,-wrap,__clzll",
+        ])
+
+    if "PICO_MEM_OPS_PICO" in env.get("CPPDEFINES"):
+        print(tab, 'PICO_MEM_OPS_PICO')
+        env.BuildSources( join(OBJ_DIR, "pico_mem_ops"), join(LIB_DIR, "pico_mem_ops") )
+        env.Append( LINKFLAGS = [
+            "-Wl,-wrap,memcpy",
+            "-Wl,-wrap,memset",
+            "-Wl,-wrap,__aeabi_memcpy",
+            "-Wl,-wrap,__aeabi_memset",
+            "-Wl,-wrap,__aeabi_memcpy4",
+            "-Wl,-wrap,__aeabi_memset4",
+            "-Wl,-wrap,__aeabi_memcpy8",
+            "-Wl,-wrap,__aeabi_memset8",
+        ])
+
+    if 'ARDUINO' == env.get("PROGNAME"):
+        return ########################################################################################
+
+    if "PICO_PRINTF_PICO" in env.get("CPPDEFINES"):
+        print(tab, 'PICO_PRINTF_PICO')
+        env.BuildSources( join(OBJ_DIR, "pico_printf"), join(LIB_DIR, "pico_printf") )
+        env.Append( LINKFLAGS = [
+            "-Wl,-wrap,sprintf",
+            "-Wl,-wrap,snprintf",
+            "-Wl,-wrap,vsnprintf",
+
+            "-Wl,-wrap,printf",
+            "-Wl,-wrap,vprintf",
+            "-Wl,-wrap,puts",
+            "-Wl,-wrap,putchar",
+        ])
+
+    if "PICO_STDIO_USB" in env.get("CPPDEFINES") or "PICO_STDIO_UART" in env.get("CPPDEFINES") or "PICO_STDIO_SEMIHOSTING" in env.get("CPPDEFINES"):     
+        env.BuildSources( join(OBJ_DIR, "pico_stdio"), join(LIB_DIR, "pico_stdio") )
+
+    if "PICO_STDIO_USB" in env.get("CPPDEFINES"):
+        print(tab, 'STDIO        : USB')
+        env.BuildSources( join(OBJ_DIR, "pico_stdio_usb"), join(LIB_DIR, "pico_stdio_usb") )        
+
+    if "PICO_STDIO_UART" in env.get("CPPDEFINES"):
+        print(tab, 'STDIO        : UART')
+        env.BuildSources( join(OBJ_DIR, "pico_stdio_uart"), join(LIB_DIR, "pico_stdio_uart") )
+
+    if "PICO_STDIO_SEMIHOSTING" in env.get("CPPDEFINES"):
+        print(tab, 'STDIO        : SEMIHOSTING')
+        env.BuildSources( join(OBJ_DIR, "pico_stdio_semihosting"), join(LIB_DIR, "pico_stdio_semihosting") )
+
+    env.Append( LINKFLAGS = [
+        "-Wl,-wrap,malloc",
+        "-Wl,-wrap,calloc",
+        "-Wl,-wrap,free",
+    ])
+
+
+def add_tinyusb(env):
+    OBJ_DIR = join( "$BUILD_DIR", env.platform, env.sdk, "pico", "usb" )
+    USB_DIR = join( env.framework_dir, env.sdk, "lib", "tinyusb", "src" )
+    for define in env.get("CPPDEFINES"):
+        if "USB" in define:
+            env.Append( CPPDEFINES = [ "CFG_TUSB_MCU=OPT_MCU_RP2040", "CFG_TUSB_OS=OPT_OS_PICO" ], CPPPATH = [ USB_DIR ]  )
+            if "PICO_USB_HOST" in define: 
+                #[ini] build_flags = -D PICO_USB_HOST ... load lib as host      
+                print('  * TINYUSB      : HOST')
+                env.BuildSources( OBJ_DIR, USB_DIR, src_filter = [ "+<*>", "-<device>", "+<class>" ] )
+            else: 
+                #[ini] build_flags = -D PICO_USB_DEVICE / PICO_STDIO_USB ... load lib as device      
+                print('  * TINYUSB      : DEVICE')        
+                env.BuildSources( OBJ_DIR, USB_DIR, src_filter = [ "+<*>", "-<host>", "+<class>" ] )            
+            break
+
+
+def add_sdk(env):
+    add_ops(env)
+    add_tinyusb(env)
+    
+    if 'ARDUINO' != env.get("PROGNAME"):
+        new_delete = "+"
+        pico_malloc = '+'
+    else:
+        new_delete = "-"
+        pico_malloc = '-'
+
+    filter = [ "+<*>",
+            "-<lib>",
+            "-<boot_stage2>",
+            "-<pico/pico_cyw43_arch>",
+            "-<pico/pico_lwip>",
+            "-<pico/pico_bit_ops>",
+            "-<pico/pico_divider>",
+            "-<pico/pico_int64_ops>",
+            "-<pico/pico_printf>",
+            "-<pico/pico_float>",
+            "-<pico/pico_double>",
+            "-<pico/pico_stdio>",
+            "-<pico/pico_stdio_usb>",
+            "-<pico/pico_stdio_uart>",
+            "-<pico/pico_stdio_semihosting>",
+            "-<pico/pico_mem_ops>",
+            "-<pico/pico_standard_link/crt0.S>",
+            new_delete + "<pico/pico_standard_link/new_delete.cpp>",
+            pico_malloc + "<pico/pico_malloc>"
+    ]
+    env.BuildSources( join("$BUILD_DIR", env.platform, env.sdk), join(env.framework_dir, env.sdk), src_filter = filter )

+ 20 - 0
builder/frameworks/sdk-RP2040.py

@@ -0,0 +1,20 @@
+# WizIO 2022 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from os.path import join
+from SCons.Script import DefaultEnvironment, Builder
+from common import *
+
+def dev_init(env, platform):
+    env.platform = platform
+    env.framework_dir = env.PioPlatform().get_package_dir("framework-wizio-pico")
+    env.libs = []
+    dev_compiler(env)
+    dev_create_template(env)
+    env.Append(
+        CPPDEFINES = [ "BAREMETAL" ],
+        CPPPATH    = [ join(env.framework_dir, env.sdk, "boards"), ]
+    )
+    dev_config_board(env)
+    dev_finalize(env)

+ 14 - 0
builder/frameworks/sdk.py

@@ -0,0 +1,14 @@
+# WizIO 2022 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from __future__ import print_function
+from SCons.Script import DefaultEnvironment
+
+env = DefaultEnvironment()
+platform = "sdk"
+module = platform + "-" + env.BoardConfig().get("build.core")
+m = __import__(module)
+globals()[module] = m
+m.dev_init(env, platform)
+#print( env.Dump() )

+ 347 - 0
builder/frameworks/uf2conv.py

@@ -0,0 +1,347 @@
+#!/usr/bin/env python3
+import sys
+import struct
+import subprocess
+import re
+import os
+import os.path
+import argparse
+import time
+import serial
+from os.path import join
+from platform import system
+
+UF2_MAGIC_START0 = 0x0A324655 # "UF2\n"
+UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected
+UF2_MAGIC_END    = 0x0AB16F30 # Ditto
+
+families = {
+    'SAMD21'        : 0x68ed2b88,
+    'SAML21'        : 0x1851780a,
+    'SAMD51'        : 0x55114460,
+    'NRF52'         : 0x1b57745f,
+    'STM32F0'       : 0x647824b6,
+    'STM32F1'       : 0x5ee21072,
+    'STM32F2'       : 0x5d1a0a2e,
+    'STM32F3'       : 0x6b846188,
+    'STM32F4'       : 0x57755a57,
+    'STM32F7'       : 0x53b80f00,
+    'STM32G0'       : 0x300f5633,
+    'STM32G4'       : 0x4c71240a,
+    'STM32H7'       : 0x6db66082,
+    'STM32L0'       : 0x202e3a91,
+    'STM32L1'       : 0x1e1f432d,
+    'STM32L4'       : 0x00ff6919,
+    'STM32L5'       : 0x04240bdf,
+    'STM32WB'       : 0x70d16653,
+    'STM32WL'       : 0x21460ff0,
+    'ATMEGA32'      : 0x16573617,
+    'MIMXRT10XX'    : 0x4FB2D5BD,
+    'LPC55'         : 0x2abc77ec,
+    'GD32F350'      : 0x31D228C6,
+    'ESP32S2'       : 0xbfdd4eee,
+    'RP2040'        : 0xe48bff56
+}
+
+INFO_FILE = "/INFO_UF2.TXT"
+
+appstartaddr    = 0x10000000 # pico flash
+familyid        = 0xe48bff56 # pico selected
+
+
+def is_uf2(buf):
+    w = struct.unpack("<II", buf[0:8])
+    return w[0] == UF2_MAGIC_START0 and w[1] == UF2_MAGIC_START1
+
+def is_hex(buf):
+    try:
+        w = buf[0:30].decode("utf-8")
+    except UnicodeDecodeError:
+        return False
+    if w[0] == ':' and re.match(b"^[:0-9a-fA-F\r\n]+$", buf):
+        return True
+    return False
+
+def convert_from_uf2(buf):
+    global appstartaddr
+    numblocks = len(buf) // 512
+    curraddr = None
+    outp = []
+    for blockno in range(numblocks):
+        ptr = blockno * 512
+        block = buf[ptr:ptr + 512]
+        hd = struct.unpack(b"<IIIIIIII", block[0:32])
+        if hd[0] != UF2_MAGIC_START0 or hd[1] != UF2_MAGIC_START1:
+            print("Skipping block at " + ptr + "; bad magic")
+            continue
+        if hd[2] & 1:
+            # NO-flash flag set; skip block
+            continue
+        datalen = hd[4]
+        if datalen > 476:
+            assert False, "Invalid UF2 data size at " + ptr
+        newaddr = hd[3]
+        if curraddr == None:
+            appstartaddr = newaddr
+            curraddr = newaddr
+        padding = newaddr - curraddr
+        if padding < 0:
+            assert False, "Block out of order at " + ptr
+        if padding > 10*1024*1024:
+            assert False, "More than 10M of padding needed at " + ptr
+        if padding % 4 != 0:
+            assert False, "Non-word padding size at " + ptr
+        while padding > 0:
+            padding -= 4
+            outp += b"\x00\x00\x00\x00"
+        outp.append(block[32 : 32 + datalen])
+        curraddr = newaddr + datalen
+    return b"".join(outp)
+
+def convert_to_carray(file_content):
+    outp = "const unsigned long bindata_len = %d;\n" % len(file_content)
+    outp += "const unsigned char bindata[] __attribute__((aligned(16))) = {"
+    for i in range(len(file_content)):
+        if i % 16 == 0:
+            outp += "\n"
+        outp += "0x%02x, " % file_content[i]
+    outp += "\n};\n"
+    return bytes(outp, "utf-8")
+
+def convert_to_uf2(file_content):
+    global familyid
+    #print("  FamilyID:", hex(familyid))
+    datapadding = b""
+    while len(datapadding) < 512 - 256 - 32 - 4:
+        datapadding += b"\x00\x00\x00\x00"
+    numblocks = (len(file_content) + 255) // 256
+    outp = []
+    for blockno in range(numblocks):
+        ptr = 256 * blockno
+        chunk = file_content[ptr:ptr + 256]
+        flags = 0x0
+        if familyid:
+            flags |= 0x2000
+        hd = struct.pack(b"<IIIIIIII",
+            UF2_MAGIC_START0, UF2_MAGIC_START1,
+            flags, ptr + appstartaddr, 256, blockno, numblocks, familyid)
+        while len(chunk) < 256:
+            chunk += b"\x00"
+        block = hd + chunk + datapadding + struct.pack(b"<I", UF2_MAGIC_END)
+        assert len(block) == 512
+        outp.append(block)
+    return b"".join(outp)
+
+class Block:
+    def __init__(self, addr):
+        self.addr = addr
+        self.bytes = bytearray(256)
+
+    def encode(self, blockno, numblocks):
+        global familyid
+        flags = 0x0
+        if familyid:
+            flags |= 0x2000
+        hd = struct.pack("<IIIIIIII",
+            UF2_MAGIC_START0, UF2_MAGIC_START1,
+            flags, self.addr, 256, blockno, numblocks, familyid)
+        hd += self.bytes[0:256]
+        while len(hd) < 512 - 4:
+            hd += b"\x00"
+        hd += struct.pack("<I", UF2_MAGIC_END)
+        return hd
+
+def convert_from_hex_to_uf2(buf):
+    global appstartaddr
+    appstartaddr = None
+    upper = 0
+    currblock = None
+    blocks = []
+    for line in buf.split('\n'):
+        if line[0] != ":":
+            continue
+        i = 1
+        rec = []
+        while i < len(line) - 1:
+            rec.append(int(line[i:i+2], 16))
+            i += 2
+        tp = rec[3]
+        if tp == 4:
+            upper = ((rec[4] << 8) | rec[5]) << 16
+        elif tp == 2:
+            upper = ((rec[4] << 8) | rec[5]) << 4
+            assert (upper & 0xffff) == 0
+        elif tp == 1:
+            break
+        elif tp == 0:
+            addr = upper | (rec[1] << 8) | rec[2]
+            if appstartaddr == None:
+                appstartaddr = addr
+            i = 4
+            while i < len(rec) - 1:
+                if not currblock or currblock.addr & ~0xff != addr & ~0xff:
+                    currblock = Block(addr & ~0xff)
+                    blocks.append(currblock)
+                currblock.bytes[addr & 0xff] = rec[i]
+                addr += 1
+                i += 1
+    numblocks = len(blocks)
+    resfile = b""
+    for i in range(0, numblocks):
+        resfile += blocks[i].encode(i, numblocks)
+    return resfile
+
+def to_str(b):
+    return b.decode("utf-8")
+
+def get_drives():
+    drives = []
+    if sys.platform == "win32":
+        r = subprocess.check_output(["wmic", "PATH", "Win32_LogicalDisk", "get", "DeviceID,", "VolumeName,", "FileSystem,", "DriveType"])
+        for line in to_str(r).split('\n'):
+            words = re.split('\s+', line)
+            if len(words) >= 3 and words[1] == "2" and words[2] == "FAT":
+                drives.append(words[0])
+    else:
+        rootpath = "/media"
+        if sys.platform == "darwin":
+            rootpath = "/Volumes"
+        elif sys.platform == "linux":
+            tmp = rootpath + "/" + os.environ["USER"]
+            if os.path.isdir(tmp):
+                rootpath = tmp
+        for d in os.listdir(rootpath):
+            drives.append(os.path.join(rootpath, d))
+
+
+    def has_info(d):
+        try:
+            return os.path.isfile(d + INFO_FILE)
+        except:
+            return False
+
+    return list(filter(has_info, drives))
+
+
+def board_id(path):
+    with open(path + INFO_FILE, mode='r') as file:
+        file_content = file.read()
+    return re.search("Board-ID: ([^\r\n]*)", file_content).group(1)
+
+
+def list_drives():
+    for d in get_drives():
+        print(d, board_id(d))
+
+
+def write_file(name, buf):
+    with open(name, "wb") as f:
+        f.write(buf)
+    print("  Wrote %d bytes to %s" % (len(buf), name))
+
+
+def main():
+    global appstartaddr, familyid
+    def error(msg):
+        print(msg)
+        sys.exit(1)
+    parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.')
+    parser.add_argument('input', metavar='INPUT', type=str, nargs='?', help='input file (HEX, BIN or UF2)')
+    parser.add_argument('-b' , '--base', dest='base', type=str, default="0x10000000", help='set base address of application for BIN format (default: 0x10000000)')
+    parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible')
+    parser.add_argument('-d' , '--device', dest="device_path", help='select a device path to flash')
+    parser.add_argument('-l' , '--list', action='store_true', help='list connected devices')
+    parser.add_argument('-c' , '--convert', action='store_true', help='do not flash, just convert')
+    parser.add_argument('-D' , '--deploy', action='store_true', help='just flash, do not convert')
+    parser.add_argument('-f' , '--family', dest='family', type=str, default="0x0", help='specify familyID - number or name (default: 0x0)')
+    parser.add_argument('-C' , '--carray', action='store_true', help='convert binary file to a C array, not UF2')
+    args = parser.parse_args()
+    appstartaddr = int(args.base, 0)
+
+    if args.family.upper() in families:
+        familyid = families[args.family.upper()]
+    else:
+        try:
+            familyid = int(args.family, 0)
+        except ValueError:
+            error("Family ID needs to be a number or one of: " + ", ".join(families.keys()))
+
+    if args.list:
+        list_drives()
+    else:
+        if not args.input:
+            error("Need input file")
+        with open(args.input, mode='rb') as f:
+            inpbuf = f.read()
+        from_uf2 = is_uf2(inpbuf)
+        ext = "uf2"
+        if args.deploy:
+            outbuf = inpbuf
+        elif from_uf2:
+            outbuf = convert_from_uf2(inpbuf)
+            ext = "bin"
+        elif is_hex(inpbuf):
+            outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8"))
+        elif args.carray:
+            outbuf = convert_to_carray(inpbuf)
+            ext = "h"
+        else:
+            outbuf = convert_to_uf2(inpbuf)
+        print("Converting to %s, output size: %d, start address: 0x%x" % (ext, len(outbuf), appstartaddr))
+        if args.convert or ext != "uf2":
+            drives = []
+            if args.output == None:
+                args.output = "flash." + ext
+        else:
+            drives = get_drives()
+
+        if args.output:
+            write_file(args.output, outbuf)
+        else:
+            if len(drives) == 0:
+                error("No drive to deploy.")
+        for d in drives:
+            print("Flashing %s (%s)" % (d, board_id(d)))
+            write_file(d + "/NEW.UF2", outbuf)
+
+
+if __name__ == "__main__":
+    main()
+
+
+# WizIO 2021 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+
+def dev_uploader(target, source, env):
+    global appstartaddr
+    appstartaddr = int(env.address, 0)
+    bin_name = join(env.get("BUILD_DIR"), env.get("PROGNAME"))+'.bin'
+    uf2_name = join(env.get("BUILD_DIR"), env.get("PROGNAME"))+'.uf2'
+    drive = env.get("UPLOAD_PORT")
+    if None != env.GetProjectOption("monitor_port"):
+        try: # reset usb stdio
+            usb = serial.Serial( env.GetProjectOption("monitor_port"), 1200)
+            time.sleep(0.1)
+            usb.close()
+        except:
+            pass
+        time.sleep(1.0) # Windows - AutoPlay
+        if 'Windows' not in system(): time.sleep(1.0)
+    print( "  Converting to UF2 ( 0x%x )" % (appstartaddr) )
+    with open( bin_name, mode='rb' ) as f: inpbuf = f.read()
+    outbuf = convert_to_uf2(inpbuf)
+    time.sleep(.1)
+    write_file(uf2_name, outbuf) # write uf2 to build folder
+    drives = get_drives()
+    if len(drives) == 0:
+        #raise RuntimeError("Pico USB drive not found.")
+        print("\033[1;37;41m                               ")
+        print("\033[1;37;41m   Pico USB drive not found.   ")
+        print("\033[1;37;41m                               ")
+        return
+    for d in drives:
+        print("Flashing %s (%s)" % (d, board_id(d)))
+        write_file(d +'/'+ env.get("PROGNAME")+'.uf2', outbuf) # write ufs to pico
+    time.sleep(1.0) # usb-serial driver up

+ 35 - 0
builder/main.py

@@ -0,0 +1,35 @@
+# WizIO 2021 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from __future__ import print_function
+from os.path import join
+from SCons.Script import (AlwaysBuild, Builder, COMMAND_LINE_TARGETS, Default, DefaultEnvironment)
+from colorama import Fore
+from wpioasm import dev_pioasm # https://github.com/Wiz-IO/wizio-pico/issues/98#issuecomment-1128747885
+
+env = DefaultEnvironment()
+print( '<<<<<<<<<<<< ' + env.BoardConfig().get("name").upper() + " 2021 Georgi Angelov >>>>>>>>>>>>" )
+
+dev_pioasm(env)
+
+elf = env.BuildProgram()
+src = env.ElfToBin( join("$BUILD_DIR", "${PROGNAME}"), elf )
+prg = env.Alias( "buildprog", src, [ env.VerboseAction("", "DONE") ] )
+AlwaysBuild( prg )
+
+upload = env.Alias("upload", prg, [ 
+    env.VerboseAction("$UPLOADCMD", "Uploading..."),
+    env.VerboseAction("", ""),
+])
+AlwaysBuild( upload )    
+
+debug_tool = env.GetProjectOption("debug_tool")
+if None == debug_tool:
+    Default( prg )
+else:   
+    if 'cmsis-dap' in debug_tool:
+        Default( upload )
+    else:
+        Default( prg )
+

+ 68 - 0
builder/wpioasm.py

@@ -0,0 +1,68 @@
+# WizIO 2021 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from __future__ import print_function
+import os, platform
+from platform import system, machine
+from os.path import join
+from SCons.Script import (AlwaysBuild, Builder, COMMAND_LINE_TARGETS, Default, DefaultEnvironment)
+from colorama import Fore
+from subprocess import check_output, CalledProcessError, call, Popen, PIPE
+from time import sleep
+
+def execute(cmd):
+    proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
+    out, err = proc.communicate()
+    lines = out.decode().split("\r\n")
+    error = err.decode().split("\r\n")
+    if proc.returncode == 0: 
+        COLOR = Fore.GREEN
+    else: 
+        COLOR = Fore.RED
+    for i in range( len(error) ):
+        print( COLOR + error[i] )
+        sleep(0.05)
+    return proc.returncode
+
+def dev_pioasm(env):
+    sys_dir = system() +'_'+ machine()
+    sys_dir = sys_dir.lower()
+    if 'windows' in sys_dir: 
+        sys_dir = 'windows'
+
+    tool = env.PioPlatform().get_package_dir("tool-wizio-pico")
+    if None == tool:
+        print( Fore.RED + '[PIO-ASM] ERROR: The', sys_dir, 'is no supported yet...' )
+        return
+
+    names = env.BoardConfig().get("build.pio", "0")
+    if '0' == names:
+        return
+
+    for src_name in names.split():
+        dst_name = src_name + '.h'
+
+        src = join(env.subst("$PROJECT_DIR"), src_name).replace("\\", "/")
+        dst = join(env.subst("$PROJECT_DIR"), dst_name).replace("\\", "/")
+
+        if True == os.path.isfile( dst ):
+            print(Fore.CYAN + '[PIO-ASM] File (', os.path.basename(dst), ') exist' )
+            continue
+
+        if False == os.path.isfile( src ):
+            print(Fore.RED + '[PIO-ASM] ERROR: Source file not exist ', src, "\n")
+            exit(1)
+
+        if False == os.path.isdir( os.path.dirname( dst )  ):
+            print(Fore.RED + '[PIO-ASM] ERROR: Destination folder not exist', os.path.dirname( dst ), "\n")     
+            exit(1)   
+
+        cmd = []
+        cmd.append(join(tool, sys_dir, 'pioasm') ) 
+        cmd.append(join(env.subst("$PROJECT_DIR"), src))        
+        cmd.append(join(env.subst("$PROJECT_DIR"), dst))  
+    
+        if execute(cmd) != 0:    
+            exit(1) 
+

File diff suppressed because it is too large
+ 40763 - 0
misc/svd/rp2040.svd


+ 54 - 0
platform.json

@@ -0,0 +1,54 @@
+{
+  "name": "wizio-pico",
+  "title": "WizIO - Raspberry Pi Pico",
+  "description": "Development platform for Raspberry Pi Pico 2021 Georgi Angelov",
+  "homepage": "http://www.wizio.eu/",
+  "license": "Apache-2.0",
+  "engines": {
+    "platformio": "^5"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/Wiz-IO/wizio-pico.git"
+  },
+  "version": "1.1.1",
+  "packageRepositories": [
+    "http://dl.platformio.org/packages/manifest.json"
+  ],
+  "frameworks": {
+      "baremetal": {
+        "package": "framework-wizio-pico",
+        "script": "builder/frameworks/sdk.py"
+      },
+      "arduino": {
+        "package": "framework-wizio-pico",
+        "script": "builder/frameworks/arduino.py"
+      },
+      "boot2": {
+        "package": "framework-wizio-pico",
+        "script": "builder/frameworks/boot2.py"
+      }
+
+  },
+  "packages": {
+    "framework-wizio-pico": {
+        "type": "framework",
+        "version": "https://github.com/Wiz-IO/framework-wizio-pico.git"
+    },
+    "toolchain-gccarmnoneeabi": {
+        "owner": "platformio",
+        "type": "toolchain",
+        "version": "~1.70201.0"
+    },
+    "tool-wizio-pico": {
+        "type": "uploader",
+        "version": "https://github.com/Wiz-IO/tool-wizio-pico.git"
+    }, 
+    "tool-pico-openocd": {
+      "optional": true,
+      "type": "debugger",
+      "version": "https://github.com/Wiz-IO/tool-pico-openocd"
+    } 
+
+  }
+}

+ 108 - 0
platform.py

@@ -0,0 +1,108 @@
+# WizIO 2021 Georgi Angelov
+#   http://www.wizio.eu/
+#   https://github.com/Wiz-IO/wizio-pico
+
+from platformio.managers.platform import PlatformBase
+import os, platform, copy
+from os.path import join
+from platform import system, machine
+
+def get_system():
+    sys_dir = system() +'_'+ machine()
+    sys_dir = sys_dir.lower()
+    if 'windows' in sys_dir: 
+        sys_dir = 'windows'
+    return sys_dir 
+
+class WiziopicoPlatform(PlatformBase):
+    def is_embedded(self):
+        return True
+
+    def get_boards(self, id_=None):
+        result = PlatformBase.get_boards(self, id_)
+        if not result:
+            return result
+        if id_:
+            return self._add_dynamic_options(result)
+        else:
+            for key, value in result.items():
+                result[key] = self._add_dynamic_options(result[key])
+        return result
+     
+    def _add_dynamic_options(self, board):
+        # upload protocols
+        if not board.get("upload.protocols", []):
+            board.manifest["upload"]["protocols"] = ["uf2"]
+        if not board.get("upload.protocol", ""):
+            board.manifest["upload"]["protocol"] = "uf2"
+        # debug tools
+        debug = board.manifest.get("debug", {})
+        non_debug_protocols   = [ "uf2" ]
+        supported_debug_tools = [ "cmsis-dap", "picoprobe", ]
+        upload_protocol  = board.manifest.get("upload", {}).get("protocol")
+        upload_protocols = board.manifest.get("upload", {}).get("protocols", [])
+        if debug:
+            upload_protocols.extend(supported_debug_tools)
+        if upload_protocol and upload_protocol not in upload_protocols:
+            upload_protocols.append(upload_protocol)
+        board.manifest["upload"]["protocols"] = upload_protocols
+        if "tools" not in debug:
+            debug["tools"] = {}
+
+        for link in upload_protocols:
+            if link in non_debug_protocols or link in debug["tools"]: continue
+            server_args = [
+                "-s", "$PACKAGE_DIR/share/openocd/scripts",
+                "-f", "interface/%s.cfg" % link,
+                "-f", "target/%s" % debug.get("openocd_target")
+            ]
+            
+            if link == "picoprobe":
+                init_cmds = [ ] # use pio default settings
+            else:
+                init_cmds = [
+                    "target extended-remote $DEBUG_PORT",
+                    "define pio_reset_halt_target",
+                    "end",
+                    "define pio_reset_run_target",
+                    "end"
+                ]
+
+            if link == 'picoprobe':
+                debug["tools"][link] = {
+                    "server": {
+                        "package"    : "tool-pico-openocd",
+                        "executable" : join(get_system(), "picoprobe"), # EXE
+                        "arguments"  : server_args,
+                    },
+                    "init_cmds"      : init_cmds,
+                    "onboard"        : link in debug.get("onboard_tools", []),
+                    "default"        : link == debug.get("default_tool"),
+                }                
+            else: # CMSIS-DAP
+                debug["tools"][link] = {
+                    "server": {
+                        "package"    : "tool-pico-openocd",
+                        "executable" : join(get_system(), "openocd_rp2040"), # EXE
+                        "arguments"  : server_args,
+                    },
+                    "init_cmds"      : init_cmds,
+                    "onboard"        : link in debug.get("onboard_tools", []),
+                    "default"        : link == debug.get("default_tool"),
+                }
+
+        board.manifest["debug"] = debug
+        return board
+
+    def configure_debug_options(self, initial_debug_options, ide_data):
+        """
+        Deprecated. Remove method when PlatformIO Core 5.2 is released
+        """
+        debug_options = copy.deepcopy(initial_debug_options)
+        if "cmsis-dap" in debug_options["tool"]:
+            debug_options["server"]["arguments"].extend( [
+                    "-c", "adapter speed %s" % (initial_debug_options.get("speed") or "20000"),
+                    "-c", "transport select swd"
+                ]
+            )
+        return debug_options