Silabs' new Pull Request for submoduling the ports/silabs/tools/slc_cli_linux/ (#7874)

Doing a squash merge to avoid having the `slc_cli_linux` .zip files in the history. They were added in one commit and removed and replaced with a submodule in another.

* Initial commit for xg24

* Fix SLC issue

* Fix SLC extract fail

* Change board's name

* Correct spelling of code

Build immediately after slc generate

* Remove VID and PID

* Change creator and creation id

* Apply new creator_id and creation_id

* Update makefile, error message, mcu_processor function

* Update mpconfigboard.mk

* Update Board extensions, PORT_DEPS

* Update makefile

* Add exclude_patterns

* Show java, jinja2 version

* Show path for debugging CI

* Add requirements-dev for slc

* Add PATH slc_cli

* Update background function

* Add jinja2 PATH

* Show PATH

* Update jinja2 path

* Update jinja2 path

* Update jinja2 path

* Update jinja2 path

* Change slc folder

* Change markupsafe folder

* Add symbolic link for slc

* Update makefile

* Update makefile

* Update MX25R3235F.toml from submodule nvm.toml

* alphabetize the list

* Remove slc_cli_linux folder

* Update slc_cli submodule

---------

Co-authored-by: Chat Nguyen <cvnguyen@silabs.com>
Co-authored-by: silabs-ChatNguyen <chat.nguyen@silabs.com>
Co-authored-by: silabs-ChatNguyen <126220343+silabs-ChatNguyen@users.noreply.github.com>
This commit is contained in:
silabs-BelaV 2023-04-18 18:42:16 +02:00 committed by GitHub
parent ebfde5c3fa
commit 4e25a4f6b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
114 changed files with 9239 additions and 1 deletions

7
.gitmodules vendored
View File

@ -324,3 +324,10 @@
path = ports/broadcom/peripherals
url = https://github.com/adafruit/broadcom-peripherals.git
branch = main-build
[submodule "ports/silabs/gecko_sdk"]
path = ports/silabs/gecko_sdk
url = https://github.com/SiliconLabs/gecko_sdk.git
branch = v4.2.1
[submodule "ports/silabs/tools/slc_cli_linux"]
path = ports/silabs/tools/slc_cli_linux
url = https://github.com/SiliconLabs/circuitpython_slc_cli_linux

View File

