Seeed XIAO BLE

Posted on
  • Just wanted to mention that Seeed Studio put an NRF52840 in the XIAO form factor:

    https://www.seeedstudio.com/Seeed-XIAO-B­LE-nRF52840-p-5201.html

    Would be a good stopgap until we finally get an official MDBT50Q breakout with Espruino programmed in, if only it's in stock :P

  • ZigBee module ?

    this could be a game changer.
    how many ZigBee compatible MCUs are out there?

  • An Espruino build for this board would be really cool. The IMU is the same as in the Puck and there's also a flash chip!!
    As a Bangle.js 2 owner, I'm also very intrigued by the concept of having a file system on the SPI flash that can be accessed via BLE through the web IDE. This would enable really cool data logging options on the simpler, cheaper espruino boards.
    Is this hard to implement? You'd require some kind of simplified, stripped-down build of Bangle.js 2 or is there a simpler way?
    In this context I also thought about spinning my own Puck PCB with the MDBT42 and for example a GD25Q16 flash chip, since I have some laying around here.

  • The Storage module on external flash is independent of Bangle.js, so actually it should be pretty easy to get it running on the XIAO. The IMU isn't independent of Puck.js though, so I guess you'd have to make a modified Puck.js build for it - even so, it wouldn't be a huge deal

  • I have a build working based of the NRF52840DK.py and changing the console to bluetooth.

    Any thoughts or points on how to get the console going on the built in USB as a serial device?

    I have tried the 'EV_USBSERIAL' without any luck, is that working on any of the other nRF52840 boards?

  • yes, works for me on nrf52840 dongle and also Particle XENON, there is no special trick except this line https://gist.github.com/fanoush/c081c1d7­c8eb2a4562785bbb684f661e#file-nrf52840do­ngle-py-L43 which is in NRF52840DK board file too.

  • I finally got a couple of these and found the time to look into making a board file.

    #!/bin/false
    # This file is part of Espruino, a JavaScript interpreter for Microcontrollers
    #
    # Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
    #
    # This Source Code Form is subject to the terms of the Mozilla Public
    # License, v. 2.0. If a copy of the MPL was not distributed with this
    # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    #
    # ----------------------------------------­----------------------------------------­--------
    # This file contains information for a specific board - the available pins, and where LEDs,
    # Buttons, and other in-built peripherals are. It is used to build documentation as well
    # as various source and header files for Espruino.
    # ----------------------------------------­----------------------------------------­--------
    
    
    '''
    source ./scripts/provision.sh ALL
    rm bin/*.hex
    make clean && BOARD=XIAOBLE RELEASE=1 make
    uf2conv.py ./bin/*.hex -c -f 0xADA52840
    mv flash.uf2 ~/Desktop/
    '''
    
    import pinutils;
    
    info = {
      'name' : "Seeed Xiao BLE",
      'link' :  [ "https://www.seeedstudio.com/Seeed-XIAO-­BLE-nRF52840-p-5201.html" ],
      'default_console' : "EV_SERIAL1",
      'default_console_tx' : "D6",
      'default_console_rx' : "D7",
      'default_console_baudrate' : "9600",
      'variables' : 14000, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
      # 'bootloader' : 1,
      'binary_name' : 'espruino_%v_xiaoble.hex',
      'build' : {
        'optimizeflags' : '-Os',
        'libraries' : [
          'BLUETOOTH',
        #  'NET',
          'GRAPHICS',
        # 'NFC',
          'NEOPIXEL',
          'JIT',
        ],
        'makefile' : [
          'DEFINES += -DCONFIG_GPIO_AS_PINRESET', # Allow the reset pin to work
          'DEFINES += -DNRF_USB=1 -DUSB',
          'DEFINES += -DNEOPIXEL_SCK_PIN=33 -DNEOPIXEL_LRCK_PIN=34', # nRF52840 needs LRCK pin defined for neopixel
          'DEFINES += -DBLUETOOTH_NAME_PREFIX=\'"XIAOBLE"\'',
          'DEFINES += -DSPIFLASH_READ2X', # Read SPI flash at 2x speed using MISO and MOSI for IO
          'DEFINES += -DESPR_UNICODE_SUPPORT=1',
          'NRF_SDK15=1',
        ]
      }
    };
    
    
    chip = {
      'part' : "NRF52840",
      'family' : "NRF52",
      'package' : "AQFN73",
      'ram' : 256,
      'flash' : 1024,
      'speed' : 64,
      'usart' : 1,
      'spi' : 1,
      'i2c' : 2,
      'adc' : 1,
      'dac' : 0,
      'saved_code' : {
        'address' : ((0xf4 - 2 - 96) * 4096), # Bootloader at 0xF4000
        'page_size' : 4096,
        'pages' : 96,
        'flash_available' : 1024 - ((0x26 + 0x20 + 2 + 96)*4) # Softdevice 140 uses 38 pages of flash, bootloader 8, FS 2, code 10. Each page is 4 kb.
      },
    };
    
    devices = {
      'LED1' : { 'pin' : 'H0' }, # Pin negated in software
      'LED2' : { 'pin' : 'H1' }, # Pin negated in software
      'LED3' : { 'pin' : 'H2' }, # Pin negated in software
      # Pin D33 and D34 are used for clock when driving neopixels - as not specifying a pin seems to break things
    
      'SPIFLASH' : {
                'pin_cs' : 'H25',
                'pin_sck' : 'H21',
                'pin_mosi' : 'H20',
                'pin_miso' : 'H24',
                'pin_wp' : 'H22',
                'pin_rst' : 'H23',
                'size' : 4096*512, # 2MB
                'memmap_base' : 0x60000000 # map into the address space (in software)
              }
    };
    
    # left-right, or top-bottom order
    board = {
    };
    
    # schematic at https://files.seeedstudio.com/wiki/XIAO-­BLE/Seeed-Studio-XIAO-nRF52840-Sense-v1.­1.pdf
    def get_pins():
      pins = [
       { "name":"PD0",  "sortingname":"D00", "port":"D", "num":"2", "functions":{}, "csv":{} },
       { "name":"PD1",  "sortingname":"D01", "port":"D", "num":"3", "functions":{}, "csv":{} },
       { "name":"PD2",  "sortingname":"D02", "port":"D", "num":"28", "functions":{}, "csv":{} },
       { "name":"PD3",  "sortingname":"D03", "port":"D", "num":"29", "functions":{}, "csv":{} },
       { "name":"PD4",  "sortingname":"D04", "port":"D", "num":"4", "functions":{}, "csv":{} },
       { "name":"PD5",  "sortingname":"D05", "port":"D", "num":"5", "functions":{}, "csv":{} },
       { "name":"PD6",  "sortingname":"D06", "port":"D", "num":"43", "functions":{}, "csv":{} },
       { "name":"PD7",  "sortingname":"D07", "port":"D", "num":"44", "functions":{}, "csv":{} },
       { "name":"PD8",  "sortingname":"D08", "port":"D", "num":"45", "functions":{}, "csv":{} },
       { "name":"PD9",  "sortingname":"D09", "port":"D", "num":"46", "functions":{}, "csv":{} },
       { "name":"PD10", "sortingname":"D10", "port":"D", "num":"47", "functions":{}, "csv":{} },
    
       { "name":"PA0", "sortingname":"A00", "port":"A", "num":"2", "functions":{ "ADC1_IN0":0 }, "csv":{} },
       { "name":"PA1", "sortingname":"A01", "port":"A", "num":"3", "functions":{ "ADC1_IN1":0 }, "csv":{} },
       { "name":"PA2", "sortingname":"A02", "port":"A", "num":"28", "functions":{ "ADC1_IN2":0 }, "csv":{} },
       { "name":"PA3", "sortingname":"A03", "port":"A", "num":"29", "functions":{ "ADC1_IN3":0 }, "csv":{} },
       { "name":"PA4", "sortingname":"A04", "port":"A", "num":"4", "functions":{ "ADC1_IN4":0 }, "csv":{} },
       { "name":"PA5", "sortingname":"A05", "port":"A", "num":"5", "functions":{ "ADC1_IN5":0 }, "csv":{} },
    
       { "name":"PH0", "sortingname":"H0", "port":"H", "num":"26", "functions":{"NEGATED":0}, "csv":{} }, # LED1
       { "name":"PH1", "sortingname":"H1", "port":"H", "num":"30", "functions":{"NEGATED":0}, "csv":{} }, # LED2
       { "name":"PH2", "sortingname":"H2", "port":"H", "num":"6", "functions":{"NEGATED":0}, "csv":{} }, # LED3
    
       { "name":"PH25", "sortingname":"H25", "port":"H", "num":"25", "functions":{}, "csv":{} },
       { "name":"PH21", "sortingname":"H21", "port":"H", "num":"21", "functions":{}, "csv":{} },
       { "name":"PH20", "sortingname":"H20", "port":"H", "num":"20", "functions":{}, "csv":{} },
       { "name":"PH24", "sortingname":"H24", "port":"H", "num":"24", "functions":{}, "csv":{} },
       { "name":"PH22", "sortingname":"H22", "port":"H", "num":"22", "functions":{}, "csv":{} },
       { "name":"PH23", "sortingname":"H23", "port":"H", "num":"23", "functions":{}, "csv":{} },
      ];
    
      # everything is non-5v tolerant
      for pin in pins:
        pin["functions"]["3.3"]=0;
      return pins
    

    not all pin assignments are implemented yet (especially on the sense version the IMU and the mic) but everything works so far. The QSPI flash is also connected although I'm not really sure how to test if the entirety of the flash is usable.

    It's also compatible with the built-in adafruit bootloader, so if you use the u2conv.py script you can create a uf2 file you can just drag and drop onto the xiao ble to flash espruino on it (no need for SWD).


    1 Attachment

  • Update: I also just tested out EV_USBSERIAL as mentioned by fanoush above, and it works well on the Web IDE (you'll need to choose Web Serial and look for the nRF CDC serial device).

    Although I really still prefer the wireless BT console :P

  • Those H pins are quite unusual for nrf52, but if they work for you ...
    nrf52 uses just Dnum as all pins except analog are universal, there are no letter named ports like on stm32.

  • Ah I didn't know that was the case :D I thought H was just a way to differentiate unexposed pins (vs D which are exposed).

    They do work though, and I guess it's somewhat an advantage that a user doesn't get to accidentally configure a pin that they're not supposed to change (like those for QSPI for example). Or would there be any issues with using non-existent ports?

  • I've experimented a bit more and yeah, the extra H port is messing up some of the pins that Espruino expects are contiguous.

    I"ve since made a board def that's a lot simpler.

    #!/bin/false
    # This file is part of Espruino, a JavaScript interpreter for Microcontrollers
    #
    # Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
    #
    # This Source Code Form is subject to the terms of the Mozilla Public
    # License, v. 2.0. If a copy of the MPL was not distributed with this
    # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    #
    # ----------------------------------------­----------------------------------------­--------
    # This file contains information for a specific board - the available pins, and where LEDs,
    # Buttons, and other in-built peripherals are. It is used to build documentation as well
    # as various source and header files for Espruino.
    # ----------------------------------------­----------------------------------------­--------
    
    
    """
    source ./scripts/provision.sh ALL
    rm bin/*.hex
    make clean && BOARD=XIAOBLE RELEASE=1 make
    uf2conv.py ./bin/*.hex -c -f 0xADA52840
    mv flash.uf2 ~/Desktop/
    """
    
    import pinutils
    
    info = {
        "name": "Seeed Xiao BLE",
        "link": ["https://www.seeedstudio.com/Seeed-XIAO­-BLE-nRF52840-p-5201.html"],
        "default_console": "EV_USBSERIAL",
        # 'default_console' : "EV_SERIAL1",
        # 'default_console_tx' : "D6",
        # 'default_console_rx' : "D7",
        # 'default_console_baudrate' : "9600",
        "variables": 14000,  # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
        # 'bootloader' : 1,
        "binary_name": "espruino_%v_xiaoble.hex",
        "build": {
            "optimizeflags": "-Os",
            "libraries": [
                "BLUETOOTH",
                #  'NET',
                "GRAPHICS",
                # 'NFC',
                "NEOPIXEL",
                "JIT",
            ],
            "makefile": [
                "DEFINES += -DESPR_LSE_ENABLE",  # Ensure low speed external osc enabled
                "DEFINES += -DCONFIG_GPIO_AS_PINRESET",  # Allow the reset pin to work
                "DEFINES += -DNRF_USB=1 -DUSB",
                "DEFINES += -DNEOPIXEL_SCK_PIN=33 -DNEOPIXEL_LRCK_PIN=34",  # nRF52840 needs LRCK pin defined for neopixel
                "DEFINES += -DBLUETOOTH_NAME_PREFIX='\"XIAOBLE\"'",
                "DEFINES += -DSPIFLASH_READ2X",  # Read SPI flash at 2x speed using MISO and MOSI for IO
                "DEFINES += -DESPR_UNICODE_SUPPORT=1",
                "DEFINES += -DNRF_SDH_BLE_GATT_MAX_MTU_SIZE=131",  # 23+x*27 rule as per https://devzone.nordicsemi.com/f/nordic-­q-a/44825/ios-mtu-size-why-only-185-byte­s
                # 'DEFINES += -DPIN_NAMES_DIRECT=1', # Package skips out some pins, so we can't assume each port starts from 0
                "LDFLAGS += -Xlinker --defsym=LD_APP_RAM_BASE=0x2ec0",  # set RAM base to match MTU
                "NRF_SDK15=1",
            ],
        },
    }
    
    
    chip = {
        "part": "NRF52840",
        "family": "NRF52",
        "package": "AQFN73",
        "ram": 256,
        "flash": 1024,
        "speed": 64,
        "usart": 1,
        "spi": 1,
        "i2c": 2,
        "adc": 1,
        "dac": 0,
        "saved_code": {
            "address": ((0xF4 - 2 - 96) * 4096),  # Bootloader at 0xF4000
            "page_size": 4096,
            "pages": 96,
            "flash_available": 1024
            - (
                (0x26 + 0x20 + 2 + 96) * 4
            ),  # Softdevice 140 uses 38 pages of flash, bootloader 8, FS 2, code 10. Each page is 4 kb.
        },
    }
    
    devices = {
        "LED1": {"pin": "D26"},  # Pin negated in software
        "LED2": {"pin": "D30"},  # Pin negated in software
        "LED3": {"pin": "D6"},  # Pin negated in software
        # Pin D33 and D34 are used for clock when driving neopixels - as not specifying a pin seems to break things
        "BAT": {
            "pin_charging": "D17",  # active low
            "pin_voltage": "D31",
        },
        "NFC": {"pin_a": "D9", "pin_b": "D10"},
        "SPIFLASH": {
            "pin_cs": "D25",
            "pin_sck": "D21",
            "pin_mosi": "D20",
            "pin_miso": "D24",
            "pin_wp": "D22",
            "pin_rst": "D23",
            "size": 4096 * 512,  # 2MB
            "memmap_base": 0x60000000,  # map into the address space (in software)
        },
    }
    
    # left-right, or top-bottom order
    board = {}
    
    
    # schematic at https://files.seeedstudio.com/wiki/XIAO-­BLE/Seeed-Studio-XIAO-nRF52840-Sense-v1.­1.pdf
    # pinout sheet https://files.seeedstudio.com/wiki/XIAO-­BLE/XIAO-nRF52840-pinout_sheet.xlsx
    # see also https://github.com/Seeed-Studio/Adafruit­_nRF52_Arduino/blob/master/variants/Seee­d_XIAO_nRF52840/variant.h
    def get_pins():
        pins = pinutils.generate_pins(0, 47)  # 48 General Purpose I/O Pins.
        pinutils.findpin(pins, "PD2", True)["functions"]["ADC1_IN0"] = 0
        pinutils.findpin(pins, "PD3", True)["functions"]["ADC1_IN1"] = 0
        pinutils.findpin(pins, "PD4", True)["functions"]["ADC1_IN2"] = 0
        pinutils.findpin(pins, "PD5", True)["functions"]["ADC1_IN3"] = 0
        pinutils.findpin(pins, "PD9", True)["functions"]["NFC1"] = 0
        pinutils.findpin(pins, "PD10", True)["functions"]["NFC2"] = 0
        pinutils.findpin(pins, "PD17", True)["functions"]["NEGATED"] = 0
        pinutils.findpin(pins, "PD26", True)["functions"]["NEGATED"]=0;
        pinutils.findpin(pins, "PD28", True)["functions"]["ADC1_IN4"] = 0
        pinutils.findpin(pins, "PD29", True)["functions"]["ADC1_IN5"] = 0
        pinutils.findpin(pins, "PD31", True)["functions"]["ADC1_IN7"] = 0
    
    
        # D13 PIN_CHARGING_CURRENT
        # battery charging current see https://wiki.seeedstudio.com/XIAO_BLE/#b­attery-charging-current
        # HIGH: 100mA, LOW: 50mA
    
        # D14 VBAT_ENABLE
        # enable battery voltage reading by digitalWrite(D14, false)
    
        # D17 CHG
        # get charge state via digitalRead(D17)
        # HIGHT: not charging, LOW: charging
    
        # D31 PIN_VBAT
    
        # everything is non-5v tolerant
        for pin in pins:
            pin["functions"]["3.3"] = 0
        return pins
    

    1 Attachment

  • I've just started playing with one of these - and this works well, I'm running over the Bluetooth serial console, and the upload as uf2 is nice and fast.
    I've connected it with a Seeed Round display before I dig too far, I wondered if anyone else had used this combo already.
    I got (slightly) excited when I saw that the screen controller GC9A01 was in the codebase, but (I think) it's only compiled into the jswrap_bangle.c file and not available to a base Espruino build as a js module, and I couldn't see a compatible module already to use.
    I did briefly try a tweaked bangle build, but unsurprisingly, that just created a screen of random garbage and appeared to freeze on boot so decided to leave that for now, although I think that might be just because I'm still using the AdaFruit uf2 bootloader and I should switch to the full bangle build.

    So, before I go any further, just wanted to ask/see if anyone had done this combination already - I assume I just need to create a new js module probably based on https://www.espruino.com/modules/ST7789.­js

    I was planning on printing a custom case and hooking up two buttons to the NFC pins so I think this would work pretty well with a bangle build.

  • brilliant @fanoush thanks, that's a great starting point... still no picture but getting there.

  • Great, progress. Thanks. Right, next to get some programs up and running.


    1 Attachment

    • 20240903_195924.jpg
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Seeed XIAO BLE

Posted by Avatar for parasquid @parasquid

Actions