@ -216,6 +216,7 @@ exclude_patterns = ["**/build*",
"ports/nrf/usb",
"ports/raspberrypi/sdk",
"ports/raspberrypi/lib",
"ports/silabs",
"ports/stm/st_driver",
"ports/stm/packages",
"ports/stm/peripherals",

@ -1 +1 @@
Subproject commit 73fafcbe4c66b23df63be31e9227353b695abb08
Subproject commit 427cc923976229bcb981ca6f218ebe8efd636df6

View File

@ -40,6 +40,7 @@ SUPPORTED_PORTS = [
"mimxrt10xx",
"nrf",
"raspberrypi",
"silabs",
"stm",
]

214
ports/silabs/Makefile Normal file
View File

@ -0,0 +1,214 @@
# This file is part of Adafruit for EFR32 project
#
# The MIT License (MIT)
#
# Copyright 2023 Silicon Laboratories Inc. www.silabs.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
.SUFFIXES: # ignore builtin rules
.PHONY: all clean slc-clean slc-generate dependents
# Values set by the initial generation
PROJECTNAME = circuitpython_efr32
# If the build directory is not given, make it reflect the board name.
SILABS_BUILD = build-$(BOARD)
# Build dir for CircuitPython
BUILD ?= $(SILABS_BUILD)
# Override Build Directories
OUTPUT_DIR = $(SILABS_BUILD)
# Python script to generate pins and pins functionalities code
PY_GEN_PINS_SRC ?= tools/make_pins.py
# SLC tool path
SLC_PATH = $(realpath $(CURDIR))/tools/slc_cli_linux
BUILD_VERBOSE ?= 1
CFLAGS = $(INCLUDES) $(C_DEFS) $(C_FLAGS) \
-Wno-expansion-to-defined \
-Wno-unused-parameter \
-Wno-missing-field-initializers \
-Wno-type-limits
ASMFLAGS = $(INCLUDES) $(ASM_DEFS) $(ASM_FLAGS) $(DEPFLAGS)
include ../../py/circuitpy_mkenv.mk
CROSS_COMPILE = arm-none-eabi-
MCU_SERIES_LOWER = $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]')
MCU_VARIANT_LOWER = $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]')
# Header files folders include
INC += -I.
INC += -I../..
INC += -I$(BUILD)
INC += -I$(BUILD)/genhdr
INC += -I$(SILABS_BUILD)/autogen
INC += -I$(SILABS_BUILD)/config
INC += -I./boards
INC += -I./peripherals
INC += -I../../lib/mp-readline
#Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -g3
# You may want to enable these flags to make setting breakpoints easier.
CFLAGS += -fno-inline -fno-ipa-sra -Og
else
CFLAGS += -DNDEBUG
OPTIMIZATION_FLAGS ?= -Os -fno-inline-functions
CFLAGS += -g
endif
# to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
CFLAGS += $(OPTIMIZATION_FLAGS)
CFLAGS += $(INC) $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT)
CFLAGS += -DEFR32_SERIES_LOWER='"$(MCU_VARIANT)"'
CFLAGS += -Wno-undef -Wno-shadow -Wno-cast-align -Wno-nested-externs -Wno-strict-prototypes
SRC_C += \
background.c \
mphalport.c \
$(SILABS_BUILD)/pins.c\
ifeq ('$(BOARD)','brd2601b')
SRC_C += boards/$(BOARD)/sensor.c
endif
SRC_S = boards/mp_efr32xg24_gchelper.s
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
$(addprefix common-hal/, $(SRC_COMMON_HAL))
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
$(addprefix shared-module/, $(SRC_SHARED_MODULE)) \
$(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL))
# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED,
# because a few modules have files both in common-hal/ and shared-module/.
# Doing a $(sort ...) removes duplicates as part of sorting.
SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED))
ifneq ($(FROZEN_MPY_DIR),)
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
endif
OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o))
ifeq ($(INTERNAL_LIBM),1)
OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o))
endif
OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
$(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os
$(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os
# List of sources for qstr extraction
SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)
# Sources that only hold QSTRs after pre-processing.
SRC_QSTR_PREPROCESSOR +=
MCU_SECTIONS = $^ $@
# Include sub-makefiles
-include $(SILABS_BUILD)/$(PROJECTNAME).project.mak
# Default goal
all: $(OUTPUT_DIR)/firmware.bin
$(OUTPUT_DIR)/firmware.bin: $(SILABS_BUILD)/$(PROJECTNAME).Makefile $(OUTPUT_DIR)/firmware.hex
+@$(MAKE) --no-print-directory $(OUTPUT_DIR)/firmware.out
@echo 'Done.'
$(SILABS_BUILD)/$(PROJECTNAME).Makefile:
+@$(MAKE) --no-print-directory slc-generate
$(OUTPUT_DIR)/firmware.out: $(SILABS_BUILD)/pin_functions.h $(SILABS_BUILD)/pins.c $(OBJ) $(OBJS) $(LIB_FILES)
@echo 'Linking $(OUTPUT_DIR)/firmware.out'
@echo "$(OBJS) $(OBJ)" > $(OUTPUT_DIR)/linker_objs
$(CC) $(LD_FLAGS) @$(OUTPUT_DIR)/linker_objs $(LIBS) -o $(OUTPUT_DIR)/firmware.out
$(OBJCOPY) $(OUTPUT_DIR)/firmware.out -O binary $(OUTPUT_DIR)/firmware.bin
$(OUTPUT_DIR)/firmware.hex:
$(SILABS_BUILD)/pin_functions.h:
$(STEPECHO) "GEN $@"
$(Q)$(PYTHON) $(PY_GEN_PINS_SRC) -e $@ boards/$(BOARD)/pins.csv boards/$(BOARD)/pin_functions.csv
@-$(RM) pins.c
$(SILABS_BUILD)/pins.c:
$(STEPECHO) "GEN $@"
$(Q)$(PYTHON) $(PY_GEN_PINS_SRC) -s $@ boards/$(BOARD)/pins.csv boards/$(BOARD)/pin_functions.csv
@-$(RM) pin_functions.h
slc-generate:
ifeq (,$(wildcard $(SLC_PATH)/bin/slc-cli/developer/adapter_packs/python/lib/python3.6/jinja2))
-@ln -s $(SLC_PATH)/bin/slc-cli/developer/adapter_packs/python/lib/python3.6/site-packages/jinja2 \
$(SLC_PATH)/bin/slc-cli/developer/adapter_packs/python/lib/python3.6/jinja2
-@ln -s $(SLC_PATH)/bin/slc-cli/developer/adapter_packs/python/lib/python3.6/site-packages/markupsafe \
$(SLC_PATH)/bin/slc-cli/developer/adapter_packs/python/lib/python3.6/markupsafe
endif
@echo 'SLC generates project'
@$(SLC_PATH)/slc configuration --sdk gecko_sdk
@$(SLC_PATH)/slc signature trust -extpath cp_efr32_extension
@$(SLC_PATH)/slc signature trust --sdk gecko_sdk
@$(SLC_PATH)/slc generate -name=$(PROJECTNAME) $(PROJECTNAME).slcp --sdk gecko_sdk --with $(BOARD_BRD) -tlcn gcc -d=$(SILABS_BUILD)
@sed -i 's/ autogen\// $(SILABS_BUILD)\/autogen\//g' $(SILABS_BUILD)/circuitpython_efr32.project.mak
@sed -i 's/-T"autogen\//-T"$(SILABS_BUILD)\/autogen\//g' $(SILABS_BUILD)/circuitpython_efr32.project.mak
#Override ECHO
$(OBJS): ECHO =
$(OBJS):
$(OUTPUT_DIR)/%.o: %.c
@echo 'Building $<'
@$(MKDIR_P) $(@D)
$(ECHO)$(CC) $(CFLAGS) -c -o $@ $<
$(OUTPUT_DIR)/%.o: %.cpp
@echo 'Building $<'
@$(MKDIR_P) $(@D)
$(ECHO)$(CXX) $(CXXFLAGS) -c -o $@ $<
$(OUTPUT_DIR)/%.o: %.cc
@echo 'Building $<'
@$(MKDIR_P) $(@D)
$(ECHO)$(CXX) $(CXXFLAGS) -c -o $@ $<
$(OUTPUT_DIR)/%.o: %.s
@echo 'Building $<'
@$(MKDIR_P) $(@D)
$(ECHO)$(CC) $(ASMFLAGS) -c -o $@ $<
$(OUTPUT_DIR)/%.o: %.S
@echo 'Building $<'
@$(MKDIR_P) $(@D)
$(ECHO)$(CC) $(ASMFLAGS) -c -o $@ $<
include $(TOP)/py/mkrules.mk
# Print out the value of a make variable.
# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile
print-%:
@echo $* = $($*)

132
ports/silabs/README.md Normal file
View File

@ -0,0 +1,132 @@
# Circuitpython on EFR32 #
![GitHub](https://img.shields.io/badge/Technology-Bluetooth_BLE-green)
![GitHub](https://img.shields.io/badge/CircuitPython-8.1.0--beta.0-green)
![GitHub](https://img.shields.io/badge/GSDK-v4.2.1-green)
![GitHub](https://img.shields.io/badge/SLC-5.6.3.0-green)
![GitHub](https://img.shields.io/badge/License-MIT-green)
![GitHub](https://img.shields.io/badge/GCC_build-passing-green)
This port brings the Silicon Labs EFR32 series of MCUs to Circuitpython.
Refer to **mpconfigport.mk** for a full list of enabled modules sorted by family.
## How this port is organized: ##
- **boards/** contains the configuration files for each development board and breakout available on the port, as well as system files and both shared and SoC-specific linker files. Board configuration includes a pin mapping of the board, oscillator information, board-specific build flags, and setup for some other peripheral where applicable.
- **common-hal/** contains the port-specific module implementations, used by shared-module and shared-bindings.
- **peripherals/** contains peripheral setup files and peripheral mapping information, sorted by family and sub-variant. Most files in this directory can be generated with the python scripts in **tools/**.
- **supervisor/** contains port-specific implementations of internal flash and serial, as well as the **port.c** file, which initializes the port at startup.
- **tools/** contains Silicon Labs configurator (SLC) tool, python scripts for generating peripheral and pin mapping files in **peripherals/** and **board/**.
At the root level, refer to **mpconfigboard.h** and **mpconfigport.mk** for port specific settings and a list of enabled modules.
## Prerequisites ##
Please ensure you set up your build environment appropriately, as per the guide. You will need:
- Linux: https://learn.adafruit.com/building-circuitpython/linux
- Windows Subsystem for Linux (WSL): https://learn.adafruit.com/building-circuitpython/windows-subsystem-for-linux
- MacOS: Not supported yet
Install necessary packages
$ sudo apt install default-jre gcc-arm-none-eabi wget python3 python3-pip git git-lfs gettext uncrustify
$ sudo python -m pip install --upgrade pip
## Board supported ##
| Board | Code | Build CMD |
| --------------------------- | ------------ | ------------------------------------------ |
| xG24 Dev Kit | brd2601b | devkit_xg24_brd2601b |
| xG24 Explorer Kit | brd2703a | explorerkit_xg24_brd2703a |
| Sparkfun Thing Plus MGM240P | brd2704a | sparkfun_thingplus_matter_mgm240p_brd2704a |
## Build instructions ##
Ensure your clone of Circuitpython is ready to build by following the [guide on the Adafruit Website](https://learn.adafruit.com/building-circuitpython/build-circuitpython). This includes installing the toolchain, synchronizing submodules, and running `mpy-cross`.
Clone the source code of CircuitPython from Github:
$ git clone https://github.com/SiliconLabs/circuitpython.git
$ cd circuitpython
$ make fetch-submodules
Checkout the branch or tag you want to build. For example:
$ git checkout main
Following the guideline below to install required packages for SLC tool:
https://www.silabs.com/documents/public/user-guides/ug520-software-project-generation-configuration-with-slc-cli.pdf
Once the one-time build tasks are complete, you can build at any time by navigating to the port directory:
$ make BOARD=explorerkit_xg24_brd2703a
You may also build with certain flags available in the makefile, depending on your board and development goals:
$ make BOARD=explorerkit_xg24_brd2703a DEBUG=1
Clean project by using:
$ make BOARD=explorerkit_xg24_brd2703a clean
## Bring-up on the board ##
### Getting a REPL prompt ###
Connect the devkit to the PC via the USB cable. The board usesserial for REPL access and debugging because the EFR32 chips has no USB support.
#### Windows ####
On Windows, we need to install a serial console e.g., PuTTY, MobaXterm. The JLink CDC UART Port can be found in the DeviceManager.
#### Linux ####
Open a terminal and issue the following command:
$ ls /dev/ttyACM*
Then note down the correct name and substitutecom-port-namein the following command with it:
$ screen /dev/'com-port-name'
### Using the REPL prompt ###
After flashing the firmware to the board, at your first connecting to the board, you might see a blank screen. Press enter and you should be presented with a Circuitpython prompt,>>>. If not, try to reset the board (see instructions below).
You can now type in simple commands such as:
```sh
>>> print("Hello world!")
Hello world
```
If something goes wrong with the board, you can reset it. Pressing CTRL+D when the prompt is open performs a soft reset.
### Recommended editors ###
**Thonny** is a simple code editor that works with the Adafruit CircuitPython boards.
Config serial: Tools > Options > Interpreter > Select MicroPython > Select Port Jlink CDC UART Port
### Running CircuitPython scripts ###
At the boot stage, two scripts will be run (if not booting in safe mode). First, the file boot.py will be executed.The file **boot.py** can be used to perform the initial setup. Then, afterboot.pyhas been completed, the file**code.py** will be executed.
Aftercode.pyhas finished executing, a REPL prompt will be presented on the serial port. Other files can also be executed by using the **Thonny** editors or using **Ampy** tool.
![Thony](./res/Thony.png)
With the boards which support USB mass storage, we can drag the files to the board file system. However, because the EFR32 boards dont support USB mass storage, we need to use a tool like **Ampy** to copy the file to the board. You can use the latest version of **Ampy** and its commandto copy the module directories to the board.
Refer to the guideline below for installing the **Ampy** tool:
https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy
## Modules supported ##
| Board | Modules Available|
| --------------------------- | ---------------- |
| xG24 Dev Kit | _asyncio, _bleio, _pixelmap, adafruit_ble, adafruit_bus_device, adafruit_pixelbuf, adafruit_register, aesio,analogio, array, atexit, binascii, bitmaptools, board, builtins, busio, collections, digitalio, displayio,errno, fontio, framebufferio, gc, getpass, gifio, json, math, microcontroller, micropython, msgpack, nvm, onewireio, os, pwmio, rainbowio, random, re, rtc, select, sharpdisplay, storage, struct, supervisor, sys, terminalio, time, traceback, ulab, uselect, vectorio, watchdog, zlib |
| xG24 Explorer Kit | _asyncio, _bleio, _pixelmap, adafruit_ble, adafruit_bus_device, adafruit_pixelbuf, adafruit_register, aesio,analogio, array, atexit, binascii, bitmaptools, board, builtins, busio, collections, digitalio, displayio,errno, fontio, framebufferio, gc, getpass, gifio, json, math, microcontroller, micropython, msgpack, nvm, onewireio, os, pwmio, rainbowio, random, re, rtc, sdcardio, select, sharpdisplay, storage, struct, supervisor, sys, terminalio, time, traceback, ulab, uselect, vectorio, watchdog, zlib |
| Sparkfun Thing Plus MGM240P | _asyncio, _bleio, _pixelmap, adafruit_ble, adafruit_bus_device, adafruit_pixelbuf, adafruit_register, aesio,analogio, array, atexit, binascii, bitmaptools, board, builtins, busio, collections, digitalio, displayio,errno, fontio, framebufferio, gc, getpass, gifio, json, math, microcontroller, micropython, msgpack, nvm, onewireio, os, pwmio, rainbowio, random, re, rtc, sdcardio, select, sharpdisplay, storage, struct, supervisor, sys, terminalio, time, traceback, ulab, uselect, vectorio, watchdog, zlib |

50
ports/silabs/background.c Normal file
View File

@ -0,0 +1,50 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "supervisor/filesystem.h"
#include "supervisor/usb.h"
#include "supervisor/shared/stack.h"
#include "FreeRTOS.h"
#include "task.h"
#if CIRCUITPY_DISPLAYIO
#include "shared-module/displayio/__init__.h"
#endif
void port_background_tick(void) {
// Zero delay in case FreeRTOS wants to switch to something else
vTaskDelay(0);
}
void port_background_task(void) {
}
void port_start_background_tick(void) {
}
void port_finish_background_tick(void) {
}

30
ports/silabs/background.h Normal file
View File

@ -0,0 +1,30 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_BACKGROUND_H
#define MICROPY_INCLUDED_EFR32_BACKGROUND_H
#endif // MICROPY_INCLUDED_EFR32_BACKGROUND_H

View File

@ -0,0 +1,28 @@
## Gen Pin instructions ##
# Input File
pins.csv : contain pin name, port number ,pin number
pin_functions.csv : contain list of pin support for peripheral
make_pins.py : python script to gen pin
# Run make_pins.py
Copy above input file to folder boards/brd2601b/
Run CMD:
$ cd boards/brd2601b/
$ python make_pins.py -s pins.c -e pin_functions.h pins.csv pin_functions.csv
-s: name/directory of output source file
-e: name/directory of output header file
# Output
pins.c : register pin to board_module_globals_table
generate array contains supported function of pin
pin_functions.h : define index of functions
Example: pin_pa0_functions[FN_EUSART0_RX] == 1 // Can assign pin pa0 for EUSART0_RX
pin_pa0_functions[FN_EUSART0_RX] == 255 // Can't assign pin pa0 for EUSART0_RX
# Read pin define on REPL
import board
dir(board)

View File

@ -0,0 +1,29 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View File

@ -0,0 +1,27 @@
id: custom_brd2601b_cp_support
label: CircuitPython BRD2601B support
description: >
CircuitPython Board support for BRD2601B.
package: custom
category: Custom
quality: production
root_path: ../boards/devkit_xg24_brd2601b
include:
- path: ''
file_list:
- path: mpconfigboard.h
source:
- path: board.c
provides:
- name: custom_brd2601b_cp_support
requires:
- name: efr32mg24b310f1536im48
- name: sensor_pressure
- name: sensor_hall
- name: sensor_imu
- name: sensor_rht
- name: sensor_lux
recommends:
- id: sensor_rht
- id: sensor_lux
- id: bt_rail_compatibility_fix

View File

@ -0,0 +1,55 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "build-devkit_xg24_brd2601b/pin_functions.h"
// Micropython setup
#define MICROPY_HW_BOARD_NAME "SiLabs xG24 Dev Kit"
#define MICROPY_HW_MCU_NAME EFR32_SERIES_LOWER
#define HSE_VALUE ((uint32_t)8000000)
#define BOARD_HSE_SOURCE (RCC_HSE_BYPASS)
#define BOARD_HAS_LOW_SPEED_CRYSTAL (0)
// On-board flash
#define SPI_FLASH_MOSI_PIN (&pin_PC3)
#define SPI_FLASH_MISO_PIN (&pin_PC2)
#define SPI_FLASH_SCK_PIN (&pin_PC1)
#define SPI_FLASH_CS_PIN (&pin_PC0)
#define DEFAULT_I2C_BUS_SDA (&pin_PC5)
#define DEFAULT_I2C_BUS_SCL (&pin_PC4)
#define DEFAULT_I2C_PERIPHERAL I2C1
#define DEFAULT_SPI_BUS_SCK (&pin_PC1)
#define DEFAULT_SPI_BUS_MOSI (&pin_PC3)
#define DEFAULT_SPI_BUS_MISO (&pin_PC2)
#define DEFAULT_SPI_BUS_SS (&pin_PA7)
#define NVM_BYTEARRAY_BUFFER_SIZE 512
#define CIRCUITPY_INTERNAL_NVM_SIZE (512)
#undef MICROPY_USE_INTERNAL_PRINTF
#define MICROPY_USE_INTERNAL_PRINTF (0)

View File

@ -0,0 +1,17 @@
BOARD_BRD = brd2601b
INTERNAL_FLASH_FILESYSTEM = 0
QSPI_FLASH_FILESYSTEM = 0
SPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICES = MX25R3235F
MCU_SERIES = MG24
MCU_VARIANT = EFR32MG24B310F1536IM48
CIRCUITPY_USB = 0
CIRCUITPY_CREATOR_ID = 0x19960000
CIRCUITPY_CREATION_ID = 0x00242601
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BLE
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register

View File

@ -0,0 +1,35 @@
EUSART0_CS,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
EUSART0_RX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
EUSART0_SCLK,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
EUSART0_TX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
EUSART1_CS,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
EUSART1_RX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
EUSART1_SCLK,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
EUSART1_TX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
I2C0_SCL,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
I2C0_SDA,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
I2C1_SCL,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
I2C1_SDA,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER0_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER0_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER0_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER1_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER1_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER1_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER2_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
TIMER2_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
TIMER2_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
TIMER3_CC0,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER3_CC1,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER3_CC2,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
TIMER4_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
TIMER4_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
TIMER4_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,,,,,,,,,,,,,,
USART0_CLK,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
USART0_CS,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
USART0_RX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
USART0_TX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PC0,PC1,PC2,PC3,PC4,PC5,PC9,PD2,PD3,PD4,PD5,,,
VDAC0_CH0,,,,,,PB0,,,,,,,,,,,,,,,,,
VDAC0_CH1,,,,,,,PB1,,,,,,,,,,,,,,,,
VDAC1_CH0,,,,,,,,PB2,,,,,,,,,,,,,,,
VDAC1_CH1,,,,,,,,,PB3,,,,,,,,,,,,,,
1 EUSART0_CS PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
2 EUSART0_RX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
3 EUSART0_SCLK PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
4 EUSART0_TX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
5 EUSART1_CS PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
6 EUSART1_RX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
7 EUSART1_SCLK PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
8 EUSART1_TX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
9 I2C0_SCL PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
10 I2C0_SDA PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
11 I2C1_SCL PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
12 I2C1_SDA PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
13 TIMER0_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
14 TIMER0_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
15 TIMER0_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
16 TIMER1_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
17 TIMER1_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
18 TIMER1_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
19 TIMER2_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
20 TIMER2_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
21 TIMER2_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
22 TIMER3_CC0 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
23 TIMER3_CC1 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
24 TIMER3_CC2 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
25 TIMER4_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
26 TIMER4_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
27 TIMER4_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3
28 USART0_CLK PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
29 USART0_CS PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
30 USART0_RX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
31 USART0_TX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PC0 PC1 PC2 PC3 PC4 PC5 PC9 PD2 PD3 PD4 PD5
32 VDAC0_CH0 PB0
33 VDAC0_CH1 PB1
34 VDAC1_CH0 PB2
35 VDAC1_CH1 PB3

View File

@ -0,0 +1,21 @@
mcu_name, board_name,port ,pin
PA0,,0,0
PA4,LEDG,0,4
PA5,TX,0,5
PA6,RX,0,6
PA7,CS,0,7
PB0,LEDB,1,0
PB1,,1,1
PB2,BTN0,1,2
PB3,BTN1,1,3
PC0,FLASH_CS,2,0
PC1,SCLK,2,1
PC2,CIPO,2,2
PC3,COPI,2,3
PC4,SCL,2,4
PC5,SDA,2,5
PC9,SENSOR_CS,2,9
PD2,LEDR,3,2
PD3,,3,3
PD4,,3,4
PD5,,3,5
1 mcu_name board_name port pin
2 PA0 0 0
3 PA4 LEDG 0 4
4 PA5 TX 0 5
5 PA6 RX 0 6
6 PA7 CS 0 7
7 PB0 LEDB 1 0
8 PB1 1 1
9 PB2 BTN0 1 2
10 PB3 BTN1 1 3
11 PC0 FLASH_CS 2 0
12 PC1 SCLK 2 1
13 PC2 CIPO 2 2
14 PC3 COPI 2 3
15 PC4 SCL 2 4
16 PC5 SDA 2 5
17 PC9 SENSOR_CS 2 9
18 PD2 LEDR 3 2
19 PD3 3 3
20 PD4 3 4
21 PD5 3 5

View File

@ -0,0 +1,214 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "common-hal/busio/I2C.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/translate/translate.h"
#include "em_i2c.h"
#include "sl_i2cspm.h"
#include "sl_i2cspm_sensor_config.h"
#include "sl_sensor_lux.h"
#include "sl_sensor_rht.h"
#include "sl_sensor_imu.h"
#include "sl_sensor_hall.h"
#include "sl_sensor_pressure.h"
STATIC mp_obj_t sensor_init(busio_i2c_obj_t *i2c) {
sl_status_t sc;
if (!common_hal_mcu_pin_is_free(&pin_PC9)) {
mp_raise_ValueError(translate("Pin PC9 is busy "));
return mp_const_false;
}
sc = sl_sensor_rht_init();
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
sc = sl_sensor_lux_init();
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
sc = sl_sensor_hall_init();
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
sc = sl_sensor_pressure_init();
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
sl_sensor_imu_init();
sc = sl_sensor_imu_enable(true);
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
common_hal_mcu_pin_claim(&pin_PC9);
return mp_const_true;
}
STATIC mp_obj_t sensor_deinit() {
sl_sensor_hall_deinit();
sl_sensor_lux_deinit();
sl_sensor_rht_deinit();
sl_sensor_pressure_deinit();
sl_sensor_imu_enable(false);
sl_sensor_imu_deinit();
common_hal_reset_pin(&pin_PC9);
return mp_const_true;
}
STATIC mp_obj_t sensor_get_temperature(void) {
sl_status_t sc;
uint32_t rh;
int32_t t;
sc = sl_sensor_rht_get(&rh, &t);
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
return mp_obj_new_float((float)t / 1000.0f);
}
STATIC mp_obj_t sensor_get_humidity(void) {
sl_status_t sc;
uint32_t rh;
int32_t t;
sc = sl_sensor_rht_get(&rh, &t);
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
return mp_obj_new_float((float)rh / 1000.0f);
}
STATIC mp_obj_t sensor_get_lux(void) {
sl_status_t sc;
float lux;
sc = sl_sensor_lux_get(&lux);
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
return mp_obj_new_float(lux);
}
STATIC mp_obj_t sensor_get_hall(void) {
sl_status_t sc;
float field_strength;
bool alert;
bool tamper;
sc = sl_sensor_hall_get(&field_strength, &alert, &tamper);
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
return mp_obj_new_float(field_strength);
}
STATIC mp_obj_t sensor_get_pressure(void) {
sl_status_t sc;
float pressure;
sc = sl_sensor_pressure_get(&pressure);
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
return mp_obj_new_float(pressure);
}
STATIC mp_obj_t sensor_imu_get(void) {
sl_status_t sc;
int16_t ovec[3];
int16_t avec[3];
mp_obj_t ovec_obj[3];
mp_obj_t avec_obj[3];
mp_obj_t ret[2];
sc = sl_sensor_imu_get(ovec, avec);
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
ovec_obj[0] = mp_obj_new_int(ovec[0]);
ovec_obj[1] = mp_obj_new_int(ovec[1]);
ovec_obj[2] = mp_obj_new_int(ovec[2]);
avec_obj[0] = mp_obj_new_int(avec[0]);
avec_obj[1] = mp_obj_new_int(avec[1]);
avec_obj[2] = mp_obj_new_int(avec[2]);
ret[0] = mp_obj_new_list(3,ovec_obj);
ret[1] = mp_obj_new_list(3,avec_obj);
return mp_obj_new_tuple(2,ret);
}
STATIC mp_obj_t sensor_imu_calibrate(void) {
sl_status_t sc;
sc = sl_sensor_imu_calibrate();
if (sc != SL_STATUS_OK) {
return mp_const_false;
}
return mp_const_true;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(sensor_init_obj,sensor_init);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_deinit_obj,sensor_deinit);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_temperature_obj,sensor_get_temperature);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_humidity_obj,sensor_get_humidity);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_lux_obj,sensor_get_lux);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_hall_obj,sensor_get_hall);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_pressure_obj,sensor_get_pressure);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_imu_get_obj,sensor_imu_get);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_imu_calibrate_obj,sensor_imu_calibrate);
STATIC const mp_rom_map_elem_t sensor_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_sensor) },
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&sensor_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sensor_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_temperature), MP_ROM_PTR(&sensor_get_temperature_obj) },
{ MP_ROM_QSTR(MP_QSTR_humidity), MP_ROM_PTR(&sensor_get_humidity_obj) },
{ MP_ROM_QSTR(MP_QSTR_lux), MP_ROM_PTR(&sensor_get_lux_obj) },
{ MP_ROM_QSTR(MP_QSTR_hall), MP_ROM_PTR(&sensor_get_hall_obj) },
{ MP_ROM_QSTR(MP_QSTR_pressure), MP_ROM_PTR(&sensor_get_pressure_obj) },
{ MP_ROM_QSTR(MP_QSTR_imu), MP_ROM_PTR(&sensor_imu_get_obj) },
{ MP_ROM_QSTR(MP_QSTR_imu_calibrate), MP_ROM_PTR(&sensor_imu_calibrate_obj) },
};
STATIC MP_DEFINE_CONST_DICT(sensor_module_globals, sensor_globals_table);
const mp_obj_module_t sensor_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&sensor_module_globals,
};
MP_REGISTER_MODULE(MP_QSTR_sensor, sensor_module,1);

View File

@ -0,0 +1,28 @@
## Gen Pin instructions ##
# Input File
pins.csv : contain pin name, port number ,pin number
pin_functions.csv : contain list of pin support for peripheral
make_pins.py : python script to gen pin
# Run make_pins.py
Copy above input file to folder boards/brd2601b/
Run CMD:
$ cd boards/brd2601b/
$ python make_pins.py -s pins.c -e pin_functions.h pins.csv pin_functions.csv
-s: name/directory of output source file
-e: name/directory of output header file
# Output
pins.c : register pin to board_module_globals_table
generate array contains supported function of pin
pin_functions.h : define index of functions
Example: pin_pa0_functions[FN_EUSART0_RX] == 1 // Can assign pin pa0 for EUSART0_RX
pin_pa0_functions[FN_EUSART0_RX] == 255 // Can't assign pin pa0 for EUSART0_RX
# Read pin define on REPL
import board
dir(board)

View File

@ -0,0 +1,33 @@
/***************************************************************************//**
* @file board.c
* @brief
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View File

@ -0,0 +1,20 @@
id: custom_brd2703a_cp_support
label: CircuitPython BRD2703A support
description: >
CircuitPython Board support for BRD2703A.
package: custom
category: Custom
quality: production
root_path: ../boards/explorerkit_xg24_brd2703a
include:
- path: ''
file_list:
- path: mpconfigboard.h
source:
- path: board.c
provides:
- name: custom_brd2703a_cp_support
requires:
- name: efr32mg24b210f1536im48
recommends:
- id: bt_rail_compatibility_fix

View File

@ -0,0 +1,52 @@
/***************************************************************************//**
* @file mpconfigboard.h
* @brief
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "build-explorerkit_xg24_brd2703a/pin_functions.h"
// Micropython setup
#define MICROPY_HW_BOARD_NAME "SiLabs xG24 Explorer Kit"
#define MICROPY_HW_MCU_NAME EFR32_SERIES_LOWER
#define HSE_VALUE ((uint32_t)8000000)
#define BOARD_HSE_SOURCE (RCC_HSE_BYPASS)
#define BOARD_HAS_LOW_SPEED_CRYSTAL (0)
#define DEFAULT_I2C_BUS_SDA (&pin_PB5)
#define DEFAULT_I2C_BUS_SCL (&pin_PB4)
#define DEFAULT_I2C_PERIPHERAL I2C0
#define DEFAULT_SPI_BUS_SCK (&pin_PC1)
#define DEFAULT_SPI_BUS_MOSI (&pin_PC3)
#define DEFAULT_SPI_BUS_MISO (&pin_PC2)
#define DEFAULT_SPI_BUS_SS (&pin_PC0)
#define NVM_BYTEARRAY_BUFFER_SIZE (512)
#define CIRCUITPY_INTERNAL_NVM_SIZE (512)
#undef MICROPY_USE_INTERNAL_PRINTF
#define MICROPY_USE_INTERNAL_PRINTF (0)

View File

@ -0,0 +1,16 @@
BOARD_BRD = brd2703a
INTERNAL_FLASH_FILESYSTEM = 1
QSPI_FLASH_FILESYSTEM = 0
SPI_FLASH_FILESYSTEM = 0
MCU_SERIES = MG24
MCU_VARIANT = EFR32MG24B210F1536IM48
CIRCUITPY_USB = 0
CIRCUITPY_CREATOR_ID = 0x19960000
CIRCUITPY_CREATION_ID = 0x00242703
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BLE
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register

View File

@ -0,0 +1,35 @@
EUSART0_CS,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
EUSART0_RX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
EUSART0_SCLK,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
EUSART0_TX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
EUSART1_CS,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
EUSART1_RX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
EUSART1_SCLK,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
EUSART1_TX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
I2C0_SCL,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PB4,PC0,PC1,PC2,PC3,PC4,PC8,PC9,PD2,PD3,PD4,PD5
I2C0_SDA,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PB4,PC0,PC1,PC2,PC3,PC4,PC8,PC9,PD2,PD3,PD4,PD5
I2C1_SCL,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
I2C1_SDA,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER0_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER0_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER0_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER1_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER1_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER1_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER2_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
TIMER2_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
TIMER2_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
TIMER3_CC0,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER3_CC1,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER3_CC2,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
TIMER4_CC0,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
TIMER4_CC1,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
TIMER4_CC2,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,,,,,,,,,,,,
USART0_CLK,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
USART0_CS,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
USART0_RX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
USART0_TX,PA0,PA4,PA5,PA6,PA7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5,PC8,PC9,PD2,PD3,PD4,PD5
VDAC0_CH0,,,,,,PB0,,,,,,,,,,,,,,,,,
VDAC0_CH1,,,,,,,PB1,,,,,,,,,,,,,,,,
VDAC1_CH0,,,,,,,,PB2,,,,,,,,,,,,,,,
VDAC1_CH1,,,,,,,,,PB3,,,,,,,,,,,,,,
1 EUSART0_CS PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
2 EUSART0_RX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
3 EUSART0_SCLK PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
4 EUSART0_TX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
5 EUSART1_CS PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
6 EUSART1_RX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
7 EUSART1_SCLK PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
8 EUSART1_TX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
9 I2C0_SCL PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PB4 PC0 PC1 PC2 PC3 PC4 PC8 PC9 PD2 PD3 PD4 PD5
10 I2C0_SDA PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PB4 PC0 PC1 PC2 PC3 PC4 PC8 PC9 PD2 PD3 PD4 PD5
11 I2C1_SCL PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
12 I2C1_SDA PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
13 TIMER0_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
14 TIMER0_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
15 TIMER0_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
16 TIMER1_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
17 TIMER1_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
18 TIMER1_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
19 TIMER2_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
20 TIMER2_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
21 TIMER2_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
22 TIMER3_CC0 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
23 TIMER3_CC1 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
24 TIMER3_CC2 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
25 TIMER4_CC0 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
26 TIMER4_CC1 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
27 TIMER4_CC2 PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5
28 USART0_CLK PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
29 USART0_CS PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
30 USART0_RX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
31 USART0_TX PA0 PA4 PA5 PA6 PA7 PB0 PB1 PB2 PB3 PB4 PB5 PC0 PC1 PC2 PC3 PC4 PC5 PC8 PC9 PD2 PD3 PD4 PD5
32 VDAC0_CH0 PB0
33 VDAC0_CH1 PB1
34 VDAC1_CH0 PB2
35 VDAC1_CH1 PB3

View File

@ -0,0 +1,24 @@
mcu_name, board_name,port ,pin
PA0,MIKROE_PWM,0,0
PA4,LED0,0,4
PA5,TX,0,5
PA6,RX,0,6
PA7,LED1,0,7
PB0,MIKROE_AN,1,0
PB1,MIKROE_INT,1,1
PB2,BTN0,1,2
PB3,BNT1,1,3
PB4,MIKROE_SCL,1,4
PB5,MIKROE_SDA,1,5
PC0,MIKROE_CS,2,0
PC1,MIKROE_SCK,2,1
PC2,MIKROE_MISO,2,2
PC3,MIKROE_MOSI,2,3
PC4,QWIIC_SCL,2,4
PC5,QWIIC_SDA,2,5
PC8,MIKROE_RST,2,8
PC9,,2,9
PD2,,3,2
PD3,,3,3
PD4,MIKROE_TX,3,4
PD5,MIKROE_RX,3,5
1 mcu_name board_name port pin
2 PA0 MIKROE_PWM 0 0
3 PA4 LED0 0 4
4 PA5 TX 0 5
5 PA6 RX 0 6
6 PA7 LED1 0 7
7 PB0 MIKROE_AN 1 0
8 PB1 MIKROE_INT 1 1
9 PB2 BTN0 1 2
10 PB3 BNT1 1 3
11 PB4 MIKROE_SCL 1 4
12 PB5 MIKROE_SDA 1 5
13 PC0 MIKROE_CS 2 0
14 PC1 MIKROE_SCK 2 1
15 PC2 MIKROE_MISO 2 2
16 PC3 MIKROE_MOSI 2 3
17 PC4 QWIIC_SCL 2 4
18 PC5 QWIIC_SDA 2 5
19 PC8 MIKROE_RST 2 8
20 PC9 2 9
21 PD2 3 2
22 PD3 3 3
23 PD4 MIKROE_TX 3 4
24 PD5 MIKROE_RX 3 5

View File

@ -0,0 +1,28 @@
.syntax unified
.cpu cortex-m33
.thumb
.text
.align 2
@ uint cpu_get_regs_and_sp(r0=uint regs[10])
.global cpu_get_regs_and_sp
.thumb
.thumb_func
.type cpu_get_regs_and_sp, %function
cpu_get_regs_and_sp:
@ store registers into given array
str r4, [r0], #4
str r5, [r0], #4
str r6, [r0], #4
str r7, [r0], #4
str r8, [r0], #4
str r9, [r0], #4
str r10, [r0], #4
str r11, [r0], #4
str r12, [r0], #4
str r13, [r0], #4
@ return the sp
@Move stack pointer to return register
mov r0, sp
@Branch to link register (return address) and change instruction set if needed
bx lr

View File

@ -0,0 +1,28 @@
## Gen Pin instructions ##
# Input File
pins.csv : contain pin name, port number ,pin number
pin_functions.csv : contain list of pin support for peripheral
make_pins.py : python script to gen pin
# Run make_pins.py
Copy above input file to folder boards/brd2601b/
Run CMD:
$ cd boards/brd2601b/
$ python make_pins.py -s pins.c -e pin_functions.h pins.csv pin_functions.csv
-s: name/directory of output source file
-e: name/directory of output header file
# Output
pins.c : register pin to board_module_globals_table
generate array contains supported function of pin
pin_functions.h : define index of functions
Example: pin_pa0_functions[FN_EUSART0_RX] == 1 // Can assign pin pa0 for EUSART0_RX
pin_pa0_functions[FN_EUSART0_RX] == 255 // Can't assign pin pa0 for EUSART0_RX
# Read pin define on REPL
import board
dir(board)

View File

@ -0,0 +1,29 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "supervisor/board.h"
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View File

@ -0,0 +1,18 @@
id: custom_brd2704a_cp_support
label: CircuitPython BRD2704A support
description: >
CircuitPython Board support for BRD2704A.
package: custom
category: Custom
quality: production
root_path: ../boards/sparkfun_thingplus_matter_mgm240p_brd2704a
include:
- path: ''
file_list:
- path: mpconfigboard.h
source:
- path: board.c
provides:
- name: custom_brd2704a_cp_support
requires:
- name: mgm240pb32vna

View File

@ -0,0 +1,49 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "build-sparkfun_thingplus_matter_mgm240p_brd2704a/pin_functions.h"
// Micropython setup
#define MICROPY_HW_BOARD_NAME "Sparkfun Thing Plus MGM240P"
#define MICROPY_HW_MCU_NAME EFR32_SERIES_LOWER
#define HSE_VALUE ((uint32_t)8000000)
#define BOARD_HSE_SOURCE (RCC_HSE_BYPASS)
#define BOARD_HAS_LOW_SPEED_CRYSTAL (0)
#define DEFAULT_I2C_BUS_SDA (&pin_PB4)
#define DEFAULT_I2C_BUS_SCL (&pin_PB3)
#define DEFAULT_I2C_PERIPHERAL I2C0
#define DEFAULT_SPI_BUS_SCK (&pin_PC2)
#define DEFAULT_SPI_BUS_MOSI (&pin_PC3)
#define DEFAULT_SPI_BUS_MISO (&pin_PC6)
#define DEFAULT_SPI_BUS_SS (&pin_PA7)
#define NVM_BYTEARRAY_BUFFER_SIZE (512)
#define CIRCUITPY_INTERNAL_NVM_SIZE (512)
#undef MICROPY_USE_INTERNAL_PRINTF
#define MICROPY_USE_INTERNAL_PRINTF (0)

View File

@ -0,0 +1,17 @@
BOARD_BRD = brd2704a
INTERNAL_FLASH_FILESYSTEM = 1
QSPI_FLASH_FILESYSTEM = 0
SPI_FLASH_FILESYSTEM = 0
MCU_SERIES = MG24
MCU_VARIANT = MGM240PB32VNA
CIRCUITPY_USB = 0
CIRCUITPY_SDCARDIO = 1
CIRCUITPY_CREATOR_ID = 0x19960000
CIRCUITPY_CREATION_ID = 0x00242704
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BLE
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register

View File

@ -0,0 +1,35 @@
EUSART0_CS,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
EUSART0_RX,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
EUSART0_SCLK,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
EUSART0_TX,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
EUSART1_CS,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
EUSART1_RX,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
EUSART1_SCLK,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
EUSART1_TX,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
I2C0_SCL,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PD0,PD1,PD2,PD3,,
I2C0_SDA,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PD0,PD1,PD2,PD3,,
I2C1_SCL,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
I2C1_SDA,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER0_CC0,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER0_CC1,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER0_CC2,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER1_CC0,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER1_CC1,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER1_CC2,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER2_CC0,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
TIMER2_CC1,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
TIMER2_CC2,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
TIMER3_CC0,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER3_CC1,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER3_CC2,,,,,,,,,,,,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
TIMER4_CC0,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
TIMER4_CC1,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
TIMER4_CC2,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,,,,,,,,,,,,,,
USART0_CLK,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
USART0_CS,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
USART0_RX,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
USART0_TX,PA0,PA4,PA5,PA6,PA7,PA8,PB0,PB1,PB2,PB3,PB4,PC0,PC1,PC2,PC3,PC4,PC5,PC6,PC7,PD0,PD1,PD2,PD3,,
VDAC0_CH0,,,,,,,PB0,,,,,,,,,,,,,,,,,,
VDAC0_CH1,,,,,,,,PB1,,,,,,,,,,,,,,,,,
VDAC1_CH0,,,,,,,,,PB2,,,,,,,,,,,,,,,,
VDAC1_CH1,,,,,,,,,,PB3,,,,,,,,,,,,,,,
1 EUSART0_CS PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
2 EUSART0_RX PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
3 EUSART0_SCLK PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
4 EUSART0_TX PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
5 EUSART1_CS PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
6 EUSART1_RX PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
7 EUSART1_SCLK PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
8 EUSART1_TX PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
9 I2C0_SCL PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PD0 PD1 PD2 PD3
10 I2C0_SDA PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PD0 PD1 PD2 PD3
11 I2C1_SCL PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
12 I2C1_SDA PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
13 TIMER0_CC0 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
14 TIMER0_CC1 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
15 TIMER0_CC2 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
16 TIMER1_CC0 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
17 TIMER1_CC1 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
18 TIMER1_CC2 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
19 TIMER2_CC0 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
20 TIMER2_CC1 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
21 TIMER2_CC2 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
22 TIMER3_CC0 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
23 TIMER3_CC1 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
24 TIMER3_CC2 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
25 TIMER4_CC0 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
26 TIMER4_CC1 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
27 TIMER4_CC2 PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4
28 USART0_CLK PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
29 USART0_CS PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
30 USART0_RX PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
31 USART0_TX PA0 PA4 PA5 PA6 PA7 PA8 PB0 PB1 PB2 PB3 PB4 PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD0 PD1 PD2 PD3
32 VDAC0_CH0 PB0
33 VDAC0_CH1 PB1
34 VDAC1_CH0 PB2
35 VDAC1_CH1 PB3

View File

@ -0,0 +1,24 @@
mcu_name, board_name,port ,pin
PA0,,0,0
PA4,,0,4
PA5,TX,0,5
PA6,RX,0,6
PA7,SD_CS,0,7
PA8,LED,0,8
PB0,,1,0
PB1,,1,1
PB2,,1,2
PB3,SCL,1,3
PB4,SDA,1,4
PC0,,2,0
PC1,,2,1
PC2,SCK,2,2
PC3,MOSI,2,3
PC4,,2,4
PC5,,2,5
PC6,MISO,2,6
PC7,,2,7
PD0,,3,0
PD1,,3,1
PD2,,3,2
PD3,,3,3
1 mcu_name board_name port pin
2 PA0 0 0
3 PA4 0 4
4 PA5 TX 0 5
5 PA6 RX 0 6
6 PA7 SD_CS 0 7
7 PA8 LED 0 8
8 PB0 1 0
9 PB1 1 1
10 PB2 1 2
11 PB3 SCL 1 3
12 PB4 SDA 1 4
13 PC0 2 0
14 PC1 2 1
15 PC2 SCK 2 2
16 PC3 MOSI 2 3
17 PC4 2 4
18 PC5 2 5
19 PC6 MISO 2 6
20 PC7 2 7
21 PD0 3 0
22 PD1 3 1
23 PD2 3 2
24 PD3 3 3

View File

@ -0,0 +1,74 @@
# Silicon Labs Project Configuration Tools: slcp, v0, Component selection file.
description: |
A project structure used as a configuration for CircuitPython + Custom Bluetooth + Standard DMP (Dynamic Multiprotocol) applications. It runs on top of FreeRTOS and multiprotocol RAIL utilizing IEEE 802.15.4 standard protocol.
filter:
- name: Capability
value: [Multiprotocol]
- name: Device Type
value: [SoC]
- name: Project Difficulty
value: [Advanced]
- name: Wireless Technology
value: [Bluetooth]
package: Bluetooth
quality: production
tag: ['hardware:rf:band:2400', 'hardware:device:ram:64']
sdk: {id: gecko_sdk, version: 4.2.1}
toolchain_settings: []
sdk_extension:
- id: cp_efr32
version: 1.0.0
component:
- {id: bluetooth_feature_nvm}
- {id: bluetooth_feature_gatt_server}
- {id: bluetooth_feature_sm}
- {id: mpu}
- {id: bluetooth_feature_legacy_advertiser}
- {id: bluetooth_feature_legacy_scanner}
- {id: gatt_configuration}
- {id: freertos}
- {id: bluetooth_stack}
- {id: bluetooth_feature_gatt}
- {id: uartdrv_core}
- {id: i2cspm_core}
- {id: spidrv_core}
- {id: pwm_core}
- {id: emlib_usart}
- {id: emlib_vdac}
- {id: emlib_iadc}
- {id: nvm3_lib}
- {id: nvm3_default}
- {id: tempdrv}
- {id: sleeptimer}
- {id: emlib_wdog}
- {id: bluetooth_feature_connection}
- {id: rail_lib_multiprotocol}
- {id: bluetooth_feature_dynamic_gattdb}
- {id: bluetooth_feature_system}
- {id: bluetooth_feature_scanner}
- {id: component_catalog}
- {id: app_assert}
requires:
- condition: [brd2601b]
name: custom_brd2601b_cp_support
- condition: [brd2704a]
name: custom_brd2704a_cp_support
- condition: [brd2703a]
name: custom_brd2703a_cp_support
configuration:
- {name: SL_SLEEPTIMER_WALLCLOCK_CONFIG, value: '1'}
- {name: NVM3_DEFAULT_MAX_OBJECT_SIZE, value: '512'}
- {name: SL_STACK_SIZE, value: '2752'}
- {name: SL_HEAP_SIZE, value: '11000'}
- name: SL_POWER_MANAGER_LOWEST_EM_ALLOWED
value: '1'
- {name: configTOTAL_HEAP_SIZE, value: '8192'}
- {name: configTIMER_TASK_PRIORITY, value: '55'}
- {name: configTIMER_TASK_STACK_DEPTH, value: '160'}
- condition: [psa_crypto]
name: SL_PSA_KEY_USER_SLOT_COUNT
value: '0'
- {name: APP_LOG_PREFIX_ENABLE, value: '0'}
ui_hints:
highlight:
- {path: config/btconf/gatt_configuration.btconf}

View File

@ -0,0 +1,650 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "py/gc.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "shared/runtime/interrupt_char.h"
#include "shared-bindings/_bleio/Address.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/ScanEntry.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/time/__init__.h"
#include "common-hal/_bleio/Connection.h"
#include "supervisor/shared/tick.h"
#define PUBLIC_ADDRESS 0
#define STATIC_ADDRESS 1
#define BLE_EXT_ADV_MAX_SIZE 32
#define UNIT_0_625_MS (625)
#define UNIT_1_25_MS (1250)
#define UNIT_10_MS (10000)
#define SCAN_TIMEOUT_MS_DEFAUT 3000
#define BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED 256
#define BLE_GAP_SCAN_BUFFER_MAX 32
#define DEVICE_NAME_LEN 15
EventGroupHandle_t xscan_event;
device_scan_info_t scan_info;
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
// Set scan data form sl_bt_on_event
void set_scan_device_info_on_ble_evt(bd_addr address,
uint8_t address_type,
int8_t rssi,
uint8array *data) {
scan_info.address = address;
scan_info.address_type = address_type;
scan_info.rssi = rssi;
memcpy(scan_info.data, data->data, data->len);
}
// Get state of the BLE adapter.
bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) {
return self->is_enable;
}
// Set state of the BLE adapter
void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self,
bool enabled) {
const bool is_enabled = common_hal_bleio_adapter_get_enabled(self);
bd_addr get_address;
uint8_t address_type;
uint8_t conn_index;
bleio_connection_internal_t *connection;
sl_status_t sc = SL_STATUS_FAIL;
uint8_t device_name[DEVICE_NAME_LEN + 1];
memset(device_name, 0, DEVICE_NAME_LEN);
// Don't enable or disable twice
if (is_enabled == enabled) {
return;
}
sc = sl_bt_system_get_identity_address(&get_address, &address_type);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Get address fail."));
}
snprintf((char *)device_name, DEVICE_NAME_LEN + 1,
"CIRCUITPY-%X%X", get_address.addr[1], get_address.addr[0]);
if (enabled) {
sl_bt_gatt_server_write_attribute_value(gattdb_device_name,
0,
DEVICE_NAME_LEN,
device_name);
// Clear all of the internal connection objects.
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
// Reset connection.
connection->conn_handle = BLEIO_HANDLE_INVALID;
}
} else {
self->is_enable = false;
}
}
// Get mac address of the BLE adapter
bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) {
bd_addr get_address;
uint8_t address_type;
sl_status_t sc = SL_STATUS_FAIL;
bleio_address_obj_t *address;
sc = sl_bt_system_get_identity_address(&get_address, &address_type);
if (SL_STATUS_OK != sc) {
return NULL;
}
address = m_new_obj(bleio_address_obj_t);
address->base.type = &bleio_address_type;
common_hal_bleio_address_construct(address, get_address.addr,
BLEIO_ADDRESS_TYPE_RANDOM_STATIC);
return address;
}
// Set identity address
bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self,
bleio_address_obj_t *address) {
sl_status_t sc = SL_STATUS_FAIL;
mp_buffer_info_t bufinfo;
bd_addr ble_addr;
if (NULL == address) {
return false;
}
if (!mp_get_buffer(address->bytes, &bufinfo, MP_BUFFER_READ)) {
return false;
}
memcpy(ble_addr.addr, bufinfo.buf, 6);
sl_bt_system_set_identity_address(ble_addr, PUBLIC_ADDRESS);
return sc == SL_STATUS_OK;
}
// Get name of the BLE adapter
mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) {
char name[DEVICE_NAME_LEN];
size_t value_len = 0;
uint8_t sc;
memset(name, 0, DEVICE_NAME_LEN);
sc = sl_bt_gatt_server_read_attribute_value(gattdb_device_name,
0,
DEVICE_NAME_LEN,
&value_len,
(uint8_t *)name);
if (SL_STATUS_OK != sc) {
return NULL;
}
return mp_obj_new_str(name, strlen(name));
}
// Set name of the BLE adapter
void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self,
const char *name) {
sl_bt_gatt_server_write_attribute_value(gattdb_device_name,
0,
DEVICE_NAME_LEN,
(const uint8_t *)name);
}
// starts a BLE scan
mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self,
uint8_t *prefixes,
size_t prefix_length,
bool extended,
mp_int_t buffer_size,
mp_float_t timeout,
mp_float_t interval,
mp_float_t window,
mp_int_t minimum_rssi,
bool active) {
sl_status_t sc;
uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t current_ticks = start_ticks;
uint32_t timeout_ms = timeout * 1000;
if (timeout_ms == 0) {
timeout_ms = SCAN_TIMEOUT_MS_DEFAUT;
}
if (self->scan_results != NULL) {
if (!shared_module_bleio_scanresults_get_done(self->scan_results)) {
mp_raise_bleio_BluetoothError(
translate("Scan already in progress. Stop with stop_scan."));
}
self->scan_results = NULL;
}
sl_bt_scanner_stop();
self->scan_results = shared_module_bleio_new_scanresults(buffer_size,
prefixes,
prefix_length,
minimum_rssi);
xscan_event = xEventGroupCreate();
if (xscan_event != NULL) {
xEventGroupClearBits(xscan_event, 1 << 0);
}
sc = sl_bt_scanner_start(sl_bt_scanner_scan_phy_1m,
sl_bt_scanner_discover_generic);
if (SL_STATUS_OK != sc) {
self->scan_results = NULL;
}
// Busy-wait until timeout or until we've read enough chars.
while (current_ticks - start_ticks <= timeout_ms) {
if (xscan_event != NULL) {
xEventGroupWaitBits(xscan_event, 1 << 0, pdTRUE, pdFALSE,
timeout_ms / portTICK_PERIOD_MS);
}
self->scan_results->prefix_length = 0;
scan_info.data_len = 28;
shared_module_bleio_scanresults_append(
self->scan_results,
supervisor_ticks_ms64(),
true,
true,
scan_info.rssi,
scan_info.address.addr,
scan_info.address_type,
scan_info.data,
scan_info.data_len);
current_ticks = supervisor_ticks_ms64();
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
break;
}
}
shared_module_bleio_scanresults_set_done(self->scan_results, true);
vEventGroupDelete(xscan_event);
return MP_OBJ_FROM_PTR(self->scan_results);
}
void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) {
if (self->scan_results == NULL) {
return;
}
sl_bt_scanner_stop();
shared_module_bleio_scanresults_set_done(self->scan_results, true);
self->scan_results = NULL;
}
// Start the advertising on an advertising set with specified
// discovery and connection modes
uint32_t _common_hal_bleio_adapter_start_advertising(
bleio_adapter_obj_t *self,
bool connectable,
bool anonymous,
uint32_t timeout,
float interval,
const uint8_t *advertising_data,
uint16_t advertising_data_len,
const uint8_t *scan_response_data,
uint16_t scan_response_data_len,
mp_int_t tx_power,
const bleio_address_obj_t *directed_to) {
sl_status_t sc = SL_STATUS_FAIL;
int16_t set_power;
uint32_t interval_min = 160;
uint32_t interval_max = 160;
bd_addr address;
uint8_t address_type;
uint8_t system_id[8];
uint8_t enable_connect;
if (self->user_advertising) {
return SL_STATUS_BUSY;
}
sc = sl_bt_advertiser_create_set(&self->advertising_handle);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Create_set fail."));
return sc;
}
sc = sl_bt_advertiser_set_channel_map(self->advertising_handle, 7);
if (SL_STATUS_OK != sc) {
return sc;
}
sc = sl_bt_system_get_identity_address(&address, &address_type);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Get address fail."));
return sc;
}
// Pad and reverse unique ID to get System ID.
system_id[0] = address.addr[5];
system_id[1] = address.addr[4];
system_id[2] = address.addr[3];
system_id[3] = 0xFF;
system_id[4] = 0xFE;
system_id[5] = address.addr[2];
system_id[6] = address.addr[1];
system_id[7] = address.addr[0];
sc = sl_bt_gatt_server_write_attribute_value(gattdb_system_id,
0,
sizeof(system_id),
system_id);
if (SL_STATUS_OK != sc) {
return sc;
}
sc = sl_bt_advertiser_set_tx_power(self->advertising_handle,
tx_power,
&set_power);
if (SL_STATUS_OK != sc) {
return sc;
}
// Set advertising interval.
sc = sl_bt_advertiser_set_timing(
self->advertising_handle,
interval_min, // min. adv. interval (milliseconds * 1.6)
interval_max, // max. adv. interval (milliseconds * 1.6)
0, // adv. duration
0); // max. num. adv. events
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Set_timing fail."));
return sc;
}
sc = sl_bt_legacy_advertiser_set_data(
self->advertising_handle,
sl_bt_advertiser_advertising_data_packet,
advertising_data_len,
advertising_data);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Set data fail."));
return sc;
}
// Start advertising and enable connections.
enable_connect = sl_bt_legacy_advertiser_scannable;
if (true == connectable) {
enable_connect = sl_bt_advertiser_connectable_scannable;
}
sc = sl_bt_legacy_advertiser_start(self->advertising_handle,
enable_connect);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Start advertise fail."));
} else {
self->user_advertising = true;
}
return sc;
}
// Check size of packet advertising to send
STATIC void check_data_fit(size_t data_len, bool connectable) {
if (data_len > BLE_EXT_ADV_MAX_SIZE ||
(connectable && data_len > BLE_EXT_ADV_MAX_SIZE)) {
mp_raise_ValueError(
translate("Data too large for advertisement packet"));
}
}
// Start advertising
void common_hal_bleio_adapter_start_advertising(
bleio_adapter_obj_t *self,
bool connectable,
bool anonymous,
uint32_t timeout,
mp_float_t interval,
mp_buffer_info_t *advertising_data_bufinfo,
mp_buffer_info_t *scan_response_data_bufinfo,
mp_int_t tx_power,
const bleio_address_obj_t *directed_to) {
if (self->user_advertising) {
common_hal_bleio_adapter_stop_advertising(self);
}
// Interval value has already been validated.
check_data_fit(advertising_data_bufinfo->len, connectable);
check_data_fit(scan_response_data_bufinfo->len, connectable);
if (advertising_data_bufinfo->len > 31 && scan_response_data_bufinfo->len > 0) {
mp_raise_bleio_BluetoothError(
translate("Extended advertisements not supported"));
}
if (advertising_data_bufinfo->len > 0 && directed_to != NULL) {
mp_raise_bleio_BluetoothError(
translate("Data not supported with directed advertising"));
}
if (anonymous) {
mp_raise_NotImplementedError(NULL);
}
if (!timeout) {
timeout = INT32_MAX;
} else if (timeout > INT32_MAX) {
mp_raise_bleio_BluetoothError(
translate("Maximum timeout length is %d seconds"), INT32_MAX / 1000);
}
_common_hal_bleio_adapter_start_advertising(self, connectable, anonymous,
timeout, interval,
advertising_data_bufinfo->buf,
advertising_data_bufinfo->len,
scan_response_data_bufinfo->buf,
scan_response_data_bufinfo->len,
tx_power,
directed_to);
}
// Stop advertising
void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
if (!common_hal_bleio_adapter_get_advertising(self)) {
return;
}
sl_bt_advertiser_delete_set(self->advertising_handle);
sl_bt_advertiser_stop(0);
self->user_advertising = false;
}
// Get status of advertising
bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) {
return self->user_advertising;
}
// Convert mac address of remote device to connect
STATIC void _convert_address(const bleio_address_obj_t *address,
bd_addr *sd_address, uint8_t *addr_type) {
mp_buffer_info_t address_buf_info;
*addr_type = address->type;
mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ);
memcpy(sd_address->addr, (uint8_t *)address_buf_info.buf, 6);
}
// Add new connection into connection list
void _new_connection(uint16_t conn_handle) {
// Find an empty connection. One must always be available because the SD has the same
// total connection limit.
bleio_connection_internal_t *connection;
uint8_t conn_index;
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
if (connection->conn_handle == BLEIO_HANDLE_INVALID) {
break;
}
}
connection->conn_handle = conn_handle;
connection->connection_obj = mp_const_none;
connection->pair_status = PAIR_NOT_PAIRED;
connection->mtu = 0;
}
// Attempts a connection to the device with the given address.
mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self,
bleio_address_obj_t *address,
mp_float_t timeout) {
bd_addr addr;
uint8_t address_type;
sl_status_t error_code;
uint8_t conn_handle;
uint8_t conn_index;
bleio_connection_internal_t *connection;
if (self->scan_results != NULL) {
common_hal_bleio_adapter_stop_scan(self);
}
conn_handle = common_hal_bleio_adapter_get_connected(self);
timeout = MSEC_TO_UNITS(timeout, UNIT_10_MS);
_convert_address(address, &addr, &address_type);
error_code = sl_bt_connection_open(addr,
address_type,
sl_bt_gap_phy_1m,
&conn_handle);
// Negative values are error codes, connection handle otherwise.
if (SL_STATUS_OK != error_code) {
return mp_const_none;
}
_new_connection(conn_handle);
// TODO: If we have keys, then try and encrypt the connection.
// TODO: Negotiate for better PHY and data lengths since we are the central. These are
// nice-to-haves so ignore any errors.
// Make the connection object and return it.
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
if (connection->conn_handle == conn_handle) {
connection->is_central = true;
connection->pair_status = PAIR_PAIRED;
return bleio_connection_new_from_internal(connection);
}
}
mp_raise_bleio_BluetoothError(
translate("Failed to connect: internal error"));
return mp_const_none;
}
// Get connected status
bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) {
uint8_t conn_index;
bleio_connection_internal_t *connection;
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
if (connection->conn_handle != BLEIO_HANDLE_INVALID) {
return true;
}
}
return false;
}
// Get connection object
mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
size_t total_connected = 0;
mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT];
uint8_t conn_index;
bleio_connection_internal_t *connection;
if (self->connection_objs != NULL) {
return self->connection_objs;
}
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
if (connection->conn_handle != BLEIO_HANDLE_INVALID) {
if (connection->connection_obj == mp_const_none) {
connection->connection_obj =
bleio_connection_new_from_internal(connection);
}
items[total_connected] = connection->connection_obj;
total_connected++;
}
}
self->connection_objs = mp_obj_new_tuple(total_connected, items);
return self->connection_objs;
}
void common_hal_bleio_adapter_remove_connection(uint8_t conn_handle) {
uint8_t conn_index;
bleio_connection_internal_t *connection;
osMutexAcquire(bluetooth_connection_mutex_id, osWaitForever);
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
if (conn_handle == connection->conn_handle) {
connection->connection_obj = NULL;
connection->conn_handle = BLEIO_HANDLE_INVALID;
}
}
osMutexRelease(bluetooth_connection_mutex_id);
}
// Delete all bonding
void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
sl_status_t sc;
sc = sl_bt_sm_delete_bondings();
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("All bonding deleted fail."));
}
}
// Get status bonding to central
bool common_hal_bleio_adapter_is_bonded_to_central(bleio_adapter_obj_t *self) {
bleio_connection_internal_t *connection;
uint8_t conn_index;
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
if (connection->conn_handle != BLEIO_HANDLE_INVALID) {
return true;
}
}
return false;
}
void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) {
// We divide by size_t so that we can scan each 32-bit aligned value to see
// if it is a pointer. This allows us to change the structs without worrying
// about collecting new pointers.
gc_collect_root((void **)adapter,
sizeof(bleio_adapter_obj_t) / (sizeof(size_t)));
gc_collect_root((void **)bleio_connections,
sizeof(bleio_connections) / (sizeof(size_t)));
}
// Reset the BLE adapter
void bleio_adapter_reset(bleio_adapter_obj_t *adapter) {
bool any_connected = false;
uint64_t start_ticks;
uint8_t conn_index;
bleio_connection_internal_t *connection;
common_hal_bleio_adapter_stop_scan(adapter);
if (common_hal_bleio_adapter_get_advertising(adapter)) {
common_hal_bleio_adapter_stop_advertising(adapter);
}
adapter->connection_objs = NULL;
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
// Disconnect all connections cleanly.
if (connection->conn_handle != BLEIO_HANDLE_INVALID) {
common_hal_bleio_connection_disconnect(connection);
}
connection->connection_obj = mp_const_none;
}
// Wait up to 125 ms (128 ticks) for disconnect to complete. This should be
// greater than most connection intervals.
start_ticks = supervisor_ticks_ms64();
while (any_connected && supervisor_ticks_ms64() - start_ticks < 128) {
any_connected = false;
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
any_connected |= connection->conn_handle != BLEIO_HANDLE_INVALID;
}
}
}

View File

@ -0,0 +1,87 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_ADAPTER_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_ADAPTER_H
#include "py/obj.h"
#include "py/objtuple.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/ScanResults.h"
#include "supervisor/background_callback.h"
#ifndef BLEIO_TOTAL_CONNECTION_COUNT
#define BLEIO_TOTAL_CONNECTION_COUNT 5
#endif
#define BLEIO_HANDLE_INVALID 0xffff
#define BLE_GAP_ADDR_LEN 6
extern bleio_connection_internal_t
bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
extern EventGroupHandle_t xscan_event;
typedef struct {
mp_obj_base_t base;
bleio_scanresults_obj_t *scan_results;
mp_obj_t name;
mp_obj_tuple_t *connection_objs;
background_callback_t background_callback;
bool user_advertising;
bool is_enable;
uint8_t advertising_handle;
} bleio_adapter_obj_t;
typedef struct {
uint8_t addr_id_peer : 1;
uint8_t addr_type : 7;
uint8_t addr[BLE_GAP_ADDR_LEN];
} ble_gap_addr_t;
typedef struct {
// Pointer to the data buffer provided to/from the application.
uint8_t *p_data;
// Length of the data buffer, in bytes.
uint16_t len;
} ble_data_t;
typedef struct {
uint8_t address_type;
uint8_t conn_handle;
uint8_t data_len;
int8_t rssi;
bd_addr address;
uint8_t data[255];
} device_scan_info_t;
void set_scan_device_info_on_ble_evt(bd_addr address, uint8_t address_type,
int8_t rssi, uint8array *data);
void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter);
void bleio_adapter_reset(bleio_adapter_obj_t *adapter);
void common_hal_bleio_adapter_remove_connection(uint8_t conn_handle);
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_ADAPTER_H

View File

@ -0,0 +1,27 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/_bleio/Attribute.h"

View File

@ -0,0 +1,32 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_ATTRIBUTE_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_ATTRIBUTE_H
#include "shared-module/_bleio/Attribute.h"
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_ATTRIBUTE_H

View File

@ -0,0 +1,407 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include "py/runtime.h"
#include "common-hal/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/tick.h"
#include "supervisor/serial.h"
EventGroupHandle_t xcharacteristic_event;
// Set the characteristic data from sl_bt_on_event
bool set_characteristic_value_on_ble_evt(uint8_t conn_handle,
uint16_t char_handle,
uint8_t *data,
size_t data_len) {
uint8_t serv_index;
uint8_t charc_index;
bleio_service_obj_t *service;
bleio_characteristic_obj_t *characteristic;
bleio_connection_internal_t *connection =
bleio_conn_handle_to_connection(conn_handle);
if (NULL == connection) {
mp_raise_bleio_BluetoothError(translate("Get connection fail."));
return false;
}
for (serv_index = 0; serv_index < connection->remote_service_list->len; serv_index++) {
service = connection->remote_service_list->items[serv_index];
for (charc_index = 0; charc_index < service->characteristic_list->len; charc_index++) {
characteristic = service->characteristic_list->items[charc_index];
if (char_handle == characteristic->handle) {
characteristic->current_value = pvPortMalloc(data_len);
characteristic->current_value_len = data_len;
memcpy(characteristic->current_value, data, data_len);
if (xcharacteristic_event != NULL) {
xEventGroupSetBits(xcharacteristic_event, 1 << 0);
}
return true;
}
}
}
return false;
}
// Get the characteristic data object
STATIC bool get_characteristic_value(uint8_t conn_handle,
uint16_t char_handle,
uint8_t *data,
size_t *data_len) {
uint8_t serv_index;
uint8_t charc_index;
bleio_service_obj_t *service;
bleio_characteristic_obj_t *characteristic;
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(conn_handle);
if (NULL == connection) {
mp_raise_bleio_BluetoothError(translate("Get connection fail."));
return false;
}
for (serv_index = 0; serv_index < connection->remote_service_list->len; serv_index++) {
service = connection->remote_service_list->items[serv_index];
for (charc_index = 0; charc_index < service->characteristic_list->len; charc_index++) {
characteristic = service->characteristic_list->items[charc_index];
if (char_handle == characteristic->handle) {
*data_len = characteristic->current_value_len;
memcpy(data, characteristic->current_value, *data_len);
vPortFree(characteristic->current_value);
return true;
}
}
}
return false;
}
// Create new bleio characteristic
void common_hal_bleio_characteristic_construct(
bleio_characteristic_obj_t *self,
bleio_service_obj_t *service,
uint16_t handle, bleio_uuid_obj_t *uuid,
bleio_characteristic_properties_t props,
bleio_attribute_security_mode_t read_perm,
bleio_attribute_security_mode_t write_perm,
mp_int_t max_length,
bool fixed_length,
mp_buffer_info_t *initial_value_bufinfo,
const char *user_description) {
self->service = service;
self->uuid = uuid;
self->handle = BLEIO_HANDLE_INVALID;
self->cccd_handle = BLEIO_HANDLE_INVALID;
self->sccd_handle = BLEIO_HANDLE_INVALID;
self->props = props;
self->read_perm = read_perm;
self->write_perm = write_perm;
self->max_length = max_length > MAX_LENGTH_DATA ? MAX_LENGTH_DATA : max_length;
self->max_length = self->max_length ? self->max_length : MAX_LENGTH_DATA;
self->fixed_length = fixed_length;
if (gc_alloc_possible()) {
self->descriptor_list = mp_obj_new_list(0, NULL);
} else {
self->descriptor_list = NULL;
}
if (service->is_remote) {
self->handle = handle;
} else {
common_hal_bleio_service_add_characteristic(self->service,
self,
initial_value_bufinfo,
user_description);
sl_bt_gatt_server_write_attribute_value(
self->handle,
0,
initial_value_bufinfo->len,
(uint8_t *)initial_value_bufinfo->buf);
}
}
// A tuple of Descriptor that describe this characteristic
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(
bleio_characteristic_obj_t *self) {
if (self->descriptor_list == NULL) {
return mp_const_empty_tuple;
}
return mp_obj_new_tuple(self->descriptor_list->len,
self->descriptor_list->items);
}
// The Service this Characteristic is a part of
bleio_service_obj_t *common_hal_bleio_characteristic_get_service(
bleio_characteristic_obj_t *self) {
return self->service;
}
// Get value of characteristic
size_t common_hal_bleio_characteristic_get_value(
bleio_characteristic_obj_t *self,
uint8_t *buf,
size_t len) {
sl_status_t sc = SL_STATUS_FAIL;
EventBits_t ux_bits;
uint8_t retry = 10;
uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t current_ticks = start_ticks;
if (self->handle == BLEIO_HANDLE_INVALID) {
return 0;
}
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
if (common_hal_bleio_service_get_is_remote(self->service)) {
// ble client gets characteristic value
if (BT_GATT_CHRC_READ & self->props) {
sc = sl_bt_gatt_read_characteristic_value(conn_handle,self->handle);
while (SL_STATUS_OK != sc && retry > 0) {
sc = sl_bt_gatt_read_characteristic_value(conn_handle,self->handle);
vTaskDelay(100 / portTICK_PERIOD_MS);
retry--;
}
}
xcharacteristic_event = xEventGroupCreate();
if (xcharacteristic_event != NULL) {
xEventGroupClearBits(xcharacteristic_event, 1 << 0);
}
while (current_ticks - start_ticks <= GET_CHARACTERISTIC_TIMEOUT_MS) {
if (xcharacteristic_event != NULL) {
ux_bits = xEventGroupWaitBits(
xcharacteristic_event, 1 << 0, pdTRUE, pdFALSE,
GET_CHARACTERISTIC_TIMEOUT_MS / portTICK_PERIOD_MS);
if ((ux_bits & (1 << 0)) == (1 << 0)) {
break;
}
}
current_ticks = supervisor_ticks_ms64();
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
break;
}
}
get_characteristic_value(conn_handle, self->handle, buf, &len);
vEventGroupDelete(xcharacteristic_event);
return len;
} else {
sc = sl_bt_gatt_server_read_attribute_value(self->handle,
0,
self->max_length,
&len,
(uint8_t *)buf);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(
translate("Read_attribute_value fail!"));
}
return len;
}
return 0;
}
// Get max length of charateristic
size_t common_hal_bleio_characteristic_get_max_length(
bleio_characteristic_obj_t *self) {
return self->max_length;
}
// Set value of this characteristic
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
mp_buffer_info_t *bufinfo) {
sl_status_t sc = SL_STATUS_FAIL;
uint16_t conn_handle;
uint16_t sent_len;
if (common_hal_bleio_service_get_is_remote(self->service)) {
conn_handle = bleio_connection_get_conn_handle(self->service->connection);
if ((self->props & CHAR_PROP_WRITE_NO_RESPONSE) != 0) {
sc = sl_bt_gatt_write_characteristic_value_without_response(
conn_handle,
self->handle,
bufinfo->len,
bufinfo->buf,
&sent_len);
} else {
sc = sl_bt_gatt_write_characteristic_value(conn_handle,
self->handle,
bufinfo->len,
bufinfo->buf);
}
} else {
if (self->props & BT_GATT_CHRC_READ) {
sc = sl_bt_gatt_server_write_attribute_value(self->handle,
0,
bufinfo->len,
(uint8_t *)bufinfo->buf);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(
translate("Write_attribute_value fail!"));
}
}
if (self->props & BT_GATT_CHRC_NOTIFY) {
sc = sl_bt_gatt_server_send_notification(
1,
self->handle,
bufinfo->len,
(uint8_t *)bufinfo->buf);
}
if (self->props & BT_GATT_CHRC_INDICATE) {
sc = sl_bt_gatt_server_send_indication(
1,
self->handle,
bufinfo->len,
(uint8_t *)bufinfo->buf);
}
}
}
// Get UUID of this characteristic
bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(
bleio_characteristic_obj_t *self) {
return self->uuid;
}
// Get properties of this characteristic
bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(
bleio_characteristic_obj_t *self) {
return self->props;
}
// Add new descriptor to characteristic
void common_hal_bleio_characteristic_add_descriptor(
bleio_characteristic_obj_t *self,
bleio_descriptor_obj_t *descriptor) {
sl_status_t sc = SL_STATUS_FAIL;
const uint8_t value;
uuid_128 bt_uuid_128;
sl_bt_uuid_16_t bt_uuid_16;
uint16_t gattdb_session;
sc = sl_bt_gattdb_new_session(&gattdb_session);
if (SL_STATUS_OK != sc && SL_STATUS_ALREADY_EXISTS != sc) {
mp_raise_bleio_BluetoothError(translate("Create new session fail."));
return;
}
if (BLE_UUID_TYPE_16 == descriptor->uuid->efr_ble_uuid.uuid.type) {
bt_uuid_16.data[0] = descriptor->uuid->efr_ble_uuid.uuid16.value & 0xff;
bt_uuid_16.data[1] = descriptor->uuid->efr_ble_uuid.uuid16.value >> 8;
sl_bt_gattdb_add_uuid16_descriptor(self->session,
self->handle,
descriptor->handle,
0,
bt_uuid_16,
sl_bt_gattdb_user_managed_value,
descriptor->max_length,
2,
&value,
&descriptor->handle);
} else {
memcpy(bt_uuid_128.data, descriptor->uuid->efr_ble_uuid.uuid128.value, 16);
sl_bt_gattdb_add_uuid128_descriptor(self->session,
self->handle,
descriptor->handle,
0,
bt_uuid_128,
sl_bt_gattdb_user_managed_value,
descriptor->max_length,
2,
&value,
&descriptor->handle);
}
sc = sl_bt_gattdb_commit(gattdb_session);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Commit descriptor fail."));
return;
}
mp_obj_list_append(MP_OBJ_FROM_PTR(self->descriptor_list),
MP_OBJ_FROM_PTR(descriptor));
}
// Set the remote characteristics CCCD to enable or disable notification and indication.
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
bool notify,bool indicate) {
sl_status_t sc = SL_STATUS_FAIL;
const uint16_t conn_handle = bleio_connection_get_conn_handle(
self->service->connection);
common_hal_bleio_check_connected(conn_handle);
notify = 1;
indicate = 0;
if (notify) {
sc = sl_bt_gatt_set_characteristic_notification(conn_handle,
self->handle,sl_bt_gatt_notification);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Notify fail"));
}
}
if (indicate) {
sc = sl_bt_gatt_set_characteristic_notification(conn_handle,
self->handle,sl_bt_gatt_indication);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Indicate fail"));
}
}
if (0 == notify && 0 == indicate) {
sc = sl_bt_gatt_set_characteristic_notification(conn_handle,
self->handle,sl_bt_gatt_disable);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Indicate fail"));
}
}
}

View File

@ -0,0 +1,68 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CHARACTERISTIC_H
#include "shared-bindings/_bleio/Attribute.h"
#include "common-hal/_bleio/Descriptor.h"
#include "shared-module/_bleio/Characteristic.h"
#include "common-hal/_bleio/Service.h"
#include "common-hal/_bleio/UUID.h"
#define MAX_LENGTH_DATA 512
#define GET_CHARACTERISTIC_TIMEOUT_MS 1000
typedef struct _bleio_characteristic_obj {
mp_obj_base_t base;
// Will be MP_OBJ_NULL before being assigned to a Service.
bleio_service_obj_t *service;
bleio_uuid_obj_t *uuid;
uint8_t *current_value;
uint16_t current_value_len;
// Our internal allocation length. If > 0, then current_value is managed by
// this characteristic.
uint16_t current_value_alloc;
uint16_t max_length;
uint16_t def_handle;
uint16_t handle;
uint16_t session;
bleio_characteristic_properties_t props;
bleio_attribute_security_mode_t read_perm;
bleio_attribute_security_mode_t write_perm;
mp_obj_list_t *descriptor_list;
uint16_t user_desc_handle;
uint16_t cccd_handle;
uint16_t sccd_handle;
bool fixed_length;
} bleio_characteristic_obj_t;
bool set_characteristic_value_on_ble_evt(uint8_t conn_handle,
uint16_t char_handle,
uint8_t *data,
size_t data_len);
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CHARACTERISTIC_H

View File

@ -0,0 +1,164 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include "py/ringbuf.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
#include "common-hal/_bleio/CharacteristicBuffer.h"
#include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/tick.h"
// Characteristic buffer list of peripheral device
bleio_characteristic_buffer_obj_list_t bleio_characteristic_buffer_list;
bool characteristic_buffer_on_ble_evt(uint16_t attribute,
uint8_t *data,
uint16_t len) {
uint16_t cindex = 0;
for (cindex = 0; cindex < bleio_characteristic_buffer_list.len; cindex++) {
if (bleio_characteristic_buffer_list.data[cindex] != NULL &&
bleio_characteristic_buffer_list.data[cindex]->characteristic->handle == attribute) {
taskENTER_CRITICAL();
if (bleio_characteristic_buffer_list.data[cindex]->watch_for_interrupt_char) {
for (uint16_t i = 0; i < len; i++) {
if (data[i] == mp_interrupt_char) {
mp_sched_keyboard_interrupt();
} else {
ringbuf_put(&bleio_characteristic_buffer_list.data[cindex]->ringbuf, data[i]);
}
}
} else {
ringbuf_put_n(&bleio_characteristic_buffer_list.data[cindex]->ringbuf,data, len);
}
taskEXIT_CRITICAL();
return true;
}
}
return false;
}
void _common_hal_bleio_characteristic_buffer_construct(
bleio_characteristic_buffer_obj_t *self,
bleio_characteristic_obj_t *characteristic,
mp_float_t timeout,
uint8_t *buffer, size_t buffer_size,
void *static_handler_entry,
bool watch_for_interrupt_char) {
self->characteristic = characteristic;
self->timeout_ms = timeout * 1000;
self->watch_for_interrupt_char = watch_for_interrupt_char;
ringbuf_init(&self->ringbuf, buffer, buffer_size);
}
void common_hal_bleio_characteristic_buffer_construct(
bleio_characteristic_buffer_obj_t *self,
bleio_characteristic_obj_t *characteristic,
mp_float_t timeout,
size_t buffer_size) {
uint8_t *buffer = m_malloc(buffer_size, true);
_common_hal_bleio_characteristic_buffer_construct(self,
characteristic,
timeout,
buffer,
buffer_size,
NULL,
false);
bleio_characteristic_buffer_list.data[bleio_characteristic_buffer_list.len] = self;
bleio_characteristic_buffer_list.len++;
}
uint32_t common_hal_bleio_characteristic_buffer_read(
bleio_characteristic_buffer_obj_t *self,
uint8_t *data,
size_t len,
int *errcode) {
uint64_t start_ticks = supervisor_ticks_ms64();
// Wait for all bytes received or timeout
while ((ringbuf_num_filled(&self->ringbuf) < len) &&
(supervisor_ticks_ms64() - start_ticks < self->timeout_ms)) {
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
return 0;
}
}
taskENTER_CRITICAL();
uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len);
taskEXIT_CRITICAL();
return num_bytes_read;
}
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(
bleio_characteristic_buffer_obj_t *self) {
return ringbuf_num_filled(&self->ringbuf);
}
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(
bleio_characteristic_buffer_obj_t *self) {
taskENTER_CRITICAL();
ringbuf_clear(&self->ringbuf);
taskEXIT_CRITICAL();
}
bool common_hal_bleio_characteristic_buffer_deinited(
bleio_characteristic_buffer_obj_t *self) {
return self->characteristic == NULL;
}
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
self->characteristic = NULL;
ringbuf_deinit(&self->ringbuf);
}
}
bool common_hal_bleio_characteristic_buffer_connected(
bleio_characteristic_buffer_obj_t *self) {
return self->characteristic != NULL &&
self->characteristic->service != NULL &&
(!self->characteristic->service->is_remote ||
(self->characteristic->service->connection != MP_OBJ_NULL &&
common_hal_bleio_connection_get_connected(self->characteristic->service->connection)));
}
void reset_characteristic_buffer_list() {
// Remove characteristic_buffer list
memset(bleio_characteristic_buffer_list.data, 0,
sizeof(bleio_characteristic_buffer_list.data));
bleio_characteristic_buffer_list.len = 0;
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
#include "py/ringbuf.h"
#include "shared-bindings/_bleio/Characteristic.h"
#define MAX_NUMBER_CHARACTERISTIC_BUFFER 64
#define GET_CHARACTERISTIC_TIMEOUT_MS 1000
typedef struct {
mp_obj_base_t base;
bleio_characteristic_obj_t *characteristic;
uint32_t timeout_ms;
// Ring buffer storing consecutive incoming values
ringbuf_t ringbuf;
bool watch_for_interrupt_char;
} bleio_characteristic_buffer_obj_t;
typedef struct
{
bleio_characteristic_buffer_obj_t *data[MAX_NUMBER_CHARACTERISTIC_BUFFER];
uint8_t len;
} bleio_characteristic_buffer_obj_list_t;
extern bleio_characteristic_buffer_obj_list_t bleio_characteristic_buffer_list;
extern bool characteristic_buffer_on_ble_evt(uint16_t attribute,
uint8_t *data,
uint16_t len);
extern void reset_characteristic_buffer_list();
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H

View File

@ -0,0 +1,274 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "py/gc.h"
#include "py/objlist.h"
#include "py/objstr.h"
#include "py/qstr.h"
#include "py/runtime.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Attribute.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-module/_bleio/Characteristic.h"
#include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/tick.h"
#include "supervisor/serial.h"
// Give 10 seconds for discovery
#define DISCOVERY_TIMEOUT_MS 10000
EventGroupHandle_t xdiscovery_event;
// Get the remote peer status
bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self) {
if (self->connection == NULL) {
return false;
}
return self->connection->pair_status == PAIR_PAIRED;
}
// Get connected status
bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) {
if (self->connection == NULL) {
return false;
}
return self->connection->conn_handle != BLEIO_HANDLE_INVALID;
}
// Disconnects from the remote peripheral
void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) {
sl_bt_connection_close(self->conn_handle);
}
// Pair to the peer to improve security
void common_hal_bleio_connection_pair(bleio_connection_internal_t *self,
bool bond) {
while (self->pair_status == PAIR_WAITING && !mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
if (self->pair_status == PAIR_PAIRED) {
return;
}
self->pair_status = PAIR_WAITING;
while (self->pair_status == PAIR_WAITING && !mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
if (mp_hal_is_interrupted()) {
return;
}
}
// Get time between transmissions in milliseconds
mp_float_t common_hal_bleio_connection_get_connection_interval(
bleio_connection_internal_t *self) {
// TODO: Implement this.
return 0;
}
// The maximum number of data bytes that can be sent in a single transmission
mp_int_t common_hal_bleio_connection_get_max_packet_length(
bleio_connection_internal_t *self) {
sl_status_t sc = sl_bt_gatt_server_get_mtu(self->conn_handle,&self->mtu);
if (sc != SL_STATUS_OK) {
mp_raise_bleio_BluetoothError(translate("gatt_server_get_mtu fail."));
}
return self->mtu;
}
// Set time between transmissions in milliseconds
void common_hal_bleio_connection_set_connection_interval(
bleio_connection_internal_t *self,
mp_float_t new_interval) {
self->conn_params_updating = true;
// TODO: Implement this.
}
// Do BLE discovery for all services
mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(
bleio_connection_obj_t *self,
mp_obj_t service_uuids_whitelist) {
EventBits_t ux_bits;
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable;
mp_obj_t uuid_obj;
mp_obj_tuple_t *services_tuple;
sl_status_t sc = SL_STATUS_FAIL;
bleio_uuid_obj_t *uuid;
uint8_t uuid16_value[2];
uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t current_ticks = start_ticks;
xdiscovery_event = xEventGroupCreate();
if (xdiscovery_event != NULL) {
xEventGroupClearBits(xdiscovery_event,1 << 0);
}
self->connection->remote_service_list = mp_obj_new_list(0, NULL);
bleio_connection_ensure_connected(self);
if (NULL == self->connection->remote_service_list) {
mp_raise_bleio_BluetoothError(
translate("Create new remote service list fail."));
return mp_const_none;
}
vTaskDelay(500 / portTICK_PERIOD_MS);
if (service_uuids_whitelist == mp_const_none) {
sc = sl_bt_gatt_discover_primary_services(self->connection->conn_handle);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Discover uuid fail."));
return mp_const_none;
}
while (current_ticks - start_ticks <= DISCOVERY_TIMEOUT_MS) {
if (xdiscovery_event != NULL) {
ux_bits = xEventGroupWaitBits(
xdiscovery_event,
1 << 0,
pdTRUE,pdFALSE,
DISCOVERY_TIMEOUT_MS / portTICK_PERIOD_MS);
if ((ux_bits & (1 << 0)) == (1 << 0)) {
break;
}
}
current_ticks = supervisor_ticks_ms64();
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
break;
}
}
} else {
iterable = mp_getiter(service_uuids_whitelist, &iter_buf);
while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (!mp_obj_is_type(uuid_obj, &bleio_uuid_type)) {
mp_raise_TypeError(
translate("non-UUID found in service_uuids_whitelist"));
}
uuid = MP_OBJ_TO_PTR(uuid_obj);
if (BLE_UUID_TYPE_16 == uuid->efr_ble_uuid.uuid.type) {
uuid16_value[0] = uuid->efr_ble_uuid.uuid16.value & 0xff;
uuid16_value[1] = uuid->efr_ble_uuid.uuid16.value >> 8;
sc = sl_bt_gatt_discover_primary_services_by_uuid(
self->connection->conn_handle,2,uuid16_value);
} else if (BLE_UUID_TYPE_128 == uuid->efr_ble_uuid.uuid.type) {
sc = sl_bt_gatt_discover_primary_services_by_uuid(
self->connection->conn_handle,
16,
uuid->efr_ble_uuid.uuid128.value);
}
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Discover fail."));
return mp_const_none;
}
while (current_ticks - start_ticks <= DISCOVERY_TIMEOUT_MS) {
if (xdiscovery_event != NULL) {
ux_bits = xEventGroupWaitBits(
xdiscovery_event,
1 << 0,
pdTRUE,
pdFALSE,
DISCOVERY_TIMEOUT_MS / portTICK_PERIOD_MS);
if ((ux_bits & (1 << 0)) == (1 << 0)) {
break;
}
}
current_ticks = supervisor_ticks_ms64();
if (mp_hal_is_interrupted()) {
break;
}
}
}
}
vEventGroupDelete(xdiscovery_event);
services_tuple = mp_obj_new_tuple(self->connection->remote_service_list->len,
self->connection->remote_service_list->items);
if (NULL == services_tuple) {
mp_raise_ValueError(translate("Create new service tuple fail."));
return mp_const_none;
}
return services_tuple;
}
// Get connection handle
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) {
if (self == NULL || self->connection == NULL) {
return BLEIO_HANDLE_INVALID;
}
return self->connection->conn_handle;
}
mp_obj_t bleio_connection_new_from_internal(
bleio_connection_internal_t *internal) {
bleio_connection_obj_t *connection;
if (internal->connection_obj != mp_const_none) {
return internal->connection_obj;
}
connection = m_new_obj(bleio_connection_obj_t);
connection->base.type = &bleio_connection_type;
connection->connection = internal;
internal->connection_obj = connection;
return MP_OBJ_FROM_PTR(connection);
}
// Get internal connection object by handle connection
bleio_connection_internal_t *bleio_conn_handle_to_connection(
uint16_t conn_handle) {
bleio_connection_internal_t *connection;
uint8_t conn_index;
for (conn_index = 0; conn_index < BLEIO_TOTAL_CONNECTION_COUNT; conn_index++) {
connection = &bleio_connections[conn_index];
if (connection->conn_handle == conn_handle) {
return connection;
}
}
return NULL;
}

View File

@ -0,0 +1,96 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CONNECTION_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_CONNECTION_H
#include <stdbool.h>
#include "common-hal/_bleio/__init__.h"
#include "py/obj.h"
#include "py/objlist.h"
#include "common-hal/_bleio/Service.h"
#include "shared-module/_bleio/Address.h"
#include "FreeRTOS.h"
#include "event_groups.h"
typedef enum {
PAIR_NOT_PAIRED,
PAIR_WAITING,
PAIR_PAIRED,
} pair_status_t;
// We split the Connection object into two so that
// the internal mechanics can live outside of theVM.
// If it were one object, then we'd risk user code seeing
// a connection object of theirs be reused.
typedef struct
{
uint16_t conn_handle;
bool is_central;
// Remote services discovered when this peripheral is acting as a client.
mp_obj_list_t *remote_service_list;
// The advertising data and scan response buffers are held by us,
// not by the SD, so we must maintain them and not change it.
// If we need to change the contents during advertising,
// there are tricks to get the SD to notice (see DevZone - TBS).
// bonding_keys_t bonding_keys;
// EDIV: Encrypted Diversifier: Identifies LTK during legacy pairing.
uint16_t ediv;
volatile pair_status_t pair_status;
uint8_t sec_status; // Internal security status.
mp_obj_t connection_obj;
volatile bool conn_params_updating;
uint16_t mtu;
// Request that CCCD values for this connection be saved,
// using sys_attr values.
volatile bool do_bond_cccds;
// Request that security key info for this connection be saved.
volatile bool do_bond_keys;
// Time of setting do_bond_ccds: we delay a bit to consolidate
// multiple CCCD changes into one write. Time is currently in ticks_ms.
uint64_t do_bond_cccds_request_time;
} bleio_connection_internal_t;
typedef struct
{
mp_obj_base_t base;
bleio_connection_internal_t *connection;
// The HCI disconnect reason.
uint8_t disconnect_reason;
} bleio_connection_obj_t;
void bleio_connection_clear(bleio_connection_internal_t *self);
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self);
mp_obj_t bleio_connection_new_from_internal(
bleio_connection_internal_t *connection);
bleio_connection_internal_t *bleio_conn_handle_to_connection(
uint16_t conn_handle);
extern EventGroupHandle_t xdiscovery_event;
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CONNECTION_H

View File

@ -0,0 +1,114 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
void common_hal_bleio_descriptor_construct(
bleio_descriptor_obj_t *self,
bleio_characteristic_obj_t *characteristic,
bleio_uuid_obj_t *uuid,
bleio_attribute_security_mode_t read_perm,
bleio_attribute_security_mode_t write_perm,
mp_int_t max_length, bool fixed_length,
mp_buffer_info_t *initial_value_bufinfo) {
const mp_int_t max_length_max = BLE_ATT_ATTR_MAX_LEN;
self->uuid = uuid;
self->handle = BLEIO_HANDLE_INVALID;
self->read_perm = read_perm;
self->write_perm = write_perm;
self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf,
initial_value_bufinfo->len);
if (max_length < 0 || max_length > max_length_max) {
mp_raise_ValueError_varg(
translate("max_length must be 0-%d when fixed_length is %s"),
max_length_max, fixed_length ? "True" : "False");
}
self->max_length = max_length;
self->fixed_length = fixed_length;
}
// Get descriptor uuid
bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(
bleio_descriptor_obj_t *self) {
return self->uuid;
}
bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(
bleio_descriptor_obj_t *self) {
return self->characteristic;
}
size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self,
uint8_t *buf, size_t len) {
uint16_t conn_handle;
if (self->handle != BLE_GATT_HANDLE_INVALID) {
conn_handle = bleio_connection_get_conn_handle(
self->characteristic->service->connection);
if (common_hal_bleio_service_get_is_remote(
self->characteristic->service)) {
sl_bt_gatt_read_descriptor_value(conn_handle, self->handle);
}
}
return 0;
}
// Set value to descriptor
void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self,
mp_buffer_info_t *bufinfo) {
uint16_t conn_handle;
if (self->handle != BLE_GATT_HANDLE_INVALID) {
conn_handle = bleio_connection_get_conn_handle(
self->characteristic->service->connection);
if (common_hal_bleio_service_get_is_remote(
self->characteristic->service)) {
// false means WRITE_REQ, not write-no-response
sl_bt_gatt_write_descriptor_value(conn_handle,
self->handle,
bufinfo->len,
bufinfo->buf);
} else {
// Validate data length for local descriptors only.
if (self->fixed_length && bufinfo->len != self->max_length) {
mp_raise_ValueError(
translate("Value length != required fixed length"));
}
if (bufinfo->len > self->max_length) {
mp_raise_ValueError(translate("Value length > max_length"));
}
}
}
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_DESCRIPTOR_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_DESCRIPTOR_H
#include "py/obj.h"
#include "common-hal/_bleio/UUID.h"
#include "shared-module/_bleio/Attribute.h"
#define BLE_ATT_ATTR_MAX_LEN 50
// Forward declare characteristic because it includes a Descriptor.
struct _bleio_characteristic_obj;
typedef struct _bleio_descriptor_obj {
mp_obj_base_t base;
// Will be MP_OBJ_NULL before being assigned to a Characteristic.
struct _bleio_characteristic_obj *characteristic;
bleio_uuid_obj_t *uuid;
mp_obj_t initial_value;
uint16_t max_length;
bool fixed_length;
uint16_t handle;
// struct ble_gatt_dsc_def def;
bleio_attribute_security_mode_t read_perm;
bleio_attribute_security_mode_t write_perm;
} bleio_descriptor_obj_t;
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_DESCRIPTOR_H

View File

@ -0,0 +1,399 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "py/runtime.h"
#include "py/stream.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/PacketBuffer.h"
#include "shared/runtime/interrupt_char.h"
#include "common-hal/_bleio/Connection.h"
#include "supervisor/shared/tick.h"
#include "supervisor/serial.h"
// List packet buffer of peripheral device
bleio_packet_buffer_obj_list_t bleio_packet_buffer_list;
// Write data to ringbuf of packet buffer
STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self,
uint8_t *data,
uint16_t len) {
uint16_t packet_length;
uint16_t packet_index;
if (len + sizeof(uint16_t) > ringbuf_size(&self->ringbuf)) {
// This shouldn't happen but can if our buffer size was much smaller than
// the writes the client actually makes.
return;
}
taskENTER_CRITICAL();
// Push all the data onto the ring buffer.
// Make room for the new value by dropping the oldest packets first.
while (ringbuf_size(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
ringbuf_get_n(&self->ringbuf,
(uint8_t *)&packet_length, sizeof(uint16_t));
for (packet_index = 0; packet_index < packet_length; packet_index++) {
ringbuf_get(&self->ringbuf);
}
}
ringbuf_put_n(&self->ringbuf, (uint8_t *)&len, sizeof(uint16_t));
ringbuf_put_n(&self->ringbuf, data, len);
taskEXIT_CRITICAL();
}
// Write characteristic or attribute value
STATIC int queue_next_write(bleio_packet_buffer_obj_t *self) {
self->packet_queued = false;
uint32_t sc = SL_STATUS_OK;
if (self->pending_size > 0) {
if (self->client) {
if (self->write_type & BT_GATT_CHRC_WRITE_WITHOUT_RESP) {
uint16_t sent_len;
sc = sl_bt_gatt_write_characteristic_value_without_response(
self->conn_handle, self->characteristic->handle,
self->pending_size,
(uint8_t *)self->outgoing[self->pending_index],
&sent_len);
} else {
sc = sl_bt_gatt_write_characteristic_value(
self->conn_handle, self->characteristic->handle,
self->pending_size,
(uint8_t *)self->outgoing[self->pending_index]);
}
} else {
if (self->write_type & BT_GATT_CHRC_READ) {
sc = sl_bt_gatt_server_write_attribute_value(self->characteristic->handle,
0,
self->pending_size,
(uint8_t *)self->outgoing[self->pending_index]);
}
if (self->write_type & BT_GATT_CHRC_NOTIFY) {
sc = sl_bt_gatt_server_send_notification(
self->conn_handle,
self->characteristic->handle,
self->pending_size,
(uint8_t *)self->outgoing[self->pending_index]);
}
if (self->write_type & BT_GATT_CHRC_INDICATE) {
sl_bt_gatt_server_send_indication(
self->conn_handle,
self->characteristic->handle,
self->pending_size,
(uint8_t *)self->outgoing[self->pending_index]);
}
}
self->pending_size = 0;
self->pending_index = (self->pending_index + 1) % 2;
self->packet_queued = true;
}
return sc;
}
// This funttion is called in sl_bt_on_event to receive
bool packet_buffer_on_ble_evt(uint16_t attribute, uint8_t *data, uint16_t len) {
uint16_t cindex = 0;
for (cindex = 0; cindex < bleio_packet_buffer_list.len; cindex++) {
if (bleio_packet_buffer_list.data[cindex]->characteristic->handle == attribute) {
taskENTER_CRITICAL();
write_to_ringbuf(bleio_packet_buffer_list.data[cindex], data, len);
taskEXIT_CRITICAL();
return true;
}
}
return false;
}
void _common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self,
bleio_characteristic_obj_t *characteristic,
uint32_t *incoming_buffer,
size_t incoming_buffer_size,
uint32_t *outgoing_buffer1,
uint32_t *outgoing_buffer2,
size_t max_packet_size,
void *static_handler_entry) {
bleio_characteristic_properties_t temp_prop;
self->characteristic = characteristic;
self->client = self->characteristic->service->is_remote;
self->max_packet_size = max_packet_size;
bleio_characteristic_properties_t incoming = self->characteristic->props & (BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_WRITE);
bleio_characteristic_properties_t outgoing = self->characteristic->props & (BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE);
if (self->client) {
// Swap if we're the client.
temp_prop = incoming;
incoming = outgoing;
outgoing = temp_prop;
self->conn_handle = bleio_connection_get_conn_handle(
MP_OBJ_TO_PTR(self->characteristic->service->connection));
} else {
self->conn_handle = BLE_CONN_HANDLE_INVALID;
}
if (incoming) {
ringbuf_init(&self->ringbuf,
(uint8_t *)incoming_buffer,
incoming_buffer_size);
}
self->packet_queued = false;
self->pending_index = 0;
self->pending_size = 0;
self->outgoing[0] = outgoing_buffer1;
self->outgoing[1] = outgoing_buffer2;
if (self->client) {
if (incoming) {
if (incoming & BT_GATT_CHRC_NOTIFY) {
common_hal_bleio_characteristic_set_cccd(self->characteristic,
true, false);
} else {
common_hal_bleio_characteristic_set_cccd(self->characteristic,
false, true);
}
}
if (outgoing) {
self->write_type = BT_GATT_CHRC_WRITE;
if (outgoing & BT_GATT_CHRC_WRITE_WITHOUT_RESP) {
self->write_type = BT_GATT_CHRC_WRITE_WITHOUT_RESP;
}
}
} else {
self->write_type = outgoing;
}
}
// Init packet buffer
void common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
size_t buffer_size, size_t max_packet_size) {
size_t incoming_buffer_size = 0;
uint32_t *incoming_buffer = NULL;
uint32_t *outgoing1 = NULL;
uint32_t *outgoing2 = NULL;
bleio_characteristic_properties_t temp_properties;
// Cap the packet size to our implementation limits.
max_packet_size = MIN(max_packet_size, BLE_GATTS_VAR_ATTR_LEN_MAX - 3);
bleio_characteristic_properties_t incoming = characteristic->props & (BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_WRITE);
bleio_characteristic_properties_t outgoing = characteristic->props & (BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE);
if (characteristic->service->is_remote) {
// Swap if we're the client.
temp_properties = incoming;
incoming = outgoing;
outgoing = temp_properties;
}
if (incoming) {
incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size);
incoming_buffer = m_malloc(incoming_buffer_size, false);
}
if (outgoing) {
outgoing1 = m_malloc(max_packet_size, false);
outgoing2 = m_malloc(max_packet_size, false);
}
_common_hal_bleio_packet_buffer_construct(self, characteristic,
incoming_buffer, incoming_buffer_size,
outgoing1, outgoing2, max_packet_size,
NULL);
bleio_packet_buffer_list.data[bleio_packet_buffer_list.len] = self;
bleio_packet_buffer_list.len++;
}
// Reads a single BLE packet into the buffer
mp_int_t common_hal_bleio_packet_buffer_readinto(
bleio_packet_buffer_obj_t *self,
uint8_t *data,
size_t len) {
mp_int_t ret;
uint16_t packet_length;
if (ringbuf_num_filled(&self->ringbuf) < 1) {
return 0;
}
taskENTER_CRITICAL();
// Get packet length, which is in first two bytes of packet.
packet_length = 5;
ringbuf_get_n(&self->ringbuf, (uint8_t *)&packet_length, sizeof(uint16_t));
if (packet_length > len) {
// Packet is longer than requested. Return negative of overrun value.
ret = len - packet_length;
// Discard the packet if it's too large. Don't fill data.
while (packet_length--) {
(void)ringbuf_get(&self->ringbuf);
}
} else {
// Read as much as possible, but might be shorter than len.
ringbuf_get_n(&self->ringbuf, data, packet_length);
ret = packet_length;
}
taskEXIT_CRITICAL();
return ret;
}
// Writes all bytes from data into the same outgoing packet
mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self,
const uint8_t *data,
size_t len,
uint8_t *header,
size_t header_len) {
mp_int_t outgoing_packet_length;
mp_int_t total_len;
size_t num_bytes_written;
uint32_t *pending;
if (!self->client) {
self->conn_handle = bleio_connections[0].conn_handle;
}
if (self->outgoing[0] == NULL) {
mp_raise_bleio_BluetoothError(
translate("Writes not supported on Characteristic"));
}
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
return -1;
}
outgoing_packet_length =
common_hal_bleio_packet_buffer_get_outgoing_packet_length(self);
if (outgoing_packet_length < 0) {
return -1;
}
total_len = len + header_len;
if (total_len > outgoing_packet_length) {
// Supplied data will not fit in a single BLE packet.
mp_raise_ValueError_varg(
translate("Total data to write is larger than %q"),
MP_QSTR_outgoing_packet_length);
}
if (total_len > self->max_packet_size) {
// Supplied data will not fit in a single BLE packet.
mp_raise_ValueError_varg(
translate("Total data to write is larger than %q"),
MP_QSTR_max_packet_size);
}
outgoing_packet_length = MIN(outgoing_packet_length, self->max_packet_size);
if (len + self->pending_size > (size_t)outgoing_packet_length) {
// No room to append len bytes to packet. Wait until we get a free buffer
// and keep checking that we haven't been disconnected.
while (self->pending_size != 0 &&
self->conn_handle != BLE_CONN_HANDLE_INVALID &&
!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
if (mp_hal_is_interrupted()) {
return -1;
}
}
if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
return -1;
}
num_bytes_written = 0;
pending = self->outgoing[self->pending_index];
if (self->pending_size == 0) {
memcpy(pending, header, header_len);
self->pending_size += header_len;
num_bytes_written += header_len;
}
memcpy(((uint8_t *)pending) + self->pending_size, data, len);
self->pending_size += len;
num_bytes_written += len;
queue_next_write(self);
return num_bytes_written;
}
// Get length of receiving packet
mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(
bleio_packet_buffer_obj_t *self) {
if (self->characteristic == NULL) {
return -1;
}
return self->characteristic->max_length;
}
// Get length of outgoing packet
mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(
bleio_packet_buffer_obj_t *self) {
if (self->characteristic == NULL) {
return -1;
}
return MIN(self->max_packet_size, self->characteristic->max_length);
}
// Flush ring buffer og packer buffer
void common_hal_bleio_packet_buffer_flush(bleio_packet_buffer_obj_t *self) {
while ((self->pending_size != 0 ||
self->packet_queued) &&
self->conn_handle != BLEIO_HANDLE_INVALID &&
!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
}
// Check status of packet buffer obj
bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
return self->characteristic == NULL;
}
// Deinit packet buffer
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
if (!common_hal_bleio_packet_buffer_deinited(self)) {
ringbuf_deinit(&self->ringbuf);
}
}
// Remove packet_buffer list when reload
void reset_packet_buffer_list() {
// Remove packet_buffer list
memset(bleio_packet_buffer_list.data, 0,
sizeof(bleio_packet_buffer_list.data));
bleio_packet_buffer_list.len = 0;
}

View File

@ -0,0 +1,64 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_PACKETBUFFER_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_PACKETBUFFER_H
#include "py/ringbuf.h"
#include "shared-bindings/_bleio/Characteristic.h"
#define MAX_NUMBER_PACKET_BUFFER 64
typedef struct {
mp_obj_base_t base;
bleio_characteristic_obj_t *characteristic;
// Ring buffer storing consecutive incoming values.
ringbuf_t ringbuf;
// Two outgoing buffers to alternate between.
// One will be queued for transmission by the SD and
// the other is waiting to be queued and can be extended.
uint32_t *outgoing[2];
volatile uint16_t pending_size;
// We remember the conn_handle so we can do a NOTIFY/INDICATE to a client.
// We can find out the conn_handle on a Characteristic write
// or a CCCD write (but not a read).
volatile uint16_t conn_handle;
uint16_t max_packet_size;
uint8_t pending_index;
uint8_t write_type;
bool client;
bool packet_queued;
} bleio_packet_buffer_obj_t;
typedef struct {
bleio_packet_buffer_obj_t *data[MAX_NUMBER_PACKET_BUFFER];
uint8_t len;
} bleio_packet_buffer_obj_list_t;
extern bool packet_buffer_on_ble_evt(uint16_t attribute,
uint8_t *data,
uint16_t len);
extern void reset_packet_buffer_list();
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_PACKETBUFFER_H

View File

@ -0,0 +1,242 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "common-hal/_bleio/__init__.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
// List ble service of central device
bleio_service_obj_list bleio_service_list;
uint32_t _common_hal_bleio_service_construct(
bleio_service_obj_t *self,
bleio_uuid_obj_t *uuid,
bool is_secondary,
mp_obj_list_t *characteristic_list) {
uint8_t service_type;
sl_status_t sc = SL_STATUS_FAIL;
uint16_t gattdb_session;
sl_bt_uuid_16_t bt_uuid;
self->handle = 0xFFFF;
self->uuid = uuid;
self->characteristic_list = characteristic_list;
self->is_remote = false;
self->connection = NULL;
self->is_secondary = is_secondary;
if (self->is_secondary) {
service_type = sl_bt_gattdb_secondary_service;
} else {
service_type = sl_bt_gattdb_primary_service;
}
sc = sl_bt_gattdb_new_session(&gattdb_session);
if (SL_STATUS_OK != sc && SL_STATUS_ALREADY_EXISTS != sc) {
mp_raise_bleio_BluetoothError(translate("Create new session fail."));
return sc;
}
if (BLE_UUID_TYPE_16 == self->uuid->efr_ble_uuid.uuid.type) {
bt_uuid.data[0] = self->uuid->efr_ble_uuid.uuid16.value & 0xff;
bt_uuid.data[1] = self->uuid->efr_ble_uuid.uuid16.value >> 8;
sc = sl_bt_gattdb_add_service(gattdb_session,
service_type,
0, 2, bt_uuid.data,
(uint16_t *)&self->handle);
} else if (BLE_UUID_TYPE_128 == self->uuid->efr_ble_uuid.uuid.type) {
sc = sl_bt_gattdb_add_service(gattdb_session,
service_type, 0, 16,
self->uuid->efr_ble_uuid.uuid128.value,
(uint16_t *)&self->handle);
}
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Create new session fail."));
return sc;
}
sc = sl_bt_gattdb_start_service(gattdb_session, self->handle);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Start service fail."));
}
sc = sl_bt_gattdb_commit(gattdb_session);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Commit service fail."));
}
bleio_service_list.data[bleio_service_list.len] = self;
bleio_service_list.len++;
return sc;
}
// Create a new Service identified by the specified UUID
void common_hal_bleio_service_construct(bleio_service_obj_t *self,
bleio_uuid_obj_t *uuid,
bool is_secondary) {
_common_hal_bleio_service_construct(self, uuid,
is_secondary,
mp_obj_new_list(0, NULL));
}
// Get service from connection
void bleio_service_from_connection(bleio_service_obj_t *self,
mp_obj_t connection) {
self->handle = BLEIO_HANDLE_INVALID;
self->uuid = NULL;
self->characteristic_list = mp_obj_new_list(0, NULL);
self->is_remote = true;
self->is_secondary = false;
self->connection = connection;
}
// Get service uuid
bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
return self->uuid;
}
// Get tuple charateristic of service
mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(
bleio_service_obj_t *self) {
return mp_obj_new_tuple(self->characteristic_list->len,
self->characteristic_list->items);
}
// This is a service provided by a remote device or not
bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
return self->is_remote;
}
// If the service is a secondary one
bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
return self->is_secondary;
}
// Add new dynamic characteristic to service
void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
bleio_characteristic_obj_t *characteristic,
mp_buffer_info_t *initial_value_bufinfo,
const char *user_description) {
bool broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0;
bool read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0;
bool write_wo_resp =
(characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) ? 1 : 0;
bool write =
write_wo_resp ? 1 : (characteristic->props & CHAR_PROP_WRITE) ? 1
: 0;
bool notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0;
bool indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0;
sl_status_t sc = SL_STATUS_FAIL;
sl_bt_uuid_16_t bt_uuid;
uint16_t gattdb_session;
sc = sl_bt_gattdb_new_session(&gattdb_session);
if (SL_STATUS_OK != sc && SL_STATUS_ALREADY_EXISTS != sc) {
mp_raise_bleio_BluetoothError(translate("Create new session fail."));
return;
}
characteristic->props = (broadcast << 0) | (read << 1) |
(write_wo_resp << 2) | (write << 3) | (notify << 4) | (indicate << 5);
if (BLE_UUID_TYPE_16 == characteristic->uuid->efr_ble_uuid.uuid.type) {
bt_uuid.data[0] = characteristic->uuid->efr_ble_uuid.uuid16.value & 0xff;
bt_uuid.data[1] = characteristic->uuid->efr_ble_uuid.uuid16.value >> 8;
sc = sl_bt_gattdb_add_uuid16_characteristic(
gattdb_session,
self->handle,
characteristic->props,
0,
0,
bt_uuid,
sl_bt_gattdb_variable_length_value,
characteristic->max_length,
0,
initial_value_bufinfo->buf,
&characteristic->handle);
} else if (BLE_UUID_TYPE_128 ==
characteristic->uuid->efr_ble_uuid.uuid.type) {
uuid_128 uuid;
memcpy(uuid.data, characteristic->uuid->efr_ble_uuid.uuid128.value, 16);
sc = sl_bt_gattdb_add_uuid128_characteristic(gattdb_session,
self->handle,
characteristic->props,
0,
0,
uuid,
sl_bt_gattdb_variable_length_value,
characteristic->max_length,
0,
initial_value_bufinfo->buf,
&characteristic->handle);
}
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Add charateristic fail."));
}
sc = sl_bt_gattdb_start_characteristic(gattdb_session,
characteristic->handle);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Start charateristic fail."));
return;
}
sc = sl_bt_gattdb_commit(gattdb_session);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Commit charateristic fail."));
return;
}
mp_obj_list_append(self->characteristic_list,
MP_OBJ_FROM_PTR(characteristic));
}
// Remove dynamic service when reload
void reset_dynamic_service() {
uint16_t gattdb_session;
uint8_t svc_index;
// Remove dynamic service
for (svc_index = 0; svc_index < bleio_service_list.len; svc_index++) {
sl_bt_gattdb_new_session(&gattdb_session);
sl_bt_gattdb_remove_service(gattdb_session,
bleio_service_list.data[svc_index]->handle);
sl_bt_gattdb_commit(gattdb_session);
}
bleio_service_list.len = 0;
}

View File

@ -0,0 +1,63 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_SERVICE_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_SERVICE_H
#include "py/objlist.h"
#include "common-hal/_bleio/UUID.h"
#define MAX_NUMBER_SERVICE 64
typedef struct bleio_service_obj
{
mp_obj_base_t base;
// Handle for the local service.
uint32_t handle;
// True if created during discovery.
bool is_remote;
bool is_secondary;
bleio_uuid_obj_t *uuid;
// The connection object is set only when this is a remote service.
// A local service doesn't know the connection.
mp_obj_t connection;
mp_obj_list_t *characteristic_list;
// Range of attribute handles of this remote service.
uint16_t start_handle;
uint16_t end_handle;
} bleio_service_obj_t;
typedef struct
{
bleio_service_obj_t *data[MAX_NUMBER_SERVICE];
uint8_t len;
} bleio_service_obj_list;
void bleio_service_from_connection(bleio_service_obj_t *self,
mp_obj_t connection);
uint16_t get_characteristic_handle(bleio_uuid_obj_t *uuid);
extern void reset_dynamic_service();
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_SERVICE_H

View File

@ -0,0 +1,83 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/UUID.h"
#include "shared-bindings/_bleio/__init__.h"
#include "common-hal/_bleio/UUID.h"
void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self,
mp_int_t uuid16,
const uint8_t uuid128[16]) {
if (uuid128 == NULL) {
self->efr_ble_uuid.uuid16.value = uuid16;
self->efr_ble_uuid.uuid.type = BLE_UUID_TYPE_16;
} else {
memcpy(self->efr_ble_uuid.uuid128.value, uuid128, 16);
self->efr_ble_uuid.uuid128.value[12] = uuid16 & 0xff;
self->efr_ble_uuid.uuid128.value[13] = (uuid16 >> 8) & 0xff;
self->efr_ble_uuid.uuid.type = BLE_UUID_TYPE_128;
}
}
uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) {
return self->efr_ble_uuid.uuid.type == BLE_UUID_TYPE_16 ? 16 : 128;
}
uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) {
return self->efr_ble_uuid.uuid16.value;
}
void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self,
uint8_t uuid128[16]) {
memcpy(uuid128, self->efr_ble_uuid.uuid128.value, 16);
}
void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t *buf) {
if (self->efr_ble_uuid.uuid.type == BLE_UUID_TYPE_16) {
buf[0] = self->efr_ble_uuid.uuid16.value & 0xff;
buf[1] = self->efr_ble_uuid.uuid16.value >> 8;
} else {
common_hal_bleio_uuid_get_uuid128(self, buf);
}
}
void bleio_uuid_construct_from_efr_ble_uuid(bleio_uuid_obj_t *self,
ble_uuid_any_t *efr_ble_uuid) {
if (self->efr_ble_uuid.uuid.type == BLE_UUID_TYPE_16) {
mp_raise_bleio_BluetoothError(translate("Unexpected efr uuid type"));
}
self->efr_ble_uuid.uuid16.value = efr_ble_uuid->uuid16.value;
}
void bleio_uuid_convert_to_efr_ble_uuid(bleio_uuid_obj_t *self,
ble_uuid_any_t *efr_ble_uuid) {
efr_ble_uuid->uuid16.value = self->efr_ble_uuid.uuid16.value;
}

View File

@ -0,0 +1,90 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_UUID_H
#define MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_UUID_H
#include "py/obj.h"
#define UUID16_LEN 2
#define UUID128_LEN 16
// Type of UUID
typedef enum {
// 16-bit UUID (BT SIG assigned)
BLE_UUID_TYPE_16 = 16,
// 32-bit UUID (BT SIG assigned)
BLE_UUID_TYPE_32 = 32,
// 128-bit UUID
BLE_UUID_TYPE_128 = 128,
} uuid_type_e;
typedef struct {
// Type of the UUID
uint8_t type;
} ble_uuid_t;
// 16-bit UUID
typedef struct {
uint8_t type;
uint16_t value;
} ble_uuid16_t;
// 32-bit UUID
typedef struct {
uint8_t type;
uint32_t value;
} ble_uuid32_t;
// 128-bit UUID
typedef struct {
uint8_t type;
uint8_t value[16];
} ble_uuid128_t;
typedef union {
ble_uuid_t uuid;
ble_uuid16_t uuid16;
ble_uuid32_t uuid32;
ble_uuid128_t uuid128;
} ble_uuid_any_t;
typedef struct {
mp_obj_base_t base;
// Use the native way of storing UUID's:
// - ble_uuid_t.uuid is a 16-bit uuid.
// - ble_uuid_t.type is BLE_UUID_TYPE_BLE if it's a 16-bit Bluetooth SIG UUID.
// or is BLE_UUID_TYPE_VENDOR_BEGIN and higher, which indexes into a table of registered
// 128-bit UUIDs.
ble_uuid_any_t efr_ble_uuid;
} bleio_uuid_obj_t;
void bleio_uuid_construct_from_efr_ble_uuid(bleio_uuid_obj_t *self,
ble_uuid_any_t *efr_ble_uuid);
void bleio_uuid_convert_to_efr_ble_uuid(bleio_uuid_obj_t *self,
ble_uuid_any_t *efr_ble_uuid);
#endif // MICROPY_INCLUDED_EFR_COMMON_HAL_BLEIO_UUID_H

View File

@ -0,0 +1,402 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
#include "shared-bindings/_bleio/PacketBuffer.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
#include "supervisor/shared/bluetooth/bluetooth.h"
#include "common-hal/_bleio/__init__.h"
STATIC conn_state_t conn_state;
osMutexId_t bluetooth_connection_mutex_id;
bleio_adapter_obj_t common_hal_bleio_adapter_obj;
__ALIGNED(4) static uint8_t bluetooth_connection_mutex_cb[osMutexCbSize];
const osMutexAttr_t bluetooth_connection_mutex_attr = {
.name = "Bluetooth Mutex",
.attr_bits = osMutexRecursive | osMutexPrioInherit,
.cb_mem = bluetooth_connection_mutex_cb,
.cb_size = osMutexCbSize
};
void bleio_user_reset() {
// Stop any user scanning or advertising.
common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj);
common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj);
// Maybe start advertising the BLE workflow.
supervisor_bluetooth_background();
}
void bleio_reset() {
reset_dynamic_service();
reset_packet_buffer_list();
reset_characteristic_buffer_list();
bleio_adapter_reset(&common_hal_bleio_adapter_obj);
// Set this explicitly to save data.
common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type;
if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
return;
}
supervisor_stop_bluetooth();
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false);
supervisor_start_bluetooth();
}
void bleio_background(void) {
}
void common_hal_bleio_gc_collect(void) {
bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
}
void check_ble_error(int error_code) {
if (error_code == SL_STATUS_OK) {
return;
}
switch (error_code) {
case SL_STATUS_TIMEOUT:
mp_raise_msg(&mp_type_TimeoutError, NULL);
return;
default:
mp_raise_bleio_BluetoothError(
translate("Unknown BLE error: %d"), error_code);
break;
}
}
void common_hal_bleio_check_connected(uint16_t conn_handle) {
if (conn_handle == BLEIO_HANDLE_INVALID) {
mp_raise_ConnectionError(translate("Not connected"));
}
}
// Bluetooth stack event handler.
void sl_bt_on_event(sl_bt_msg_t *evt) {
sl_status_t sc = SL_STATUS_OK;
bd_addr address;
uint8_t address_type = 0;
STATIC uint8_t serv_idx = 0;
STATIC uint8_t device_name[16];
bleio_connection_internal_t *connection;
bleio_service_obj_t *service;
bleio_characteristic_obj_t *characteristic;
bleio_uuid_obj_t *uuid;
bleio_characteristic_properties_t props;
switch (SL_BT_MSG_ID(evt->header)) {
case sl_bt_evt_system_boot_id:
sc = sl_bt_system_get_identity_address(&address, &address_type);
snprintf((char *)device_name, 14 + 1,
"CIRCUITPY-%X%X",address.addr[1], address.addr[0]);
sl_bt_gatt_server_write_attribute_value(gattdb_device_name,
0,14,device_name);
sc = sl_bt_sm_configure(0x00,sl_bt_sm_io_capability_noinputnooutput);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Sm configure fail"));
}
sc = sl_bt_sm_set_bondable_mode(1);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(translate("Set bondable mode fail"));
}
sl_bt_sm_delete_bondings();
break;
// This event indicates that a new connection was opened.
case sl_bt_evt_connection_opened_id:
serv_idx = 0;
osMutexAcquire(bluetooth_connection_mutex_id, osWaitForever);
// Device role is Peripheral
if (evt->data.evt_connection_opened.master == 0) {
bleio_connections[0].conn_handle =
evt->data.evt_connection_opened.connection;
bleio_connections[0].connection_obj = mp_const_none;
bleio_connections[0].pair_status = PAIR_PAIRED;
bleio_connections[0].is_central = false;
bleio_connections[0].mtu = 0;
}
sc = sl_bt_sm_increase_security(
evt->data.evt_connection_opened.connection);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(
translate("Increase security fail."));
}
osMutexRelease(bluetooth_connection_mutex_id);
break;
case sl_bt_evt_scanner_legacy_advertisement_report_id:
set_scan_device_info_on_ble_evt(
evt->data.evt_scanner_legacy_advertisement_report.address,
evt->data.evt_scanner_legacy_advertisement_report.address_type,
evt->data.evt_scanner_legacy_advertisement_report.rssi,
&evt->data.evt_scanner_legacy_advertisement_report.data);
if (xscan_event != NULL) {
xEventGroupSetBits(xscan_event,1 << 0);
}
break;
case sl_bt_evt_connection_closed_id:
common_hal_bleio_adapter_remove_connection(
evt->data.evt_connection_closed.connection);
break;
case sl_bt_evt_system_external_signal_id:
if (evt->data.evt_system_external_signal.extsignals & 1) {
sl_bt_external_signal(0);
}
break;
case sl_bt_evt_gatt_service_id:
osMutexAcquire(bluetooth_connection_mutex_id, osWaitForever);
connection = bleio_conn_handle_to_connection(
evt->data.evt_gatt_service.connection);
service = m_new_obj(bleio_service_obj_t);
if (NULL == service) {
mp_raise_bleio_BluetoothError(
translate("Create new service obj fail"));
}
service->base.type = &bleio_service_type;
bleio_service_from_connection(service,
bleio_connection_new_from_internal(connection));
service->is_remote = true;
service->handle = evt->data.evt_gatt_service.service;
uuid = m_new_obj(bleio_uuid_obj_t);
if (NULL == uuid) {
osMutexRelease(bluetooth_connection_mutex_id);
mp_raise_bleio_BluetoothError(
translate("Create new service uuid obj fail"));
break;
}
uuid->base.type = &bleio_uuid_type;
if (UUID16_LEN == evt->data.evt_gatt_service.uuid.len) {
uuid->efr_ble_uuid.uuid16.value &= 0x0000;
uuid->efr_ble_uuid.uuid16.value
|= evt->data.evt_gatt_service.uuid.data[1];
uuid->efr_ble_uuid.uuid16.value =
(uuid->efr_ble_uuid.uuid16.value << 8)
| evt->data.evt_gatt_service.uuid.data[0];
uuid->efr_ble_uuid.uuid.type = BLE_UUID_TYPE_16;
} else if (UUID128_LEN == evt->data.evt_gatt_service.uuid.len) {
memcpy(uuid->efr_ble_uuid.uuid128.value,
evt->data.evt_gatt_service.uuid.data, UUID128_LEN);
uuid->efr_ble_uuid.uuid.type = BLE_UUID_TYPE_128;
}
service->uuid = uuid;
mp_obj_list_append(MP_OBJ_FROM_PTR(connection->remote_service_list),
MP_OBJ_FROM_PTR(service));
conn_state = DISCOVER_SERVICES;
osMutexRelease(bluetooth_connection_mutex_id);
break;
case sl_bt_evt_gatt_characteristic_id:
osMutexAcquire(bluetooth_connection_mutex_id, osWaitForever);
connection = bleio_conn_handle_to_connection(
evt->data.evt_gatt_characteristic.connection);
service =
MP_OBJ_TO_PTR(connection->remote_service_list->items[serv_idx - 1]);
characteristic = m_new_obj(bleio_characteristic_obj_t);
if (characteristic == NULL) {
mp_raise_bleio_BluetoothError(
translate("Create new characteristic obj fail."));
}
characteristic->base.type = &bleio_characteristic_type;
uuid = m_new_obj(bleio_uuid_obj_t);
if (uuid == NULL) {
mp_raise_bleio_BluetoothError(
translate("Create new characteristic uuid obj fail."));
break;
}
uuid->base.type = &bleio_uuid_type;
if (UUID16_LEN == evt->data.evt_gatt_characteristic.uuid.len) {
uuid->efr_ble_uuid.uuid16.value &= 0x0000;
uuid->efr_ble_uuid.uuid16.value
|= evt->data.evt_gatt_characteristic.uuid.data[1];
uuid->efr_ble_uuid.uuid16.value =
(uuid->efr_ble_uuid.uuid16.value << 8)
| evt->data.evt_gatt_characteristic.uuid.data[0];
uuid->efr_ble_uuid.uuid.type = BLE_UUID_TYPE_16;
} else if (
UUID128_LEN == evt->data.evt_gatt_characteristic.uuid.len) {
memcpy(uuid->efr_ble_uuid.uuid128.value,
evt->data.evt_gatt_characteristic.uuid.data,
UUID128_LEN);
uuid->efr_ble_uuid.uuid.type = BLE_UUID_TYPE_128;
}
props = evt->data.evt_gatt_characteristic.properties;
characteristic->handle =
evt->data.evt_gatt_characteristic.characteristic;
characteristic->props = props;
common_hal_bleio_characteristic_construct(
characteristic, service,
evt->data.evt_gatt_characteristic.characteristic, uuid,
props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
0, false,
mp_const_empty_bytes,
NULL);
mp_obj_list_append(MP_OBJ_FROM_PTR(service->characteristic_list),
MP_OBJ_FROM_PTR(characteristic));
osMutexRelease(bluetooth_connection_mutex_id);
break;
case sl_bt_evt_gatt_procedure_completed_id:
if (conn_state == DISCOVER_SERVICES
|| conn_state == DISCOVER_CHARACTERISTICS) {
connection = MP_OBJ_TO_PTR(
bleio_conn_handle_to_connection(
evt->data.evt_gatt_procedure_completed.connection));
if (connection != NULL
&& serv_idx < connection->remote_service_list->len) {
service = connection->remote_service_list->items[serv_idx];
sc = sl_bt_gatt_discover_characteristics(
evt->data.evt_gatt_procedure_completed.connection,
service->handle);
conn_state = DISCOVER_CHARACTERISTICS;
serv_idx++;
} else {
conn_state = RUNNING;
serv_idx = 0;
if (xdiscovery_event != NULL) {
xEventGroupSetBits(xdiscovery_event,1 << 0);
}
}
}
break;
case sl_bt_evt_gatt_characteristic_value_id:
if (characteristic_buffer_on_ble_evt(
evt->data.evt_gatt_characteristic_value.characteristic,
evt->data.evt_gatt_characteristic_value.value.data,
evt->data.evt_gatt_characteristic_value.value.len)) {
} else if (packet_buffer_on_ble_evt(
evt->data.evt_gatt_characteristic_value.characteristic,
evt->data.evt_gatt_characteristic_value.value.data,
evt->data.evt_gatt_characteristic_value.value.len)) {
} else {
set_characteristic_value_on_ble_evt(
evt->data.evt_gatt_characteristic_value.connection,
evt->data.evt_gatt_characteristic_value.characteristic,
evt->data.evt_gatt_characteristic_value.value.data,
evt->data.evt_gatt_characteristic_value.value.len);
}
sl_bt_gatt_send_characteristic_confirmation(
evt->data.evt_gatt_characteristic_value.connection);
break;
case sl_bt_evt_gatt_server_attribute_value_id:
if (characteristic_buffer_on_ble_evt(
evt->data.evt_gatt_server_attribute_value.attribute,
evt->data.evt_gatt_server_attribute_value.value.data,
evt->data.evt_gatt_server_attribute_value.value.len)) {
} else {
packet_buffer_on_ble_evt(
evt->data.evt_gatt_server_attribute_value.attribute,
evt->data.evt_gatt_server_attribute_value.value.data,
evt->data.evt_gatt_server_attribute_value.value.len);
}
break;
case sl_bt_evt_gatt_server_characteristic_status_id:
break;
case sl_bt_evt_sm_passkey_display_id:
break;
case sl_bt_evt_sm_confirm_bonding_id:
sc = sl_bt_sm_bonding_confirm(
evt->data.evt_sm_confirm_bonding.connection,1);
if (SL_STATUS_OK != sc) {
mp_raise_bleio_BluetoothError(
translate("Bonding confirm fail"));
}
break;
case sl_bt_evt_sm_bonded_id:
break;
case sl_bt_evt_sm_bonding_failed_id:
break;
case sl_bt_evt_connection_parameters_id:
switch (evt->data.evt_connection_parameters.security_mode)
{
case connection_mode1_level1:
break;
case connection_mode1_level2:
break;
case connection_mode1_level3:
break;
case connection_mode1_level4:
break;
default:
break;
}
break;
default:
break;
}
}

View File

@ -0,0 +1,80 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
#include <stdbool.h>
#include <stdio.h>
#include "shared-bindings/_bleio/UUID.h"
#include "gatt_db.h"
#include "sl_status.h"
#include "sl_bt_api.h"
#include "sl_bgapi.h"
#include "sl_bluetooth.h"
#include "sl_bt_rtos_adaptation.h"
#include "sl_cmsis_os2_common.h"
#include <cmsis_os2.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME)*(RESOLUTION)) / 1000000)
// We assume variable length data. 20 bytes max (23 - 3).
#define GATT_MAX_DATA_LENGTH (BT_ATT_DEFAULT_LE_MTU - 3)
#define BLE_GATT_HANDLE_INVALID 0x0000
#define BLE_CONN_HANDLE_INVALID 0xFFFF
// Maximum length for fixed length Attribute Values.
#define BLE_GATTS_FIX_ATTR_LEN_MAX (510)
// Maximum length for variable length Attribute Values.
#define BLE_GATTS_VAR_ATTR_LEN_MAX (512)
// Track if the user code modified the BLE state
// to know if we need to undo it on reload.
extern bool vm_used_ble;
// UUID shared by all CCCD's.
extern bleio_uuid_obj_t cccd_uuid;
extern void bleio_reset();
extern osMutexId_t bluetooth_connection_mutex_id;
extern const osMutexAttr_t bluetooth_connection_mutex_attr;
typedef enum {
DISCOVER_SERVICES,
DISCOVER_CHARACTERISTICS,
RUNNING
} conn_state_t;
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H

View File

@ -0,0 +1,216 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "common-hal/analogio/AnalogIn.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/translate/translate.h"
#include "em_cmu.h"
#include "em_iadc.h"
// Set CLK_ADC to 10MHz
#define CLK_SRC_ADC_FREQ 20000000 // CLK_SRC_ADC
#define CLK_ADC_FREQ 10000000 // CLK_ADC - 10 MHz max in normal mode
// Number of scan channels
#define NUM_INPUTS 8
STATIC uint8_t num_current_input = 0;
STATIC volatile uint16_t scan_result[NUM_INPUTS];
STATIC volatile uint8_t scan_flag = 0;
STATIC IADC_ScanTable_t init_scan_table = IADC_SCANTABLE_DEFAULT; // Scan Table
// Construct analogin pin. This function is called when init AnalogIn
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self,
const mcu_pin_obj_t *pin) {
uint8_t adc_index;
if (self->pin == NULL) {
self->id = NUM_INPUTS + 1;
for (adc_index = 0; adc_index < NUM_INPUTS; adc_index++) {
if (init_scan_table.entries[adc_index].includeInScan == false) {
self->id = adc_index;
self->pin = pin;
init_scan_table.entries[adc_index].includeInScan = true;
init_scan_table.entries[adc_index].negInput = iadcNegInputGnd;
init_scan_table.entries[adc_index].posInput
= IADC_portPinToPosInput(self->pin->port, self->pin->number);
num_current_input++;
break;
}
}
}
if (self->id == NUM_INPUTS + 1) {
mp_raise_ValueError(translate("ADC busy pin"));
}
// Declare init structs
IADC_Init_t init = IADC_INIT_DEFAULT;
IADC_AllConfigs_t initAllConfigs = IADC_ALLCONFIGS_DEFAULT;
IADC_InitScan_t initScan = IADC_INITSCAN_DEFAULT;
CMU_ClockEnable(cmuClock_IADC0, true);
// Select clock for IADC
CMU_ClockSelectSet(cmuClock_IADCCLK, cmuSelect_FSRCO);
// Modify init structures and initialize
init.warmup = iadcWarmupKeepWarm;
// Set the HFSCLK prescale value here
init.srcClkPrescale = IADC_calcSrcClkPrescale(IADC0, CLK_SRC_ADC_FREQ, 0);
// Configuration 0 is used by both scan and single conversions by
// default. Use internal bandgap as the reference and specify the
// reference voltage in mV.
// Resolution is not configurable directly but is based on the
// selected oversampling ratio (osrHighSpeed), which defaults to
// 2x and generates 12-bit results.
initAllConfigs.configs[0].reference = iadcCfgReferenceInt1V2;
initAllConfigs.configs[0].vRef = 1210;
initAllConfigs.configs[0].osrHighSpeed = iadcCfgOsrHighSpeed2x;
initAllConfigs.configs[0].analogGain = iadcCfgAnalogGain0P5x;
// Divide CLK_SRC_ADC to set the CLK_ADC frequency
initAllConfigs.configs[0].adcClkPrescale
= IADC_calcAdcClkPrescale(IADC0,
CLK_ADC_FREQ,
0,
iadcCfgModeNormal,
init.srcClkPrescale);
// Set the SCANFIFODVL flag when there are 8 entries in the scan
// FIFO. Note that in this example, the interrupt associated with
// the SCANFIFODVL flag in the IADC_IF register is not used.
// Similarly, the fifoDmaWakeup member of the initScan structure
// is left at its default setting of false, so LDMA service is not
// requested when the FIFO holds the specified number of samples.
initScan.dataValidLevel = _IADC_SCANFIFOCFG_DVL_VALID8;
// Tag FIFO entry with scan table entry id
initScan.showId = true;
// Initialize IADC
IADC_init(IADC0, &init, &initAllConfigs);
// Initialize scan
IADC_initScan(IADC0, &initScan, &init_scan_table);
if (self->pin->port == gpioPortA) {
GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AEVEN0_ADC0;
GPIO->ABUSALLOC |= GPIO_ABUSALLOC_AODD0_ADC0;
} else if (self->pin->port == gpioPortB) {
GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BEVEN0_ADC0;
GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BODD0_ADC0;
} else {
GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDEVEN0_ADC0;
GPIO->CDBUSALLOC |= GPIO_CDBUSALLOC_CDODD0_ADC0;
}
// Clear any previous interrupt flags
IADC_clearInt(IADC0, _IADC_IF_MASK);
// Enable Scan interrupts
IADC_enableInt(IADC0, IADC_IEN_SCANTABLEDONE);
// Enable ADC interrupts
NVIC_ClearPendingIRQ(IADC_IRQn);
NVIC_EnableIRQ(IADC_IRQn);
common_hal_mcu_pin_claim(pin);
}
// Check obj is deinited or not
bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t *self) {
return self->pin == NULL;
}
// Deinit a analogin obj
void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
if (num_current_input > 0) {
num_current_input--;
if (num_current_input == 0) {
IADC_reset(IADC0);
}
}
init_scan_table.entries[self->id].includeInScan = false;
init_scan_table.entries[self->id].posInput = iadcPosInputGnd;
scan_result[self->id] = 0;
common_hal_reset_pin(self->pin);
self->pin = NULL;
}
// IADC Handler to read adc value
void IADC_IRQHandler(void) {
IADC_Result_t result = {0, 0};
// While the FIFO count is non-zero
while (IADC_getScanFifoCnt(IADC0)) {
// Pull a scan result from the FIFO
result = IADC_pullScanFifoResult(IADC0);
scan_result[result.id] = result.data;
scan_result[result.id] *= 16;
}
scan_flag = 1;
IADC_clearInt(IADC0, IADC_IF_SCANTABLEDONE);
}
// Get adc value, use IADC_IRQHandler
// adc value 0 - 65535
uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
// Start scan
IADC_command(IADC0, iadcCmdStartScan);
uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t current_ticks = start_ticks;
// Busy-wait until timeout or until we've read enough chars.
while (current_ticks - start_ticks <= 1000) {
current_ticks = supervisor_ticks_ms64();
if (scan_flag == 1) {
scan_flag = 0;
break;
}
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
break;
}
}
uint16_t ret = scan_result[self->id];
scan_result[self->id] = 0;
return ret;
}
// Get adc ref value
float common_hal_analogio_analogin_get_reference_voltage
(analogio_analogin_obj_t *self) {
return 2.42f;
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_ANALOGIO_ANALOGIN_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_ANALOGIO_ANALOGIN_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
uint8_t id;
} analogio_analogin_obj_t;
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_ANALOGIO_ANALOGIN_H

View File

@ -0,0 +1,167 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mperrno.h"
#include "py/runtime.h"
#include "shared-bindings/analogio/AnalogOut.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/translate/translate.h"
#include "common-hal/microcontroller/Pin.h"
#include "em_vdac.h"
// Set the VDAC to max frequency of 1 MHz
#define CLK_VDAC_FREQ 1000000
// List DAC pin and channel supported
mcu_dac_pin_obj_t mcu_dac_list[DAC_BANK_ARRAY_LEN] = {
DAC(VDAC0, 0, FN_VDAC0_CH0, false, 0, &pin_PB0),
DAC(VDAC0, 1, FN_VDAC0_CH1, false, 0, &pin_PB1),
DAC(VDAC1, 0, FN_VDAC1_CH0, false, 0, &pin_PB2),
DAC(VDAC1, 1, FN_VDAC1_CH1, false, 0, &pin_PB3),
};
// Construct analogout pin. This function is called when init analogout
void common_hal_analogio_analogout_construct(analogio_analogout_obj_t *self,
const mcu_pin_obj_t *pin) {
uint8_t dac_num = DAC_BANK_ARRAY_LEN;
mcu_dac_pin_obj_t *p_dac;
uint8_t dac_index;
if (self->dac == NULL) {
for (dac_index = 0; dac_index < dac_num; dac_index++) {
p_dac = &mcu_dac_list[dac_index];
if (p_dac->pin == pin) {
self->dac = p_dac;
self->dac->is_used = true;
self->dac->value = 0;
break;
}
}
}
if (self->dac == NULL) {
mp_raise_ValueError(translate("DAC Device Init Error"));
}
// Use default settings
VDAC_Init_TypeDef init = VDAC_INIT_DEFAULT;
VDAC_InitChannel_TypeDef initChannel = VDAC_INITCHANNEL_DEFAULT;
// Use the HFRCOEM23 to clock the VDAC in order to operate in EM3 mode
CMU_ClockSelectSet(self->dac->vdac == VDAC0 ?
cmuClock_VDAC0:cmuClock_VDAC1, cmuSelect_HFRCOEM23);
// Enable the HFRCOEM23 and VDAC clocks
CMU_ClockEnable(cmuClock_HFRCOEM23, true);
CMU_ClockEnable(self->dac->vdac == VDAC0 ?
cmuClock_VDAC0 : cmuClock_VDAC1, true);
// Calculate the VDAC clock prescaler value resulting in a 1 MHz VDAC clock
init.prescaler = VDAC_PrescaleCalc(VDAC0, CLK_VDAC_FREQ);
init.reference = vdacRef2V5;
// Clocking is requested on demand
init.onDemandClk = false;
// Disable High Capacitance Load mode
initChannel.highCapLoadEnable = false;
// Use Low Power mode
initChannel.powerMode = vdacPowerModeLowPower;
// Initialize the VDAC and VDAC channel
VDAC_Init(self->dac->vdac, &init);
VDAC_InitChannel(self->dac->vdac, &initChannel, self->dac->channel);
// Enable the VDAC
VDAC_Enable(self->dac->vdac, self->dac->channel, true);
for (dac_index = 0; dac_index < dac_num; dac_index++) {
p_dac = &mcu_dac_list[dac_index];
if (p_dac->vdac == self->dac->vdac && p_dac->pin != self->dac->pin
&& p_dac->is_used == true) {
VDAC_InitChannel(p_dac->vdac, &initChannel, p_dac->channel);
VDAC_Enable(p_dac->vdac, p_dac->channel, true);
VDAC_ChannelOutputSet(p_dac->vdac, p_dac->channel,
p_dac->value >> 4);
break;
}
}
VDAC_ChannelOutputSet(self->dac->vdac, self->dac->channel, 0);
common_hal_mcu_pin_claim(pin);
}
// Check obj is deinited or not
bool common_hal_analogio_analogout_deinited(analogio_analogout_obj_t *self) {
return self->dac == NULL;
}
// Deinit analogout obj
void common_hal_analogio_analogout_deinit(analogio_analogout_obj_t *self) {
uint8_t dac_num = DAC_BANK_ARRAY_LEN;
mcu_dac_pin_obj_t *p_dac;
uint8_t dac_index;
VDAC_Enable(self->dac->vdac, self->dac->channel, false);
for (dac_index = 0; dac_index < dac_num; dac_index++) {
p_dac = &mcu_dac_list[dac_index];
if (p_dac->vdac == self->dac->vdac && p_dac->pin != self->dac->pin
&& p_dac->is_used == false) {
VDAC_Reset(self->dac->vdac);
}
}
common_hal_reset_pin(self->dac->pin);
self->dac->value = 0;
self->dac->is_used = false;
self->dac = NULL;
}
// Set value for dac pin
// dac value 0 - 65535 (0 - 2.5V)
void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self,
uint16_t value) {
self->dac->value = value;
// Write the output value to VDAC DATA register
VDAC_ChannelOutputSet(self->dac->vdac, self->dac->channel, value >> 4);
}
// Function reset dac peripheral
void analogout_reset(void) {
uint8_t dac_index;
mcu_dac_pin_obj_t *p_dac;
for (dac_index = 0; dac_index < DAC_BANK_ARRAY_LEN; dac_index++) {
p_dac = &mcu_dac_list[dac_index];
if (p_dac->is_used == true) {
VDAC_Reset(p_dac->vdac);
}
}
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_ANALOGIO_ANALOGOUT_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_ANALOGIO_ANALOGOUT_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
#include "peripherals/periph.h"
typedef struct
{
mp_obj_base_t base;
mcu_dac_pin_obj_t *dac;
} analogio_analogout_obj_t;
void analogout_reset(void);
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_ANALOGIO_ANALOGOUT_H

View File

@ -0,0 +1 @@
// No analogio module functions.

View File

View File

@ -0,0 +1,212 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/busio/I2C.h"
#include "py/mperrno.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/shared/translate/translate.h"
#include "shared-bindings/microcontroller/Pin.h"
STATIC I2CSPM_Init_TypeDef i2cspm_init;
STATIC bool in_used = false;
STATIC bool never_reset = false;
// Reser I2C peripheral
void i2c_reset(void) {
if ((!never_reset) && in_used) {
I2C_Reset(DEFAULT_I2C_PERIPHERAL);
in_used = false;
}
}
// Construct I2C protocol, this function init i2c peripheral
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
const mcu_pin_obj_t *scl,
const mcu_pin_obj_t *sda,
uint32_t frequency, uint32_t timeout) {
if ((scl != NULL) && (sda != NULL)) {
if (scl->function_list[ DEFAULT_I2C_PERIPHERAL == I2C1?
FN_I2C1_SCL : FN_I2C0_SCL] == 1 &&
scl->function_list[DEFAULT_I2C_PERIPHERAL == I2C1?
FN_I2C1_SDA : FN_I2C0_SDA] == 1) {
self->scl = scl;
self->sda = sda;
self->has_lock = false;
i2cspm_init.sclPort = self->scl->port;
i2cspm_init.sclPin = self->scl->number;
i2cspm_init.sdaPort = self->sda->port;
i2cspm_init.sdaPin = self->sda->number;
i2cspm_init.port = DEFAULT_I2C_PERIPHERAL;
i2cspm_init.i2cRefFreq = 0;
i2cspm_init.i2cMaxFreq = I2C_FREQ_STANDARD_MAX;
i2cspm_init.i2cClhr = i2cClockHLRStandard;
self->i2cspm = i2cspm_init.port;
I2CSPM_Init(&i2cspm_init);
common_hal_mcu_pin_claim(scl);
common_hal_mcu_pin_claim(sda);
in_used = true;
} else {
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
}
} else {
raise_ValueError_invalid_pins();
}
}
// Never reset I2C obj when reload
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
never_reset = true;
common_hal_never_reset_pin(self->sda);
common_hal_never_reset_pin(self->scl);
}
// Check I2C status, deinited or not
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
return self->sda == NULL;
}
// Deinit i2c obj, reset I2C pin
void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
if (common_hal_busio_i2c_deinited(self)) {
return;
}
I2C_Reset(self->i2cspm);
common_hal_reset_pin(self->sda);
common_hal_reset_pin(self->scl);
self->sda = NULL;
self->scl = NULL;
self->i2cspm = NULL;
in_used = false;
}
// Probe device in I2C bus
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret;
uint8_t data = 0;
seq.addr = addr << 1;
seq.flags = I2C_FLAG_READ;
seq.buf[0].data = &data;
seq.buf[0].len = 1;
ret = I2CSPM_Transfer(self->i2cspm, &seq);
if (ret != i2cTransferDone) {
return false;
}
return true;
}
// Lock I2C bus
bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
bool grabbed_lock = false;
if (!self->has_lock) {
grabbed_lock = true;
self->has_lock = true;
}
return grabbed_lock;
}
// Check I2C lock status
bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
return self->has_lock;
}
// Unlock I2C bus
void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
self->has_lock = false;
}
// Write data to the device selected by address
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
const uint8_t *data, size_t len) {
I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret;
seq.addr = addr << 1;
seq.flags = I2C_FLAG_WRITE;
seq.buf[0].data = (uint8_t *)data;
seq.buf[0].len = len;
ret = I2CSPM_Transfer(self->i2cspm, &seq);
if (ret != i2cTransferDone) {
return MP_EIO;
}
return 0;
}
// Read into buffer from the device selected by address
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self,
uint16_t addr,
uint8_t *data, size_t len) {
I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret;
seq.addr = addr << 1;
seq.flags = I2C_FLAG_READ;
seq.buf[0].data = data;
seq.buf[0].len = len;
ret = I2CSPM_Transfer(self->i2cspm, &seq);
if (ret != i2cTransferDone) {
return MP_EIO;
}
return 0;
}
// Write the bytes from out_data to the device selected by address,
uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr,
uint8_t *out_data, size_t out_len,
uint8_t *in_data, size_t in_len) {
I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret;
seq.addr = addr << 1;
seq.flags = I2C_FLAG_WRITE_READ;
// Select command to issue
seq.buf[0].data = out_data;
seq.buf[0].len = out_len;
// Select location/length of data to be read
seq.buf[1].data = in_data;
seq.buf[1].len = in_len;
ret = I2CSPM_Transfer(self->i2cspm, &seq);
if (ret != i2cTransferDone) {
return MP_EIO;
}
return 0;
}

View File

@ -0,0 +1,46 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_I2C_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_I2C_H
#include "common-hal/microcontroller/Pin.h"
#include "peripherals/periph.h"
#include "py/obj.h"
#include "em_i2c.h"
#include "sl_i2cspm.h"
typedef struct {
mp_obj_base_t base;
I2C_TypeDef *i2cspm;
bool has_lock;
const mcu_pin_obj_t *scl;
const mcu_pin_obj_t *sda;
} busio_i2c_obj_t;
void i2c_reset(void);
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_I2C_H

View File

@ -0,0 +1,252 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/busio/SPI.h"
#include "py/mperrno.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/board.h"
#include "supervisor/shared/translate/translate.h"
#include "shared-bindings/microcontroller/Pin.h"
// Note that any bugs introduced in this file can cause crashes
// at startupfor chips using external SPI flash.
STATIC SPIDRV_HandleData_t spidrv_eusart_handle;
STATIC SPIDRV_Init_t spidrv_eusart_init = SPIDRV_MASTER_EUSART1;
STATIC bool in_used = false;
STATIC bool never_reset = false;
// Reset SPI when reload
void spi_reset(void) {
if (!never_reset && in_used) {
SPIDRV_DeInit(&spidrv_eusart_handle);
in_used = false;
}
return;
}
// Construct SPI protocol, this function init SPI peripheral
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
const mcu_pin_obj_t *sck,
const mcu_pin_obj_t *mosi,
const mcu_pin_obj_t *miso,
bool half_duplex) {
Ecode_t sc = ECODE_OK;
if (half_duplex) {
mp_raise_NotImplementedError(
translate("Half duplex SPI is not implemented"));
}
if ((sck != NULL) && (mosi != NULL) && (miso != NULL)) {
if (sck->function_list[FN_EUSART1_SCLK] == 1
&& miso->function_list[FN_EUSART1_RX] == 1
&& mosi->function_list[FN_EUSART1_TX] == 1) {
self->sck = sck;
self->mosi = mosi;
self->miso = miso;
self->handle = &spidrv_eusart_handle;
self->polarity = 0;
self->phase = 0;
self->bits = 8;
spidrv_eusart_init.portTx = mosi->port;
spidrv_eusart_init.portRx = miso->port;
spidrv_eusart_init.portClk = sck->port;
spidrv_eusart_init.pinTx = mosi->number;
spidrv_eusart_init.pinRx = miso->number;
spidrv_eusart_init.pinClk = sck->number;
spidrv_eusart_init.bitRate = 1000000;
spidrv_eusart_init.frameLength = 8;
spidrv_eusart_init.dummyTxValue = 0;
spidrv_eusart_init.type = spidrvMaster;
spidrv_eusart_init.bitOrder = spidrvBitOrderMsbFirst;
spidrv_eusart_init.clockMode = spidrvClockMode0;
spidrv_eusart_init.csControl = spidrvCsControlApplication;
spidrv_eusart_init.slaveStartMode = spidrvSlaveStartImmediate;
sc = SPIDRV_Init(self->handle, &spidrv_eusart_init);
if (sc != ECODE_EMDRV_SPIDRV_OK) {
mp_raise_ValueError(translate("SPI init error"));
}
} else {
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
}
} else {
raise_ValueError_invalid_pins();
}
in_used = true;
common_hal_mcu_pin_claim(sck);
common_hal_mcu_pin_claim(mosi);
common_hal_mcu_pin_claim(miso);
}
// Never reset SPI when reload
void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
never_reset = true;
common_hal_never_reset_pin(self->mosi);
common_hal_never_reset_pin(self->miso);
common_hal_never_reset_pin(self->sck);
}
// Check SPI status, deinited or not
bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
return self->sck == NULL;
}
// Deinit SPI obj
void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
if (common_hal_busio_spi_deinited(self)) {
return;
}
Ecode_t sc = SPIDRV_DeInit(self->handle);
if (sc != ECODE_EMDRV_SPIDRV_OK) {
mp_raise_RuntimeError(translate("SPI re-init"));
}
in_used = false;
self->sck = NULL;
self->mosi = NULL;
self->miso = NULL;
self->handle = NULL;
common_hal_reset_pin(self->mosi);
common_hal_reset_pin(self->miso);
common_hal_reset_pin(self->sck);
}
// Configures the SPI bus. The SPI object must be locked.
bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
uint32_t baudrate,
uint8_t polarity,
uint8_t phase,
uint8_t bits) {
Ecode_t sc;
// This resets the SPI, so check before updating it redundantly
if (baudrate == self->baudrate && polarity == self->polarity
&& phase == self->phase && bits == self->bits) {
return true;
}
sc = SPIDRV_DeInit(self->handle);
if (sc != ECODE_EMDRV_SPIDRV_OK) {
mp_raise_RuntimeError(translate("SPI re-init"));
}
in_used = false;
self->baudrate = baudrate;
self->phase = phase;
self->bits = bits;
self->polarity = polarity;
spidrv_eusart_init.bitRate = baudrate;
spidrv_eusart_init.frameLength = 8;
if (polarity == 0 && phase == 0) {
spidrv_eusart_init.clockMode = spidrvClockMode0;
} else if (polarity == 0 && phase == 1) {
spidrv_eusart_init.clockMode = spidrvClockMode1;
} else if (polarity == 1 && phase == 0) {
spidrv_eusart_init.clockMode = spidrvClockMode2;
} else if (polarity == 1 && phase == 1) {
spidrv_eusart_init.clockMode = spidrvClockMode3;
}
sc = SPIDRV_Init(self->handle, &spidrv_eusart_init);
if (sc != ECODE_EMDRV_SPIDRV_OK) {
mp_raise_RuntimeError(translate("SPI re-init"));
}
in_used = true;
return true;
}
// Lock SPI bus
bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
bool grabbed_lock = false;
if (!self->has_lock) {
grabbed_lock = true;
self->has_lock = true;
}
return grabbed_lock;
}
// Check SPI lock status
bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) {
return self->has_lock;
}
// Unlock SPI bus
void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
self->has_lock = false;
}
// Write the data contained in buffer
bool common_hal_busio_spi_write(busio_spi_obj_t *self,
const uint8_t *data,
size_t len) {
Ecode_t result = SPIDRV_MTransmitB(self->handle, data, len);
return result == ECODE_EMDRV_SPIDRV_OK;
}
// Read data into buffer
bool common_hal_busio_spi_read(busio_spi_obj_t *self,
uint8_t *data, size_t len,
uint8_t write_value) {
self->handle->initData.dummyTxValue = write_value;
Ecode_t result = SPIDRV_MReceiveB(self->handle, data, len);
return result == ECODE_EMDRV_SPIDRV_OK;
}
// Write out the data in data_out
// while simultaneously reading data into data_in
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self,
const uint8_t *data_out,
uint8_t *data_in,
size_t len) {
Ecode_t result = SPIDRV_MTransferB(self->handle, data_out, data_in, len);
return result == ECODE_EMDRV_SPIDRV_OK;
}
// Get SPI baudrate
uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t *self) {
return self->baudrate;
}
// Get SPI phase
uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t *self) {
return self->phase;
}
// Get SPI polarity
uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self) {
return self->polarity;
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_SPI_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_SPI_H
#include "common-hal/microcontroller/Pin.h"
#include "peripherals/periph.h"
#include "py/obj.h"
#include "spidrv.h"
typedef struct {
mp_obj_base_t base;
SPIDRV_Handle_t handle;
bool has_lock;
const mcu_pin_obj_t *sck;
const mcu_pin_obj_t *mosi;
const mcu_pin_obj_t *miso;
const mcu_pin_obj_t *nss;
uint32_t baudrate;
uint16_t prescaler;
uint8_t polarity;
uint8_t phase;
uint8_t bits;
} busio_spi_obj_t;
void spi_reset(void);
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_SPI_H

View File

@ -0,0 +1,299 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/busio/UART.h"
#include "mpconfigport.h"
#include "shared/readline/readline.h"
#include "shared/runtime/interrupt_char.h"
#include "py/gc.h"
#include "py/mperrno.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "supervisor/shared/translate/translate.h"
#define UARTDRV_USART_BUFFER_SIZE 6
// Define RX and TX buffer queues
DEFINE_BUF_QUEUE(UARTDRV_USART_BUFFER_SIZE, uartdrv_usart_rx_buffer);
DEFINE_BUF_QUEUE(UARTDRV_USART_BUFFER_SIZE, uartdrv_usart_tx_buffer);
STATIC UARTDRV_HandleData_t uartdrv_usart_handle;
STATIC UARTDRV_InitUart_t uartdrv_usart_init;
STATIC bool in_used = false;
STATIC bool never_reset = false;
busio_uart_obj_t *context;
volatile Ecode_t errflag; // Used to restart read halts
// Reset uart peripheral
void uart_reset(void) {
if ((!never_reset) && in_used) {
if (UARTDRV_DeInit(&uartdrv_usart_handle) != ECODE_EMDRV_UARTDRV_OK) {
mp_raise_ValueError(translate("UART Deinit fail"));
}
in_used = false;
}
}
// Construct uart obj
void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t *tx,
const mcu_pin_obj_t *rx,
const mcu_pin_obj_t *rts,
const mcu_pin_obj_t *cts,
const mcu_pin_obj_t *rs485_dir,
bool rs485_invert,
uint32_t baudrate,
uint8_t bits,
busio_uart_parity_t parity,
uint8_t stop,
mp_float_t timeout,
uint16_t receiver_buffer_size,
byte *receiver_buffer,
bool sigint_enabled) {
if ((rts != NULL) || (cts != NULL) || (rs485_dir != NULL)
|| (rs485_invert == true)) {
mp_raise_NotImplementedError(translate("RS485"));
}
if ((tx != NULL) && (rx != NULL)) {
if (tx->function_list[FN_USART0_TX] == 1
&& tx->function_list[FN_USART0_RX] == 1) {
self->handle = &uartdrv_usart_handle;
self->baudrate = baudrate;
self->tx = tx;
self->rx = rx;
self->sigint_enabled = sigint_enabled;
self->timeout_ms = timeout * 1000;
uartdrv_usart_init.port = USART0;
uartdrv_usart_init.baudRate = baudrate;
uartdrv_usart_init.txPort = tx->port;
uartdrv_usart_init.rxPort = rx->port;
uartdrv_usart_init.txPin = tx->number;
uartdrv_usart_init.rxPin = rx->number;
uartdrv_usart_init.uartNum = 0;
uartdrv_usart_init.stopBits = (stop >= 2) ? usartStopbits2
:usartStopbits1;
uartdrv_usart_init.parity = (USART_Parity_TypeDef)parity;
uartdrv_usart_init.oversampling = usartOVS4;
uartdrv_usart_init.mvdis = false;
uartdrv_usart_init.fcType = uartdrvFlowControlNone;
uartdrv_usart_init.rxQueue = (UARTDRV_Buffer_FifoQueue_t *)
&uartdrv_usart_rx_buffer;
uartdrv_usart_init.txQueue = (UARTDRV_Buffer_FifoQueue_t *)
&uartdrv_usart_tx_buffer;
if (UARTDRV_InitUart(self->handle,&uartdrv_usart_init)
!= ECODE_EMDRV_UARTDRV_OK) {
mp_raise_RuntimeError(translate("UART init"));
}
common_hal_mcu_pin_claim(tx);
common_hal_mcu_pin_claim(rx);
in_used = true;
// Use the provided buffer when given.
if (receiver_buffer != NULL) {
ringbuf_init(&self->ringbuf, receiver_buffer, receiver_buffer_size);
} else {
if (!ringbuf_alloc(&self->ringbuf, receiver_buffer_size, true)) {
m_malloc_fail(receiver_buffer_size);
}
}
errflag = ECODE_EMDRV_UARTDRV_OK;
context = self;
} else {
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
}
} else {
raise_ValueError_invalid_pins();
}
}
// Never reset UART obj when reload
void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) {
never_reset = true;
common_hal_never_reset_pin(self->tx);
common_hal_never_reset_pin(self->rx);
return;
}
// Check Uart status, deinited or not
bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
return self->handle == NULL;
}
// Deinit uart obj
void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
if (common_hal_busio_uart_deinited(self)) {
return;
}
if (UARTDRV_DeInit(self->handle) != ECODE_EMDRV_UARTDRV_OK) {
mp_raise_RuntimeError(translate("UART de-init"));
}
common_hal_reset_pin(self->rx);
common_hal_reset_pin(self->tx);
self->tx = NULL;
self->rx = NULL;
self->handle = NULL;
in_used = false;
}
// Callback function for UARTDRV_Receive
void UARTDRV_Receive_Callback(UARTDRV_Handle_t *handle,
Ecode_t transferStatus,
uint8_t *data,
UARTDRV_Count_t transferCount) {
(void)handle;
(void)transferStatus;
(void)data;
(void)transferCount;
taskENTER_CRITICAL();
ringbuf_put_n(&context->ringbuf, &context->rx_char, 1);
taskEXIT_CRITICAL();
errflag = UARTDRV_Receive(context->handle,&context->rx_char,1,
(UARTDRV_Callback_t)UARTDRV_Receive_Callback);
if (context->sigint_enabled) {
if (context->rx_char == CHAR_CTRL_C) {
common_hal_busio_uart_clear_rx_buffer(context);
mp_sched_keyboard_interrupt();
}
}
}
// Read bytes. If nbytes is specified then read at most that many bytes.
// Otherwise, read everything that arrives until the connection times out.
// Providing the number of bytes expected is highly recommended because it will be faster.
// If no bytes are read, return None.
size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data,
size_t len, int *errcode) {
uint64_t start_ticks = supervisor_ticks_ms64();
if (len == 0) {
// Nothing to read.
return 0;
}
errflag = ECODE_EMDRV_UARTDRV_WAITING;
// Wait for all bytes received or timeout, same as nrf
while ((ringbuf_num_filled(&self->ringbuf) < len) &&
(supervisor_ticks_ms64() - start_ticks < self->timeout_ms)) {
RUN_BACKGROUND_TASKS;
// restart if it failed in the callback
if (errflag != ECODE_EMDRV_UARTDRV_OK) {
errflag = UARTDRV_Receive(self->handle,&self->rx_char,1,
(UARTDRV_Callback_t)UARTDRV_Receive_Callback);
}
// Allow user to break out of a timeout with a KeyboardInterrupt.
if (mp_hal_is_interrupted()) {
return 0;
}
}
taskENTER_CRITICAL();
// Copy as much received data as available, up to len bytes.
size_t rx_bytes = ringbuf_get_n(&self->ringbuf, data, len);
taskEXIT_CRITICAL();
if (rx_bytes == 0) {
*errcode = EAGAIN;
return MP_STREAM_ERROR;
}
return rx_bytes;
}
// Write the buffer of bytes to the bus.
size_t common_hal_busio_uart_write(busio_uart_obj_t *self,
const uint8_t *data,
size_t len,
int *errcode) {
Ecode_t ret = UARTDRV_TransmitB(self->handle, (uint8_t *)data, len);
if (ret != ECODE_EMDRV_UARTDRV_OK) {
mp_raise_RuntimeError(translate("UART write"));
}
return len;
}
// Get uart baudrate value
uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) {
return self->baudrate;
}
// Set uart baudrate value
void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self,
uint32_t baudrate) {
// Don't reset if it's the same value
if (baudrate == self->baudrate) {
return;
}
uartdrv_usart_init.baudRate = baudrate;
if (UARTDRV_InitUart(self->handle, &uartdrv_usart_init)
!= ECODE_EMDRV_UARTDRV_OK) {
mp_raise_RuntimeError(translate("UART re-init"));
}
}
// Get timeout for receive
mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) {
return (mp_float_t)(self->timeout_ms / 1000.0f);
}
// Set timeout for receive
void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self,
mp_float_t timeout) {
self->timeout_ms = timeout * 1000;
}
// Query characters available to read
uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
return ringbuf_num_filled(&self->ringbuf);
}
// Clear rx buffer
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
taskENTER_CRITICAL();
ringbuf_clear(&self->ringbuf);
taskEXIT_CRITICAL();
self->handle->rxQueue->head = 0;
self->handle->rxQueue->tail = 0;
self->handle->rxQueue->used = 0;
}
// Check uart bus ready to transmit or not
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
return UARTDRV_GetTransmitDepth(self->handle) == 0;
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_UART_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_UART_H
#include "common-hal/microcontroller/Pin.h"
#include "peripherals/periph.h"
#include "py/obj.h"
#include "py/ringbuf.h"
#include "uartdrv.h"
#include "FreeRTOS.h"
#include "task.h"
typedef struct {
mp_obj_base_t base;
UARTDRV_Handle_t handle;
const mcu_pin_obj_t *rx;
const mcu_pin_obj_t *tx;
ringbuf_t ringbuf;
uint8_t rx_char;
uint32_t baudrate;
uint32_t timeout_ms;
bool sigint_enabled;
} busio_uart_obj_t;
void uart_reset(void);
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_UART_H

View File

@ -0,0 +1 @@
// No busio module functions.

View File

@ -0,0 +1,159 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "py/runtime.h"
#include "supervisor/shared/translate/translate.h"
// Never reset pin when reload
void common_hal_digitalio_digitalinout_never_reset(
digitalio_digitalinout_obj_t *self) {
common_hal_never_reset_pin(self->pin);
}
// Construct Digitalio obj
digitalinout_result_t common_hal_digitalio_digitalinout_construct(
digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) {
common_hal_mcu_pin_claim(pin);
self->pin = pin;
GPIO_PinModeSet(pin->port, pin->number, gpioModeInput, 1);
return DIGITALINOUT_OK;
}
// Check Digitalio status, deinited or not
bool common_hal_digitalio_digitalinout_deinited(
digitalio_digitalinout_obj_t *self) {
return self->pin == NULL;
}
// Deinit Digitalio obj
void common_hal_digitalio_digitalinout_deinit(
digitalio_digitalinout_obj_t *self) {
if (common_hal_digitalio_digitalinout_deinited(self)) {
return;
}
common_hal_reset_pin(self->pin);
self->pin = NULL;
}
// Switch pin to input
digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_input(
digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
if (pull == PULL_NONE) {
GPIO_PinModeSet(self->pin->port,self->pin->number,gpioModeInput,1);
} else if (pull == PULL_UP) {
GPIO_PinModeSet(self->pin->port,self->pin->number,gpioModeInputPull,1);
} else {
GPIO_PinModeSet(self->pin->port,self->pin->number,gpioModeInputPull,0);
}
return DIGITALINOUT_OK;
}
// Switch pin to output
digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output(
digitalio_digitalinout_obj_t *self, bool value,
digitalio_drive_mode_t drive_mode) {
if (drive_mode == DRIVE_MODE_OPEN_DRAIN) {
GPIO_PinModeSet(self->pin->port,self->pin->number,
gpioModeWiredAnd,value);
} else {
GPIO_PinModeSet(self->pin->port,self->pin->number,
gpioModePushPull,value);
}
if (value) {
GPIO_PinOutSet(self->pin->port, self->pin->number);
} else {
GPIO_PinOutClear(self->pin->port, self->pin->number);
}
return DIGITALINOUT_OK;
}
// Get direction of the pin
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
digitalio_digitalinout_obj_t *self) {
GPIO_Mode_TypeDef mode = GPIO_PinModeGet(self->pin->port,self->pin->number);
if (mode >= gpioModePushPull) {
return DIRECTION_OUTPUT;
}
return DIRECTION_INPUT;
}
// Set digital logic level of the pin
void common_hal_digitalio_digitalinout_set_value(
digitalio_digitalinout_obj_t *self, bool value) {
if (value) {
GPIO_PinOutSet(self->pin->port, self->pin->number);
} else {
GPIO_PinOutClear(self->pin->port, self->pin->number);
}
}
// The digital logic level of the pin
bool common_hal_digitalio_digitalinout_get_value(
digitalio_digitalinout_obj_t *self) {
if (common_hal_digitalio_digitalinout_get_direction(self)
== DIRECTION_OUTPUT) {
return GPIO_PinOutGet(self->pin->port, self->pin->number);
}
return GPIO_PinInGet(self->pin->port, self->pin->number);
}
// Set drive mode
digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode(
digitalio_digitalinout_obj_t *self,
digitalio_drive_mode_t drive_mode) {
if (drive_mode == DRIVE_MODE_OPEN_DRAIN) {
GPIO_PinModeSet(self->pin->port,self->pin->number,gpioModeWiredAnd,1);
} else {
GPIO_PinModeSet(self->pin->port,self->pin->number,gpioModePushPull,1);
}
return DIGITALINOUT_OK;
}
// Get drive mode
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
digitalio_digitalinout_obj_t *self) {
GPIO_Mode_TypeDef mode = GPIO_PinModeGet(self->pin->port,self->pin->number);
if (mode >= gpioModeWiredAnd) {
return DRIVE_MODE_OPEN_DRAIN;
}
return DRIVE_MODE_PUSH_PULL;
}
// Set pull direction
digitalinout_result_t common_hal_digitalio_digitalinout_set_pull(
digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) {
return DIGITALINOUT_OK;
}
// Get pull direction
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
digitalio_digitalinout_obj_t *self) {
return PULL_NONE;
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_DIGITALIO_DIGITALINOUT_H
#include "common-hal/microcontroller/Pin.h"
#include "em_gpio.h"
typedef struct
{
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
} digitalio_digitalinout_obj_t;
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_DIGITALIO_DIGITALINOUT_H

View File

@ -0,0 +1 @@
// No digitalio module functions.

View File

@ -0,0 +1,115 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "py/mphal.h"
#include "em_gpio.h"
#define GPIO_PORT_COUNT (MP_ARRAY_SIZE(ports))
GPIO_Port_TypeDef ports[] = {gpioPortA, gpioPortB, gpioPortC, gpioPortD};
STATIC uint16_t claimed_pins[GPIO_PORT_COUNT];
STATIC uint16_t __ALIGNED(4) never_reset_pins[GPIO_PORT_COUNT];
// Reset all pin except pin in never_reset_pins list
void reset_all_pins(void) {
uint8_t pin_num;
uint8_t port_num;
// Reset claimed pins
for (pin_num = 0; pin_num < GPIO_PORT_COUNT; pin_num++) {
claimed_pins[pin_num] = never_reset_pins[pin_num];
}
for (port_num = 0; port_num < GPIO_PORT_COUNT; port_num++) {
for (pin_num = 0; pin_num < 16; pin_num++) {
if (GPIO_PORT_PIN_VALID(ports[port_num],pin_num)
&& !(never_reset_pins[port_num] >> pin_num & 0x01)) {
GPIO_PinModeSet(ports[port_num], pin_num,gpioModeInput,1);
}
}
}
}
// Mark pin as free and return it to a quiescent state.
void reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
// Clear claimed bit & reset
claimed_pins[pin_port] &= ~(1 << pin_number);
never_reset_pins[pin_port] &= ~(1 << pin_number);
GPIO_PinModeSet(pin_port, pin_number, gpioModeInput, 1);
}
// Mark pin as never reset
void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
never_reset_pins[pin_port] |= 1 << pin_number;
// Make sure never reset pins are also always claimed
claimed_pins[pin_port] |= 1 << pin_number;
}
// Mark pin as never reset
void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) {
never_reset_pin_number(pin->port, pin->number);
}
// Reset pin
void common_hal_reset_pin(const mcu_pin_obj_t *pin) {
if (pin == NULL) {
return;
}
reset_pin_number(pin->port, pin->number);
}
// Mark pin as in used
void claim_pin(uint8_t pin_port, uint8_t pin_number) {
// Set bit in claimed_pins bitmask.
claimed_pins[pin_port] |= 1 << pin_number;
}
// Check pin status free or in used
bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) {
return !(claimed_pins[pin_port] & (1 << pin_number));
}
// Check pin status free or in used
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
return pin_number_is_free(pin->port, pin->number);
}
// Calculate pin number for a pin obj
uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t *pin) {
return pin->port * 16 + pin->number;
}
// Mark pin is in used
void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
claim_pin(pin->port, pin->number);
}
// Reset pin by pin number
void common_hal_mcu_pin_reset_number(uint8_t pin_no) {
reset_pin_number(pin_no / 16, pin_no % 16);
}

View File

@ -0,0 +1,36 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_MICROCONTROLLER_PIN_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_MICROCONTROLLER_PIN_H
#include "py/mphal.h"
#include "peripherals/pins.h"
void reset_all_pins(void);
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_MICROCONTROLLER_PIN_H

View File

@ -0,0 +1,67 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <math.h>
#include "py/runtime.h"
#if CIRCUITPY_ALARM
#include "common-hal/alarm/__init__.h"
#endif
#include "common-hal/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h"
#include "supervisor/shared/translate/translate.h"
#include "tempdrv.h"
#include "em_system.h"
#include "em_cmu.h"
float common_hal_mcu_processor_get_temperature(void) {
TEMPDRV_Init();
return (float)TEMPDRV_GetTemp();
}
float common_hal_mcu_processor_get_voltage(void) {
// xG24 does not have built-in direct reading of processor voltage
// Have Only 1 of IADC, already used for analogio module
return 3.3f;
}
uint32_t common_hal_mcu_processor_get_frequency(void) {
return CMU_ClockFreqGet(cmuClock_HCLK);
}
void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
size_t byte_index;
uint64_t serial = SYSTEM_GetUnique();
for (byte_index = 0; byte_index < sizeof(uint64_t); byte_index++) {
raw_id[byte_index] = (serial >> (64 - ((byte_index + 1) * 8))) & 0xff;
}
}
mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) {
return RESET_REASON_UNKNOWN;
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 12
#include "py/obj.h"
typedef struct
{
mp_obj_base_t base;
} mcu_processor_obj_t;
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H

View File

@ -0,0 +1,223 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mphal.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/microcontroller/Processor.h"
#include "shared-bindings/nvm/ByteArray.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/safe_mode.h"
#include "em_chip.h"
#include "em_core.h"
#include "sl_udelay.h"
void common_hal_mcu_delay_us(uint32_t delay) {
sl_udelay_wait(delay);
}
void common_hal_mcu_disable_interrupts(void) {
CORE_CriticalDisableIrq();
}
void common_hal_mcu_enable_interrupts(void) {
CORE_CriticalEnableIrq();
}
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if (runmode == RUNMODE_SAFE_MODE) {
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
}
}
void common_hal_mcu_reset(void) {
filesystem_flush(); // TODO: implement as part of flash improvements
CHIP_Reset();
}
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
// It currently only has properties, and no state.
const mcu_processor_obj_t common_hal_mcu_processor_obj = {
.base = {
.type = &mcu_processor_type,
},
};
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
// The singleton nvm.ByteArray object.
const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
.base = {
.type = &nvm_bytearray_type,
},
.len = NVM_BYTEARRAY_BUFFER_SIZE
};
#endif
#if CIRCUITPY_WATCHDOG
// The singleton watchdog.WatchDogTimer object.
watchdog_watchdogtimer_obj_t common_hal_mcu_watchdogtimer_obj = {
.base = {
.type = &watchdog_watchdogtimer_type,
},
.timeout = 0.0f,
.mode = WATCHDOGMODE_NONE,
};
#endif
// This maps MCU pin names to pin objects.
const mp_rom_map_elem_t mcu_pin_global_dict_table[] = {
#ifdef GPIO_PA0_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA0), MP_ROM_PTR(&pin_PA0) },
#endif
#ifdef GPIO_PA1_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA1), MP_ROM_PTR(&pin_PA1) },
#endif
#ifdef GPIO_PA2_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA2), MP_ROM_PTR(&pin_PA2) },
#endif
#ifdef GPIO_PA3_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA3), MP_ROM_PTR(&pin_PA3) },
#endif
#ifdef GPIO_PA4_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA4), MP_ROM_PTR(&pin_PA4) },
#endif
#ifdef GPIO_PA5_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA5), MP_ROM_PTR(&pin_PA5) },
#endif
#ifdef GPIO_PA6_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA6), MP_ROM_PTR(&pin_PA6) },
#endif
#ifdef GPIO_PA7_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA7), MP_ROM_PTR(&pin_PA7) },
#endif
#ifdef GPIO_PA8_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PA8), MP_ROM_PTR(&pin_PA8) },
#endif
#ifdef GPIO_PB0_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PB0), MP_ROM_PTR(&pin_PB0) },
#endif
#ifdef GPIO_PB1_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PB1), MP_ROM_PTR(&pin_PB1) },
#endif
#ifdef GPIO_PB2_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PB2), MP_ROM_PTR(&pin_PB2) },
#endif
#ifdef GPIO_PB3_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PB3), MP_ROM_PTR(&pin_PB3) },
#endif
#ifdef GPIO_PB4_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PB4), MP_ROM_PTR(&pin_PB4) },
#endif
#ifdef GPIO_PB5_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PB5), MP_ROM_PTR(&pin_PB5) },
#endif
#ifdef GPIO_PC0_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC0), MP_ROM_PTR(&pin_PC0) },
#endif
#ifdef GPIO_PC1_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC1), MP_ROM_PTR(&pin_PC1) },
#endif
#ifdef GPIO_PC2_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC2), MP_ROM_PTR(&pin_PC2) },
#endif
#ifdef GPIO_PC3_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC3), MP_ROM_PTR(&pin_PC3) },
#endif
#ifdef GPIO_PC4_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC4), MP_ROM_PTR(&pin_PC4) },
#endif
#ifdef GPIO_PC5_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC5), MP_ROM_PTR(&pin_PC5) },
#endif
#ifdef GPIO_PC6_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC6), MP_ROM_PTR(&pin_PC6) },
#endif
#ifdef GPIO_PC7_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC7), MP_ROM_PTR(&pin_PC7) },
#endif
#ifdef GPIO_PC8_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC8), MP_ROM_PTR(&pin_PC8) },
#endif
#ifdef GPIO_PC9_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PC9), MP_ROM_PTR(&pin_PC9) },
#endif
#ifdef GPIO_PD0_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PD0), MP_ROM_PTR(&pin_PD0) },
#endif
#ifdef GPIO_PD1_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PD1), MP_ROM_PTR(&pin_PD1) },
#endif
#ifdef GPIO_PD2_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PD2), MP_ROM_PTR(&pin_PD2) },
#endif
#ifdef GPIO_PD3_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PD3), MP_ROM_PTR(&pin_PD3) },
#endif
#ifdef GPIO_PD4_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PD4), MP_ROM_PTR(&pin_PD4) },
#endif
#ifdef GPIO_PD5_EXISTS
{ MP_ROM_QSTR(MP_QSTR_PD5), MP_ROM_PTR(&pin_PD5) }
#endif
};
MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table);

View File

@ -0,0 +1,98 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "common-hal/nvm/ByteArray.h"
#include "supervisor/shared/stack.h"
#include "py/runtime.h"
#include "supervisor/shared/translate/translate.h"
#include "nvm3_default.h"
#include "nvm3_default_config.h"
uint8_t nvm_array[NVM_BYTEARRAY_BUFFER_SIZE];
STATIC bool isInitialized = false;
#define NVM_KEY 98
// Get length of nvm bytearray
uint32_t common_hal_nvm_bytearray_get_length(nvm_bytearray_obj_t *self) {
return self->len;
}
uint32_t nvm3_read(nvm_bytearray_obj_t *self) {
uint32_t type;
Ecode_t err;
size_t len;
if (isInitialized == false) {
nvm3_initDefault();
isInitialized = true;
}
err = nvm3_getObjectInfo(nvm3_defaultHandle, NVM_KEY, &type, &len);
if (err != ECODE_NVM3_OK || type != NVM3_OBJECTTYPE_DATA
|| len != NVM_BYTEARRAY_BUFFER_SIZE) {
nvm3_deleteObject(nvm3_defaultHandle, NVM_KEY);
nvm3_writeData(nvm3_defaultHandle, NVM_KEY, nvm_array,
NVM_BYTEARRAY_BUFFER_SIZE);
}
err = nvm3_readData(nvm3_defaultHandle, NVM_KEY, nvm_array,
NVM_BYTEARRAY_BUFFER_SIZE);
return err;
}
// Write n bytes to nvm bytearray
bool common_hal_nvm_bytearray_set_bytes(nvm_bytearray_obj_t *self,
uint32_t start_index, uint8_t *values,
uint32_t len) {
Ecode_t err;
err = nvm3_read(self);
if (err != ECODE_NVM3_OK) {
mp_raise_RuntimeError(translate("NVM3 read false"));
}
// Set bytes in buffer
memmove(nvm_array + start_index, values, len);
err = nvm3_writeData(nvm3_defaultHandle, NVM_KEY, nvm_array,
NVM_BYTEARRAY_BUFFER_SIZE);
if (err != ECODE_NVM3_OK) {
mp_raise_RuntimeError(translate("NVM3 write false"));
}
return true;
}
// Read n bytes from nvm bytearray
void common_hal_nvm_bytearray_get_bytes(nvm_bytearray_obj_t *self,
uint32_t start_index,
uint32_t len, uint8_t *values) {
nvm3_read(self);
memcpy(values, nvm_array + start_index, len);
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_NVM_BYTEARRAY_H
#define MICROPY_INCLUDED_EFR32_COMMON_HAL_NVM_BYTEARRAY_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
uint32_t len;
} nvm_bytearray_obj_t;
#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_NVM_BYTEARRAY_H

View File

@ -0,0 +1 @@
// No nvm module functions.

View File

@ -0,0 +1,66 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "genhdr/mpversion.h"
#include "py/mpconfig.h"
#include "py/objstr.h"
#include "py/objtuple.h"
#include "py/mperrno.h"
#include "py/runtime.h"
#include "peripherals/periph.h"
#define RNG_TIMEOUT 5
STATIC const qstr os_uname_info_fields[] = {
MP_QSTR_sysname, MP_QSTR_nodename,
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
};
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, EFR32_SERIES_LOWER);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, EFR32_SERIES_LOWER);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
STATIC MP_DEFINE_ATTRTUPLE(
os_uname_info_obj,
os_uname_info_fields,
5,
(mp_obj_t)&os_uname_info_sysname_obj,
(mp_obj_t)&os_uname_info_nodename_obj,
(mp_obj_t)&os_uname_info_release_obj,
(mp_obj_t)&os_uname_info_version_obj,
(mp_obj_t)&os_uname_info_machine_obj);
mp_obj_t common_hal_os_uname(void) {
return (mp_obj_t)&os_uname_info_obj;
}
bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) {
return false;
}

View File

@ -0,0 +1,181 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "common-hal/pwmio/PWMOut.h"
#include "shared-bindings/pwmio/PWMOut.h"
#include "supervisor/shared/translate/translate.h"
#include "shared-bindings/microcontroller/Pin.h"
STATIC sl_pwm_instance_t pwm_handle[TIM_BANK_ARRAY_LEN];
STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN];
mcu_tim_pin_obj_t mcu_tim_list[TIM_BANK_ARRAY_LEN] = {
TIM(TIMER0, 0, FN_TIMER0_CC0, NULL),
TIM(TIMER1, 0, FN_TIMER1_CC0, NULL),
TIM(TIMER2, 0, FN_TIMER2_CC0, NULL),
TIM(TIMER3, 0, FN_TIMER3_CC0, NULL),
TIM(TIMER4, 0, FN_TIMER4_CC0, NULL),
};
// Reset all pwm channel
void pwmout_reset(void) {
uint8_t tim_index;
for (tim_index = 0; tim_index < TIM_BANK_ARRAY_LEN; tim_index++) {
mcu_tim_pin_obj_t *l_tim = &mcu_tim_list[tim_index];
if (l_tim->pin != NULL) {
sl_pwm_deinit(&pwm_handle[tim_index]);
}
}
}
// Create a PWM object associated with the given pin
pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
const mcu_pin_obj_t *pin,
uint16_t duty,
uint32_t frequency,
bool variable_frequency) {
uint8_t tim_num = TIM_BANK_ARRAY_LEN;
uint8_t percent = (duty * 100) / 65535;
sl_pwm_config_t pwm_config;
pwm_config.frequency = frequency;
pwm_config.polarity = PWM_ACTIVE_LOW;
mcu_tim_pin_obj_t *l_tim;
uint8_t tim_index;
if (self->tim == NULL) {
for (tim_index = 0; tim_index < tim_num; tim_index++) {
l_tim = &mcu_tim_list[tim_index];
if ((l_tim->pin == NULL && pin->function_list[l_tim->fn_index] == 1)
|| l_tim->pin == pin) {
l_tim->pin = pin;
self->tim = l_tim;
self->handle = &pwm_handle[tim_index];
break;
}
}
}
if (self->tim == NULL) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
self->duty_cycle = duty;
self->variable_frequency = variable_frequency;
self->frequency = frequency;
self->handle->port = pin->port;
self->handle->pin = pin->number;
self->handle->timer = self->tim->timer;
self->handle->channel = self->tim->channel;
self->tim->pin = pin;
if (SL_STATUS_OK != sl_pwm_init(self->handle, &pwm_config)) {
return PWMOUT_INITIALIZATION_ERROR;
}
sl_pwm_start(self->handle);
sl_pwm_set_duty_cycle(self->handle, percent);
common_hal_mcu_pin_claim(pin);
return PWMOUT_OK;
}
// Mark pwm obj to never reset after reload
void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) {
uint8_t tim_index;
for (tim_index = 0; tim_index < TIM_BANK_ARRAY_LEN; tim_index++) {
if (&mcu_tim_list[tim_index] == self->tim) {
never_reset_tim[tim_index] = true;
common_hal_never_reset_pin(self->tim->pin);
break;
}
}
}
// Pwm will be reset after reloading.
void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) {
uint8_t tim_index;
for (tim_index = 0; tim_index < TIM_BANK_ARRAY_LEN; tim_index++) {
if (&mcu_tim_list[tim_index] == self->tim) {
never_reset_tim[tim_index] = false;
break;
}
}
}
// Check pwm obj status, deinited or not
bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t *self) {
return self->tim == NULL;
}
// Deint pwm obj
void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
sl_pwm_deinit(self->handle);
common_hal_reset_pin(self->tim->pin);
mcu_tim_pin_obj_t *l_tim = self->tim;
l_tim->pin = NULL;
}
// Set pwm duty cycle
void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self,
uint16_t duty) {
uint8_t percent = (duty * 100) / 65535;
sl_pwm_set_duty_cycle(self->handle, percent);
self->duty_cycle = duty;
}
// Get pwm duty cycle
uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t *self) {
return self->duty_cycle;
}
// Set pwm frequency
void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t *self,
uint32_t frequency) {
sl_pwm_config_t pwm_config;
pwm_config.frequency = frequency;
pwm_config.polarity = PWM_ACTIVE_LOW;
sl_pwm_init(self->handle, &pwm_config);
}
// Get pwm frequency
uint32_t common_hal_pwmio_pwmout_get_frequency(pwmio_pwmout_obj_t *self) {
return self->frequency;
}
// Check variable frequency
bool common_hal_pwmio_pwmout_get_variable_frequency(pwmio_pwmout_obj_t *self) {
return self->variable_frequency;
}
// Get pin value in pwmio obj
const mcu_pin_obj_t *common_hal_pwmio_pwmout_get_pin(pwmio_pwmout_obj_t *self) {
return self->tim->pin;
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM32F4_COMMON_HAL_PWMIO_PWMOUT_H
#define MICROPY_INCLUDED_STM32F4_COMMON_HAL_PWMIO_PWMOUT_H
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
#include "peripherals/periph.h"
#include "sl_pwm.h"
typedef struct {
mp_obj_base_t base;
sl_pwm_instance_t *handle;
mcu_tim_pin_obj_t *tim;
bool variable_frequency : 1;
uint16_t duty_cycle;
uint32_t frequency;
} pwmio_pwmout_obj_t;
void pwmout_reset(void);
#endif // MICROPY_INCLUDED_STM32F4_COMMON_HAL_PWMIO_PWMOUT_H

View File

@ -0,0 +1 @@
// No pwmio module functions.

View File

@ -0,0 +1,78 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "shared/timeutils/timeutils.h"
#include "shared-bindings/rtc/__init__.h"
#include "common-hal/rtc/RTC.h"
#include "shared-bindings/rtc/RTC.h"
#include "supervisor/port.h"
#include "supervisor/shared/translate/translate.h"
#include "peripherals/rtc.h"
#include "sl_sleeptimer.h"
// Set rtc time
void common_hal_rtc_set_time(timeutils_struct_time_t *tm) {
sl_sleeptimer_date_t date = { 0 };
date.year = tm->tm_year - 1900;
// Month enum begins at
date.month = tm->tm_mon - 1;
date.month_day = tm->tm_mday;
date.day_of_week = tm->tm_wday == 6?0:tm->tm_wday + 1;
date.hour = tm->tm_hour;
date.min = tm->tm_min;
date.sec = tm->tm_sec;
date.day_of_year = tm->tm_yday;
sl_sleeptimer_set_datetime(&date);
}
// Get rtc time
void common_hal_rtc_get_time(timeutils_struct_time_t *tm) {
sl_sleeptimer_date_t date;
sl_sleeptimer_get_datetime(&date);
tm->tm_year = date.year + 1900;
tm->tm_mon = date.month + 1;
tm->tm_mday = date.month_day;
tm->tm_wday = date.day_of_week == 0?6:date.day_of_week - 1;
tm->tm_hour = date.hour;
tm->tm_min = date.min;
tm->tm_sec = date.sec;
tm->tm_yday = date.day_of_year;
}
int common_hal_rtc_get_calibration(void) {
return 0;
}
void common_hal_rtc_set_calibration(int calibration) {
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_calibration);
}

View File

@ -0,0 +1,33 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM_COMMON_HAL_RTC_RTC_H
#define MICROPY_INCLUDED_STM_COMMON_HAL_RTC_RTC_H
extern void rtc_init(void);
extern void rtc_reset(void);
#endif // MICROPY_INCLUDED_STM_COMMON_HAL_RTC_RTC_H

View File

View File

View File

@ -0,0 +1,37 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdbool.h>
#include "shared-bindings/supervisor/Runtime.h"
#include "supervisor/serial.h"
bool common_hal_supervisor_runtime_get_serial_connected(void) {
return (bool)serial_connected();
}
bool common_hal_supervisor_runtime_get_serial_bytes_available(void) {
return (bool)serial_bytes_available();
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_SUPERVISOR_RUNTIME_H
#define MICROPY_INCLUDED_STM32_COMMON_HAL_SUPERVISOR_RUNTIME_H
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
// Stores no state currently.
} super_runtime_obj_t;
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_SUPERVISOR_RUNTIME_H

View File

@ -0,0 +1,38 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/obj.h"
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/Runtime.h"
// The singleton supervisor.Runtime object, bound to supervisor.runtime
// It currently only has properties, and no state.
const super_runtime_obj_t common_hal_supervisor_runtime_obj = {
.base = {
.type = &supervisor_runtime_type,
},
};

View File

@ -0,0 +1,25 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

View File

@ -0,0 +1,133 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "common-hal/watchdog/WatchDogTimer.h"
#include "shared-bindings/watchdog/__init__.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "em_wdog.h"
#include "em_cmu.h"
void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) {
WDOGn_Feed(DEFAULT_WDOG);
}
void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) {
WDOG_Enable(false);
}
void watchdog_reset(void) {
common_hal_watchdog_deinit(&common_hal_mcu_watchdogtimer_obj);
}
mp_float_t common_hal_watchdog_get_timeout(watchdog_watchdogtimer_obj_t *self) {
return self->timeout;
}
void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self,
mp_float_t new_timeout) {
// Max timeout is 256000 ms
uint64_t timeout = new_timeout * 1000;
mp_arg_validate_int_max(timeout, 256000, MP_QSTR_WatchDogTimeout);
if ((uint32_t)self->timeout != (uint32_t)new_timeout) {
// Watchdog Initialize settings
WDOG_Init_TypeDef wdogInit = WDOG_INIT_DEFAULT;
switch ((uint32_t)new_timeout)
{
case 1:
wdogInit.perSel = wdogPeriod_1k;
break;
case 2:
wdogInit.perSel = wdogPeriod_2k;
break;
case 4:
wdogInit.perSel = wdogPeriod_4k;
break;
case 8:
wdogInit.perSel = wdogPeriod_8k;
break;
case 16:
wdogInit.perSel = wdogPeriod_16k;
break;
case 32:
wdogInit.perSel = wdogPeriod_32k;
break;
case 64:
wdogInit.perSel = wdogPeriod_64k;
break;
case 128:
wdogInit.perSel = wdogPeriod_128k;
break;
case 256:
wdogInit.perSel = wdogPeriod_256k;
break;
default:
mp_raise_ValueError(
translate("Timeout value supported: 1,2,4,8,16,32,64,128,256"));
}
self->timeout = new_timeout;
// Enable clock for the WDOG module; has no effect on xG21
CMU_ClockEnable(cmuClock_WDOG0, true);
// ULFRCO as clock source
CMU_ClockSelectSet(cmuClock_WDOG0, cmuSelect_ULFRCO);
wdogInit.em1Run = true;
wdogInit.em2Run = true;
wdogInit.em3Run = true;
// Initializing watchdog with chosen settings
WDOGn_Init(DEFAULT_WDOG, &wdogInit);
}
}
watchdog_watchdogmode_t common_hal_watchdog_get_mode
(watchdog_watchdogtimer_obj_t *self) {
return self->mode;
}
void common_hal_watchdog_set_mode(watchdog_watchdogtimer_obj_t *self,
watchdog_watchdogmode_t new_mode) {
if (self->mode != new_mode) {
if (new_mode == WATCHDOGMODE_RAISE) {
mp_raise_NotImplementedError(
translate("RAISE mode is not implemented"));
} else if (new_mode == WATCHDOGMODE_NONE) {
self->mode = WATCHDOGMODE_NONE;
common_hal_watchdog_deinit(self);
}
self->mode = new_mode;
common_hal_watchdog_set_timeout(self, self->timeout);
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H
#include "py/obj.h"
#include "shared-bindings/watchdog/WatchDogMode.h"
#include "shared-bindings/watchdog/WatchDogTimer.h"
struct _watchdog_watchdogtimer_obj_t {
mp_obj_base_t base;
mp_float_t timeout;
watchdog_watchdogmode_t mode;
};
// This needs to be called in order to disable the watchdog
void watchdog_reset(void);
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H

View File

@ -0,0 +1,10 @@
id: cp_efr32
label: CircuitPython support
version: 1.0.0
sdk:
id: "gecko_sdk"
version: 4.2.1
component_path:
- path: ../boards/devkit_xg24_brd2601b/
- path: ../boards/explorerkit_xg24_brd2703a/
- path: ../boards/sparkfun_thingplus_matter_mgm240p_brd2704a/

@ -0,0 +1 @@
Subproject commit 3fbadf9fb4e904fd8ed087642a41762b833ae0fe

21
ports/silabs/license.md Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-2022 Damien P. George and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,73 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef EFR32_MPCONFIGPORT_H__
#define EFR32_MPCONFIGPORT_H__
#include <stdint.h>
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
// 24kiB stack
#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000
// Board flags:
#ifndef BOARD_OVERWRITE_SWD
#define BOARD_OVERWRITE_SWD (0)
#endif
#ifndef BOARD_VTOR_DEFER
#define BOARD_VTOR_DEFER (0)
#endif
#ifndef BOARD_NO_VBUS_SENSE
#define BOARD_NO_VBUS_SENSE (0)
#endif
#ifndef BOARD_NO_USB_OTG_ID_SENSE
#define BOARD_NO_USB_OTG_ID_SENSE (0)
#endif
#if INTERNAL_FLASH_FILESYSTEM
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR (0x080E0000UL)
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (512 * 1024)
#else
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0)
#endif
// Peripheral implementation counts
#define MAX_UART 1
#define MAX_I2C 1
#define MAX_SPI 1
#define asm(str) __asm(str)
#include "py/circuitpy_mpconfig.h"
#define MICROPY_PORT_ROOT_POINTERS \
void *cpy_uart_obj_all[MAX_UART]; \
void *cpy_i2c_obj_all[MAX_I2C]; \
CIRCUITPY_COMMON_ROOT_POINTERS
#endif // EFR32_MPCONFIGPORT_H__

View File

@ -0,0 +1,37 @@
LONGINT_IMPL ?= MPZ
INTERNAL_LIBM ?= 1
USB_NUM_ENDPOINT_PAIRS ?= 0
CIRCUITPY_ANALOGIO ?= 1
CIRCUITPY_BLEIO ?= 1
CIRCUITPY_BUSDEVICE ?= 1
CIRCUITPY_BUSIO ?= 1
CIRCUITPY_DIGITALIO ?= 1
CIRCUITPY_DISPLAYIO ?= 1
CIRCUITPY_FRAMEBUFFERIO ?= 1
CIRCUITPY_NVM ?= 1
CIRCUITPY_PWMIO ?= 1
CIRCUITPY_RTC ?= 1
CIRCUITPY_WATCHDOG ?=1
ifeq ($(MCU_SERIES),MG24)
# Not yet implemented common-hal modules:
CIRCUITPY_AUDIOIO ?= 0
CIRCUITPY_AUDIOCORE ?= 0
CIRCUITPY_AUDIOPWMIO ?= 0
CIRCUITPY_AUDIOBUSIO ?= 0
CIRCUITPY_BITBANGIO ?= 0
CIRCUITPY_BLEIO_HCI ?= 0
CIRCUITPY_COUNTIO ?= 0
CIRCUITPY_FREQUENCYIO ?= 0
CIRCUITPY_I2CTARGET ?= 0
CIRCUITPY_KEYPAD ?= 0
CIRCUITPY_NEOPIXEL_WRITE ?= 0
CIRCUITPY_PARALLELDISPLAY ?= 0
CIRCUITPY_PULSEIO ?= 0
CIRCUITPY_ROTARYIO ?= 0
CIRCUITPY_TOUCHIO ?= 0
CIRCUITPY_USB ?= 0
endif
CIRCUITPY_BUILD_EXTENSIONS ?= bin

46
ports/silabs/mphalport.c Normal file
View File

@ -0,0 +1,46 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/mphal.h"
#include "py/mpstate.h"
#include "py/gc.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/shared/tick.h"
void mp_hal_delay_us(mp_uint_t delay) {
common_hal_mcu_delay_us(delay);
}
void mp_hal_disable_all_interrupts(void) {
common_hal_mcu_disable_interrupts();
}
void mp_hal_enable_all_interrupts(void) {
common_hal_mcu_enable_interrupts();
}

51
ports/silabs/mphalport.h Normal file
View File

@ -0,0 +1,51 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EFR32_MPHALPORT_H
#define MICROPY_INCLUDED_EFR32_MPHALPORT_H
#include "py/obj.h"
#include "lib/oofatfs/ff.h"
#include "supervisor/shared/tick.h"
// Global millisecond tick count (driven by SysTick interrupt).
static inline mp_uint_t mp_hal_ticks_ms(void) {
return supervisor_ticks_ms32();
}
// Number of bytes in receive buffer
extern volatile uint8_t usb_rx_count;
extern volatile bool mp_cdc_enabled;
int receive_usb(void);
void mp_hal_set_interrupt_char(int c);
void mp_hal_disable_all_interrupts(void);
void mp_hal_enable_all_interrupts(void);
#endif // MICROPY_INCLUDED_EFR32_MPHALPORT_H

View File

@ -0,0 +1,81 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __MICROPY_INCLUDED_EFR32_PERIPHERALS_PERIPH_H__
#define __MICROPY_INCLUDED_EFR32_PERIPHERALS_PERIPH_H__
#include <stdint.h>
#include <stdbool.h>
#include "pins.h"
#include "uartdrv.h"
#include "sl_pwm.h"
#include "em_vdac.h"
#define TIM_BANK_ARRAY_LEN 5
// Timer Peripheral
typedef struct {
TIMER_TypeDef *timer;
uint8_t channel;
uint8_t fn_index;
const mcu_pin_obj_t *pin;
} mcu_tim_pin_obj_t;
#define TIM(timer_index, channel_index, pin_fun, pin_num) \
{ \
.timer = timer_index, \
.channel = channel_index, \
.fn_index = pin_fun, \
.pin = pin_num \
}
extern mcu_tim_pin_obj_t mcu_tim_list[TIM_BANK_ARRAY_LEN];
#define DAC_BANK_ARRAY_LEN 4
typedef struct {
VDAC_TypeDef *vdac;
uint8_t channel;
uint8_t fn_index;
bool is_used;
uint16_t value;
const mcu_pin_obj_t *pin;
} mcu_dac_pin_obj_t;
#define DAC(vdac_index, channel_index, pin_fun, used, dac_value, pin_num) \
{ \
.vdac = vdac_index, \
.channel = channel_index, \
.fn_index = pin_fun, \
.is_used = used, \
.value = dac_value, \
.pin = pin_num \
}
extern mcu_dac_pin_obj_t mcu_dac_list[DAC_BANK_ARRAY_LEN];
#endif // __MICROPY_INCLUDED_EFR32_PERIPHERALS_PERIPH_H__

View File

@ -0,0 +1,171 @@
/*
* This file is part of Adafruit for EFR32 project
*
* The MIT License (MIT)
*
* Copyright 2023 Silicon Laboratories Inc. www.silabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __MICROPY_INCLUDED_EFR32_PERIPHERALS_PINS_H__
#define __MICROPY_INCLUDED_EFR32_PERIPHERALS_PINS_H__
typedef struct {
mp_obj_base_t base;
const uint8_t port : 4;
const uint8_t number : 4;
const uint8_t *const function_list;
} mcu_pin_obj_t;
extern const mp_obj_type_t mcu_pin_type;
#define PIN(p_port, p_number, p_funtion_list) \
{ \
{&mcu_pin_type}, \
.port = p_port, \
.number = p_number, \
.function_list = p_funtion_list \
}
#ifdef GPIO_PA0_EXISTS
extern const mcu_pin_obj_t pin_PA0;
#endif
#ifdef GPIO_PA1_EXISTS
extern const mcu_pin_obj_t pin_PA1;
#endif
#ifdef GPIO_PA2_EXISTS
extern const mcu_pin_obj_t pin_PA2;
#endif
#ifdef GPIO_PA3_EXISTS
extern const mcu_pin_obj_t pin_PA3;
#endif
#ifdef GPIO_PA4_EXISTS
extern const mcu_pin_obj_t pin_PA4;
#endif
#ifdef GPIO_PA5_EXISTS
extern const mcu_pin_obj_t pin_PA5;
#endif
#ifdef GPIO_PA6_EXISTS
extern const mcu_pin_obj_t pin_PA6;
#endif
#ifdef GPIO_PA7_EXISTS
extern const mcu_pin_obj_t pin_PA7;
#endif
#ifdef GPIO_PA8_EXISTS
extern const mcu_pin_obj_t pin_PA8;
#endif
#ifdef GPIO_PB0_EXISTS
extern const mcu_pin_obj_t pin_PB0;
#endif
#ifdef GPIO_PB1_EXISTS
extern const mcu_pin_obj_t pin_PB1;
#endif
#ifdef GPIO_PB2_EXISTS
extern const mcu_pin_obj_t pin_PB2;
#endif
#ifdef GPIO_PB3_EXISTS
extern const mcu_pin_obj_t pin_PB3;
#endif
#ifdef GPIO_PB4_EXISTS
extern const mcu_pin_obj_t pin_PB4;
#endif
#ifdef GPIO_PB5_EXISTS
extern const mcu_pin_obj_t pin_PB5;
#endif
#ifdef GPIO_PC0_EXISTS
extern const mcu_pin_obj_t pin_PC0;
#endif
#ifdef GPIO_PC1_EXISTS
extern const mcu_pin_obj_t pin_PC1;
#endif
#ifdef GPIO_PC2_EXISTS
extern const mcu_pin_obj_t pin_PC2;
#endif
#ifdef GPIO_PC3_EXISTS
extern const mcu_pin_obj_t pin_PC3;
#endif
#ifdef GPIO_PC4_EXISTS
extern const mcu_pin_obj_t pin_PC4;
#endif
#ifdef GPIO_PC5_EXISTS
extern const mcu_pin_obj_t pin_PC5;
#endif
#ifdef GPIO_PC6_EXISTS
extern const mcu_pin_obj_t pin_PC6;
#endif
#ifdef GPIO_PC7_EXISTS
extern const mcu_pin_obj_t pin_PC7;
#endif
#ifdef GPIO_PC8_EXISTS
extern const mcu_pin_obj_t pin_PC8;
#endif
#ifdef GPIO_PC9_EXISTS
extern const mcu_pin_obj_t pin_PC9;
#endif
#ifdef GPIO_PD0_EXISTS
extern const mcu_pin_obj_t pin_PD0;
#endif
#ifdef GPIO_PD1_EXISTS
extern const mcu_pin_obj_t pin_PD1;
#endif
#ifdef GPIO_PD2_EXISTS
extern const mcu_pin_obj_t pin_PD2;
#endif
#ifdef GPIO_PD3_EXISTS
extern const mcu_pin_obj_t pin_PD3;
#endif
#ifdef GPIO_PD4_EXISTS
extern const mcu_pin_obj_t pin_PD4;
#endif
#ifdef GPIO_PD5_EXISTS
extern const mcu_pin_obj_t pin_PD5;
#endif
#endif // __MICROPY_INCLUDED_EFR32_PERIPHERALS_PINS_H__

Some files were not shown because too many files have changed in this diff Show More