From d7dc0b789d3c6987dc44b8d43f541f77c1e7f164 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Tue, 13 Dec 2016 20:27:26 +0100 Subject: [PATCH] nrf5: Updating port with new content. SPI, SDcard (trough sdcard.py), Pin, and machine module. Also adding some basic modules depending on SDK and bluetooth stack from nordic semiconductor. NUS is module copied from original port by tralamazza, and new basic module for 6lowpan over BLE which can be used by modnetwork and modusocket. Basic BLE module to enable bluetooth stack and start a eddystone advertisment is kept, and still works without SDK, even if in the SDK folder (its placed there as it needs bluetooth stack from an SDK). --- nrf5/Makefile | 145 +- nrf5/boards/common.ld | 6 +- nrf5/boards/make-pins.py | 398 ++++ nrf5/boards/nrf51822_aa.ld | 6 +- nrf5/boards/nrf51822_aa_s110.ld | 6 +- nrf5/boards/nrf51822_ac_s110.ld | 4 +- nrf5/boards/nrf51822_ac_s120.ld | 2 +- nrf5/boards/nrf51822_ac_s130.ld | 4 +- nrf5/boards/nrf51_prefix.c | 32 + nrf5/boards/nrf52832_aa_s132.ld | 2 +- nrf5/boards/nrf52832_aa_s1xx.ld | 118 +- nrf5/boards/nrf52_prefix.c | 32 + nrf5/boards/pca10000/mpconfigboard.h | 2 + nrf5/boards/pca10000/mpconfigboard.mk | 4 +- nrf5/boards/pca10000/mpconfigboard_s110.mk | 12 +- nrf5/boards/pca10000/nrf51_hal_conf.h | 7 + nrf5/boards/pca10000/pins.csv | 7 + nrf5/boards/pca10001/mpconfigboard.mk | 5 +- nrf5/boards/pca10001/mpconfigboard_s110.mk | 3 + nrf5/boards/pca10001/nrf51_hal_conf.h | 8 + nrf5/boards/pca10001/pins.csv | 32 + nrf5/boards/pca10028/mpconfigboard.h | 10 + nrf5/boards/pca10028/mpconfigboard.mk | 4 +- nrf5/boards/pca10028/mpconfigboard_s110.mk | 11 +- nrf5/boards/pca10028/mpconfigboard_s120.mk | 12 +- nrf5/boards/pca10028/mpconfigboard_s130.mk | 11 +- nrf5/boards/pca10028/nrf51_hal_conf.h | 8 + nrf5/boards/pca10028/pins.csv | 32 + nrf5/boards/pca10031/mpconfigboard.h | 8 + nrf5/boards/pca10031/mpconfigboard.mk | 5 +- nrf5/boards/pca10031/mpconfigboard_s110.mk | 11 +- nrf5/boards/pca10031/mpconfigboard_s120.mk | 11 +- nrf5/boards/pca10031/mpconfigboard_s130.mk | 11 +- nrf5/boards/pca10031/nrf51_hal_conf.h | 8 + nrf5/boards/pca10031/pins.csv | 13 + nrf5/boards/pca10040/mpconfigboard.h | 8 + nrf5/boards/pca10040/mpconfigboard.mk | 4 +- nrf5/boards/pca10040/mpconfigboard_s132.mk | 12 +- nrf5/boards/pca10040/mpconfigboard_s1xx.mk | 12 +- nrf5/boards/pca10040/nrf52_hal_conf.h | 10 + nrf5/boards/pca10040/pins.csv | 30 + nrf5/builtin_open.c | 30 + nrf5/device/nrf52/startup_nrf52.s | 30 +- nrf5/fatfs_port.c | 46 + nrf5/gccollect.h | 1 + nrf5/hal/hal_spi.c | 122 ++ nrf5/hal/hal_spi.h | 105 + nrf5/hal/hal_spie.c | 135 ++ nrf5/hal/hal_time.c | 116 + nrf5/hal/hal_time.h | 32 + nrf5/hal/hal_uart.c | 4 + nrf5/hal/hal_uarte.c | 24 +- nrf5/hal/nrf51_hal.h | 31 + nrf5/hal/nrf52_hal.h | 31 + nrf5/help.c | 1 + nrf5/led.c | 1 + nrf5/led.h | 1 + nrf5/lexerfatfs.c | 35 + nrf5/main.c | 76 +- nrf5/modmachine.c | 185 ++ nrf5/modmachine.h | 42 + nrf5/modnetwork.c | 97 + nrf5/modnetwork.h | 81 + nrf5/modpyb.c | 5 +- nrf5/modules/mountsd.py | 9 + nrf5/modules/sdcard.py | 278 +++ nrf5/moduos.c | 411 ++++ nrf5/modusocket.c | 480 ++++ nrf5/modutime.c | 52 + nrf5/mpconfigport.h | 85 +- nrf5/mphalport.c | 5 + nrf5/mphalport.h | 37 +- nrf5/nrf51_af.csv | 32 + nrf5/nrf52_af.csv | 32 + nrf5/pin.c | 611 ++++++ nrf5/pin.h | 101 + nrf5/pin_defs_nrf5.h | 58 + nrf5/pin_named_pins.c | 92 + nrf5/sdk/help_sd.h | 8 + nrf5/sdk/iot_0.9.0/build.mk | 118 + nrf5/sdk/iot_0.9.0/modnwble6lowpan.c | 217 ++ nrf5/sdk/iot_0.9.0/sdk.mk | 12 + nrf5/sdk/iot_0.9.0/sdk_config.h | 46 + nrf5/sdk/iot_0.9.0/sdkhelp.c | 256 +++ nrf5/sdk/iot_0.9.0/sdkhelp.h | 27 + nrf5/sdk/modble.c | 14 +- nrf5/sdk/nrf5_sdk_conf.h | 40 + nrf5/sdk/sdk_10.0.0/sdk.mk | 17 + nrf5/sdk/sdk_12.1.0/build.mk | 103 + nrf5/sdk/sdk_12.1.0/nrf52832_aa_s132.ld | 40 + nrf5/sdk/sdk_12.1.0/nrf52_app_error.c | 19 + nrf5/sdk/sdk_12.1.0/nrf52_ble.c | 487 +++++ nrf5/sdk/sdk_12.1.0/nrf52_ble.h | 4 + nrf5/sdk/sdk_12.1.0/nrf52_board.h | 9 + nrf5/sdk/sdk_12.1.0/sdk.mk | 19 + nrf5/sdk/sdk_12.1.0/sdk_config.h | 2299 ++++++++++++++++++++ nrf5/sdk/sdk_common.mk | 27 + nrf5/sdk/softdevice.c | 10 +- nrf5/sdk/softdevice.h | 10 +- nrf5/spi.c | 326 +++ nrf5/spi.h | 32 + nrf5/uart.c | 2 + nrf5/uart.h | 1 + 103 files changed, 8409 insertions(+), 314 deletions(-) create mode 100644 nrf5/boards/make-pins.py create mode 100644 nrf5/boards/nrf51_prefix.c create mode 100644 nrf5/boards/nrf52_prefix.c create mode 100644 nrf5/boards/pca10000/nrf51_hal_conf.h create mode 100644 nrf5/boards/pca10000/pins.csv create mode 100644 nrf5/boards/pca10001/mpconfigboard_s110.mk create mode 100644 nrf5/boards/pca10001/nrf51_hal_conf.h create mode 100644 nrf5/boards/pca10001/pins.csv create mode 100644 nrf5/boards/pca10028/nrf51_hal_conf.h create mode 100644 nrf5/boards/pca10028/pins.csv create mode 100644 nrf5/boards/pca10031/nrf51_hal_conf.h create mode 100644 nrf5/boards/pca10031/pins.csv create mode 100644 nrf5/boards/pca10040/nrf52_hal_conf.h create mode 100644 nrf5/boards/pca10040/pins.csv create mode 100644 nrf5/builtin_open.c create mode 100644 nrf5/fatfs_port.c create mode 100644 nrf5/hal/hal_spi.c create mode 100644 nrf5/hal/hal_spi.h create mode 100644 nrf5/hal/hal_spie.c create mode 100644 nrf5/hal/hal_time.c create mode 100644 nrf5/hal/hal_time.h create mode 100644 nrf5/hal/nrf51_hal.h create mode 100644 nrf5/hal/nrf52_hal.h create mode 100644 nrf5/lexerfatfs.c create mode 100644 nrf5/modmachine.c create mode 100644 nrf5/modmachine.h create mode 100644 nrf5/modnetwork.c create mode 100644 nrf5/modnetwork.h create mode 100644 nrf5/modules/mountsd.py create mode 100644 nrf5/modules/sdcard.py create mode 100644 nrf5/moduos.c create mode 100644 nrf5/modusocket.c create mode 100644 nrf5/modutime.c create mode 100644 nrf5/nrf51_af.csv create mode 100644 nrf5/nrf52_af.csv create mode 100644 nrf5/pin.c create mode 100644 nrf5/pin.h create mode 100644 nrf5/pin_defs_nrf5.h create mode 100644 nrf5/pin_named_pins.c create mode 100644 nrf5/sdk/iot_0.9.0/build.mk create mode 100644 nrf5/sdk/iot_0.9.0/modnwble6lowpan.c create mode 100644 nrf5/sdk/iot_0.9.0/sdk.mk create mode 100644 nrf5/sdk/iot_0.9.0/sdk_config.h create mode 100644 nrf5/sdk/iot_0.9.0/sdkhelp.c create mode 100644 nrf5/sdk/iot_0.9.0/sdkhelp.h create mode 100644 nrf5/sdk/nrf5_sdk_conf.h create mode 100644 nrf5/sdk/sdk_10.0.0/sdk.mk create mode 100644 nrf5/sdk/sdk_12.1.0/build.mk create mode 100644 nrf5/sdk/sdk_12.1.0/nrf52832_aa_s132.ld create mode 100644 nrf5/sdk/sdk_12.1.0/nrf52_app_error.c create mode 100644 nrf5/sdk/sdk_12.1.0/nrf52_ble.c create mode 100644 nrf5/sdk/sdk_12.1.0/nrf52_ble.h create mode 100644 nrf5/sdk/sdk_12.1.0/nrf52_board.h create mode 100644 nrf5/sdk/sdk_12.1.0/sdk.mk create mode 100644 nrf5/sdk/sdk_12.1.0/sdk_config.h create mode 100644 nrf5/sdk/sdk_common.mk create mode 100644 nrf5/spi.c create mode 100644 nrf5/spi.h diff --git a/nrf5/Makefile b/nrf5/Makefile index f258e160f7..1685573f60 100644 --- a/nrf5/Makefile +++ b/nrf5/Makefile @@ -5,66 +5,89 @@ ifeq ($(wildcard boards/$(BOARD)/.),) $(error Invalid BOARD specified) endif +check_defined = \ + $(strip $(foreach 1,$1, \ + $(call __check_defined,$1,$(strip $(value 2))))) +__check_defined = \ + $(if $(value $1),, \ + $(error Undefined $1$(if $2, ($2)))) + # If SoftDevice is selected, try to use that one. -SD ?= none +SD ?= SD_LOWER = $(shell echo $(SD) | tr '[:upper:]' '[:lower:]') # TODO: Verify that it is a valid target. -ifeq ($(SD), none) +ifeq ($(SD), ) # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) include ../py/mkenv.mk include boards/$(BOARD)/mpconfigboard.mk else + $(call check_defined, SDK_ROOT, path to SDK containing softdevice) # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD)-$(SD_LOWER) include ../py/mkenv.mk include boards/$(BOARD)/mpconfigboard_$(SD_LOWER).mk + + include sdk/sdk_common.mk endif # qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h +QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h + +FROZEN_MPY_DIR = modules # include py core make definitions include ../py/py.mk + +FATFS_DIR = lib/fatfs +MPY_CROSS = ../mpy-cross/mpy-cross +MPY_TOOL = ../tools/mpy-tool.py + CROSS_COMPILE = arm-none-eabi- -MCU_VARIANT_LOWER = $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]') +MCU_VARIANT_UPPER = $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') -INC = -I. +INC += -I. INC += -I.. INC += -I$(BUILD) INC += -I./device INC += -I./../lib/cmsis/inc INC += -I./device -INC += -I./device/$(MCU_VARIANT_LOWER) +INC += -I./device/$(MCU_VARIANT) INC += -I./hal -INC += -I./hal/$(MCU_VARIANT_LOWER) +INC += -I./hal/$(MCU_VARIANT) INC += -I./drivers INC += -I../lib/mp-readline -NRF_DEFINES = -D$(MCU_VARIANT) +NRF_DEFINES = -D$(MCU_VARIANT_UPPER) NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion -CFLAGS_MCU_m4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +CFLAGS_MCU_m4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections CFLAGS_MCU_m0 = $(CFLAGS_CORTEX_M) --short-enums -mtune=cortex-m0 -mcpu=cortex-m0 -mfloat-abi=soft -fno-builtin + CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(COPT) $(NRF_DEFINES) +CFLAGS += -fno-strict-aliasing CFLAGS += -Iboards/$(BOARD) +CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>' +CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool +CFLAGS += -DMICROPY_MODULE_FROZEN_MPY LDFLAGS = $(CFLAGS) LDFLAGS += -Xlinker -Map=$(@:.elf=.map) -LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE) +LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE) -L boards/ #Debugging/Optimization ifeq ($(DEBUG), 1) +#ASMFLAGS += -g -gtabs+ CFLAGS += -O0 -ggdb LDFLAGS += -O0 else @@ -72,46 +95,132 @@ CFLAGS += -Os -DNDEBUG LDFLAGS += -Os endif -LIBS = +LIBS += \ SRC_LIB = $(addprefix lib/,\ libc/string0.c \ mp-readline/readline.c \ utils/pyexec.c \ - utils/pyhelp.c \ + utils/pyhelp.c \ + timeutils/timeutils.c \ + fatfs/ff.c \ + fatfs/option/ccsbcs.c \ + netutils/netutils.c \ + ) + +SRC_HAL = $(addprefix hal/,\ + hal_uart.c \ + hal_uarte.c \ + hal_spi.c \ + hal_spie.c \ + hal_time.c \ ) SRC_C += \ main.c \ - device/$(MCU_VARIANT_LOWER)/system_$(MCU_VARIANT_LOWER).c \ modpyb.c \ led.c \ mphalport.c \ uart.c \ + spi.c \ help.c \ gccollect.c \ + pin_named_pins.c \ + modmachine.c \ + pin.c \ + modutime.c \ + moduos.c \ + fatfs_port.c \ + builtin_open.c \ + lexerfatfs.c \ + modusocket.c \ + modnetwork.c \ + +#ifeq ($(SD), ) + +SRC_C += \ + device/$(MCU_VARIANT)/system_$(MCU_VARIANT).c \ SRC_S = \ - device/$(MCU_VARIANT_LOWER)/startup_$(MCU_VARIANT_LOWER).s \ + device/$(MCU_VARIANT)/startup_$(MCU_VARIANT).s \ -OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o)) +#endif + +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)) + +OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o)) +OBJ += $(BUILD)/pins_gen.o +OBJ += $(BUILD)/$(BUILD)/frozen_mpy.o -.phony: all flash +$(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os +$(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os + +.phony: all flash sd all: $(BUILD)/firmware.elf binary hex flash: $(BUILD)/firmware.elf - nrfjprog --program $(BUILD)/firmware.hex --sectorerase -f $(MCU_VARIANT_LOWER) - nrfjprog --pinreset -f $(MCU_VARIANT_LOWER) + nrfjprog --program $(BUILD)/firmware.hex --sectorerase -f $(MCU_VARIANT) + nrfjprog --pinreset -f $(MCU_VARIANT) + +sd: + nrfjprog --eraseall -f $(MCU_VARIANT) + nrfjprog --program $(SOFTDEV_HEX) -f $(MCU_VARIANT) + nrfjprog --program $(BUILD)/firmware.hex --sectorerase -f $(MCU_VARIANT) + nrfjprog --pinreset -f $(MCU_VARIANT) $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(Q)$(SIZE) $@ +# List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(SRC_MOD) $(SRC_LIB) +# Append any auto-generated sources that are needed by sources listed in +# SRC_QSTR +SRC_QSTR_AUTO_DEPS += + +# Making OBJ use an order-only depenedency on the generated pins.h file +# has the side effect of making the pins.h file before we actually compile +# any of the objects. The normal dependency generation will deal with the +# case when pins.h is modified. But when it doesn't exist, we don't know +# which source files might need it. +$(OBJ): | $(HEADER_BUILD)/pins.h + +# Use a pattern rule here so that make will only call make-pins.py once to make +# both pins_$(BOARD).c and pins.h +$(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qstr.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) + $(ECHO) "Create $@" + $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) + +$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c + $(call compile_c) + +MAKE_PINS = boards/make-pins.py +BOARD_PINS = boards/$(BOARD)/pins.csv +AF_FILE = $(MCU_VARIANT)_af.csv +PREFIX_FILE = boards/$(MCU_VARIANT)_prefix.c +GEN_PINS_SRC = $(BUILD)/pins_gen.c +GEN_PINS_HDR = $(HEADER_BUILD)/pins.h +GEN_PINS_QSTR = $(BUILD)/pins_qstr.h +GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h +GEN_PINS_AF_PY = $(BUILD)/pins_af.py + +# to build .mpy files from .py files +$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py + @$(ECHO) "MPY $<" + $(Q)$(MKDIR) -p $(dir $@) + $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^ + +# to build frozen_mpy.c from all .mpy files +$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h + @$(ECHO) "Creating $@" + $(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl mpz $(FROZEN_MPY_MPY_FILES) > $@ + include ../py/mkrules.mk include mkrules.mk diff --git a/nrf5/boards/common.ld b/nrf5/boards/common.ld index fd2dc70461..c6e4952b45 100644 --- a/nrf5/boards/common.ld +++ b/nrf5/boards/common.ld @@ -40,13 +40,13 @@ SECTIONS */ /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); + _sidata = .; /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). It is one task of the startup to copy the initial values from FLASH to RAM. */ - .data : + .data : AT (_sidata) { . = ALIGN(4); _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ @@ -56,7 +56,7 @@ SECTIONS . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ - } >RAM AT> FLASH_TEXT + } >RAM /* Uninitialized data section */ .bss : diff --git a/nrf5/boards/make-pins.py b/nrf5/boards/make-pins.py new file mode 100644 index 0000000000..11f9ffb3fd --- /dev/null +++ b/nrf5/boards/make-pins.py @@ -0,0 +1,398 @@ +#!/usr/bin/env python +"""Creates the pin file for the nRF5.""" + +from __future__ import print_function + +import argparse +import sys +import csv + +SUPPORTED_FN = { + 'UART' : ['RX', 'TX', 'CTS', 'RTS'] +} + +def parse_port_pin(name_str): + """Parses a string and returns a (port-num, pin-num) tuple.""" + if len(name_str) < 3: + raise ValueError("Expecting pin name to be at least 4 charcters.") + if name_str[0] != 'P': + raise ValueError("Expecting pin name to start with P") + if name_str[1] not in ('A'): + raise ValueError("Expecting pin port to be in A") + port = ord(name_str[1]) - ord('A') + pin_str = name_str[2:].split('/')[0] + if not pin_str.isdigit(): + raise ValueError("Expecting numeric pin number.") + return (port, int(pin_str)) + +def split_name_num(name_num): + num = None + for num_idx in range(len(name_num) - 1, -1, -1): + if not name_num[num_idx].isdigit(): + name = name_num[0:num_idx + 1] + num_str = name_num[num_idx + 1:] + if len(num_str) > 0: + num = int(num_str) + break + return name, num + + +class AlternateFunction(object): + """Holds the information associated with a pins alternate function.""" + + def __init__(self, idx, af_str): + self.idx = idx + self.af_str = af_str + + self.func = '' + self.fn_num = None + self.pin_type = '' + self.supported = False + + af_words = af_str.split('_', 1) + self.func, self.fn_num = split_name_num(af_words[0]) + if len(af_words) > 1: + self.pin_type = af_words[1] + if self.func in SUPPORTED_FN: + pin_types = SUPPORTED_FN[self.func] + if self.pin_type in pin_types: + self.supported = True + + def is_supported(self): + return self.supported + + def ptr(self): + """Returns the numbered function (i.e. USART6) for this AF.""" + if self.fn_num is None: + return self.func + return '{:s}{:d}'.format(self.func, self.fn_num) + + def mux_name(self): + return 'AF{:d}_{:s}'.format(self.idx, self.ptr()) + + def print(self): + """Prints the C representation of this AF.""" + if self.supported: + print(' AF', end='') + else: + print(' //', end='') + fn_num = self.fn_num + if fn_num is None: + fn_num = 0 + print('({:2d}, {:8s}, {:2d}, {:10s}, {:8s}), // {:s}'.format(self.idx, + self.func, fn_num, self.pin_type, self.ptr(), self.af_str)) + + def qstr_list(self): + return [self.mux_name()] + + +class Pin(object): + """Holds the information associated with a pin.""" + + def __init__(self, port, pin): + self.port = port + self.pin = pin + self.alt_fn = [] + self.alt_fn_count = 0 + self.adc_num = 0 + self.adc_channel = 0 + self.board_pin = False + + def port_letter(self): + return chr(self.port + ord('A')) + + def cpu_pin_name(self): + return '{:s}{:d}'.format(self.port_letter(), self.pin) + + def is_board_pin(self): + return self.board_pin + + def set_is_board_pin(self): + self.board_pin = True + + def parse_adc(self, adc_str): + if (adc_str[:3] != 'ADC'): + return + (adc,channel) = adc_str.split('_') + for idx in range(3, len(adc)): + adc_num = int(adc[idx]) # 1, 2, or 3 + self.adc_num |= (1 << (adc_num - 1)) + self.adc_channel = int(channel[2:]) + + def parse_af(self, af_idx, af_strs_in): + if len(af_strs_in) == 0: + return + # If there is a slash, then the slash separates 2 aliases for the + # same alternate function. + af_strs = af_strs_in.split('/') + for af_str in af_strs: + alt_fn = AlternateFunction(af_idx, af_str) + self.alt_fn.append(alt_fn) + if alt_fn.is_supported(): + self.alt_fn_count += 1 + + def alt_fn_name(self, null_if_0=False): + if null_if_0 and self.alt_fn_count == 0: + return 'NULL' + return 'pin_{:s}_af'.format(self.cpu_pin_name()) + + def adc_num_str(self): + str = '' + for adc_num in range(1,4): + if self.adc_num & (1 << (adc_num - 1)): + if len(str) > 0: + str += ' | ' + str += 'PIN_ADC' + str += chr(ord('0') + adc_num) + if len(str) == 0: + str = '0' + return str + + def print(self): + if self.alt_fn_count == 0: + print("// ", end='') + print('const pin_af_obj_t {:s}[] = {{'.format(self.alt_fn_name())) + for alt_fn in self.alt_fn: + alt_fn.print() + if self.alt_fn_count == 0: + print("// ", end='') + print('};') + print('') + print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:s}, {:s}, {:d});'.format( + self.cpu_pin_name(), self.port_letter(), self.pin, + self.alt_fn_name(null_if_0=True), + self.adc_num_str(), self.adc_channel)) + print('') + + def print_header(self, hdr_file): + hdr_file.write('extern const pin_obj_t pin_{:s};\n'. + format(self.cpu_pin_name())) + if self.alt_fn_count > 0: + hdr_file.write('extern const pin_af_obj_t pin_{:s}_af[];\n'. + format(self.cpu_pin_name())) + + def qstr_list(self): + result = [] + for alt_fn in self.alt_fn: + if alt_fn.is_supported(): + result += alt_fn.qstr_list() + return result + + +class NamedPin(object): + + def __init__(self, name, pin): + self._name = name + self._pin = pin + + def pin(self): + return self._pin + + def name(self): + return self._name + + +class Pins(object): + + def __init__(self): + self.cpu_pins = [] # list of NamedPin objects + self.board_pins = [] # list of NamedPin objects + + def find_pin(self, port_num, pin_num): + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.port == port_num and pin.pin == pin_num: + return pin + + def parse_af_file(self, filename, pinname_col, af_col): + with open(filename, 'r') as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + (port_num, pin_num) = parse_port_pin(row[pinname_col]) + except: + continue + pin = Pin(port_num, pin_num) + for af_idx in range(af_col, len(row)): + if af_idx >= af_col: + pin.parse_af(af_idx - af_col, row[af_idx]) + self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin)) + + def parse_board_file(self, filename): + with open(filename, 'r') as csvfile: + rows = csv.reader(csvfile) + for row in rows: + try: + (port_num, pin_num) = parse_port_pin(row[1]) + except: + continue + pin = self.find_pin(port_num, pin_num) + if pin: + pin.set_is_board_pin() + self.board_pins.append(NamedPin(row[0], pin)) + + def print_named(self, label, named_pins): + print('STATIC const mp_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label)) + for named_pin in named_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + print(' {{ MP_OBJ_NEW_QSTR(MP_QSTR_{:s}), (mp_obj_t)&pin_{:s} }},'.format(named_pin.name(), pin.cpu_pin_name())) + print('};') + print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label)); + + def print(self): + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + pin.print() + self.print_named('cpu', self.cpu_pins) + print('') + self.print_named('board', self.board_pins) + + def print_adc(self, adc_num): + print(''); + print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num)) + for channel in range(16): + adc_found = False + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if (pin.is_board_pin() and + (pin.adc_num & (1 << (adc_num - 1))) and (pin.adc_channel == channel)): + print(' &pin_{:s}, // {:d}'.format(pin.cpu_pin_name(), channel)) + adc_found = True + break + if not adc_found: + print(' NULL, // {:d}'.format(channel)) + print('};') + + + def print_header(self, hdr_filename): + with open(hdr_filename, 'wt') as hdr_file: + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + pin.print_header(hdr_file) + hdr_file.write('extern const pin_obj_t * const pin_adc1[];\n') + hdr_file.write('extern const pin_obj_t * const pin_adc2[];\n') + hdr_file.write('extern const pin_obj_t * const pin_adc3[];\n') + + def print_qstr(self, qstr_filename): + with open(qstr_filename, 'wt') as qstr_file: + qstr_set = set([]) + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + qstr_set |= set(pin.qstr_list()) + qstr_set |= set([named_pin.name()]) + for named_pin in self.board_pins: + qstr_set |= set([named_pin.name()]) + for qstr in sorted(qstr_set): + print('Q({})'.format(qstr), file=qstr_file) + + + def print_af_hdr(self, af_const_filename): + with open(af_const_filename, 'wt') as af_const_file: + af_hdr_set = set([]) + mux_name_width = 0 + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + for af in pin.alt_fn: + if af.is_supported(): + mux_name = af.mux_name() + af_hdr_set |= set([mux_name]) + if len(mux_name) > mux_name_width: + mux_name_width = len(mux_name) + for mux_name in sorted(af_hdr_set): + key = 'MP_OBJ_NEW_QSTR(MP_QSTR_{}),'.format(mux_name) + val = 'MP_OBJ_NEW_SMALL_INT(GPIO_{})'.format(mux_name) + print(' { %-*s %s },' % (mux_name_width + 26, key, val), + file=af_const_file) + + def print_af_py(self, af_py_filename): + with open(af_py_filename, 'wt') as af_py_file: + print('PINS_AF = (', file=af_py_file); + for named_pin in self.board_pins: + print(" ('%s', " % named_pin.name(), end='', file=af_py_file) + for af in named_pin.pin().alt_fn: + if af.is_supported(): + print("(%d, '%s'), " % (af.idx, af.af_str), end='', file=af_py_file) + print('),', file=af_py_file) + print(')', file=af_py_file) + + +def main(): + parser = argparse.ArgumentParser( + prog="make-pins.py", + usage="%(prog)s [options] [command]", + description="Generate board specific pin file" + ) + parser.add_argument( + "-a", "--af", + dest="af_filename", + help="Specifies the alternate function file for the chip", + default="nrf.csv" + ) + parser.add_argument( + "--af-const", + dest="af_const_filename", + help="Specifies header file for alternate function constants.", + default="build/pins_af_const.h" + ) + parser.add_argument( + "--af-py", + dest="af_py_filename", + help="Specifies the filename for the python alternate function mappings.", + default="build/pins_af.py" + ) + parser.add_argument( + "-b", "--board", + dest="board_filename", + help="Specifies the board file", + ) + parser.add_argument( + "-p", "--prefix", + dest="prefix_filename", + help="Specifies beginning portion of generated pins file", + default="nrf52_prefix.c" + ) + parser.add_argument( + "-q", "--qstr", + dest="qstr_filename", + help="Specifies name of generated qstr header file", + default="build/pins_qstr.h" + ) + parser.add_argument( + "-r", "--hdr", + dest="hdr_filename", + help="Specifies name of generated pin header file", + default="build/pins.h" + ) + args = parser.parse_args(sys.argv[1:]) + + pins = Pins() + + print('// This file was automatically generated by make-pins.py') + print('//') + if args.af_filename: + print('// --af {:s}'.format(args.af_filename)) + pins.parse_af_file(args.af_filename, 1, 2) + + if args.board_filename: + print('// --board {:s}'.format(args.board_filename)) + pins.parse_board_file(args.board_filename) + + if args.prefix_filename: + print('// --prefix {:s}'.format(args.prefix_filename)) + print('') + with open(args.prefix_filename, 'r') as prefix_file: + print(prefix_file.read()) + pins.print() + pins.print_header(args.hdr_filename) + pins.print_qstr(args.qstr_filename) + pins.print_af_hdr(args.af_const_filename) + pins.print_af_py(args.af_py_filename) + + +if __name__ == "__main__": + main() diff --git a/nrf5/boards/nrf51822_aa.ld b/nrf5/boards/nrf51822_aa.ld index ddbd5847fb..e25ae3b874 100644 --- a/nrf5/boards/nrf51822_aa.ld +++ b/nrf5/boards/nrf51822_aa.ld @@ -13,8 +13,8 @@ MEMORY } /* produce a link error if there is not this amount of RAM for these sections */ -_minimum_stack_size = 2K; -_minimum_heap_size = 10K; +_minimum_stack_size = 4K; +_minimum_heap_size = 8K; /* top end of the stack */ @@ -23,6 +23,6 @@ _estack = ORIGIN(RAM) + LENGTH(RAM); /* RAM extents for the garbage collector */ _ram_end = ORIGIN(RAM) + LENGTH(RAM); -_heap_end = 0x20001000; /* tunable */ +_heap_end = 0x20002000; /* tunable */ INCLUDE "boards/common.ld" diff --git a/nrf5/boards/nrf51822_aa_s110.ld b/nrf5/boards/nrf51822_aa_s110.ld index ef9a2c2f44..e798bf3afe 100644 --- a/nrf5/boards/nrf51822_aa_s110.ld +++ b/nrf5/boards/nrf51822_aa_s110.ld @@ -8,10 +8,10 @@ MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x040000 /* entire flash, 256 KiB */ FLASH_ISR (rx) : ORIGIN = 0x00018000, LENGTH = 0x000400 /* sector 0, 1 KiB */ - FLASH_TEXT (rx) : ORIGIN = 0x00018400, LENGTH = 0x027c00 /* 175 KiB */ - RAM (xrw) : ORIGIN = 0x20002000, LENGTH = 0x002000 /* 9.89 KiB */ + FLASH_TEXT (rx) : ORIGIN = 0x00018400, LENGTH = 0x027c00 /* 159 KiB */ + RAM (xrw) : ORIGIN = 0x20002000, LENGTH = 0x002000 /* 8 KiB */ } - + /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 4K; diff --git a/nrf5/boards/nrf51822_ac_s110.ld b/nrf5/boards/nrf51822_ac_s110.ld index e1863c8bab..ec1aff397d 100644 --- a/nrf5/boards/nrf51822_ac_s110.ld +++ b/nrf5/boards/nrf51822_ac_s110.ld @@ -8,8 +8,8 @@ MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x040000 /* entire flash, 256 KiB */ FLASH_ISR (rx) : ORIGIN = 0x00018000, LENGTH = 0x000400 /* sector 0, 1 KiB */ - FLASH_TEXT (rx) : ORIGIN = 0x00018400, LENGTH = 0x027c00 /* 175 KiB */ - RAM (xrw) : ORIGIN = 0x20002000, LENGTH = 0x006000 /* 9.89 KiB */ + FLASH_TEXT (rx) : ORIGIN = 0x00018400, LENGTH = 0x027c00 /* 159 KiB */ + RAM (xrw) : ORIGIN = 0x20002000, LENGTH = 0x006000 /* 24 KiB */ } /* produce a link error if there is not this amount of RAM for these sections */ diff --git a/nrf5/boards/nrf51822_ac_s120.ld b/nrf5/boards/nrf51822_ac_s120.ld index e7a67f2b08..3de7083fd7 100644 --- a/nrf5/boards/nrf51822_ac_s120.ld +++ b/nrf5/boards/nrf51822_ac_s120.ld @@ -8,7 +8,7 @@ MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x040000 /* entire flash, 256 KiB */ FLASH_ISR (rx) : ORIGIN = 0x0001D000, LENGTH = 0x000400 /* sector 0, 1 KiB */ - FLASH_TEXT (rx) : ORIGIN = 0x0001D400, LENGTH = 0x027c00 /* 139 KiB */ + FLASH_TEXT (rx) : ORIGIN = 0x0001D400, LENGTH = 0x022c00 /* 139 KiB */ RAM (xrw) : ORIGIN = 0x20002800, LENGTH = 0x005800 /* 22 KiB */ } diff --git a/nrf5/boards/nrf51822_ac_s130.ld b/nrf5/boards/nrf51822_ac_s130.ld index f0e3bdbabb..1845f973ff 100644 --- a/nrf5/boards/nrf51822_ac_s130.ld +++ b/nrf5/boards/nrf51822_ac_s130.ld @@ -1,5 +1,5 @@ /* - GNU linker script for NRF51822 AC w/ S130 2.0.0 SoftDevice + GNU linker script for NRF51822 AC w/ S130 2.0.1 SoftDevice */ /* Specify the memory areas */ SEARCH_DIR(.) @@ -9,7 +9,7 @@ MEMORY FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x040000 /* entire flash, 256 KiB */ FLASH_ISR (rx) : ORIGIN = 0x0001b000, LENGTH = 0x000400 /* sector 0, 1 KiB */ FLASH_TEXT (rx) : ORIGIN = 0x0001b400, LENGTH = 0x024c00 /* 147 KiB */ - RAM (xrw) : ORIGIN = 0x20001870, LENGTH = 0x002970 /* 9.89 KiB */ + RAM (xrw) : ORIGIN = 0x200013c8, LENGTH = 0x006c38 /* 27 KiB */ } /* produce a link error if there is not this amount of RAM for these sections */ diff --git a/nrf5/boards/nrf51_prefix.c b/nrf5/boards/nrf51_prefix.c new file mode 100644 index 0000000000..402bde1a60 --- /dev/null +++ b/nrf5/boards/nrf51_prefix.c @@ -0,0 +1,32 @@ +// nrf51_prefix.c becomes the initial portion of the generated pins file. + +#include + +#include "py/obj.h" +#include "py/mphal.h" +#include "pin.h" + +#define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ +{ \ + { &pin_af_type }, \ + .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ + .idx = (af_idx), \ + .fn = AF_FN_ ## af_fn, \ + .unit = (af_unit), \ + .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ + .af_fn = (af_ptr) \ +} + +#define PIN(p_port, p_pin, p_af, p_adc_num, p_adc_channel) \ +{ \ + { &pin_type }, \ + .name = MP_QSTR_ ## p_port ## p_pin, \ + .port = PORT_ ## p_port, \ + .pin = (p_pin), \ + .num_af = (sizeof(p_af) / sizeof(pin_af_obj_t)), \ + .pin_mask = (1 << p_pin), \ + .gpio = GPIO_BASE, \ + .af = p_af, \ + .adc_num = p_adc_num, \ + .adc_channel = p_adc_channel, \ +} diff --git a/nrf5/boards/nrf52832_aa_s132.ld b/nrf5/boards/nrf52832_aa_s132.ld index 9aabfac28e..629ed12c9c 100644 --- a/nrf5/boards/nrf52832_aa_s132.ld +++ b/nrf5/boards/nrf52832_aa_s132.ld @@ -8,7 +8,7 @@ MEMORY FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x080000 /* entire flash, 512 KiB */ FLASH_ISR (rx) : ORIGIN = 0x0001f000, LENGTH = 0x001000 /* sector 0, 4 KiB */ FLASH_TEXT (rx) : ORIGIN = 0x00020000, LENGTH = 0x060000 /* 396 KiB */ - RAM (xrw) : ORIGIN = 0x200039c0, LENGTH = 0x0c640 /* 57.89 KiB, give 8KiB headroom for softdevice */ + RAM (xrw) : ORIGIN = 0x200039c0, LENGTH = 0x0c640 /* 49.5 KiB, give 8KiB headroom for softdevice */ } /* produce a link error if there is not this amount of RAM for these sections */ diff --git a/nrf5/boards/nrf52832_aa_s1xx.ld b/nrf5/boards/nrf52832_aa_s1xx.ld index 781492085c..c2188afd47 100644 --- a/nrf5/boards/nrf52832_aa_s1xx.ld +++ b/nrf5/boards/nrf52832_aa_s1xx.ld @@ -5,15 +5,15 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x0001F000, LENGTH = 0x61000 - FLASH_ISR (rx) : ORIGIN = 0x0001F000, LENGTH = 0x00400 - FLASH_TEXT (rx) : ORIGIN = 0x0001F400, LENGTH = 0x60c00 - RAM (xrw) : ORIGIN = 0x20002800, LENGTH = 0x0D800 + FLASH (rx) : ORIGIN = 0x0001F000, LENGTH = 0x061000 /* entire flash, 512 KiB */ + FLASH_ISR (rx) : ORIGIN = 0x0001F000, LENGTH = 0x000400 /* sector 0, 4 KiB */ + FLASH_TEXT (rx) : ORIGIN = 0x0001F400, LENGTH = 0x060c00 /* 396 KiB */ + RAM (xrw) : ORIGIN = 0x20002800, LENGTH = 0x00D800 /* 54 KiB */ } /* produce a link error if there is not this amount of RAM for these sections */ -_minimum_stack_size = 6K; -_minimum_heap_size = 16K; +_minimum_stack_size = 16K; +_minimum_heap_size = 20K; /* top end of the stack */ @@ -22,108 +22,6 @@ _estack = ORIGIN(RAM) + LENGTH(RAM); /* RAM extents for the garbage collector */ _ram_end = ORIGIN(RAM) + LENGTH(RAM); -_heap_end = 0x20005000; /* tunable */ +_heap_end = 0x20008800; /* tunable */ -/* define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - - . = ALIGN(4); - } >FLASH_ISR - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - /* *(.glue_7) */ /* glue arm to thumb code */ - /* *(.glue_7t) */ /* glue thumb to arm code */ - - . = ALIGN(4); - _etext = .; /* define a global symbol at end of code */ - } >FLASH_TEXT - - /* - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } >FLASH - - .ARM : - { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - */ - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* This is the initialized data section - The program executes knowing that the data is in the RAM - but the loader puts the initial values in the FLASH (inidata). - It is one task of the startup to copy the initial values from FLASH to RAM. */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ - _ram_start = .; /* create a global symbol at ram start for garbage collector */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ - } >RAM AT> FLASH_TEXT - - /* Uninitialized data section */ - .bss : - { - . = ALIGN(4); - _sbss = .; /* define a global symbol at bss start; used by startup code */ - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ - } >RAM - - /* this is to define the start of the heap, and make sure we have a minimum size */ - .heap : - { - . = ALIGN(4); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - _heap_start = .; /* define a global symbol at heap start */ - . = . + _minimum_heap_size; - } >RAM - - /* this just checks there is enough RAM for the stack */ - .stack : - { - . = ALIGN(4); - . = . + _minimum_stack_size; - . = ALIGN(4); - } >RAM - - /* Remove information from the standard libraries */ - /* - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - */ - - .ARM.attributes 0 : { *(.ARM.attributes) } -} +INCLUDE "boards/common.ld" diff --git a/nrf5/boards/nrf52_prefix.c b/nrf5/boards/nrf52_prefix.c new file mode 100644 index 0000000000..6bb07dd3a1 --- /dev/null +++ b/nrf5/boards/nrf52_prefix.c @@ -0,0 +1,32 @@ +// nrf52_prefix.c becomes the initial portion of the generated pins file. + +#include + +#include "py/obj.h" +#include "py/mphal.h" +#include "pin.h" + +#define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ +{ \ + { &pin_af_type }, \ + .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ + .idx = (af_idx), \ + .fn = AF_FN_ ## af_fn, \ + .unit = (af_unit), \ + .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ + .af_fn = (af_ptr) \ +} + +#define PIN(p_port, p_pin, p_af, p_adc_num, p_adc_channel) \ +{ \ + { &pin_type }, \ + .name = MP_QSTR_ ## p_port ## p_pin, \ + .port = PORT_ ## p_port, \ + .pin = (p_pin), \ + .num_af = (sizeof(p_af) / sizeof(pin_af_obj_t)), \ + .pin_mask = (1 << p_pin), \ + .gpio = GPIO_BASE, \ + .af = p_af, \ + .adc_num = p_adc_num, \ + .adc_channel = p_adc_channel, \ +} diff --git a/nrf5/boards/pca10000/mpconfigboard.h b/nrf5/boards/pca10000/mpconfigboard.h index f922fe8761..2e2326da20 100644 --- a/nrf5/boards/pca10000/mpconfigboard.h +++ b/nrf5/boards/pca10000/mpconfigboard.h @@ -30,6 +30,8 @@ #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51-dongle" +#define MICROPY_PY_MACHINE_SPI (0) + #define MICROPY_HW_HAS_SWITCH (0) #define MICROPY_HW_HAS_FLASH (0) #define MICROPY_HW_HAS_SDCARD (0) diff --git a/nrf5/boards/pca10000/mpconfigboard.mk b/nrf5/boards/pca10000/mpconfigboard.mk index 5cc291bb92..d2a566aea8 100644 --- a/nrf5/boards/pca10000/mpconfigboard.mk +++ b/nrf5/boards/pca10000/mpconfigboard.mk @@ -1,6 +1,4 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_aa.ld -SRC_C += \ - hal/hal_uart.c diff --git a/nrf5/boards/pca10000/mpconfigboard_s110.mk b/nrf5/boards/pca10000/mpconfigboard_s110.mk index b706522ccf..5a3fa8e1c3 100644 --- a/nrf5/boards/pca10000/mpconfigboard_s110.mk +++ b/nrf5/boards/pca10000/mpconfigboard_s110.mk @@ -1,13 +1,3 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_aa_s110.ld - -SRC_C += \ - hal/hal_uart.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s110/headers -CFLAGS += -DBLUETOOTH_SD=110 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10000/nrf51_hal_conf.h b/nrf5/boards/pca10000/nrf51_hal_conf.h new file mode 100644 index 0000000000..1848c81034 --- /dev/null +++ b/nrf5/boards/pca10000/nrf51_hal_conf.h @@ -0,0 +1,7 @@ +#ifndef NRF51_HAL_CONF_H__ +#define NRF51_HAL_CONF_H__ + +#define HAL_UART_MODULE_ENABLED +#define HAL_TIME_MODULE_ENABLED + +#endif // NRF51_HAL_CONF_H__ diff --git a/nrf5/boards/pca10000/pins.csv b/nrf5/boards/pca10000/pins.csv new file mode 100644 index 0000000000..cc3f62db1a --- /dev/null +++ b/nrf5/boards/pca10000/pins.csv @@ -0,0 +1,7 @@ +UART_RTS,PA8 +UART_TX,PA9 +UART_CTS,PA10 +UART_RX,PA11 +LED_RED,PA21 +LED_GREEN,PA22 +LED_BLUE,PA23 \ No newline at end of file diff --git a/nrf5/boards/pca10001/mpconfigboard.mk b/nrf5/boards/pca10001/mpconfigboard.mk index 5cc291bb92..40a74fd176 100644 --- a/nrf5/boards/pca10001/mpconfigboard.mk +++ b/nrf5/boards/pca10001/mpconfigboard.mk @@ -1,6 +1,3 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_aa.ld - -SRC_C += \ - hal/hal_uart.c diff --git a/nrf5/boards/pca10001/mpconfigboard_s110.mk b/nrf5/boards/pca10001/mpconfigboard_s110.mk new file mode 100644 index 0000000000..5a3fa8e1c3 --- /dev/null +++ b/nrf5/boards/pca10001/mpconfigboard_s110.mk @@ -0,0 +1,3 @@ +MCU_SERIES = m0 +MCU_VARIANT = nrf51 +LD_FILE = boards/nrf51822_aa_s110.ld diff --git a/nrf5/boards/pca10001/nrf51_hal_conf.h b/nrf5/boards/pca10001/nrf51_hal_conf.h new file mode 100644 index 0000000000..67cbc983ba --- /dev/null +++ b/nrf5/boards/pca10001/nrf51_hal_conf.h @@ -0,0 +1,8 @@ +#ifndef NRF51_HAL_CONF_H__ +#define NRF51_HAL_CONF_H__ + +#define HAL_UART_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIME_MODULE_ENABLED + +#endif // NRF51_HAL_CONF_H__ diff --git a/nrf5/boards/pca10001/pins.csv b/nrf5/boards/pca10001/pins.csv new file mode 100644 index 0000000000..2b16969869 --- /dev/null +++ b/nrf5/boards/pca10001/pins.csv @@ -0,0 +1,32 @@ +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +UART_RTS,PA8 +UART_TX,PA9 +UART_CTS,PA10 +UART_RX,PA11 +PA12,PA12 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PA16,PA16 +PA17,PA17 +PA18,PA18 +PA19,PA19 +PA20,PA20 +PA21,PA21 +PA22,PA22 +PA23,PA23 +PA24,PA24 +PA25,PA25 +PA26,PA26 +PA27,PA27 +PA28,PA28 +PA29,PA29 +PA30,PA30 +PA31,PA31 \ No newline at end of file diff --git a/nrf5/boards/pca10028/mpconfigboard.h b/nrf5/boards/pca10028/mpconfigboard.h index cde989bc25..b854e685e3 100644 --- a/nrf5/boards/pca10028/mpconfigboard.h +++ b/nrf5/boards/pca10028/mpconfigboard.h @@ -30,6 +30,9 @@ #define MICROPY_HW_MCU_NAME "NRF51822" #define MICROPY_PY_SYS_PLATFORM "nrf51-DK" +#define MICROPY_PY_USOCKET (0) +#define MICROPY_PY_NETWORK (0) + #define MICROPY_HW_HAS_SWITCH (0) #define MICROPY_HW_HAS_FLASH (0) #define MICROPY_HW_HAS_SDCARD (0) @@ -57,4 +60,11 @@ #define MICROPY_HW_UART1_RTS (8) #define MICROPY_HW_UART1_HWFC (0) +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (1) // A3 +#define MICROPY_HW_SPI0_MOSI (2) // A2 +#define MICROPY_HW_SPI0_MISO (3) // A1 +#define MICROPY_HW_SPI0_NSS (4) // A4 + #define HELP_TEXT_BOARD_LED "1,2,3,4" diff --git a/nrf5/boards/pca10028/mpconfigboard.mk b/nrf5/boards/pca10028/mpconfigboard.mk index 293efb4583..ac92424ec7 100644 --- a/nrf5/boards/pca10028/mpconfigboard.mk +++ b/nrf5/boards/pca10028/mpconfigboard.mk @@ -1,6 +1,4 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac.ld -SRC_C += \ - hal/hal_uart.c diff --git a/nrf5/boards/pca10028/mpconfigboard_s110.mk b/nrf5/boards/pca10028/mpconfigboard_s110.mk index c2bd3b42ef..54766bd429 100644 --- a/nrf5/boards/pca10028/mpconfigboard_s110.mk +++ b/nrf5/boards/pca10028/mpconfigboard_s110.mk @@ -1,13 +1,4 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac_s110.ld -SRC_C += \ - hal/hal_uart.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s110/headers -CFLAGS += -DBLUETOOTH_SD=110 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10028/mpconfigboard_s120.mk b/nrf5/boards/pca10028/mpconfigboard_s120.mk index 629f8c6178..e9b7770dd0 100644 --- a/nrf5/boards/pca10028/mpconfigboard_s120.mk +++ b/nrf5/boards/pca10028/mpconfigboard_s120.mk @@ -1,13 +1,3 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac_s120.ld - -SRC_C += \ - hal/hal_uart.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s120/headers -CFLAGS += -DBLUETOOTH_SD=120 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10028/mpconfigboard_s130.mk b/nrf5/boards/pca10028/mpconfigboard_s130.mk index d4bc2e48c8..3f55086b49 100644 --- a/nrf5/boards/pca10028/mpconfigboard_s130.mk +++ b/nrf5/boards/pca10028/mpconfigboard_s130.mk @@ -1,13 +1,4 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac_s130.ld -SRC_C += \ - hal/hal_uart.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s130/headers -CFLAGS += -DBLUETOOTH_SD=130 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10028/nrf51_hal_conf.h b/nrf5/boards/pca10028/nrf51_hal_conf.h new file mode 100644 index 0000000000..67cbc983ba --- /dev/null +++ b/nrf5/boards/pca10028/nrf51_hal_conf.h @@ -0,0 +1,8 @@ +#ifndef NRF51_HAL_CONF_H__ +#define NRF51_HAL_CONF_H__ + +#define HAL_UART_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIME_MODULE_ENABLED + +#endif // NRF51_HAL_CONF_H__ diff --git a/nrf5/boards/pca10028/pins.csv b/nrf5/boards/pca10028/pins.csv new file mode 100644 index 0000000000..2b16969869 --- /dev/null +++ b/nrf5/boards/pca10028/pins.csv @@ -0,0 +1,32 @@ +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +UART_RTS,PA8 +UART_TX,PA9 +UART_CTS,PA10 +UART_RX,PA11 +PA12,PA12 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PA16,PA16 +PA17,PA17 +PA18,PA18 +PA19,PA19 +PA20,PA20 +PA21,PA21 +PA22,PA22 +PA23,PA23 +PA24,PA24 +PA25,PA25 +PA26,PA26 +PA27,PA27 +PA28,PA28 +PA29,PA29 +PA30,PA30 +PA31,PA31 \ No newline at end of file diff --git a/nrf5/boards/pca10031/mpconfigboard.h b/nrf5/boards/pca10031/mpconfigboard.h index 2cda988ff0..743375ea0e 100644 --- a/nrf5/boards/pca10031/mpconfigboard.h +++ b/nrf5/boards/pca10031/mpconfigboard.h @@ -57,4 +57,12 @@ #define MICROPY_HW_UART1_RTS (8) #define MICROPY_HW_UART1_HWFC (0) +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (15) // A15 +#define MICROPY_HW_SPI0_MOSI (16) // A16 +#define MICROPY_HW_SPI0_MISO (17) // A17 +#define MICROPY_HW_SPI0_NSS (18) // A18 + + #define HELP_TEXT_BOARD_LED "1,2,3" diff --git a/nrf5/boards/pca10031/mpconfigboard.mk b/nrf5/boards/pca10031/mpconfigboard.mk index 293efb4583..72a21aa76f 100644 --- a/nrf5/boards/pca10031/mpconfigboard.mk +++ b/nrf5/boards/pca10031/mpconfigboard.mk @@ -1,6 +1,3 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac.ld - -SRC_C += \ - hal/hal_uart.c diff --git a/nrf5/boards/pca10031/mpconfigboard_s110.mk b/nrf5/boards/pca10031/mpconfigboard_s110.mk index c2bd3b42ef..54766bd429 100644 --- a/nrf5/boards/pca10031/mpconfigboard_s110.mk +++ b/nrf5/boards/pca10031/mpconfigboard_s110.mk @@ -1,13 +1,4 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac_s110.ld -SRC_C += \ - hal/hal_uart.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s110/headers -CFLAGS += -DBLUETOOTH_SD=110 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10031/mpconfigboard_s120.mk b/nrf5/boards/pca10031/mpconfigboard_s120.mk index 629f8c6178..dc1de98188 100644 --- a/nrf5/boards/pca10031/mpconfigboard_s120.mk +++ b/nrf5/boards/pca10031/mpconfigboard_s120.mk @@ -1,13 +1,4 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac_s120.ld -SRC_C += \ - hal/hal_uart.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s120/headers -CFLAGS += -DBLUETOOTH_SD=120 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10031/mpconfigboard_s130.mk b/nrf5/boards/pca10031/mpconfigboard_s130.mk index d4bc2e48c8..3f55086b49 100644 --- a/nrf5/boards/pca10031/mpconfigboard_s130.mk +++ b/nrf5/boards/pca10031/mpconfigboard_s130.mk @@ -1,13 +1,4 @@ MCU_SERIES = m0 -MCU_VARIANT = NRF51 +MCU_VARIANT = nrf51 LD_FILE = boards/nrf51822_ac_s130.ld -SRC_C += \ - hal/hal_uart.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s130/headers -CFLAGS += -DBLUETOOTH_SD=130 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10031/nrf51_hal_conf.h b/nrf5/boards/pca10031/nrf51_hal_conf.h new file mode 100644 index 0000000000..67cbc983ba --- /dev/null +++ b/nrf5/boards/pca10031/nrf51_hal_conf.h @@ -0,0 +1,8 @@ +#ifndef NRF51_HAL_CONF_H__ +#define NRF51_HAL_CONF_H__ + +#define HAL_UART_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIME_MODULE_ENABLED + +#endif // NRF51_HAL_CONF_H__ diff --git a/nrf5/boards/pca10031/pins.csv b/nrf5/boards/pca10031/pins.csv new file mode 100644 index 0000000000..b27a12b91a --- /dev/null +++ b/nrf5/boards/pca10031/pins.csv @@ -0,0 +1,13 @@ +UART_RTS,PA8 +UART_TX,PA9 +UART_CTS,PA10 +UART_RX,PA11 +LED_RED,PA21 +LED_GREEN,PA22 +LED_BLUE,PA23 +PA15,PA15 +PA16,PA16 +PA17,PA17 +PA18,PA18 +PA19,PA19 +PA20,PA20 \ No newline at end of file diff --git a/nrf5/boards/pca10040/mpconfigboard.h b/nrf5/boards/pca10040/mpconfigboard.h index af655f0209..8dd0d43d0c 100644 --- a/nrf5/boards/pca10040/mpconfigboard.h +++ b/nrf5/boards/pca10040/mpconfigboard.h @@ -57,4 +57,12 @@ #define MICROPY_HW_UART1_RTS (5) #define MICROPY_HW_UART1_HWFC (1) +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (25) // A25 (Arduino D13) +#define MICROPY_HW_SPI0_MOSI (23) // A23 (Arduino D11) +#define MICROPY_HW_SPI0_MISO (24) // A24 (Arduino D12) +#define MICROPY_HW_SPI0_NSS (22) // A22 (Arduino D10) + + #define HELP_TEXT_BOARD_LED "1,2,3,4" diff --git a/nrf5/boards/pca10040/mpconfigboard.mk b/nrf5/boards/pca10040/mpconfigboard.mk index bbdbe3a931..3b6af95f75 100644 --- a/nrf5/boards/pca10040/mpconfigboard.mk +++ b/nrf5/boards/pca10040/mpconfigboard.mk @@ -1,6 +1,4 @@ MCU_SERIES = m4 -MCU_VARIANT = NRF52 +MCU_VARIANT = nrf52 LD_FILE = boards/nrf52832_aa.ld -SRC_C += \ - hal/hal_uart.c diff --git a/nrf5/boards/pca10040/mpconfigboard_s132.mk b/nrf5/boards/pca10040/mpconfigboard_s132.mk index 28f6549a28..090a08b4b6 100644 --- a/nrf5/boards/pca10040/mpconfigboard_s132.mk +++ b/nrf5/boards/pca10040/mpconfigboard_s132.mk @@ -1,14 +1,4 @@ MCU_SERIES = m4 -MCU_VARIANT = NRF52 +MCU_VARIANT = nrf52 LD_FILE = boards/nrf52832_aa_s132.ld -SRC_C += \ - hal/hal_uarte.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s132/headers -CFLAGS += -I./softdevice/s132/headers/nrf52 -CFLAGS += -DBLUETOOTH_SD=132 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10040/mpconfigboard_s1xx.mk b/nrf5/boards/pca10040/mpconfigboard_s1xx.mk index 73f9dc9018..81727fe5de 100644 --- a/nrf5/boards/pca10040/mpconfigboard_s1xx.mk +++ b/nrf5/boards/pca10040/mpconfigboard_s1xx.mk @@ -1,14 +1,4 @@ MCU_SERIES = m4 -MCU_VARIANT = NRF52 +MCU_VARIANT = nrf52 LD_FILE = boards/nrf52832_aa_s1xx.ld -SRC_C += \ - hal/hal_uarte.c \ - softdevice/modble.c \ - softdevice/softdevice.c - -CFLAGS += -I./softdevice -CFLAGS += -I./softdevice/s1xx/headers -CFLAGS += -I./softdevice/s1xx/headers/nrf52 -CFLAGS += -DBLUETOOTH_SD=100 -CFLAGS += -DBLUETOOTH_SD_DEBUG=1 diff --git a/nrf5/boards/pca10040/nrf52_hal_conf.h b/nrf5/boards/pca10040/nrf52_hal_conf.h new file mode 100644 index 0000000000..b879b974aa --- /dev/null +++ b/nrf5/boards/pca10040/nrf52_hal_conf.h @@ -0,0 +1,10 @@ +#ifndef NRF52_HAL_CONF_H__ +#define NRF52_HAL_CONF_H__ + +#define HAL_UART_MODULE_ENABLED +// #define HAL_UARTE_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +// #define HAL_SPIE_MODULE_ENABLED +#define HAL_TIME_MODULE_ENABLED + +#endif // NRF52_HAL_CONF_H__ diff --git a/nrf5/boards/pca10040/pins.csv b/nrf5/boards/pca10040/pins.csv new file mode 100644 index 0000000000..c177133983 --- /dev/null +++ b/nrf5/boards/pca10040/pins.csv @@ -0,0 +1,30 @@ +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +PA8,PA8 +PA9,PA9 +PA10,PA10 +PA11,PA11 +PA12,PA12 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PA16,PA16 +PA17,PA17 +PA18,PA18 +PA19,PA19 +PA20,PA20 +PA21,PA21 +PA22,PA22 +PA23,PA23 +PA24,PA24 +PA25,PA25 +PA26,PA26 +PA27,PA27 +PA28,PA28 +PA29,PA29 +PA30,PA30 +PA31,PA31 \ No newline at end of file diff --git a/nrf5/builtin_open.c b/nrf5/builtin_open.c new file mode 100644 index 0000000000..697eec8eaa --- /dev/null +++ b/nrf5/builtin_open.c @@ -0,0 +1,30 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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 "extmod/vfs_fat_file.h" + +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, fatfs_builtin_open); diff --git a/nrf5/device/nrf52/startup_nrf52.s b/nrf5/device/nrf52/startup_nrf52.s index 1f39a39530..28906b7d9f 100644 --- a/nrf5/device/nrf52/startup_nrf52.s +++ b/nrf5/device/nrf52/startup_nrf52.s @@ -52,20 +52,36 @@ Reset_Handler: ldr r1, =_sidata ldr r2, =_sdata - ldr r3, =_edata + ldr r3, =_sbss subs r3, r2 - ble LC0 + ble CopyDone + b CopyData -LC1: - subs r3, 4 +CopyData: + subs r3, #4 ldr r0, [r1,r3] str r0, [r2,r3] - bgt LC1 + bgt CopyData + +CopyDone: + ldr r1, =_sbss + ldr r2, =_ebss + + movs r0, 0 + + subs r2, r1 + ble ZeroDone + +ZeroLoop: + subs r2, #4 + str r0, [r1, r2] + bgt ZeroLoop + +ZeroDone: -LC0: bl SystemInit - bl main + bl _start bx lr .pool diff --git a/nrf5/fatfs_port.c b/nrf5/fatfs_port.c new file mode 100644 index 0000000000..c7b15a703c --- /dev/null +++ b/nrf5/fatfs_port.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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/runtime.h" +#include "lib/fatfs/ff.h" /* FatFs lower layer API */ +#include "lib/fatfs/diskio.h" /* FatFs lower layer API */ +//#include "rtc.h" + +const PARTITION VolToPart[MICROPY_FATFS_VOLUMES] = { + {0, 1}, // Logical drive 0 ==> Physical drive 0, 1st partition + {1, 0}, // Logical drive 1 ==> Physical drive 1 (auto detection) + {2, 0}, // Logical drive 2 ==> Physical drive 2 (auto detection) + {3, 0}, // Logical drive 3 ==> Physical drive 3 (auto detection) + /* + {0, 2}, // Logical drive 2 ==> Physical drive 0, 2nd partition + {0, 3}, // Logical drive 3 ==> Physical drive 0, 3rd partition + */ +}; + +DWORD get_fattime(void) { + return ((2000 + 2016 - 1980) << 25) | ((12) << 21) | ((4) << 16) | ((00) << 11) | ((18) << 5) | (23 / 2); +} diff --git a/nrf5/gccollect.h b/nrf5/gccollect.h index be5419a56f..297a9d53ae 100644 --- a/nrf5/gccollect.h +++ b/nrf5/gccollect.h @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/nrf5/hal/hal_spi.c b/nrf5/hal/hal_spi.c new file mode 100644 index 0000000000..dc86a0cd52 --- /dev/null +++ b/nrf5/hal/hal_spi.c @@ -0,0 +1,122 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 +#include + +#include "mphalport.h" +#include "hal_spi.h" + +#ifdef HAL_SPI_MODULE_ENABLED + +static uint32_t m_ss_pin; + +static const uint32_t hal_spi_frequency_lookup[] = { + SPI_FREQUENCY_FREQUENCY_K125, // 125 kbps + SPI_FREQUENCY_FREQUENCY_K250, // 250 kbps + SPI_FREQUENCY_FREQUENCY_K500, // 500 kbps + SPI_FREQUENCY_FREQUENCY_M1, // 1 Mbps + SPI_FREQUENCY_FREQUENCY_M2, // 2 Mbps + SPI_FREQUENCY_FREQUENCY_M4, // 4 Mbps + SPI_FREQUENCY_FREQUENCY_M8 // 8 Mbps +}; + +void hal_spi_master_init(NRF_SPI_Type * p_instance, hal_spi_init_t const * p_spi_init) { + hal_gpio_pin_set(p_spi_init->enable_pin); + m_ss_pin = p_spi_init->enable_pin; + + hal_gpio_cfg_pin_output(p_spi_init->clk_pin); + hal_gpio_cfg_pin_output(p_spi_init->mosi_pin); + hal_gpio_cfg_pin_input(p_spi_init->miso_pin, HAL_GPIO_PULL_DISABLED); + hal_gpio_cfg_pin_output(p_spi_init->enable_pin); + +#if NRF51 + p_instance->PSELSCK = p_spi_init->clk_pin; + p_instance->PSELMOSI = p_spi_init->mosi_pin; + p_instance->PSELMISO = p_spi_init->miso_pin; +#else + p_instance->PSEL.SCK = p_spi_init->clk_pin; + p_instance->PSEL.MOSI = p_spi_init->mosi_pin; + p_instance->PSEL.MISO = p_spi_init->miso_pin; +#endif + + p_instance->FREQUENCY = hal_spi_frequency_lookup[p_spi_init->freq]; + + uint32_t mode; + switch (p_spi_init->mode) { + case HAL_SPI_MODE_CPOL0_CPHA0: + mode = (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos); + break; + case HAL_SPI_MODE_CPOL0_CPHA1: + mode = (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos); + break; + case HAL_SPI_MODE_CPOL1_CPHA0: + mode = (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos); + break; + case HAL_SPI_MODE_CPOL1_CPHA1: + mode = (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos); + break; + default: + mode = 0; + break; + } + + if (p_spi_init->lsb_first) { + p_instance->CONFIG = (mode | (SPI_CONFIG_ORDER_LsbFirst << SPI_CONFIG_ORDER_Pos)); + } else { + p_instance->CONFIG = (mode | (SPI_CONFIG_ORDER_MsbFirst << SPI_CONFIG_ORDER_Pos)); + } + + p_instance->EVENTS_READY = 0U; + p_instance->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); +} + +void hal_spi_master_tx_rx(NRF_SPI_Type * p_instance, uint16_t transfer_size, const uint8_t * tx_data, uint8_t * rx_data) { + + uint16_t number_of_txd_bytes = 0; + + p_instance->EVENTS_READY = 0; + + hal_gpio_pin_clear(m_ss_pin); + + while (number_of_txd_bytes < transfer_size) { + p_instance->TXD = (uint32_t)(tx_data[number_of_txd_bytes]); + + // wait for the transaction complete or timeout (about 10ms - 20 ms) + while (p_instance->EVENTS_READY == 0) { + ; + } + p_instance->EVENTS_READY = 0; + + rx_data[number_of_txd_bytes] = (uint8_t)p_instance->RXD; + number_of_txd_bytes++; + }; + + hal_gpio_pin_set(m_ss_pin); + +} + +#endif // HAL_SPI_MODULE_ENABLED diff --git a/nrf5/hal/hal_spi.h b/nrf5/hal/hal_spi.h new file mode 100644 index 0000000000..9c30c0ed4f --- /dev/null +++ b/nrf5/hal/hal_spi.h @@ -0,0 +1,105 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 HAL_SPI_H__ +#define HAL_SPI_H__ + +#include "nrf.h" + +#if NRF51 + +#define SPI0 ((NRF_SPI_Type *) NRF_SPI0) +#define SPI0_IRQ_NUM SPI0_TWI0_IRQn +#define SPI1 ((NRF_SPI_Type *) NRF_SPI1) +#define SPI1_IRQ_NUM SPI1_TWI1_IRQn + +#elif NRF52 + +#define SPI0 ((NRF_SPI_Type *) NRF_SPI0_BASE) +#define SPI0_IRQ_NUM SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn +#define SPI1 ((NRF_SPI_Type *) NRF_SPI1_BASE) +#define SPI1_IRQ_NUM SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn +#define SPI2 ((NRF_SPI_Type *) NRF_SPI2_BASE) +#define SPI2_IRQ_NUM SPIM2_SPIS2_SPI2_IRQn + +#else +#error "Device not supported." +#endif + +/** + * @brief SPI clock frequency type definition + */ +typedef enum { + HAL_FREQ_125_Kbps = 0, + HAL_FREQ_250_Kbps, + HAL_FREQ_500_Kbps, + HAL_FREQ_1_Mbps, + HAL_FREQ_2_Mbps, + HAL_FREQ_4_Mbps, + HAL_FREQ_8_Mbps +} hal_spi_clk_freq_t; + +/** + * @brief SPI mode type definition + */ +typedef enum { + HAL_SPI_MODE_CPOL0_CPHA0 = 0, // CPOL = 0, CPHA = 0 (data on leading edge) + HAL_SPI_MODE_CPOL0_CPHA1, // CPOL = 0, CPHA = 1 (data on trailing edge) + HAL_SPI_MODE_CPOL1_CPHA0, // CPOL = 1, CPHA = 0 (data on leading edge) + HAL_SPI_MODE_CPOL1_CPHA1 // CPOL = 1, CPHA = 1 (data on trailing edge) +} hal_spi_mode_t; + +/** + * @brief SPI Configuration Structure definition + */ +typedef struct { + uint8_t mosi_pin; + uint8_t miso_pin; + uint8_t clk_pin; + uint8_t enable_pin; + bool lsb_first; + hal_spi_mode_t mode; + uint32_t irq_priority; + hal_spi_clk_freq_t freq; +} hal_spi_init_t; + +/** + * @brief SPI handle Structure definition + */ +typedef struct __SPI_HandleTypeDef +{ + NRF_SPI_Type *instance; /* SPI registers base address */ + hal_spi_init_t init; /* SPI initialization parameters */ +} SPI_HandleTypeDef; + +void hal_spi_master_init(NRF_SPI_Type * p_instance, hal_spi_init_t const * p_spi_init); + +void hal_spi_master_tx_rx(NRF_SPI_Type * p_instance, + uint16_t transfer_size, + const uint8_t * tx_data, + uint8_t * rx_data); + +#endif // HAL_SPI_H__ diff --git a/nrf5/hal/hal_spie.c b/nrf5/hal/hal_spie.c new file mode 100644 index 0000000000..6af19afa91 --- /dev/null +++ b/nrf5/hal/hal_spie.c @@ -0,0 +1,135 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 +#include + +#include "mphalport.h" +#include "hal_spi.h" + +#ifdef HAL_SPIE_MODULE_ENABLED + +#if NRF52 + +#define SPIM0 ((NRF_SPI_Type *) NRF_SPIM0_BASE) +#define SPIM0_IRQ_NUM SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn +#define SPIM1 ((NRF_SPI_Type *) NRF_SPIM1_BASE) +#define SPIM1_IRQ_NUM SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn +#define SPIM2 ((NRF_SPI_Type *) NRF_SPIM2_BASE) +#define SPIM2_IRQ_NUM SPIM2_SPIS2_SPI2_IRQn + +#else +#error "Device not supported." +#endif + +static uint32_t m_ss_pin; + +static const uint32_t hal_spi_frequency_lookup[] = { + SPI_FREQUENCY_FREQUENCY_K125, // 125 kbps + SPI_FREQUENCY_FREQUENCY_K250, // 250 kbps + SPI_FREQUENCY_FREQUENCY_K500, // 500 kbps + SPI_FREQUENCY_FREQUENCY_M1, // 1 Mbps + SPI_FREQUENCY_FREQUENCY_M2, // 2 Mbps + SPI_FREQUENCY_FREQUENCY_M4, // 4 Mbps + SPI_FREQUENCY_FREQUENCY_M8 // 8 Mbps +}; + +void hal_spi_master_init(NRF_SPI_Type * p_instance, hal_spi_init_t const * p_spi_init) { + // cast to master type + NRF_SPIM_Type * spim_instance = (NRF_SPIM_Type *)p_instance; + + hal_gpio_pin_set(p_spi_init->enable_pin); + m_ss_pin = p_spi_init->enable_pin; + + hal_gpio_cfg_pin_output(p_spi_init->clk_pin); + hal_gpio_cfg_pin_output(p_spi_init->mosi_pin); + hal_gpio_cfg_pin_input(p_spi_init->miso_pin, HAL_GPIO_PULL_DISABLED); + hal_gpio_cfg_pin_output(p_spi_init->enable_pin); + +#if NRF51 + spim_instance->PSELSCK = p_spi_init->clk_pin; + spim_instance->PSELMOSI = p_spi_init->mosi_pin; + spim_instance->PSELMISO = p_spi_init->miso_pin; +#else + spim_instance->PSEL.SCK = p_spi_init->clk_pin; + spim_instance->PSEL.MOSI = p_spi_init->mosi_pin; + spim_instance->PSEL.MISO = p_spi_init->miso_pin; +#endif + + spim_instance->FREQUENCY = hal_spi_frequency_lookup[p_spi_init->freq]; + + uint32_t mode; + switch (p_spi_init->mode) { + case HAL_SPI_MODE_CPOL0_CPHA0: + mode = (SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos) | (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos); + break; + case HAL_SPI_MODE_CPOL0_CPHA1: + mode = (SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos) | (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos); + break; + case HAL_SPI_MODE_CPOL1_CPHA0: + mode = (SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos) | (SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos); + break; + case HAL_SPI_MODE_CPOL1_CPHA1: + mode = (SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos) | (SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos); + break; + default: + mode = 0; + break; + } + + if (p_spi_init->lsb_first) { + spim_instance->CONFIG = (mode | (SPIM_CONFIG_ORDER_LsbFirst << SPIM_CONFIG_ORDER_Pos)); + } else { + spim_instance->CONFIG = (mode | (SPIM_CONFIG_ORDER_MsbFirst << SPIM_CONFIG_ORDER_Pos)); + } + + spim_instance->EVENTS_END = 0; + spim_instance->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); +} + +void hal_spi_master_tx_rx(NRF_SPI_Type * p_instance, uint16_t transfer_size, const uint8_t * tx_data, uint8_t * rx_data) { + + // cast to master type + NRF_SPIM_Type * spim_instance = (NRF_SPIM_Type *)p_instance; + + hal_gpio_pin_clear(m_ss_pin); + + spim_instance->TXD.PTR = (uint32_t)(tx_data); + spim_instance->TXD.MAXCNT = transfer_size; + spim_instance->RXD.PTR = (uint32_t)(rx_data); + spim_instance->RXD.MAXCNT = transfer_size; + + spim_instance->TASKS_START = 1; + + while((0 == spim_instance->EVENTS_END)); + + spim_instance->EVENTS_END = 0; + spim_instance->TASKS_STOP = 1; + + hal_gpio_pin_set(m_ss_pin); +} + +#endif // HAL_SPIE_MODULE_ENABLED diff --git a/nrf5/hal/hal_time.c b/nrf5/hal/hal_time.c new file mode 100644 index 0000000000..d98dd4de8c --- /dev/null +++ b/nrf5/hal/hal_time.c @@ -0,0 +1,116 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 "mphalport.h" +#include "hal_time.h" + +#ifdef HAL_TIME_MODULE_ENABLED + +void mp_hal_delay_us(mp_uint_t us) +{ + register uint32_t delay __ASM ("r0") = us; + __ASM volatile ( +#ifdef NRF51 + ".syntax unified\n" +#endif + "1:\n" + " SUBS %0, %0, #1\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" +#ifdef NRF52 + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" +#endif + " BNE 1b\n" +#ifdef NRF51 + ".syntax divided\n" +#endif + : "+r" (delay)); +} + +void mp_hal_delay_ms(mp_uint_t ms) +{ + for (mp_uint_t i = 0; i < ms; i++) + { + mp_hal_delay_us(999); + } +} + +#endif // HAL_TIME_MODULE_ENABLED diff --git a/nrf5/hal/hal_time.h b/nrf5/hal/hal_time.h new file mode 100644 index 0000000000..1cef8b9521 --- /dev/null +++ b/nrf5/hal/hal_time.h @@ -0,0 +1,32 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 HAL_TIME_H__ +#define HAL_TIME_H__ + +void mp_hal_delay_ms(mp_uint_t ms); + +#endif // HAL_TIME_H__ diff --git a/nrf5/hal/hal_uart.c b/nrf5/hal/hal_uart.c index 56a6d889fd..4c4a0d99f4 100644 --- a/nrf5/hal/hal_uart.c +++ b/nrf5/hal/hal_uart.c @@ -30,6 +30,8 @@ #include "mphalport.h" #include "hal_uart.h" +#ifdef HAL_UART_MODULE_ENABLED + #ifdef NRF51 #include "nrf51.h" #include "nrf51_bitfields.h" @@ -123,3 +125,5 @@ void nrf_uart_init(hal_uart_init_t const * p_uart_init) { UART_BASE->TASKS_STARTTX = 1; UART_BASE->TASKS_STARTRX = 1; } + +#endif // HAL_UART_MODULE_ENABLED diff --git a/nrf5/hal/hal_uarte.c b/nrf5/hal/hal_uarte.c index 9e2535b22f..1990988758 100644 --- a/nrf5/hal/hal_uarte.c +++ b/nrf5/hal/hal_uarte.c @@ -29,19 +29,28 @@ #include "mphalport.h" #include "hal_uart.h" + +#ifdef HAL_UARTE_MODULE_ENABLED + #include "nrf52.h" #include "nrf52_bitfields.h" +#if NRF52 + #define UARTE_BASE ((NRF_UARTE_Type *) NRF_UARTE0_BASE) #define UART_IRQ_NUM UARTE0_UART0_IRQn +#else +#error "Device not supported." +#endif + #define TX_BUF_SIZE 1 #define RX_BUF_SIZE 1 static uart_complete_cb dma_read_cb = NULL; static uart_complete_cb dma_write_cb = NULL; -uint32_t hal_uart_baudrate_lookup[] = { +static const uint32_t hal_uart_baudrate_lookup[] = { UARTE_BAUDRATE_BAUDRATE_Baud1200, ///< 1200 baud. UARTE_BAUDRATE_BAUDRATE_Baud2400, ///< 2400 baud. UARTE_BAUDRATE_BAUDRATE_Baud4800, ///< 4800 baud. @@ -208,13 +217,18 @@ static void dma_write_complete(void) { } void UARTE0_UART0_IRQHandler(void) { - if ((UARTE_BASE->EVENTS_ENDRX) && - (UARTE_BASE->INTEN & UARTE_INTENSET_ENDRX_Msk)) { + if ((UARTE_BASE->EVENTS_ENDRX) + && (UARTE_BASE->INTEN & UARTE_INTENSET_ENDRX_Msk)) { + UARTE_BASE->EVENTS_ENDRX = 0; dma_read_complete(); - } else if ((UARTE_BASE->EVENTS_ENDTX) && - (UARTE_BASE->INTEN & UARTE_INTENSET_ENDTX_Msk)) { + + } else if ((UARTE_BASE->EVENTS_ENDTX) + && (UARTE_BASE->INTEN & UARTE_INTENSET_ENDTX_Msk)) { + UARTE_BASE->EVENTS_ENDTX = 0; dma_write_complete(); } } + +#endif // HAL_UARTE_MODULE_ENABLED diff --git a/nrf5/hal/nrf51_hal.h b/nrf5/hal/nrf51_hal.h new file mode 100644 index 0000000000..f6975aaa8e --- /dev/null +++ b/nrf5/hal/nrf51_hal.h @@ -0,0 +1,31 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 +#include + +// include config from board +#include "nrf51_hal_conf.h" diff --git a/nrf5/hal/nrf52_hal.h b/nrf5/hal/nrf52_hal.h new file mode 100644 index 0000000000..3ebd45cf97 --- /dev/null +++ b/nrf5/hal/nrf52_hal.h @@ -0,0 +1,31 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 +#include + +// include config from board +#include "nrf52_hal_conf.h" diff --git a/nrf5/help.c b/nrf5/help.c index c5b47a47c0..04b0b00d34 100644 --- a/nrf5/help.c +++ b/nrf5/help.c @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2016 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/nrf5/led.c b/nrf5/led.c index 38dbe1b97c..a47a9de656 100644 --- a/nrf5/led.c +++ b/nrf5/led.c @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2013-2016 Damien P. George * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/nrf5/led.h b/nrf5/led.h index 7bc0d7fa9d..29139a4d48 100644 --- a/nrf5/led.h +++ b/nrf5/led.h @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/nrf5/lexerfatfs.c b/nrf5/lexerfatfs.c new file mode 100644 index 0000000000..fd7f62dfdd --- /dev/null +++ b/nrf5/lexerfatfs.c @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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/lexer.h" + +mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename); + +// TODO: Instead of such shims, probably better to let port #define +// mp_lexer_new_from_file to a function it wants to use. +mp_lexer_t *mp_lexer_new_from_file(const char *filename) { + return fat_vfs_lexer_new_from_file(filename); +} diff --git a/nrf5/main.c b/nrf5/main.c index db55581834..290926b76f 100644 --- a/nrf5/main.c +++ b/nrf5/main.c @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,6 +24,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include #include #include @@ -38,9 +40,17 @@ #include "lib/utils/pyexec.h" #include "readline.h" #include "gccollect.h" +#include "modmachine.h" +#include "modnetwork.h" #include "led.h" #include "uart.h" #include "nrf.h" +#include "pin.h" +#include "spi.h" + +#if (BLUETOOTH_SD == 132) +#include "nrf52_ble.h" +#endif void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); @@ -69,11 +79,17 @@ int main(int argc, char **argv) { // Stack limit should be less than real stack size, so we have a chance // to recover from limit hit. (Limit is measured in bytes.) - mp_stack_set_limit((char*)&_ram_end - (char*)&_heap_end - 1024); + mp_stack_set_limit((char*)&_ram_end - (char*)&_heap_end - 400); led_init(); + machine_init(); gc_init(&_heap_start, &_heap_end); + +#if (BLUETOOTH_SD == 132) + nrf52_ble_init(); +#endif + mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) @@ -81,6 +97,17 @@ int main(int argc, char **argv) { readline_init0(); + pin_init0(); +#if MICROPY_PY_MACHINE_SPI + spi_init0(); +#endif + + /* + extint_init0(); + timer_init0(); + */ + +#if (BLUETOOTH_SD != 132) uart_init0(); { mp_obj_t args[2] = { @@ -89,6 +116,44 @@ int main(int argc, char **argv) { }; MP_STATE_PORT(pyb_stdio_uart) = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args); } +#endif + +#if MICROPY_HW_HAS_SDCARD + // if an SD card is present then mount it on /sd/ + if (sdcard_is_present()) { + // create vfs object + fs_user_mount_t *vfs = m_new_obj_maybe(fs_user_mount_t); + if (vfs == NULL) { + goto no_mem_for_sd; + } + vfs->str = "/sd"; + vfs->len = 3; + vfs->flags = FSUSER_FREE_OBJ; + sdcard_init_vfs(vfs); + + // put the sd device in slot 1 (it will be unused at this point) + MP_STATE_PORT(fs_user_mount)[1] = vfs; + + FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1); + if (res != FR_OK) { + printf("PYB: can't mount SD card\n"); + MP_STATE_PORT(fs_user_mount)[1] = NULL; + m_del_obj(fs_user_mount_t, vfs); + } else { + // TODO these should go before the /flash entries in the path + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); + + // use SD card as current directory + f_chdrive("/sd"); + } + no_mem_for_sd:; + } +#endif + +#if MICROPY_PY_NETWORK + mod_network_init(); +#endif #if MICROPY_HW_LED_TRICOLOR do_str("import pyb\r\n" \ @@ -133,19 +198,10 @@ void HardFault_Handler(void) #endif } -mp_lexer_t *mp_lexer_new_from_file(const char *filename) { - return NULL; -} - mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } -mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) { - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); - void nlr_jump_fail(void *val) { } diff --git a/nrf5/modmachine.c b/nrf5/modmachine.c new file mode 100644 index 0000000000..a1b28cdd2d --- /dev/null +++ b/nrf5/modmachine.c @@ -0,0 +1,185 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2015 Damien P. George + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 + +#include "modmachine.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "extmod/machine_mem.h" +#include "extmod/machine_pulse.h" +#include "extmod/machine_i2c.h" +#include "lib/utils/pyexec.h" +#include "lib/fatfs/ff.h" +#include "lib/fatfs/diskio.h" +#include "gccollect.h" +#include "pin.h" +#include "spi.h" + +#define PYB_RESET_HARD (0) +#define PYB_RESET_WDT (1) +#define PYB_RESET_SOFT (2) +#define PYB_RESET_LOCKUP (3) +#define PYB_RESET_POWER_ON (16) +#define PYB_RESET_LPCOMP (17) +#define PYB_RESET_DIF (18) +#define PYB_RESET_NFC (19) + +STATIC uint32_t reset_cause; + +void machine_init(void) { + uint32_t state = NRF_POWER->RESETREAS; + if (state & POWER_RESETREAS_RESETPIN_Msk) { + reset_cause = PYB_RESET_HARD; + } else if (state & POWER_RESETREAS_DOG_Msk) { + reset_cause = PYB_RESET_WDT; + } else if (state & POWER_RESETREAS_SREQ_Msk) { + reset_cause = PYB_RESET_SOFT; + } else if (state & POWER_RESETREAS_LOCKUP_Msk) { + reset_cause = PYB_RESET_LOCKUP; + } else if (state & POWER_RESETREAS_OFF_Msk) { + reset_cause = PYB_RESET_POWER_ON; + } else if (state & POWER_RESETREAS_LPCOMP_Msk) { + reset_cause = PYB_RESET_LPCOMP; + } else if (state & POWER_RESETREAS_DIF_Msk) { + reset_cause = PYB_RESET_DIF; +#if NRF52 + } else if (state & POWER_RESETREAS_NFC_Msk) { + reset_cause = PYB_RESET_NFC; +#endif + } + + // clear reset reason + NRF_POWER->RESETREAS = (1 << reset_cause); +} + +// machine.info([dump_alloc_table]) +// Print out lots of information about the board. +STATIC mp_obj_t machine_info(mp_uint_t n_args, const mp_obj_t *args) { + // to print info about memory + { + printf("_etext=%p\n", &_etext); + printf("_sidata=%p\n", &_sidata); + printf("_sdata=%p\n", &_sdata); + printf("_edata=%p\n", &_edata); + printf("_sbss=%p\n", &_sbss); + printf("_ebss=%p\n", &_ebss); + printf("_estack=%p\n", &_estack); + printf("_ram_start=%p\n", &_ram_start); + printf("_heap_start=%p\n", &_heap_start); + printf("_heap_end=%p\n", &_heap_end); + printf("_ram_end=%p\n", &_ram_end); + } + + // qstr info + { + mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; + qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); + printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); + } + + // GC info + { + gc_info_t info; + gc_info(&info); + printf("GC:\n"); + printf(" " UINT_FMT " total\n", info.total); + printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); + printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); + } + + if (n_args == 1) { + // arg given means dump gc allocation table + gc_dump_alloc_table(); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info); + +// Resets the pyboard in a manner similar to pushing the external RESET button. +STATIC mp_obj_t machine_reset(void) { + NVIC_SystemReset(); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); + +STATIC mp_obj_t machine_soft_reset(void) { + pyexec_system_exit = PYEXEC_FORCED_EXIT; + nlr_raise(mp_obj_new_exception(&mp_type_SystemExit)); +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); + +STATIC mp_obj_t machine_sleep(void) { + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep); + +STATIC mp_obj_t machine_deepsleep(void) { + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep); + +STATIC mp_obj_t machine_reset_cause(void) { + return MP_OBJ_NEW_SMALL_INT(reset_cause); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); + +STATIC const mp_map_elem_t machine_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_umachine) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&machine_reset_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_soft_reset), (mp_obj_t)&machine_soft_reset_obj }, +#if MICROPY_HW_ENABLE_RNG + { MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj }, +#endif + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&machine_sleep_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&machine_deepsleep_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_reset_cause), (mp_obj_t)&machine_reset_cause_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type }, +#if MICROPY_PY_MACHINE_SPI + { MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&machine_hard_spi_type }, +#endif + { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_HARD) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_WDT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_SOFT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LOCKUP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_LOCKUP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_POWER_ON) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LPCOMP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_LPCOMP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_DEBUG_IF_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_DIF) }, +#if NRF52 + { MP_OBJ_NEW_QSTR(MP_QSTR_NFC_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_NFC) }, +#endif +}; + +STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); + +const mp_obj_module_t machine_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&machine_module_globals, +}; + diff --git a/nrf5/modmachine.h b/nrf5/modmachine.h new file mode 100644 index 0000000000..35852ffec3 --- /dev/null +++ b/nrf5/modmachine.h @@ -0,0 +1,42 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2015 Damien P. George + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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_NRF5_MODMACHINE_H__ +#define __MICROPY_INCLUDED_NRF5_MODMACHINE_H__ + +#include "py/mpstate.h" +#include "py/nlr.h" +#include "py/obj.h" + +void machine_init(void); + +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj); +MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj); +MP_DECLARE_CONST_FUN_OBJ_0(machine_sleep_obj); +MP_DECLARE_CONST_FUN_OBJ_0(machine_deepsleep_obj); + +#endif // __MICROPY_INCLUDED_NRF5_MODMACHINE_H__ diff --git a/nrf5/modnetwork.c b/nrf5/modnetwork.c new file mode 100644 index 0000000000..f47df0db4e --- /dev/null +++ b/nrf5/modnetwork.c @@ -0,0 +1,97 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * 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 +#include +#include + +#include "py/nlr.h" +#include "py/objlist.h" +#include "py/runtime.h" +#include "modnetwork.h" + +#if MICROPY_PY_NETWORK + +/// \module network - network configuration +/// +/// This module provides network drivers and routing configuration. + +void mod_network_init(void) { + mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0); +} + +void mod_network_register_nic(mp_obj_t nic) { + for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { + if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) { + // nic already registered + return; + } + } + // nic not registered so add to list + mp_obj_list_append(&MP_STATE_PORT(mod_network_nic_list), nic); +} + +mp_obj_t mod_network_find_nic(const uint8_t *ip) { + // find a NIC that is suited to given IP address + for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { + mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; + // TODO check IP suitability here + //mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); + return nic; + } + + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); +} + +STATIC mp_obj_t network_route(void) { + return &MP_STATE_PORT(mod_network_nic_list); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route); + +STATIC const mp_map_elem_t mp_module_network_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) }, + + #if MICROPY_PY_WIZNET5K + { MP_OBJ_NEW_QSTR(MP_QSTR_WIZNET5K), (mp_obj_t)&mod_network_nic_type_wiznet5k }, + #endif + #if MICROPY_PY_CC3K + { MP_OBJ_NEW_QSTR(MP_QSTR_CC3K), (mp_obj_t)&mod_network_nic_type_cc3k }, + #endif + #if MICROPY_PY_BLE_6LOWPAN + { MP_OBJ_NEW_QSTR(MP_QSTR_ble_6lowpan), (mp_obj_t)&mod_network_nic_type_ble_6lowpan }, + #endif + + { MP_OBJ_NEW_QSTR(MP_QSTR_route), (mp_obj_t)&network_route_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); + +const mp_obj_module_t mp_module_network = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_network_globals, +}; + +#endif // MICROPY_PY_NETWORK diff --git a/nrf5/modnetwork.h b/nrf5/modnetwork.h new file mode 100644 index 0000000000..73f8b628fc --- /dev/null +++ b/nrf5/modnetwork.h @@ -0,0 +1,81 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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. + */ + +#define MOD_NETWORK_IPADDR_BUF_SIZE (16) + +#define MOD_NETWORK_AF_INET (2) +#define MOD_NETWORK_AF_INET6 (10) + +#define MOD_NETWORK_SOCK_STREAM (1) +#define MOD_NETWORK_SOCK_DGRAM (2) +#define MOD_NETWORK_SOCK_RAW (3) + +struct _mod_network_socket_obj_t; + +typedef struct _mod_network_nic_type_t { + mp_obj_type_t base; + + // API for non-socket operations + int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out); + + // API for socket operations; return -1 on error + int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno); + void (*close)(struct _mod_network_socket_obj_t *socket); + int (*bind)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); + int (*listen)(struct _mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno); + int (*accept)(struct _mod_network_socket_obj_t *socket, struct _mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno); + int (*connect)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); + mp_uint_t (*send)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno); + mp_uint_t (*recv)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno); + mp_uint_t (*sendto)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); + mp_uint_t (*recvfrom)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); + int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); + int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); + int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); +} mod_network_nic_type_t; + +typedef struct _mod_network_socket_obj_t { + mp_obj_base_t base; + mp_obj_t nic; + mod_network_nic_type_t *nic_type; + union { + struct { + uint8_t domain; + uint8_t type; + int8_t fileno; + } u_param; + mp_uint_t u_state; + }; + struct udp_pcb * p_socket; +} mod_network_socket_obj_t; + +extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; +extern const mod_network_nic_type_t mod_network_nic_type_cc3k; +extern const mod_network_nic_type_t mod_network_nic_type_ble_6lowpan; + +void mod_network_init(void); +void mod_network_register_nic(mp_obj_t nic); +mp_obj_t mod_network_find_nic(const uint8_t *ip); diff --git a/nrf5/modpyb.c b/nrf5/modpyb.c index d7b2e24b2d..b436c2468c 100644 --- a/nrf5/modpyb.c +++ b/nrf5/modpyb.c @@ -30,12 +30,15 @@ #include "py/obj.h" #include "uart.h" #include "led.h" +#include "nrf.h" // TODO: figure out where to put this import +#include "pin.h" STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) }, { MP_OBJ_NEW_QSTR(MP_QSTR_LED), (mp_obj_t)&pyb_led_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_repl_info), (mp_obj_t)&pyb_set_repl_info_obj}, - { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type } + { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type }, + { MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type }, /* { MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_obj }*/ }; diff --git a/nrf5/modules/mountsd.py b/nrf5/modules/mountsd.py new file mode 100644 index 0000000000..2b4ac26362 --- /dev/null +++ b/nrf5/modules/mountsd.py @@ -0,0 +1,9 @@ +import os +from machine import SPI +from pyb import Pin +from sdcard import SDCard + +def mount_sd(): + sd = SDCard(SPI(0), Pin("A22")) + os.mount(sd, '/') + diff --git a/nrf5/modules/sdcard.py b/nrf5/modules/sdcard.py new file mode 100644 index 0000000000..4fdb3bd045 --- /dev/null +++ b/nrf5/modules/sdcard.py @@ -0,0 +1,278 @@ +""" +Micro Python driver for SD cards using SPI bus. + +Requires an SPI bus and a CS pin. Provides readblocks and writeblocks +methods so the device can be mounted as a filesystem. + +Example usage on pyboard: + + import pyb, sdcard, os + sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5) + pyb.mount(sd, '/sd2') + os.listdir('/') + +Example usage on ESP8266: + + import machine, sdcard, os + sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15)) + os.umount() + os.VfsFat(sd, "") + os.listdir() + +Example usage on NRF52832: + + import machine, pyb, os + sd = sdcard.SDCard(machine.SPI(0), machine.PIN("A22")) + os.mount(sd, "") + os.listdir() + +""" + +import time + + +_CMD_TIMEOUT = const(100) + +_R1_IDLE_STATE = const(1 << 0) +#R1_ERASE_RESET = const(1 << 1) +_R1_ILLEGAL_COMMAND = const(1 << 2) +#R1_COM_CRC_ERROR = const(1 << 3) +#R1_ERASE_SEQUENCE_ERROR = const(1 << 4) +#R1_ADDRESS_ERROR = const(1 << 5) +#R1_PARAMETER_ERROR = const(1 << 6) +_TOKEN_CMD25 = const(0xfc) +_TOKEN_STOP_TRAN = const(0xfd) +_TOKEN_DATA = const(0xfe) + + +class SDCard: + def __init__(self, spi, cs): + self.spi = spi + self.cs = cs + + self.cmdbuf = bytearray(6) + self.dummybuf = bytearray(512) + for i in range(512): + self.dummybuf[i] = 0xff + self.dummybuf_memoryview = memoryview(self.dummybuf) + + # initialise the card + self.init_card() + + def init_spi(self, baudrate): + try: + master = self.spi.MASTER + except AttributeError: + # on ESP8266 + self.spi.init(baudrate=baudrate, phase=0, polarity=0) + else: + # on pyboard + self.spi.init(master, baudrate=baudrate, phase=0, polarity=0) + + def init_card(self): + # init CS pin + #self.cs.init(self.cs.OUT, value=1) + + # init SPI bus; use low data rate for initialisation + self.init_spi(100000) + + # clock card at least 100 cycles with cs high + for i in range(16): + self.spi.write(b'\xff') + + # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) + for _ in range(5): + if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: + break + else: + raise OSError("no SD card") + + # CMD8: determine card version + r = self.cmd(8, 0x01aa, 0x87, 4) + if r == _R1_IDLE_STATE: + self.init_card_v2() + elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): + self.init_card_v1() + else: + raise OSError("couldn't determine SD card version") + + # get the number of sectors + # CMD9: response R2 (R1 byte + 16-byte block read) + if self.cmd(9, 0, 0, 0, False) != 0: + raise OSError("no response from SD card") + csd = bytearray(16) + self.readinto(csd) + if csd[0] & 0xc0 != 0x40: + raise OSError("SD card CSD format not supported") + self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 2014 + #print('sectors', self.sectors) + + # CMD16: set block length to 512 bytes + if self.cmd(16, 512, 0) != 0: + raise OSError("can't set 512 block size") + + # set to high data rate now that it's initialised + self.init_spi(1320000) + + def init_card_v1(self): + for i in range(_CMD_TIMEOUT): + self.cmd(55, 0, 0) + if self.cmd(41, 0, 0) == 0: + self.cdv = 512 + #print("[SDCard] v1 card") + return + raise OSError("timeout waiting for v1 card") + + def init_card_v2(self): + for i in range(_CMD_TIMEOUT): + time.sleep_ms(50) + self.cmd(58, 0, 0, 4) + self.cmd(55, 0, 0) + if self.cmd(41, 0x40000000, 0) == 0: + self.cmd(58, 0, 0, 4) + self.cdv = 1 + #print("[SDCard] v2 card") + return + raise OSError("timeout waiting for v2 card") + + def cmd(self, cmd, arg, crc, final=0, release=True): + self.cs.low() + + # create and send the command + buf = self.cmdbuf + buf[0] = 0x40 | cmd + buf[1] = arg >> 24 + buf[2] = arg >> 16 + buf[3] = arg >> 8 + buf[4] = arg + buf[5] = crc + self.spi.write(buf) + + # wait for the repsonse (response[7] == 0) + for i in range(_CMD_TIMEOUT): + response = self.spi.read(1, 0xff)[0] + if not (response & 0x80): + # this could be a big-endian integer that we are getting here + for j in range(final): + self.spi.write(b'\xff') + if release: + self.cs.high() + self.spi.write(b'\xff') + return response + + # timeout + self.cs.high() + self.spi.write(b'\xff') + return -1 + + def cmd_nodata(self, cmd): + self.spi.write(cmd) + self.spi.read(1, 0xff) # ignore stuff byte + for _ in range(_CMD_TIMEOUT): + if self.spi.read(1, 0xff)[0] == 0xff: + self.cs.high() + self.spi.write(b'\xff') + return 0 # OK + self.cs.high() + self.spi.write(b'\xff') + return 1 # timeout + + def readinto(self, buf): + self.cs.low() + + # read until start byte (0xff) + while self.spi.read(1, 0xff)[0] != 0xfe: + pass + + # read data + mv = self.dummybuf_memoryview[:len(buf)] + self.spi.write_readinto(mv, buf) + + # read checksum + self.spi.write(b'\xff') + self.spi.write(b'\xff') + + self.cs.high() + self.spi.write(b'\xff') + + def write(self, token, buf): + self.cs.low() + + # send: start of block, data, checksum + self.spi.read(1, token) + self.spi.write(buf) + self.spi.write(b'\xff') + self.spi.write(b'\xff') + + # check the response + if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05: + self.cs.high() + self.spi.write(b'\xff') + return + + # wait for write to finish + while self.spi.read(1, 0xff)[0] == 0: + pass + + self.cs.high() + self.spi.write(b'\xff') + + def write_token(self, token): + self.cs.low() + self.spi.read(1, token) + self.spi.write(b'\xff') + # wait for write to finish + while self.spi.read(1, 0xff)[0] == 0x00: + pass + + self.cs.high() + self.spi.write(b'\xff') + + def count(self): + return self.sectors + + def readblocks(self, block_num, buf): + nblocks, err = divmod(len(buf), 512) + assert nblocks and not err, 'Buffer length is invalid' + if nblocks == 1: + # CMD17: set read address for single block + if self.cmd(17, block_num * self.cdv, 0) != 0: + return 1 + # receive the data + self.readinto(buf) + else: + # CMD18: set read address for multiple blocks + if self.cmd(18, block_num * self.cdv, 0) != 0: + return 1 + offset = 0 + mv = memoryview(buf) + while nblocks: + self.readinto(mv[offset : offset + 512]) + offset += 512 + nblocks -= 1 + return self.cmd_nodata(b'\x0c') # cmd 12 + return 0 + + def writeblocks(self, block_num, buf): + nblocks, err = divmod(len(buf), 512) + assert nblocks and not err, 'Buffer length is invalid' + if nblocks == 1: + # CMD24: set write address for single block + if self.cmd(24, block_num * self.cdv, 0) != 0: + return 1 + + # send the data + self.write(_TOKEN_DATA, buf) + else: + # CMD25: set write address for first block + if self.cmd(25, block_num * self.cdv, 0) != 0: + return 1 + # send the data + offset = 0 + mv = memoryview(buf) + while nblocks: + self.write(_TOKEN_CMD25, mv[offset : offset + 512]) + offset += 512 + nblocks -= 1 + self.write_token(_TOKEN_STOP_TRAN) + return 0 diff --git a/nrf5/moduos.c b/nrf5/moduos.c new file mode 100644 index 0000000000..e3bf4c1ae1 --- /dev/null +++ b/nrf5/moduos.c @@ -0,0 +1,411 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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 +#include + +#include "py/mpstate.h" +#include "py/runtime.h" +#include "py/objtuple.h" +#include "py/objstr.h" +#include "genhdr/mpversion.h" +#include "lib/fatfs/ff.h" +#include "lib/fatfs/diskio.h" +#include "lib/timeutils/timeutils.h" +//#include "rng.h" +#include "uart.h" +#include "extmod/vfs_fat_file.h" +//#include "sdcard.h" +#include "extmod/fsusermount.h" +//#include "portmodules.h" + +/// \module os - basic "operating system" services +/// +/// The `os` module contains functions for filesystem access and `urandom`. +/// +/// The filesystem has `/` as the root directory, and the available physical +/// drives are accessible from here. They are currently: +/// +/// /flash -- the internal flash filesystem +/// /sd -- the SD card (if it exists) +/// +/// On boot up, the current directory is `/flash` if no SD card is inserted, +/// otherwise it is `/sd`. + +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, "pyboard"); +STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "pyboard"); +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 +); + +STATIC mp_obj_t os_uname(void) { + return (mp_obj_t)&os_uname_info_obj; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); + +/// \function chdir(path) +/// Change current directory. +STATIC mp_obj_t os_chdir(mp_obj_t path_in) { + const char *path; + path = mp_obj_str_get_str(path_in); + + FRESULT res = f_chdrive(path); + + if (res == FR_OK) { + res = f_chdir(path); + } + + if (res != FR_OK) { + // TODO should be mp_type_FileNotFoundError + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path)); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir); + +/// \function getcwd() +/// Get the current directory. +STATIC mp_obj_t os_getcwd(void) { + char buf[MICROPY_ALLOC_PATH_MAX + 1]; + FRESULT res = f_getcwd(buf, sizeof buf); + + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + + return mp_obj_new_str(buf, strlen(buf), false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); + +/// \function listdir([dir]) +/// With no argument, list the current directory. Otherwise list the given directory. +STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) { + bool is_str_type = true; + const char *path; + if (n_args == 1) { + if (mp_obj_get_type(args[0]) == &mp_type_bytes) { + is_str_type = false; + } + path = mp_obj_str_get_str(args[0]); + } else { + path = ""; + } + + // "hack" to list root directory + if (path[0] == '/' && path[1] == '\0') { + mp_obj_t dir_list = mp_obj_new_list(0, NULL); + for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) { + fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i]; + if (vfs != NULL) { + mp_obj_list_append(dir_list, mp_obj_new_str(vfs->str + 1, vfs->len - 1, false)); + } + } + return dir_list; + } + + return fat_vfs_listdir(path, is_str_type); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir); + +/// \function mkdir(path) +/// Create a new directory. +STATIC mp_obj_t os_mkdir(mp_obj_t path_o) { + const char *path = mp_obj_str_get_str(path_o); + FRESULT res = f_mkdir(path); + switch (res) { + case FR_OK: + return mp_const_none; + case FR_EXIST: + // TODO should be FileExistsError + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path)); + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path)); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir); + +/// \function remove(path) +/// Remove a file. +STATIC mp_obj_t os_remove(mp_obj_t path_o) { + const char *path = mp_obj_str_get_str(path_o); + // TODO check that path is actually a file before trying to unlink it + FRESULT res = f_unlink(path); + switch (res) { + case FR_OK: + return mp_const_none; + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path)); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove); + +/// \function rename(old_path, new_path) +/// Rename a file +STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) { + const char *old_path = mp_obj_str_get_str(path_in); + const char *new_path = mp_obj_str_get_str(path_out); + FRESULT res = f_rename(old_path, new_path); + switch (res) { + case FR_OK: + return mp_const_none; + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error renaming file '%s' to '%s'", old_path, new_path)); + } + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename); + +/// \function rmdir(path) +/// Remove a directory. +STATIC mp_obj_t os_rmdir(mp_obj_t path_o) { + const char *path = mp_obj_str_get_str(path_o); + // TODO check that path is actually a directory before trying to unlink it + FRESULT res = f_unlink(path); + switch (res) { + case FR_OK: + return mp_const_none; + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path)); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir); + +// Checks for path equality, ignoring trailing slashes: +// path_equal(/, /) -> true +// path_equal(/flash//, /flash) -> true +// second argument must be in canonical form (meaning no trailing slash, unless it's just /) +STATIC bool path_equal(const char *path, const char *path_canonical) { + for (; *path_canonical != '\0' && *path == *path_canonical; ++path, ++path_canonical) { + } + if (*path_canonical != '\0') { + return false; + } + for (; *path == '/'; ++path) { + } + return *path == '\0'; +} + +/// \function stat(path) +/// Get the status of a file or directory. +STATIC mp_obj_t os_stat(mp_obj_t path_in) { + const char *path = mp_obj_str_get_str(path_in); + + FILINFO fno; +#if _USE_LFN + fno.lfname = NULL; + fno.lfsize = 0; +#endif + + FRESULT res; + if (path_equal(path, "/")) { + // stat root directory + fno.fsize = 0; + fno.fdate = 0; + fno.ftime = 0; + fno.fattrib = AM_DIR; + } else { + res = FR_NO_PATH; + for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) { + fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i]; + if (vfs != NULL && path_equal(path, vfs->str)) { + // stat mounted device directory + fno.fsize = 0; + fno.fdate = 0; + fno.ftime = 0; + fno.fattrib = AM_DIR; + res = FR_OK; + } + } + if (res == FR_NO_PATH) { + // stat normal file + res = f_stat(path, &fno); + } + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + } + + mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL); + mp_int_t mode = 0; + if (fno.fattrib & AM_DIR) { + mode |= 0x4000; // stat.S_IFDIR + } else { + mode |= 0x8000; // stat.S_IFREG + } + mp_int_t seconds = timeutils_seconds_since_2000( + 1980 + ((fno.fdate >> 9) & 0x7f), + (fno.fdate >> 5) & 0x0f, + fno.fdate & 0x1f, + (fno.ftime >> 11) & 0x1f, + (fno.ftime >> 5) & 0x3f, + 2 * (fno.ftime & 0x1f) + ); + t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode + t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev + t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink + t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid + t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid + t->items[6] = MP_OBJ_NEW_SMALL_INT(fno.fsize); // st_size + t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime + t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime + t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime + + return t; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat); + +STATIC mp_obj_t os_statvfs(mp_obj_t path_in) { + const char *path = mp_obj_str_get_str(path_in); + + DWORD nclst; + FATFS *fatfs; + FRESULT res = f_getfree(path, &nclst, &fatfs); + if (res != FR_OK) { + goto error; + } + + mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL); + + t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * 512); // f_bsize - block size + t->items[1] = t->items[0]; // f_frsize - fragment size + t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2) * fatfs->csize); // f_blocks - total number of blocks + t->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfree - number of free blocks + t->items[4] = t->items[3]; // f_bavail - free blocks avail to unpriviledged users + t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files - # inodes + t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree - # free inodes + t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail - # free inodes avail to unpriviledges users + t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags + t->items[9] = MP_OBJ_NEW_SMALL_INT(_MAX_LFN); // f_namemax + + return t; + +error: + mp_raise_OSError(fresult_to_errno_table[res]); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_statvfs_obj, os_statvfs); + +/// \function sync() +/// Sync all filesystems. +STATIC mp_obj_t os_sync(void) { + disk_ioctl(0, CTRL_SYNC, NULL); + disk_ioctl(1, CTRL_SYNC, NULL); + disk_ioctl(2, CTRL_SYNC, NULL); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(mod_os_sync_obj, os_sync); + +#if MICROPY_HW_ENABLE_RNG +/// \function urandom(n) +/// Return a bytes object with n random bytes, generated by the hardware +/// random number generator. +STATIC mp_obj_t os_urandom(mp_obj_t num) { + mp_int_t n = mp_obj_get_int(num); + vstr_t vstr; + vstr_init_len(&vstr, n); + for (int i = 0; i < n; i++) { + vstr.buf[i] = rng_get(); + } + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); +#endif + +// Get or set the UART object that the REPL is repeated on. +// TODO should accept any object with read/write methods. +STATIC mp_obj_t os_dupterm(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + if (MP_STATE_PORT(pyb_stdio_uart) == NULL) { + return mp_const_none; + } else { + return MP_STATE_PORT(pyb_stdio_uart); + } + } else { + if (args[0] == mp_const_none) { + MP_STATE_PORT(pyb_stdio_uart) = NULL; + } else if (mp_obj_get_type(args[0]) == &pyb_uart_type) { + MP_STATE_PORT(pyb_stdio_uart) = args[0]; + } else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "need a UART object")); + } + return mp_const_none; + } +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_dupterm_obj, 0, 1, os_dupterm); + +STATIC const mp_map_elem_t os_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_uname), (mp_obj_t)&os_uname_obj }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&os_chdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&os_getcwd_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_rename),(mp_obj_t)&os_rename_obj}, + { MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&os_rmdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&os_stat_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_statvfs), (mp_obj_t)&os_statvfs_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&os_remove_obj }, // unlink aliases to remove + + { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&mod_os_sync_obj }, + + /// \constant sep - separation character used in paths + { MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) }, + +#if MICROPY_HW_ENABLE_RNG + { MP_OBJ_NEW_QSTR(MP_QSTR_urandom), (mp_obj_t)&os_urandom_obj }, +#endif + + // these are MicroPython extensions + { MP_OBJ_NEW_QSTR(MP_QSTR_dupterm), (mp_obj_t)&mod_os_dupterm_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&fsuser_mount_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_umount), (mp_obj_t)&fsuser_umount_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mkfs), (mp_obj_t)&fsuser_mkfs_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); + +const mp_obj_module_t mp_module_uos = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&os_module_globals, +}; diff --git a/nrf5/modusocket.c b/nrf5/modusocket.c new file mode 100644 index 0000000000..4c49788793 --- /dev/null +++ b/nrf5/modusocket.c @@ -0,0 +1,480 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * 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 +#include + +#include "py/nlr.h" +#include "py/objtuple.h" +#include "py/objlist.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "netutils.h" +#include "modnetwork.h" + +#if MICROPY_PY_USOCKET + +/******************************************************************************/ +// socket class + +STATIC const mp_obj_type_t socket_type; + +// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) +STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 4, false); + + // create socket object (not bound to any NIC yet) + mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t); + s->base.type = (mp_obj_t)&socket_type; + s->nic = MP_OBJ_NULL; + s->nic_type = NULL; + s->u_param.domain = MOD_NETWORK_AF_INET; + s->u_param.type = MOD_NETWORK_SOCK_STREAM; + s->u_param.fileno = -1; + if (n_args >= 1) { + s->u_param.domain = mp_obj_get_int(args[0]); + if (n_args >= 2) { + s->u_param.type = mp_obj_get_int(args[1]); + if (n_args >= 4) { + s->u_param.fileno = mp_obj_get_int(args[3]); + } + } + } + + return s; +} + +STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) { + if (self->nic == MP_OBJ_NULL) { + // select NIC based on IP + self->nic = mod_network_find_nic(ip); + self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic); + + // call the NIC to open the socket + int _errno; + if (self->nic_type->socket(self, &_errno) != 0) { + mp_raise_OSError(_errno); + } + } +} +// method socket.close() +STATIC mp_obj_t socket_close(mp_obj_t self_in) { + mod_network_socket_obj_t *self = self_in; + if (self->nic != MP_OBJ_NULL) { + self->nic_type->close(self); + self->nic = MP_OBJ_NULL; + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); + +#include + +// method socket.bind(address) +STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { + mod_network_socket_obj_t *self = self_in; + + // get address + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + + mp_uint_t port; + if (self->u_param.domain == MOD_NETWORK_AF_INET) { + port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); + } else { + port = netutils_parse_inet6_addr(addr_in, ip, NETUTILS_BIG); + } + + // check if we need to select a NIC + socket_select_nic(self, ip); + + // call the NIC to bind the socket + int _errno; + if (self->nic_type->bind(self, ip, port, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); + +// method socket.listen(backlog) +STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) { + mod_network_socket_obj_t *self = self_in; + + if (self->nic == MP_OBJ_NULL) { + // not connected + // TODO I think we can listen even if not bound... + mp_raise_OSError(MP_ENOTCONN); + } + + int _errno; + if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); + +// method socket.accept() +STATIC mp_obj_t socket_accept(mp_obj_t self_in) { + mod_network_socket_obj_t *self = self_in; + + // create new socket object + // starts with empty NIC so that finaliser doesn't run close() method if accept() fails + mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); + socket2->base.type = (mp_obj_t)&socket_type; + socket2->nic = MP_OBJ_NULL; + socket2->nic_type = NULL; + + // accept incoming connection + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + mp_uint_t port; + int _errno; + if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + // new socket has valid state, so set the NIC to the same as parent + socket2->nic = self->nic; + socket2->nic_type = self->nic_type; + + // make the return value + mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); + client->items[0] = socket2; + + if (self->u_param.domain == MOD_NETWORK_AF_INET) { + client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + } else { + client->items[1] = netutils_format_inet6_addr(ip, port, NETUTILS_BIG); + } + + return client; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); + +// method socket.connect(address) +STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { + mod_network_socket_obj_t *self = self_in; + + // get address + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + + mp_uint_t port; + if (self->u_param.domain == MOD_NETWORK_AF_INET) { + port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); + } else { + port = netutils_parse_inet6_addr(addr_in, ip, NETUTILS_BIG); + } + // check if we need to select a NIC + socket_select_nic(self, ip); + + // call the NIC to connect the socket + int _errno; + if (self->nic_type->connect(self, ip, port, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); + +// method socket.send(bytes) +STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { + mod_network_socket_obj_t *self = self_in; + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_EPIPE); + } + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + int _errno; + mp_uint_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + return mp_obj_new_int_from_uint(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); + +// method socket.recv(bufsize) +STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { + mod_network_socket_obj_t *self = self_in; + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_ENOTCONN); + } + mp_int_t len = mp_obj_get_int(len_in); + vstr_t vstr; + vstr_init_len(&vstr, len); + int _errno; + mp_uint_t ret = self->nic_type->recv(self, (byte*)vstr.buf, len, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + if (ret == 0) { + return mp_const_empty_bytes; + } + vstr.len = ret; + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); + +// method socket.sendto(bytes, address) +STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { + mod_network_socket_obj_t *self = self_in; + + // get the data + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); + + // get address + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + mp_uint_t port; + if (self->u_param.domain == MOD_NETWORK_AF_INET) { + port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); + } else { + port = netutils_parse_inet6_addr(addr_in, ip, NETUTILS_BIG); + } + + // check if we need to select a NIC + socket_select_nic(self, ip); + + // call the NIC to sendto + int _errno; + mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); + +// method socket.recvfrom(bufsize) +STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { + mod_network_socket_obj_t *self = self_in; + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_ENOTCONN); + } + vstr_t vstr; + vstr_init_len(&vstr, mp_obj_get_int(len_in)); + byte ip[4]; + mp_uint_t port; + int _errno; + mp_int_t ret = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + mp_obj_t tuple[2]; + if (ret == 0) { + tuple[0] = mp_const_empty_bytes; + } else { + vstr.len = ret; + tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + } + + if (self->u_param.domain == MOD_NETWORK_AF_INET) { + tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + } else { + tuple[1] = netutils_format_inet6_addr(ip, port, NETUTILS_BIG); + } + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); + +// method socket.setsockopt(level, optname, value) +STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) { + mod_network_socket_obj_t *self = args[0]; + + mp_int_t level = mp_obj_get_int(args[1]); + mp_int_t opt = mp_obj_get_int(args[2]); + + const void *optval; + mp_uint_t optlen; + mp_int_t val; + if (mp_obj_is_integer(args[3])) { + val = mp_obj_get_int_truncated(args[3]); + optval = &val; + optlen = sizeof(val); + } else { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + optval = bufinfo.buf; + optlen = bufinfo.len; + } + + int _errno; + if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); + +// method socket.settimeout(value) +// timeout=0 means non-blocking +// timeout=None means blocking +// otherwise, timeout is in seconds +STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { + mod_network_socket_obj_t *self = self_in; + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_ENOTCONN); + } + mp_uint_t timeout; + if (timeout_in == mp_const_none) { + timeout = -1; + } else { + #if MICROPY_PY_BUILTINS_FLOAT + timeout = 1000 * mp_obj_get_float(timeout_in); + #else + timeout = 1000 * mp_obj_get_int(timeout_in); + #endif + } + int _errno; + if (self->nic_type->settimeout(self, timeout, &_errno) != 0) { + mp_raise_OSError(_errno); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); + +// method socket.setblocking(flag) +STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { + if (mp_obj_is_true(blocking)) { + return socket_settimeout(self_in, mp_const_none); + } else { + return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0)); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); + +STATIC const mp_map_elem_t socket_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); + +mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { + mod_network_socket_obj_t *self = self_in; + return self->nic_type->ioctl(self, request, arg, errcode); +} + +STATIC const mp_stream_p_t socket_stream_p = { + .ioctl = socket_ioctl, + .is_text = false, +}; + +STATIC const mp_obj_type_t socket_type = { + { &mp_type_type }, + .name = MP_QSTR_socket, + .make_new = socket_make_new, + .protocol = &socket_stream_p, + .locals_dict = (mp_obj_t)&socket_locals_dict, +}; + +/******************************************************************************/ +// usocket module + +// function usocket.getaddrinfo(host, port) +STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { + mp_uint_t hlen; + const char *host = mp_obj_str_get_data(host_in, &hlen); + mp_int_t port = mp_obj_get_int(port_in); + + // find a NIC that can do a name lookup + for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { + mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; + mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); + if (nic_type->gethostbyname != NULL) { + uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); + if (ret != 0) { + // TODO CPython raises: socket.gaierror: [Errno -2] Name or service not known + mp_raise_OSError(ret); + } + mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); + tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); + tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG); + return mp_obj_new_list(1, (mp_obj_t*)&tuple); + } + } + + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo); + +STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type }, + { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_usocket_getaddrinfo_obj }, + + // class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET6) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_DGRAM) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_RAW) }, + + /* + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_ICMP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_ICMP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV4), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IPV4) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_TCP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_UDP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV6), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IPV6) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_RAW), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_RAW) }, + */ +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); + +const mp_obj_module_t mp_module_usocket = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, +}; + +#endif // MICROPY_PY_USOCKET diff --git a/nrf5/modutime.c b/nrf5/modutime.c new file mode 100644 index 0000000000..a0e4f904c4 --- /dev/null +++ b/nrf5/modutime.c @@ -0,0 +1,52 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 +#include +#include NRF5_HAL_H + +#include "py/nlr.h" +#include "py/smallint.h" +#include "py/obj.h" +#include "extmod/utime_mphal.h" + +/// \module time - time related functions +/// +/// The `time` module provides functions for getting the current time and date, +/// and for sleeping. + +STATIC const mp_rom_map_elem_t time_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, + + { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); + +const mp_obj_module_t mp_module_utime = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&time_module_globals, +}; diff --git a/nrf5/mpconfigport.h b/nrf5/mpconfigport.h index 9a8865dce0..b43dc9940e 100644 --- a/nrf5/mpconfigport.h +++ b/nrf5/mpconfigport.h @@ -27,7 +27,7 @@ #ifndef NRF5_MPCONFIGPORT_H__ #define NRF5_MPCONFIGPORT_H__ -#include +#include // options to control how Micro Python is built // options to control how Micro Python is built @@ -45,20 +45,20 @@ #define MICROPY_REPL_EMACS_KEYS (0) #define MICROPY_REPL_AUTO_INDENT (0) #define MICROPY_ENABLE_SOURCE_LINE (0) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0) #define MICROPY_OPT_MPZ_BITWISE (0) // fatfs configuration used in ffconf.h -#define MICROPY_FATFS_ENABLE_LFN (0) +#define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_FATFS_USE_LABEL (0) -#define MICROPY_FATFS_RPATH (0) -#define MICROPY_FATFS_VOLUMES (0) -#define MICROPY_FATFS_MULTI_PARTITION (0) -#define MICROPY_FSUSERMOUNT (0) +#define MICROPY_FATFS_USE_LABEL (1) +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_VOLUMES (4) +#define MICROPY_FATFS_MULTI_PARTITION (1) +#define MICROPY_FSUSERMOUNT (1) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_MODULE_WEAK_LINKS (1) @@ -69,8 +69,8 @@ #define MICROPY_PY_BUILTINS_STR_CENTER (0) #define MICROPY_PY_BUILTINS_STR_PARTITION (0) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (0) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) -#define MICROPY_PY_BUILTINS_FROZENSET (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_EXECFILE (0) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (0) @@ -96,25 +96,34 @@ #define MICROPY_PY_URE (0) #define MICROPY_PY_UHEAPQ (0) #define MICROPY_PY_UHASHLIB (0) -#define MICROPY_PY_UTIME_MP_HAL (0) -#define MICROPY_PY_MACHINE (0) +#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (0) #define MICROPY_PY_MACHINE_I2C (0) -#define MICROPY_PY_MACHINE_SPI (0) + +#ifndef MICROPY_PY_MACHINE_SPI +#define MICROPY_PY_MACHINE_SPI (1) +#endif + #define MICROPY_PY_MACHINE_SPI_MIN_DELAY (0) #define MICROPY_PY_FRAMEBUF (0) #ifndef MICROPY_PY_USOCKET -#define MICROPY_PY_USOCKET (0) +#define MICROPY_PY_USOCKET (1) #endif #ifndef MICROPY_PY_NETWORK -#define MICROPY_PY_NETWORK (0) +#define MICROPY_PY_NETWORK (1) #endif #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) +// if sdk is in use, import configuration +#if BLUETOOTH_SD +#include "nrf5_sdk_conf.h" +#endif + // type definitions for the specific machine #define BYTES_PER_WORD (4) @@ -131,33 +140,68 @@ typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size typedef long mp_off_t; -// board specific definitions -#include "mpconfigboard.h" - // extra built in modules to add to the list of known ones extern const struct _mp_obj_module_t pyb_module; +extern const struct _mp_obj_module_t machine_module; +extern const struct _mp_obj_module_t mp_module_utime; +extern const struct _mp_obj_module_t mp_module_uos; +extern const struct _mp_obj_module_t mp_module_usocket; +extern const struct _mp_obj_module_t mp_module_network; + +#if MICROPY_PY_USOCKET +#define SOCKET_BUILTIN_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, +#define SOCKET_BUILTIN_MODULE_WEAK_LINKS { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, +#else +#define SOCKET_BUILTIN_MODULE +#define SOCKET_BUILTIN_MODULE_WEAK_LINKS +#endif + +#if MICROPY_PY_NETWORK +#define NETWORK_BUILTIN_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, +#else +#define NETWORK_BUILTIN_MODULE +#endif + #if BLUETOOTH_SD extern const struct _mp_obj_module_t ble_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_ble), (mp_obj_t)&ble_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&mp_module_utime }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_utime }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_uos }, \ + SOCKET_BUILTIN_MODULE \ + NETWORK_BUILTIN_MODULE \ + #else extern const struct _mp_obj_module_t ble_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&mp_module_utime }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_uos }, \ + #endif // BLUETOOTH_SD +#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ + { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&mp_module_uos }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_utime }, \ + SOCKET_BUILTIN_MODULE_WEAK_LINKS \ + // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, \ // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_ble), (mp_obj_t)&ble_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \ #define MP_STATE_PORT MP_STATE_VM @@ -174,12 +218,15 @@ extern const struct _mp_obj_module_t ble_module; \ /* pointers to all UART objects (if they have been created) */ \ struct _pyb_uart_obj_t *pyb_uart_obj_all[1]; \ + \ + /* list of registered NICs */ \ + mp_obj_list_t mod_network_nic_list; \ #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) // We need to provide a declaration/definition of alloca() #include -#include "mpconfigboard.h" +#define MICROPY_PIN_DEFS_PORT_H "pin_defs_nrf5.h" #endif diff --git a/nrf5/mphalport.c b/nrf5/mphalport.c index 54283adde7..2de06d2314 100644 --- a/nrf5/mphalport.c +++ b/nrf5/mphalport.c @@ -23,6 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include #include @@ -47,6 +48,7 @@ void mp_hal_set_interrupt_char(int c) { } +#if (BLUETOOTH_SD != 132) int mp_hal_stdin_rx_chr(void) { for (;;) { if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { @@ -56,16 +58,19 @@ int mp_hal_stdin_rx_chr(void) { return 0; } +#endif void mp_hal_stdout_tx_str(const char *str) { mp_hal_stdout_tx_strn(str, strlen(str)); } +#if (BLUETOOTH_SD != 132) void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len); } } +#endif void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { diff --git a/nrf5/mphalport.h b/nrf5/mphalport.h index 47fb617c47..5d80d5142b 100644 --- a/nrf5/mphalport.h +++ b/nrf5/mphalport.h @@ -27,10 +27,9 @@ #ifndef __NRF52_HAL #define __NRF52_HAL -#include - #include "py/mpconfig.h" -#include "nrf.h" +#include NRF5_HAL_H +#include "pin.h" typedef enum { @@ -47,6 +46,27 @@ typedef enum #define GPIO_BASE ((NRF_GPIO_Type *)NRF_P0_BASE) #endif +/** + * @brief GPIO Init structure definition + */ +typedef struct +{ + uint32_t Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins_define */ + + uint32_t Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIO_mode_define */ + + uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins. + This parameter can be a value of @ref GPIO_pull_define */ + + uint32_t Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIO_speed_define */ + + uint32_t Alternate; /*!< Peripheral to be connected to the selected pins. + This parameter can be a value of @ref GPIO_Alternat_function_selection */ +} GPIO_InitTypeDef; + typedef enum { HAL_GPIO_PULL_DISABLED = (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos), HAL_GPIO_PULL_DOWN = (GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos), @@ -106,5 +126,16 @@ void mp_hal_set_interrupt_char(int c); // -1 to disable int mp_hal_stdin_rx_chr(void); void mp_hal_stdout_tx_str(const char *str); +#define mp_hal_pin_obj_t const pin_obj_t* +#define mp_hal_pin_high(p) (((NRF_GPIO_Type *)((p)->gpio))->OUTSET = (p)->pin_mask) +#define mp_hal_pin_low(p) (((NRF_GPIO_Type *)((p)->gpio))->OUTCLR = (p)->pin_mask) +#define mp_hal_pin_read(p) (((NRF_GPIO_Type *)((p)->gpio))->OUT >> ((p)->pin) & 1) +#define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) + +// TODO: empty implementation for now. Used by machine_spi.c:69 +#define mp_hal_delay_us_fast(p) +#define mp_hal_ticks_us() (0) +#define mp_hal_ticks_cpu() (0) + #endif diff --git a/nrf5/nrf51_af.csv b/nrf5/nrf51_af.csv new file mode 100644 index 0000000000..b54aaa1e31 --- /dev/null +++ b/nrf5/nrf51_af.csv @@ -0,0 +1,32 @@ +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +PA8,PA8 +PA9,PA9 +PA10,PA10 +PA11,PA11 +PA12,PA12 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PA16,PA16 +PA17,PA17 +PA18,PA18 +PA19,PA19 +PA20,PA20 +PA21,PA21 +PA22,PA22 +PA23,PA23 +PA24,PA24 +PA25,PA25 +PA26,PA26 +PA27,PA27 +PA28,PA28 +PA29,PA29 +PA30,PA30 +PA31,PA31 \ No newline at end of file diff --git a/nrf5/nrf52_af.csv b/nrf5/nrf52_af.csv new file mode 100644 index 0000000000..b54aaa1e31 --- /dev/null +++ b/nrf5/nrf52_af.csv @@ -0,0 +1,32 @@ +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +PA8,PA8 +PA9,PA9 +PA10,PA10 +PA11,PA11 +PA12,PA12 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PA16,PA16 +PA17,PA17 +PA18,PA18 +PA19,PA19 +PA20,PA20 +PA21,PA21 +PA22,PA22 +PA23,PA23 +PA24,PA24 +PA25,PA25 +PA26,PA26 +PA27,PA27 +PA28,PA28 +PA29,PA29 +PA30,PA30 +PA31,PA31 \ No newline at end of file diff --git a/nrf5/pin.c b/nrf5/pin.c new file mode 100644 index 0000000000..5172ec27d1 --- /dev/null +++ b/nrf5/pin.c @@ -0,0 +1,611 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 +#include +#include + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "pin.h" + +/// \moduleref pyb +/// \class Pin - control I/O pins +/// +/// A pin is the basic object to control I/O pins. It has methods to set +/// the mode of the pin (input, output, etc) and methods to get and set the +/// digital logic level. For analog control of a pin, see the ADC class. +/// +/// Usage Model: +/// +/// All Board Pins are predefined as pyb.Pin.board.Name +/// +/// x1_pin = pyb.Pin.board.X1 +/// +/// g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN) +/// +/// CPU pins which correspond to the board pins are available +/// as `pyb.cpu.Name`. For the CPU pins, the names are the port letter +/// followed by the pin number. On the PYBv1.0, `pyb.Pin.board.X1` and +/// `pyb.Pin.cpu.B6` are the same pin. +/// +/// You can also use strings: +/// +/// g = pyb.Pin('X1', pyb.Pin.OUT_PP) +/// +/// Users can add their own names: +/// +/// MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 } +/// pyb.Pin.dict(MyMapperDict) +/// g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD) +/// +/// and can query mappings +/// +/// pin = pyb.Pin("LeftMotorDir") +/// +/// Users can also add their own mapping function: +/// +/// def MyMapper(pin_name): +/// if pin_name == "LeftMotorDir": +/// return pyb.Pin.cpu.A0 +/// +/// pyb.Pin.mapper(MyMapper) +/// +/// So, if you were to call: `pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)` +/// then `"LeftMotorDir"` is passed directly to the mapper function. +/// +/// To summarise, the following order determines how things get mapped into +/// an ordinal pin number: +/// +/// 1. Directly specify a pin object +/// 2. User supplied mapping function +/// 3. User supplied mapping (object must be usable as a dictionary key) +/// 4. Supply a string which matches a board pin +/// 5. Supply a string which matches a CPU port/pin +/// +/// You can set `pyb.Pin.debug(True)` to get some debug information about +/// how a particular object gets mapped to a pin. + +// Pin class variables +STATIC bool pin_class_debug; + +void pin_init0(void) { + MP_STATE_PORT(pin_class_mapper) = mp_const_none; + MP_STATE_PORT(pin_class_map_dict) = mp_const_none; + pin_class_debug = false; +} + +// C API used to convert a user-supplied pin name into an ordinal pin number. +const pin_obj_t *pin_find(mp_obj_t user_obj) { + const pin_obj_t *pin_obj; + + // If a pin was provided, then use it + if (MP_OBJ_IS_TYPE(user_obj, &pin_type)) { + pin_obj = user_obj; + if (pin_class_debug) { + printf("Pin map passed pin "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + if (MP_STATE_PORT(pin_class_mapper) != mp_const_none) { + pin_obj = mp_call_function_1(MP_STATE_PORT(pin_class_mapper), user_obj); + if (pin_obj != mp_const_none) { + if (!MP_OBJ_IS_TYPE(pin_obj, &pin_type)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object")); + } + if (pin_class_debug) { + printf("Pin.mapper maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + // The pin mapping function returned mp_const_none, fall through to + // other lookup methods. + } + + if (MP_STATE_PORT(pin_class_map_dict) != mp_const_none) { + mp_map_t *pin_map_map = mp_obj_dict_get_map(MP_STATE_PORT(pin_class_map_dict)); + mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP); + if (elem != NULL && elem->value != NULL) { + pin_obj = elem->value; + if (pin_class_debug) { + printf("Pin.map_dict maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + } + + // See if the pin name matches a board pin + pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj); + if (pin_obj) { + if (pin_class_debug) { + printf("Pin.board maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + // See if the pin name matches a cpu pin + pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj); + if (pin_obj) { + if (pin_class_debug) { + printf("Pin.cpu maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", mp_obj_str_get_str(user_obj))); +} + +/// \method __str__() +/// Return a string describing the pin object. +STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pin_obj_t *self = self_in; + + // pin name + mp_printf(print, "Pin(Pin.cpu.%q, mode=Pin.", self->name); + mp_printf(print, "gpio=0x%x,", self->gpio); + mp_printf(print, "pin_mask=0x%x,", self->pin_mask); +/* + uint32_t mode = pin_get_mode(self); + + if (mode == GPIO_MODE_ANALOG) { + // analog + mp_print_str(print, "ANALOG)"); + + } else { + // IO mode + bool af = false; + qstr mode_qst; + if (mode == GPIO_MODE_INPUT) { + mode_qst = MP_QSTR_IN; + } else if (mode == GPIO_MODE_OUTPUT_PP) { + mode_qst = MP_QSTR_OUT; + } else if (mode == GPIO_MODE_OUTPUT_OD) { + mode_qst = MP_QSTR_OPEN_DRAIN; + } else { + af = true; + if (mode == GPIO_MODE_AF_PP) { + mode_qst = MP_QSTR_ALT; + } else { + mode_qst = MP_QSTR_ALT_OPEN_DRAIN; + } + } + mp_print_str(print, qstr_str(mode_qst)); + + // pull mode + qstr pull_qst = MP_QSTR_NULL; + uint32_t pull = pin_get_pull(self); + if (pull == GPIO_PULLUP) { + pull_qst = MP_QSTR_PULL_UP; + } else if (pull == GPIO_PULLDOWN) { + pull_qst = MP_QSTR_PULL_DOWN; + } + if (pull_qst != MP_QSTR_NULL) { + mp_printf(print, ", pull=Pin.%q", pull_qst); + } + + // AF mode + if (af) { + mp_uint_t af_idx = pin_get_af(self); + const pin_af_obj_t *af_obj = pin_find_af_by_index(self, af_idx); + if (af_obj == NULL) { + mp_printf(print, ", af=%d)", af_idx); + } else { + mp_printf(print, ", af=Pin.%q)", af_obj->name); + } + } else { +*/ + mp_print_str(print, ")"); + /* } + }*/ + +} + +STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args); + +/// \classmethod \constructor(id, ...) +/// Create a new Pin object associated with the id. If additional arguments are given, +/// they are used to initialise the pin. See `init`. +STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + // Run an argument through the mapper and return the result. + const pin_obj_t *pin = pin_find(args[0]); + + if (n_args > 1 || n_kw > 0) { + // pin mode given, so configure this GPIO + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); + } + + return (mp_obj_t)pin; +} + +// fast method for getting/setting pin value +STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + pin_obj_t *self = self_in; + if (n_args == 0) { + // get pin + return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self)); + } else { + // set pin + mp_hal_pin_write(self, mp_obj_is_true(args[0])); + return mp_const_none; + } +} + +/// \classmethod mapper([fun]) +/// Get or set the pin mapper function. +STATIC mp_obj_t pin_mapper(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args > 1) { + MP_STATE_PORT(pin_class_mapper) = args[1]; + return mp_const_none; + } + return MP_STATE_PORT(pin_class_mapper); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_mapper_fun_obj, 1, 2, pin_mapper); +STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_mapper_obj, (mp_obj_t)&pin_mapper_fun_obj); + +/// \classmethod dict([dict]) +/// Get or set the pin mapper dictionary. +STATIC mp_obj_t pin_map_dict(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args > 1) { + MP_STATE_PORT(pin_class_map_dict) = args[1]; + return mp_const_none; + } + return MP_STATE_PORT(pin_class_map_dict); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_dict_fun_obj, 1, 2, pin_map_dict); +STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_map_dict_obj, (mp_obj_t)&pin_map_dict_fun_obj); + +/// \classmethod af_list() +/// Returns an array of alternate functions available for this pin. +STATIC mp_obj_t pin_af_list(mp_obj_t self_in) { + pin_obj_t *self = self_in; + mp_obj_t result = mp_obj_new_list(0, NULL); + + const pin_af_obj_t *af = self->af; + for (mp_uint_t i = 0; i < self->num_af; i++, af++) { + mp_obj_list_append(result, (mp_obj_t)af); + } + return result; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_list_obj, pin_af_list); + +/// \classmethod debug([state]) +/// Get or set the debugging state (`True` or `False` for on or off). +STATIC mp_obj_t pin_debug(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args > 1) { + pin_class_debug = mp_obj_is_true(args[1]); + return mp_const_none; + } + return mp_obj_new_bool(pin_class_debug); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_debug_fun_obj, 1, 2, pin_debug); +STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_obj); + +// init(mode, pull=None, af=-1, *, value, alt) +STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}}, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); +/* + // get io mode + uint mode = args[0].u_int; + if (!IS_GPIO_MODE(mode)) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode)); + } +*/ + // get pull mode + uint pull = HAL_GPIO_PULL_DISABLED; + if (args[1].u_obj != mp_const_none) { + pull = mp_obj_get_int(args[1].u_obj); + } + + (void)pull; + + // if given, set the pin value before initialising to prevent glitches + if (args[3].u_obj != MP_OBJ_NULL) { + mp_hal_pin_write(self, mp_obj_is_true(args[3].u_obj)); + } + + hal_gpio_cfg_pin_output(self->pin_mask); + + return mp_const_none; +} + +STATIC mp_obj_t pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init); + +/// \method value([value]) +/// Get or set the digital logic level of the pin: +/// +/// - With no argument, return 0 or 1 depending on the logic level of the pin. +/// - With `value` given, set the logic level of the pin. `value` can be +/// anything that converts to a boolean. If it converts to `True`, the pin +/// is set high, otherwise it is set low. +STATIC mp_obj_t pin_value(mp_uint_t n_args, const mp_obj_t *args) { + return pin_call(args[0], n_args - 1, 0, args + 1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value); + +/// \method low() +/// Set the pin to a low logic level. +STATIC mp_obj_t pin_low(mp_obj_t self_in) { + pin_obj_t *self = self_in; + mp_hal_pin_low(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low); + +/// \method high() +/// Set the pin to a high logic level. +STATIC mp_obj_t pin_high(mp_obj_t self_in) { + pin_obj_t *self = self_in; + mp_hal_pin_high(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high); + +/// \method name() +/// Get the pin name. +STATIC mp_obj_t pin_name(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_QSTR(self->name); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name); + +/// \method names() +/// Returns the cpu and board names for this pin. +STATIC mp_obj_t pin_names(mp_obj_t self_in) { + pin_obj_t *self = self_in; + mp_obj_t result = mp_obj_new_list(0, NULL); + mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name)); + + mp_map_t *map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict); + mp_map_elem_t *elem = map->table; + + for (mp_uint_t i = 0; i < map->used; i++, elem++) { + if (elem->value == self) { + mp_obj_list_append(result, elem->key); + } + } + return result; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_names_obj, pin_names); + +/// \method port() +/// Get the pin port. +STATIC mp_obj_t pin_port(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_SMALL_INT(self->port); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_port_obj, pin_port); + +/// \method pin() +/// Get the pin number. +STATIC mp_obj_t pin_pin(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_SMALL_INT(self->pin); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin); + +/// \method gpio() +/// Returns the base address of the GPIO block associated with this pin. +STATIC mp_obj_t pin_gpio(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_SMALL_INT((mp_int_t)self->gpio); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_gpio_obj, pin_gpio); + +/// \method mode() +/// Returns the currently configured mode of the pin. The integer returned +/// will match one of the allowed constants for the mode argument to the init +/// function. +STATIC mp_obj_t pin_mode(mp_obj_t self_in) { + return mp_const_none; // TODO: MP_OBJ_NEW_SMALL_INT(pin_get_mode(self_in)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_mode_obj, pin_mode); + +/// \method pull() +/// Returns the currently configured pull of the pin. The integer returned +/// will match one of the allowed constants for the pull argument to the init +/// function. +STATIC mp_obj_t pin_pull(mp_obj_t self_in) { + return mp_const_none; // TODO: MP_OBJ_NEW_SMALL_INT(pin_get_pull(self_in)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pull_obj, pin_pull); + +/// \method af() +/// Returns the currently configured alternate-function of the pin. The +/// integer returned will match one of the allowed constants for the af +/// argument to the init function. +STATIC mp_obj_t pin_af(mp_obj_t self_in) { + return mp_const_none; // TODO: MP_OBJ_NEW_SMALL_INT(pin_get_af(self_in)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af); + +STATIC const mp_map_elem_t pin_locals_dict_table[] = { + // instance methods + { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pin_init_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pin_value_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_names), (mp_obj_t)&pin_names_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_af_list), (mp_obj_t)&pin_af_list_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&pin_port_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_gpio), (mp_obj_t)&pin_gpio_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&pin_mode_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_pull), (mp_obj_t)&pin_pull_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_af), (mp_obj_t)&pin_af_obj }, + + // class methods + { MP_OBJ_NEW_QSTR(MP_QSTR_mapper), (mp_obj_t)&pin_mapper_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&pin_map_dict_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_debug), (mp_obj_t)&pin_debug_obj }, +/* + // class attributes + { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&pin_board_pins_obj_type }, + { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type }, + + // class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ALT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ANALOG), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_ANALOG) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) }, + + // legacy class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AF_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AF_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_NOPULL) }, +*/ +#include "genhdr/pins_af_const.h" +}; + +STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table); + +const mp_obj_type_t pin_type = { + { &mp_type_type }, + .name = MP_QSTR_Pin, + .print = pin_print, + .make_new = pin_make_new, + .call = pin_call, + .locals_dict = (mp_obj_t)&pin_locals_dict, +}; + +/// \moduleref pyb +/// \class PinAF - Pin Alternate Functions +/// +/// A Pin represents a physical pin on the microcprocessor. Each pin +/// can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF +/// object represents a particular function for a pin. +/// +/// Usage Model: +/// +/// x3 = pyb.Pin.board.X3 +/// x3_af = x3.af_list() +/// +/// x3_af will now contain an array of PinAF objects which are availble on +/// pin X3. +/// +/// For the pyboard, x3_af would contain: +/// [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2] +/// +/// Normally, each peripheral would configure the af automatically, but sometimes +/// the same function is available on multiple pins, and having more control +/// is desired. +/// +/// To configure X3 to expose TIM2_CH3, you could use: +/// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2) +/// or: +/// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1) + +/// \method __str__() +/// Return a string describing the alternate function. +STATIC void pin_af_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pin_af_obj_t *self = self_in; + mp_printf(print, "Pin.%q", self->name); +} + +/// \method index() +/// Return the alternate function index. +STATIC mp_obj_t pin_af_index(mp_obj_t self_in) { + pin_af_obj_t *af = self_in; + return MP_OBJ_NEW_SMALL_INT(af->idx); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_index_obj, pin_af_index); + +/// \method name() +/// Return the name of the alternate function. +STATIC mp_obj_t pin_af_name(mp_obj_t self_in) { + pin_af_obj_t *af = self_in; + return MP_OBJ_NEW_QSTR(af->name); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_name_obj, pin_af_name); + +/// \method reg() +/// Return the base register associated with the peripheral assigned to this +/// alternate function. +STATIC mp_obj_t pin_af_reg(mp_obj_t self_in) { + pin_af_obj_t *af = self_in; + return MP_OBJ_NEW_SMALL_INT((mp_uint_t)af->reg); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_reg_obj, pin_af_reg); + +STATIC const mp_map_elem_t pin_af_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&pin_af_index_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_af_name_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_reg), (mp_obj_t)&pin_af_reg_obj }, +}; +STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table); + +const mp_obj_type_t pin_af_type = { + { &mp_type_type }, + .name = MP_QSTR_PinAF, + .print = pin_af_obj_print, + .locals_dict = (mp_obj_t)&pin_af_locals_dict, +}; diff --git a/nrf5/pin.h b/nrf5/pin.h new file mode 100644 index 0000000000..d2b6e863c9 --- /dev/null +++ b/nrf5/pin.h @@ -0,0 +1,101 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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_NRF5_PIN_H__ +#define __MICROPY_INCLUDED_NRF5_PIN_H__ + +// This file requires pin_defs_xxx.h (which has port specific enums and +// defines, so we include it here. It should never be included directly + +#include MICROPY_PIN_DEFS_PORT_H +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + qstr name; + uint8_t idx; + uint8_t fn; + uint8_t unit; + uint8_t type; + + union { + void *reg; + + PIN_DEFS_PORT_AF_UNION + }; +} pin_af_obj_t; + +typedef struct { + mp_obj_base_t base; + qstr name; + uint32_t port : 4; + uint32_t pin : 5; // Some ARM processors use 32 bits/PORT + uint32_t num_af : 4; + uint32_t adc_channel : 5; // Some ARM processors use 32 bits/PORT + uint32_t adc_num : 3; // 1 bit per ADC + uint32_t pin_mask; + pin_gpio_t *gpio; + const pin_af_obj_t *af; +} pin_obj_t; + +extern const mp_obj_type_t pin_type; +extern const mp_obj_type_t pin_af_type; + +typedef struct { + const char *name; + const pin_obj_t *pin; +} pin_named_pin_t; + +extern const pin_named_pin_t pin_board_pins[]; +extern const pin_named_pin_t pin_cpu_pins[]; + +//extern pin_map_obj_t pin_map_obj; + +typedef struct { + mp_obj_base_t base; + qstr name; + const pin_named_pin_t *named_pins; +} pin_named_pins_obj_t; + +extern const mp_obj_type_t pin_board_pins_obj_type; +extern const mp_obj_type_t pin_cpu_pins_obj_type; + +extern const mp_obj_dict_t pin_cpu_pins_locals_dict; +extern const mp_obj_dict_t pin_board_pins_locals_dict; + +MP_DECLARE_CONST_FUN_OBJ_KW(pin_init_obj); + +void pin_init0(void); +uint32_t pin_get_mode(const pin_obj_t *pin); +uint32_t pin_get_pull(const pin_obj_t *pin); +uint32_t pin_get_af(const pin_obj_t *pin); +const pin_obj_t *pin_find(mp_obj_t user_obj); +const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name); +const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit); +const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx); +const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name); + +#endif // __MICROPY_INCLUDED_NRF5_PIN_H__ diff --git a/nrf5/pin_defs_nrf5.h b/nrf5/pin_defs_nrf5.h new file mode 100644 index 0000000000..739b674d63 --- /dev/null +++ b/nrf5/pin_defs_nrf5.h @@ -0,0 +1,58 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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. + */ + +// This file contains pin definitions that are specific to the nrf5 port. +// This file should only ever be #included by pin.h and not directly. + +enum { + PORT_A, +}; + +enum { + AF_FN_UART, + AF_FN_SPI, +}; + +enum { + AF_PIN_TYPE_UART_TX = 0, + AF_PIN_TYPE_UART_RX, + AF_PIN_TYPE_UART_CTS, + AF_PIN_TYPE_UART_RTS, + + AF_PIN_TYPE_SPI_MOSI = 0, + AF_PIN_TYPE_SPI_MISO, + AF_PIN_TYPE_SPI_SCK, + AF_PIN_TYPE_SPI_NSS, +}; + +#define PIN_DEFS_PORT_AF_UNION \ + NRF_UART_Type *UART; +// NRF_SPI_Type *SPIM; +// NRF_SPIS_Type *SPIS; + + +typedef NRF_GPIO_Type pin_gpio_t; diff --git a/nrf5/pin_named_pins.c b/nrf5/pin_named_pins.c new file mode 100644 index 0000000000..9e5f9593b4 --- /dev/null +++ b/nrf5/pin_named_pins.c @@ -0,0 +1,92 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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 +#include + +#include "py/runtime.h" +#include "py/mphal.h" +#include "pin.h" + +STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pin_named_pins_obj_t *self = self_in; + mp_printf(print, "", self->name); +} + +const mp_obj_type_t pin_cpu_pins_obj_type = { + { &mp_type_type }, + .name = MP_QSTR_cpu, + .print = pin_named_pins_obj_print, + .locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict, +}; + +const mp_obj_type_t pin_board_pins_obj_type = { + { &mp_type_type }, + .name = MP_QSTR_board, + .print = pin_named_pins_obj_print, + .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict, +}; + +const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { + mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins); + mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP); + if (named_elem != NULL && named_elem->value != NULL) { + return named_elem->value; + } + return NULL; +} + +const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit) { + const pin_af_obj_t *af = pin->af; + for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { + if (af->fn == fn && af->unit == unit) { + return af; + } + } + return NULL; +} + +const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx) { + const pin_af_obj_t *af = pin->af; + for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { + if (af->idx == af_idx) { + return af; + } + } + return NULL; +} + +/* unused +const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name) { + const pin_af_obj_t *af = pin->af; + for (mp_uint_t i = 0; i < pin->num_af; i++, af++) { + if (strcmp(name, qstr_str(af->name)) == 0) { + return af; + } + } + return NULL; +} +*/ diff --git a/nrf5/sdk/help_sd.h b/nrf5/sdk/help_sd.h index ff6c1ad044..f6d5ef6565 100644 --- a/nrf5/sdk/help_sd.h +++ b/nrf5/sdk/help_sd.h @@ -27,6 +27,10 @@ #ifndef HELP_SD_H__ #define HELP_SD_H__ +#include "nrf5_sdk_conf.h" + +#if MICROPY_PY_BLE + #define HELP_TEXT_SD \ "If compiled with SD= the additional commands are\n" \ "available:\n" \ @@ -35,4 +39,8 @@ " ble.advertise() -- Start advertising Eddystone beacon\n" \ "\n" +#else +#define HELP_TEXT_SD +#endif // MICROPY_PY_BLE + #endif diff --git a/nrf5/sdk/iot_0.9.0/build.mk b/nrf5/sdk/iot_0.9.0/build.mk new file mode 100644 index 0000000000..763aa5a424 --- /dev/null +++ b/nrf5/sdk/iot_0.9.0/build.mk @@ -0,0 +1,118 @@ +# this file's folder +SDK_DIR := $(SDK_ROOT) + +# -D in CFLAGS +DEFINES += __HEAP_SIZE=0 +DEFINES += BLE_STACK_SUPPORT_REQD +DEFINES += CONFIG_GPIO_AS_PINRESET +DEFINES += NRF52 +DEFINES += NRF52_PAN_12 +DEFINES += NRF52_PAN_15 +DEFINES += NRF52_PAN_20 +DEFINES += NRF52_PAN_30 +DEFINES += NRF52_PAN_31 +DEFINES += NRF52_PAN_36 +DEFINES += NRF52_PAN_51 +DEFINES += NRF52_PAN_53 +DEFINES += NRF52_PAN_54 +DEFINES += NRF52_PAN_55 +DEFINES += NRF52_PAN_58 +DEFINES += NRF52_PAN_62 +DEFINES += NRF52_PAN_63 +DEFINES += NRF52_PAN_64 +DEFINES += s1xx +DEFINES += SOFTDEVICE_PRESENT +DEFINES += SWI_DISABLE0 +DEFINES += NRF_SD_BLE_API_VERSION=3 +DEFINES += PEER_MANAGER_ENABLED=1 +DEFINES += FDS_ENABLED=1 +DEFINES += LWIP_DEBUG=0 + +# nordic SDK C sources (relative path) +SDK_SRC_C += \ + components/ble/common/ble_advdata.c \ + components/ble/common/ble_conn_params.c \ + components/ble/common/ble_srv_common.c \ + components/libraries/fifo/app_fifo.c \ + components/libraries/timer/app_timer.c \ + components/libraries/util/app_util_platform.c \ + components/softdevice/common/softdevice_handler/softdevice_handler.c \ + components/drivers_nrf/clock/nrf_drv_clock.c \ + components/libraries/util/app_error.c \ + components/drivers_nrf/common/nrf_drv_common.c \ + components/libraries/mem_manager/mem_manager.c \ + components/libraries/trace/app_trace.c \ + components/iot/context_manager/iot_context_manager.c \ + components/iot/iot_timer/iot_timer.c \ + external/lwip/src/core/def.c \ + external/lwip/src/core/dhcp.c \ + external/lwip/src/core/ipv6/dhcp6.c \ + external/lwip/src/core/dns.c \ + external/lwip/src/core/ipv4/icmp.c \ + external/lwip/src/core/ipv6/icmp6.c \ + external/lwip/src/core/ipv6/inet6.c \ + external/lwip/src/core/inet_chksum.c \ + external/lwip/src/core/init.c \ + external/lwip/src/core/ipv4/ip4.c \ + external/lwip/src/core/ipv4/ip4_addr.c \ + external/lwip/src/core/ipv6/ip6.c \ + external/lwip/src/core/ipv6/ip6_addr.c \ + external/lwip/src/core/memp.c \ + external/lwip/src/core/ipv6/mld6.c \ + external/lwip/src/core/ipv6/nd6.c \ + external/lwip/src/core/netif.c \ + external/lwip/src/port/nrf_platform_port.c \ + external/lwip/src/core/pbuf.c \ + external/lwip/src/core/raw.c \ + external/lwip/src/core/sys.c \ + external/lwip/src/core/tcp.c \ + external/lwip/src/core/tcp_in.c \ + external/lwip/src/core/tcp_out.c \ + external/lwip/src/core/timers.c \ + external/lwip/src/core/udp.c \ + +# include source folders (sort removes duplicates) +SDK_INC_DIRS += $(sort $(dir $(SDK_SRC_C))) +# nrf_drv_config.h +SDK_INC_DIRS += components/drivers_nrf/config +# app_util.h +SDK_INC_DIRS += components/libraries/util +# nrf_log.h +SDK_INC_DIRS += components/libraries/log/ +# nrf_log_internal.h +SDK_INC_DIRS += components/libraries/log/src +# nrf_clock.h +SDK_INC_DIRS += components/drivers_nrf/hal +# nrf_drv_common.h +SDK_INC_DIRS += components/drivers_nrf/common +# nrf_delay.h +SDK_INC_DIRS += components/drivers_nrf/delay +# ble_6lowpan.h +SDK_INC_DIRS += components/iot/ble_6lowpan +# ble_ipsp.h +SDK_INC_DIRS += components/iot/ble_ipsp +# iot_defines.h +SDK_INC_DIRS += components/iot/common +# SDK lwip includes +SDK_INC_DIRS += external/lwip/src/port/arch +SDK_INC_DIRS += external/lwip/src/include +SDK_INC_DIRS += external/lwip/src/include/netif +SDK_INC_DIRS += external/lwip/src/port +SDK_INC_DIRS += external/lwip/src/include/lwip + +LIBS += $(SDK_ROOT)/components/iot/ble_6lowpan/lib/ble_6lowpan.a + +CFLAGS += $(patsubst %,-D%,${DEFINES}) + +# include full path +INC += $(patsubst %,-I${SDK_DIR}/%, ${SDK_INC_DIRS}) + +# additional SDK source files +SRC_C += $(addprefix ${SDK_ROOT}/, $(SDK_SRC_C)) + +# Wrappers +SRC_C += \ + $(SDK_MODULES_PATH)sdkhelp.c \ + $(SDK_MODULES_PATH)modnwble6lowpan.c \ + + diff --git a/nrf5/sdk/iot_0.9.0/modnwble6lowpan.c b/nrf5/sdk/iot_0.9.0/modnwble6lowpan.c new file mode 100644 index 0000000000..80f1b81e0a --- /dev/null +++ b/nrf5/sdk/iot_0.9.0/modnwble6lowpan.c @@ -0,0 +1,217 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 "nrf5_sdk_conf.h" + +#if MICROPY_PY_BLE_6LOWPAN + +#include "lwip/ip6_addr.h" +#include "lwip/udp.h" + +#ifdef MAX +#undef MAX +#endif + +#ifdef MIN +#undef MIN +#endif + +#include +#include +#include + +#include "py/nlr.h" +#include "py/objlist.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "netutils.h" +#include "modnetwork.h" +#include "pin.h" +#include "genhdr/pins.h" +#include "lwip/ip6_addr.h" +#include "lwip/udp.h" + +/// \moduleref network + +typedef struct _ble_6lowpan_obj_t { + mp_obj_base_t base; +} ble_6lowpan_obj_t; + +STATIC ble_6lowpan_obj_t ble_6lowpan_obj; + + + +STATIC int ble_6lowpan_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { + return MP_ENOENT; +} + +STATIC int ble_6lowpan_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC void ble_6lowpan_socket_close(mod_network_socket_obj_t *socket) { +} + +STATIC int ble_6lowpan_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { + err_t err; + socket->p_socket = udp_new_ip6(); + if (socket->p_socket) { + + + err = udp_bind_ip6(socket->p_socket, ip, port); + if (err != ERR_OK) { + *_errno = err; + udp_remove(socket->p_socket); + } + } + + return 0; +} + +STATIC int ble_6lowpan_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC int ble_6lowpan_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC int ble_6lowpan_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC mp_uint_t ble_6lowpan_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC mp_uint_t ble_6lowpan_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +#include "netutils/netutils.h" + +STATIC mp_uint_t ble_6lowpan_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { + + struct pbuf * lwip_buffer = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + memcpy(lwip_buffer->payload, buf, len); + + printf("Sendto\n"); + + err_t err = udp_sendto_ip6(socket->p_socket, + lwip_buffer, + ip, + port); + + printf("dest: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + ip[0], ip[1], ip[2], ip[3], + ip[4], ip[5], ip[6], ip[7], + ip[8], ip[9], ip[10], ip[11], + ip[12], ip[13], ip[14], ip[15]); + + printf("port: %x\n", port); + printf("len: %d\n", len); + + if (err != ERR_OK) { + *_errno = err; + } + + return 0; +} + +STATIC mp_uint_t ble_6lowpan_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC int ble_6lowpan_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC int ble_6lowpan_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +STATIC int ble_6lowpan_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { + *_errno = MP_EINVAL; + return -1; +} + +#include "sdkhelp.h" + +/******************************************************************************/ +// Micro Python bindings + +/// \classmethod \constructor +/// Create and return a BLE 6LoWPAN object. +STATIC mp_obj_t ble_6lowpan_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + // check arguments + //mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // init the BLE 6lowpan object + ble_6lowpan_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_ble_6lowpan; + + // blocking call to wait for connection with peer. + transport_init(); + + // regiser NIC with network module + mod_network_register_nic(&ble_6lowpan_obj); + + // return BLE 6LoWPAN object + return &ble_6lowpan_obj; +} + +const mod_network_nic_type_t mod_network_nic_type_ble_6lowpan = { + .base = { + { &mp_type_type }, + .name = MP_QSTR_BLE6LOWPAN, + .make_new = ble_6lowpan_make_new, + }, + .gethostbyname = ble_6lowpan_gethostbyname, + .socket = ble_6lowpan_socket_socket, + .close = ble_6lowpan_socket_close, + .bind = ble_6lowpan_socket_bind, + .listen = ble_6lowpan_socket_listen, + .accept = ble_6lowpan_socket_accept, + .connect = ble_6lowpan_socket_connect, + .send = ble_6lowpan_socket_send, + .recv = ble_6lowpan_socket_recv, + .sendto = ble_6lowpan_socket_sendto, + .recvfrom = ble_6lowpan_socket_recvfrom, + .setsockopt = ble_6lowpan_socket_setsockopt, + .settimeout = ble_6lowpan_socket_settimeout, + .ioctl = ble_6lowpan_socket_ioctl, +}; + +#endif diff --git a/nrf5/sdk/iot_0.9.0/sdk.mk b/nrf5/sdk/iot_0.9.0/sdk.mk new file mode 100644 index 0000000000..81be3000cc --- /dev/null +++ b/nrf5/sdk/iot_0.9.0/sdk.mk @@ -0,0 +1,12 @@ + +INC += -I./$(SDK_MODULES_PATH) + +include $(SDK_MODULES_PATH)build.mk + +INC += -I$(SDK_ROOT)components/softdevice/s1xx_iot/headers +INC += -I$(SDK_ROOT)components/softdevice/s1xx_iot/headers/nrf52 +CFLAGS += -DBLUETOOTH_SD=100 +CFLAGS += -DBLUETOOTH_SD_DEBUG=1 + +# softdevice .hex file +SOFTDEV_HEX ?= $(lastword $(wildcard $(SDK_ROOT)/components/softdevice/s1xx_iot/hex/s1xx*softdevice.hex)) diff --git a/nrf5/sdk/iot_0.9.0/sdk_config.h b/nrf5/sdk/iot_0.9.0/sdk_config.h new file mode 100644 index 0000000000..fa851f540f --- /dev/null +++ b/nrf5/sdk/iot_0.9.0/sdk_config.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 SDK_CONFIG_H__ +#define SDK_CONFIG_H__ + +#define MEMORY_MANAGER_SMALL_BLOCK_COUNT (8) +#define MEMORY_MANAGER_SMALL_BLOCK_SIZE (128) +#define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT (4) +#define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE (256) +#define MEMORY_MANAGER_LARGE_BLOCK_COUNT (3) +#define MEMORY_MANAGER_LARGE_BLOCK_SIZE (1024) +#define MEM_MANAGER_ENABLE_LOGS (0) +#define MEM_MANAGER_DISABLE_API_PARAM_CHECK (0) +#define IOT_CONTEXT_MANAGER_ENABLE_LOGS (0) +#define IOT_CONTEXT_MANAGER_DISABLE_API_PARAM_CHECK (0) +#define IOT_CONTEXT_MANAGER_MAX_CONTEXTS (16) +#define IOT_CONTEXT_MANAGER_MAX_TABLES (1) +#define NRF_LWIP_DRIVER_ENABLE_LOGS (0) +#define IOT_TIMER_RESOLUTION_IN_MS (100) +#define IOT_TIMER_DISABLE_API_PARAM_CHECK (0) + +#endif // SDK_CONFIG_H__ diff --git a/nrf5/sdk/iot_0.9.0/sdkhelp.c b/nrf5/sdk/iot_0.9.0/sdkhelp.c new file mode 100644 index 0000000000..f3b1bf7991 --- /dev/null +++ b/nrf5/sdk/iot_0.9.0/sdkhelp.c @@ -0,0 +1,256 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 + +#include "softdevice_handler.h" +#include "app_trace.h" +#include "app_timer_appsh.h" +#include "ble_advdata.h" +#include "ble_srv_common.h" +#include "ble_ipsp.h" +#include "ble_6lowpan.h" +#include "mem_manager.h" +#include "app_trace.h" +#include "lwip/init.h" +#include "lwip/inet6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/timers.h" +#include "nrf_platform_port.h" +#include "app_util_platform.h" +#include "ble_gap.h" +#include "sdkhelp.h" +#include "mpconfigport.h" +#include "app_timer_appsh.h" +#include "iot_timer.h" + +#include "iot_defines.h" + +eui64_t eui64_local_iid; + +bool m_interface_up = false; + +void nrf_driver_interface_up(void) +{ + // sys_check_timeouts(); + m_interface_up = true; +} + +void nrf_driver_interface_down(void) +{ + m_interface_up = false; +} + +#define DEVICE_NAME "MPY_IPv6" +#define APP_ADV_TIMEOUT (0) // disable timeout +#define APP_ADV_ADV_INTERVAL MSEC_TO_UNITS(333, UNIT_0_625_MS) +#define IOT_TIMER_RESOLUTION_IN_MS 100 +#define LWIP_SYS_TICK_MS 100 +#define APP_TIMER_PRESCALER 31 // Value of the RTC1 PRESCALER register. */ +#define APP_TIMER_MAX_TIMERS 1 +#define APP_TIMER_OP_QUEUE_SIZE 5 + +APP_TIMER_DEF(m_iot_timer_tick_src_id); + +static ble_gap_adv_params_t m_adv_params; +static ble_gap_addr_t m_local_ble_addr; + +static void app_lwip_time_tick(iot_timer_time_in_ms_t wall_clock_value) +{ + sys_check_timeouts(); +} + +static void iot_timer_init(void) +{ + uint32_t err_code; + + static const iot_timer_client_t list_of_clients[] = + { + {app_lwip_time_tick, LWIP_SYS_TICK_MS} + }; + + // The list of IoT Timer clients is declared as a constant. + static const iot_timer_clients_list_t iot_timer_clients = + { + (sizeof(list_of_clients) / sizeof(iot_timer_client_t)), + &(list_of_clients[0]), + }; + + // Passing the list of clients to the IoT Timer module. + err_code = iot_timer_client_list_set(&iot_timer_clients); + APP_ERROR_CHECK(err_code); + + // Starting the app timer instance that is the tick source for the IoT Timer. + err_code = app_timer_start(m_iot_timer_tick_src_id, \ + APP_TIMER_TICKS(IOT_TIMER_RESOLUTION_IN_MS, APP_TIMER_PRESCALER), \ + NULL); + APP_ERROR_CHECK(err_code); +} + +static void iot_timer_tick_callback(void * p_context) +{ + UNUSED_VARIABLE(p_context); + uint32_t err_code = iot_timer_update(); + APP_ERROR_CHECK(err_code); +} + +static void timers_init(void) +{ + uint32_t err_code; + + // Initialize timer module, making it use the scheduler + APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false); + + // Create a sys timer. + err_code = app_timer_create(&m_iot_timer_tick_src_id, + APP_TIMER_MODE_REPEATED, + iot_timer_tick_callback); + APP_ERROR_CHECK(err_code); +} + +static void on_ble_evt(ble_evt_t * p_ble_evt) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + break; + case BLE_GAP_EVT_DISCONNECTED: + sd_ble_gap_adv_start(&m_adv_params); + break; + default: + break; + } +} + +static void ble_evt_dispatch(ble_evt_t * p_ble_evt) +{ + ble_ipsp_evt_handler(p_ble_evt); + on_ble_evt(p_ble_evt); +} + +void transport_init(void) { + + // if interface is already up, return + if (m_interface_up) { + return; + } + + uint32_t err_code; + + timers_init(); + + // Initialize the SoftDevice handler module. + SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false); + printf("Softdevice init done\n"); + + // Enable BLE stack. + ble_enable_params_t ble_enable_params; + memset(&ble_enable_params, 0x00, sizeof(ble_enable_params)); + ble_enable_params.gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT; + ble_enable_params.gatts_enable_params.service_changed = false; + err_code = sd_ble_enable(&ble_enable_params); + printf("Softdevice enable:" UINT_FMT "\n", (uint16_t)err_code); + + // Register with the SoftDevice handler module for BLE events. + err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); + printf("Softdevice evt handler set:" UINT_FMT "\n", (uint16_t)err_code); + APP_ERROR_CHECK(err_code); + + ble_advdata_t advdata; + uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, + (const uint8_t *)DEVICE_NAME, + strlen(DEVICE_NAME)); + printf("Device name set:" UINT_FMT "\n", (uint16_t)err_code); + APP_ERROR_CHECK(err_code); + + err_code = sd_ble_gap_address_get(&m_local_ble_addr); + APP_ERROR_CHECK(err_code); + printf("GAP address get:" UINT_FMT "\n", (uint16_t)err_code); + + m_local_ble_addr.addr[5] = 0x00; + m_local_ble_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + + err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &m_local_ble_addr); + APP_ERROR_CHECK(err_code); + printf("GAP address set:" UINT_FMT "\n", (uint16_t)err_code); + IPV6_EUI64_CREATE_FROM_EUI48(eui64_local_iid.identifier, + m_local_ble_addr.addr, + m_local_ble_addr.addr_type); + + ble_uuid_t adv_uuids[] = + { + {BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE} + }; + + // build and set advertising data + memset(&advdata, 0, sizeof(advdata)); + + advdata.name_type = BLE_ADVDATA_FULL_NAME; + advdata.flags = flags; + advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]); + advdata.uuids_complete.p_uuids = adv_uuids; + + err_code = ble_advdata_set(&advdata, NULL); + APP_ERROR_CHECK(err_code); + printf("Adv data set:" UINT_FMT "\n", (uint16_t)err_code); + // initialize advertising parameters (used when starting advertising) + memset(&m_adv_params, 0, sizeof(m_adv_params)); + + m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; + m_adv_params.p_peer_addr = NULL; // undirected advertisement + m_adv_params.fp = BLE_GAP_ADV_FP_ANY; + m_adv_params.interval = APP_ADV_ADV_INTERVAL; + m_adv_params.timeout = APP_ADV_TIMEOUT; + + // initialize memory manager + err_code = nrf_mem_init(); + APP_ERROR_CHECK(err_code); + printf("mem init:" UINT_FMT "\n", (uint16_t)err_code); + // initialize lwip stack driver + err_code = nrf_driver_init(); + APP_ERROR_CHECK(err_code); + printf("driver init:" UINT_FMT "\n", (uint16_t)err_code); + // initialize lwip stack + lwip_init(); + printf("lwip init:" UINT_FMT "\n", (uint16_t)err_code); + + iot_timer_init(); + + printf("Starting adv:" UINT_FMT "\n", (uint16_t)err_code); + err_code = sd_ble_gap_adv_start(&m_adv_params); + + while (!m_interface_up) { + ; + } +} + diff --git a/nrf5/sdk/iot_0.9.0/sdkhelp.h b/nrf5/sdk/iot_0.9.0/sdkhelp.h new file mode 100644 index 0000000000..c3e8a122fb --- /dev/null +++ b/nrf5/sdk/iot_0.9.0/sdkhelp.h @@ -0,0 +1,27 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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. + */ + +void transport_init(void); diff --git a/nrf5/sdk/modble.c b/nrf5/sdk/modble.c index 80a113e077..07655b0f83 100644 --- a/nrf5/sdk/modble.c +++ b/nrf5/sdk/modble.c @@ -28,6 +28,8 @@ #include #include "py/runtime.h" +#if MICROPY_PY_BLE + #include "led.h" #include "mpconfigboard.h" #include "softdevice.h" @@ -36,7 +38,7 @@ /// Enable BLE softdevice. mp_obj_t ble_obj_enable(void) { printf("SoftDevice enabled\n"); - uint32_t err_code = softdevice_enable(); + uint32_t err_code = sd_enable(); if (err_code < 0) { // TODO: raise exception. } @@ -46,14 +48,14 @@ mp_obj_t ble_obj_enable(void) { /// \method disable() /// Disable BLE softdevice. mp_obj_t ble_obj_disable(void) { - softdevice_disable(); + sd_disable(); return mp_const_none; } /// \method enabled() /// Get state of whether the softdevice is enabled or not. mp_obj_t ble_obj_enabled(void) { - uint8_t is_enabled = softdevice_enabled(); + uint8_t is_enabled = sd_enabled(); mp_int_t enabled = is_enabled; return MP_OBJ_NEW_SMALL_INT(enabled); } @@ -61,14 +63,14 @@ mp_obj_t ble_obj_enabled(void) { /// \method address_print() /// Print device address. mp_obj_t ble_obj_address_print(void) { - softdevice_address_get(); + sd_address_get(); return mp_const_none; } /// \method advertise() /// Bluetooth Low Energy advertise. mp_obj_t ble_obj_advertise(void) { - softdevice_advertise(); + sd_advertise(); return mp_const_none; } @@ -94,3 +96,5 @@ const mp_obj_module_t ble_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&ble_module_globals, }; + +#endif // MICROPY_PY_BLE diff --git a/nrf5/sdk/nrf5_sdk_conf.h b/nrf5/sdk/nrf5_sdk_conf.h new file mode 100644 index 0000000000..ab256be1f3 --- /dev/null +++ b/nrf5/sdk/nrf5_sdk_conf.h @@ -0,0 +1,40 @@ +#ifndef NRF_SDK_CONF_H__ +#define NRF_SDK_CONF_H__ + +// SD specific configurations. + +#if (BLUETOOTH_SD == 100) + +#define MICROPY_PY_BLE (1) +#define MICROPY_PY_BLE_6LOWPAN (1) +#define MICROPY_PY_USOCKET (1) +#define MICROPY_PY_NETWORK (1) + +#elif (BLUETOOTH_SD == 110) + +#define MICROPY_PY_BLE (1) + +#elif (BLUETOOTH_SD == 132) + +#define MICROPY_PY_BLE (1) +#define MICROPY_PY_BLE_NUS (1) + +#else +#error "SD not supported" +#endif + +// Default defines. + +#ifndef MICROPY_PY_BLE_6LOWPAN +#define MICROPY_PY_BLE_6LOWPAN (0) +#endif + +#ifndef MICROPY_PY_BLE +#define MICROPY_PY_BLE (0) +#endif + +#ifndef MICROPY_PY_BLE_NUS +#define MICROPY_PY_BLE_NUS (0) +#endif + +#endif diff --git a/nrf5/sdk/sdk_10.0.0/sdk.mk b/nrf5/sdk/sdk_10.0.0/sdk.mk new file mode 100644 index 0000000000..a5097eabc9 --- /dev/null +++ b/nrf5/sdk/sdk_10.0.0/sdk.mk @@ -0,0 +1,17 @@ + +INC += -I./$(SDK_MODULES_PATH) + +# Nothing to build from SDK. +# include $(SDK_MODULES_PATH)build.mk + +INC += -I$(SDK_ROOT)components/softdevice/$(SD)/headers +CFLAGS += -DBLUETOOTH_SD_DEBUG=1 + +# softdevice .hex file +ifeq ($(SD), s110) +CFLAGS += -DBLUETOOTH_SD=110 +SOFTDEV_HEX ?= $(lastword $(wildcard $(SDK_ROOT)/components/softdevice/s110/hex/s110_nrf51_8.0.0_softdevice.hex)) +else ifeq ($(SD), s120) +CFLAGS += -DBLUETOOTH_SD=120 +SOFTDEV_HEX ?= $(lastword $(wildcard $(SDK_ROOT)/components/softdevice/s120/hex/s120_nrf51_2.1.0_softdevice.hex)) +endif \ No newline at end of file diff --git a/nrf5/sdk/sdk_12.1.0/build.mk b/nrf5/sdk/sdk_12.1.0/build.mk new file mode 100644 index 0000000000..e14ec76448 --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/build.mk @@ -0,0 +1,103 @@ +# this file's folder +SDK_DIR := $(SDK_ROOT) + +# -D in CFLAGS +DEFINES += __HEAP_SIZE=0 +DEFINES += BLE_STACK_SUPPORT_REQD +DEFINES += CONFIG_GPIO_AS_PINRESET +DEFINES += NRF52 +DEFINES += NRF52_PAN_12 +DEFINES += NRF52_PAN_15 +DEFINES += NRF52_PAN_20 +DEFINES += NRF52_PAN_30 +DEFINES += NRF52_PAN_31 +DEFINES += NRF52_PAN_36 +DEFINES += NRF52_PAN_51 +DEFINES += NRF52_PAN_53 +DEFINES += NRF52_PAN_54 +DEFINES += NRF52_PAN_55 +DEFINES += NRF52_PAN_58 +DEFINES += NRF52_PAN_62 +DEFINES += NRF52_PAN_63 +DEFINES += NRF52_PAN_64 +DEFINES += S132 +DEFINES += SOFTDEVICE_PRESENT +DEFINES += SWI_DISABLE0 +DEFINES += NRF_SD_BLE_API_VERSION=3 +DEFINES += PEER_MANAGER_ENABLED=1 +DEFINES += FDS_ENABLED=1 + +# nordic SDK C sources (relative path) +SDK_SRC_C += \ + components/ble/ble_advertising/ble_advertising.c \ + components/ble/ble_services/ble_nus/ble_nus.c \ + components/ble/common/ble_advdata.c \ + components/ble/common/ble_conn_params.c \ + components/ble/common/ble_conn_state.c \ + components/ble/common/ble_srv_common.c \ + components/ble/peer_manager/gatt_cache_manager.c \ + components/ble/peer_manager/gatts_cache_manager.c \ + components/ble/peer_manager/id_manager.c \ + components/ble/peer_manager/peer_data.c \ + components/ble/peer_manager/peer_data_storage.c \ + components/ble/peer_manager/peer_database.c \ + components/ble/peer_manager/peer_id.c \ + components/ble/peer_manager/peer_manager.c \ + components/ble/peer_manager/pm_buffer.c \ + components/ble/peer_manager/pm_mutex.c \ + components/ble/peer_manager/security_dispatcher.c \ + components/ble/peer_manager/security_manager.c \ + components/libraries/fds/fds.c \ + components/libraries/fifo/app_fifo.c \ + components/libraries/fstorage/fstorage.c \ + components/libraries/timer/app_timer.c \ + components/libraries/util/app_util_platform.c \ + components/libraries/util/sdk_mapped_flags.c \ + components/softdevice/common/softdevice_handler/softdevice_handler.c \ + components/drivers_nrf/clock/nrf_drv_clock.c \ + components/libraries/util/app_error.c \ + components/libraries/util/app_error_weak.c \ + components/drivers_nrf/common/nrf_drv_common.c + +# include source folders (sort removes duplicates) +SDK_INC_DIRS += $(sort $(dir $(SDK_SRC_C))) +#SDK_INC_DIRS += $(sort $(${SDK_ROOT} ${SDK_SRC_C})) +# ble.h +SDK_INC_DIRS += components/softdevice/s132/headers +# nrf52.h compiler_abstraction.h +SDK_INC_DIRS += components/device +# core_cm4.h +SDK_INC_DIRS += components/toolchain/CMSIS/Include +# section_vars.h +SDK_INC_DIRS += components/libraries/experimental_section_vars +# fstorage_config.h +SDK_INC_DIRS += components/libraries/fstorage/config +# nrf_drv_config.h +SDK_INC_DIRS += components/drivers_nrf/config +# app_util.h +SDK_INC_DIRS += components/libraries/util +# fds_config.h +SDK_INC_DIRS += components/libraries/fds/config +# nrf_log.h +SDK_INC_DIRS += components/libraries/log/ +# nrf_log_internal.h +SDK_INC_DIRS += components/libraries/log/src +# nrf_clock.h +SDK_INC_DIRS += components/drivers_nrf/hal +# nrf_drv_common.h +SDK_INC_DIRS += components/drivers_nrf/common +# nrf_delay.h +SDK_INC_DIRS += components/drivers_nrf/delay + +CFLAGS += $(patsubst %,-D%,${DEFINES}) + +# include full path +INC += $(patsubst %,-I${SDK_DIR}/%, ${SDK_INC_DIRS}) + +# additional SDK source files +SRC_C += $(addprefix ${SDK_ROOT}/, $(SDK_SRC_C)) + +# Wrappers +SRC_C += \ + $(SDK_MODULES_PATH)nrf52_ble.c \ + diff --git a/nrf5/sdk/sdk_12.1.0/nrf52832_aa_s132.ld b/nrf5/sdk/sdk_12.1.0/nrf52832_aa_s132.ld new file mode 100644 index 0000000000..094a8c45ca --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/nrf52832_aa_s132.ld @@ -0,0 +1,40 @@ +/* + GNU linker script for NRF52 w/ s132 3.0.0 SoftDevice +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x080000 /* entire flash, 512 KiB */ + FLASH_ISR (rx) : ORIGIN = 0x0001f000, LENGTH = 0x001000 /* sector 0, 4 KiB */ + FLASH_TEXT (rx) : ORIGIN = 0x00020000, LENGTH = 0x060000 /* 396 KiB */ + RAM (xrw) : ORIGIN = 0x200039c0, LENGTH = 0x0c640 /* 57.89 KiB, give 8KiB headroom for softdevice */ +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 8K; +_minimum_heap_size = 8K; + +/* top end of the stack */ + +/*_stack_end = ORIGIN(RAM) + LENGTH(RAM);*/ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +/* RAM extents for the garbage collector */ +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_end = 0x200069c0; /* tunable */ + +__data_start__ = ORIGIN(RAM); + +SECTIONS +{ + .fs_data : + { + PROVIDE(__start_fs_data = .); + KEEP(*(.fs_data)) + PROVIDE(__stop_fs_data = .); + } > RAM +} INSERT AFTER .data; + + +INCLUDE "boards/common.ld" diff --git a/nrf5/sdk/sdk_12.1.0/nrf52_app_error.c b/nrf5/sdk/sdk_12.1.0/nrf52_app_error.c new file mode 100644 index 0000000000..5775a3e3a3 --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/nrf52_app_error.c @@ -0,0 +1,19 @@ +#include +#include "app_error.h" + + +void +#ifdef DEBUG +app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) +#else +app_error_handler_bare(ret_code_t error_code) +#endif +{ +#ifdef DEBUG + for (;;) { + /* FOREVER */ + } +#else + NVIC_SystemReset(); +#endif +} diff --git a/nrf5/sdk/sdk_12.1.0/nrf52_ble.c b/nrf5/sdk/sdk_12.1.0/nrf52_ble.c new file mode 100644 index 0000000000..abaec5eac4 --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/nrf52_ble.c @@ -0,0 +1,487 @@ +#include "nrf52_ble.h" +#include "nrf52_board.h" + +#include "sdk_config.h" +#include "app_error.h" +#include "app_fifo.h" +#include "app_timer.h" +#include "ble_advertising.h" +#include "ble_conn_params.h" +#include "ble_conn_state.h" +#include "ble_hci.h" +#include "ble_nus.h" +#include "ble_srv_common.h" +#include "fds.h" +#include "fstorage.h" +#include "peer_manager.h" +#include "softdevice_handler.h" + +#define CENTRAL_LINK_COUNT 0 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/ +#define PERIPHERAL_LINK_COUNT 1 /**< Number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/ + +#define DEVICE_NAME "micropython" + +#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.02 seconds). */ +#define MAX_CONN_INTERVAL MSEC_TO_UNITS(200, UNIT_1_25_MS) /**< Maximum acceptable connection interval (0.2 second). */ +#define SLAVE_LATENCY 0 /**< Slave latency. */ +#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(3000, UNIT_10_MS) /**< Connection supervisory timeout (3 seconds). */ + +#define APP_ADV_INTERVAL MSEC_TO_UNITS(25, UNIT_0_625_MS) +#define APP_ADV_TIMEOUT_IN_SECONDS 180 + +#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */ +#define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */ + +#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000, APP_TIMER_PRESCALER) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ +#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000, APP_TIMER_PRESCALER) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ +#define MAX_CONN_PARAMS_UPDATE_COUNT 3 + +#define SEC_PARAM_BOND 1 /**< Perform bonding. */ +#define SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */ +#define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */ +#define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ +#define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ +#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ +#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ +#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ + +#define NUS_RX_FIFO_BUFFER_SIZE 64 + +static ble_uuid_t m_adv_uuids[] = {{BLE_UUID_NUS_SERVICE, 0}}; /**< Universally unique service identifiers. */ + +static ble_nus_t m_nus; +static app_fifo_t m_nus_rx_fifo; +static uint8_t m_nus_rx_fifo_buffer[NUS_RX_FIFO_BUFFER_SIZE]; + + +static void +ble_evt_dispatch(ble_evt_t * p_ble_evt) +{ + ble_conn_state_on_ble_evt(p_ble_evt); + pm_on_ble_evt(p_ble_evt); + ble_conn_params_on_ble_evt(p_ble_evt); + ble_advertising_on_ble_evt(p_ble_evt); + ble_nus_on_ble_evt(&m_nus, p_ble_evt); +} + +static void +sys_evt_dispatch(uint32_t sys_evt) +{ + fs_sys_event_handler(sys_evt); + ble_advertising_on_sys_evt(sys_evt); +} + +static void +ble_stack_init(void) +{ + nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; + + // Initialize the SoftDevice handler module. + SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL); + + ble_enable_params_t ble_enable_params; + uint32_t err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT, + PERIPHERAL_LINK_COUNT, + &ble_enable_params); + APP_ERROR_CHECK(err_code); + + //Check the ram settings against the used number of links + CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT); + + // Enable BLE stack. + err_code = softdevice_enable(&ble_enable_params); + APP_ERROR_CHECK(err_code); + + // Register with the SoftDevice handler module for BLE events. + err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); + APP_ERROR_CHECK(err_code); + + // Register with the SoftDevice handler module for BLE events. + err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for the GAP initialization. + * + * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the + * device including the device name, appearance, and the preferred connection parameters. + */ +static void +gap_params_init(void) +{ + uint32_t err_code; + ble_gap_conn_params_t gap_conn_params; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, + (const uint8_t *)DEVICE_NAME, + strlen(DEVICE_NAME)); + APP_ERROR_CHECK(err_code); + + err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN); + APP_ERROR_CHECK(err_code); + + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); + + gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; + gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + + err_code = sd_ble_gap_ppcp_set(&gap_conn_params); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling advertising events. + * + * @details This function will be called for advertising events which are passed to the application. + * + * @param[in] ble_adv_evt Advertising event. + */ +static void +on_adv_evt(ble_adv_evt_t ble_adv_evt) +{ + switch (ble_adv_evt) + { + case BLE_ADV_EVT_FAST: + break; + case BLE_ADV_EVT_IDLE: + break; + default: + break; + } +} + +/**@brief Function for initializing the Advertising functionality. + */ +static void +advertising_init(void) +{ + uint32_t err_code; + ble_advdata_t advdata; + + // Build advertising data struct to pass into @ref ble_advertising_init. + memset(&advdata, 0, sizeof(advdata)); + + advdata.name_type = BLE_ADVDATA_FULL_NAME; + advdata.include_appearance = true; + advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); + advdata.uuids_complete.p_uuids = m_adv_uuids; + + ble_adv_modes_config_t options = {0}; + options.ble_adv_fast_enabled = true; + options.ble_adv_fast_interval = APP_ADV_INTERVAL; + options.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS; + + err_code = ble_advertising_init(&advdata, NULL, &options, on_adv_evt, NULL); + APP_ERROR_CHECK(err_code); +} + +static void +nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length) +{ + for (uint32_t i = 0; i < length; i++) { + // XXX + app_fifo_put(&m_nus_rx_fifo, p_data[i]); + } +} + +static void +services_init(void) +{ + uint32_t err_code; + ble_nus_init_t nus_init = {0}; + nus_init.data_handler = nus_data_handler; + err_code = ble_nus_init(&m_nus, &nus_init); + APP_ERROR_CHECK(err_code); + + m_adv_uuids[0].type = m_nus.uuid_type; + + err_code = app_fifo_init(&m_nus_rx_fifo, m_nus_rx_fifo_buffer, NUS_RX_FIFO_BUFFER_SIZE); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling a Connection Parameters error. + * + * @param[in] nrf_error Error code containing information about what went wrong. + */ +static void conn_params_error_handler(uint32_t nrf_error) +{ + APP_ERROR_HANDLER(nrf_error); +} + +/**@brief Function for initializing the Connection Parameters module. + */ +static void +conn_params_init(void) +{ + uint32_t err_code; + ble_conn_params_init_t cp_init; + + memset(&cp_init, 0, sizeof(cp_init)); + + cp_init.p_conn_params = NULL; + cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; + cp_init.disconnect_on_fail = true; + cp_init.evt_handler = NULL; + cp_init.error_handler = conn_params_error_handler; + + err_code = ble_conn_params_init(&cp_init); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for starting advertising. + */ +static void +advertising_start(void) +{ + uint32_t err_code = ble_advertising_start(BLE_ADV_MODE_FAST); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling Peer Manager events. + * + * @param[in] p_evt Peer Manager event. + */ +static void +pm_evt_handler(pm_evt_t const * p_evt) +{ + ret_code_t err_code; + + switch(p_evt->evt_id) + { + case PM_EVT_BONDED_PEER_CONNECTED: + err_code = pm_peer_rank_highest(p_evt->peer_id); + if (err_code != NRF_ERROR_BUSY) + { + APP_ERROR_CHECK(err_code); + } + break;//PM_EVT_BONDED_PEER_CONNECTED + + case PM_EVT_CONN_SEC_START: + break;//PM_EVT_CONN_SEC_START + + case PM_EVT_CONN_SEC_SUCCEEDED: + { + /* + NRF_LOG_PRINTF_DEBUG("Link secured. Role: %d. conn_handle: %d, Procedure: %d\r\n", + ble_conn_state_role(p_evt->conn_handle), + p_evt->conn_handle, + p_evt->params.conn_sec_succeeded.procedure); + */ + err_code = pm_peer_rank_highest(p_evt->peer_id); + if (err_code != NRF_ERROR_BUSY) + { + APP_ERROR_CHECK(err_code); + } + } + break;//PM_EVT_CONN_SEC_SUCCEEDED + + case PM_EVT_CONN_SEC_FAILED: + { + /** In some cases, when securing fails, it can be restarted directly. Sometimes it can + * be restarted, but only after changing some Security Parameters. Sometimes, it cannot + * be restarted until the link is disconnected and reconnected. Sometimes it is + * impossible, to secure the link, or the peer device does not support it. How to + * handle this error is highly application dependent. */ + switch (p_evt->params.conn_sec_failed.error) + { + case PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING: + // Rebond if one party has lost its keys. + err_code = pm_conn_secure(p_evt->conn_handle, true); + if (err_code != NRF_ERROR_INVALID_STATE) + { + APP_ERROR_CHECK(err_code); + } + break;//PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING + + default: + break; + } + } + break;//PM_EVT_CONN_SEC_FAILED + + case PM_EVT_CONN_SEC_CONFIG_REQ: + { + // Reject pairing request from an already bonded peer. + pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false}; + pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); + } + break;//PM_EVT_CONN_SEC_CONFIG_REQ + + case PM_EVT_STORAGE_FULL: + { + // Run garbage collection on the flash. + err_code = fds_gc(); + if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) + { + // Retry. + } + else + { + APP_ERROR_CHECK(err_code); + } + } + break;//PM_EVT_STORAGE_FULL + + case PM_EVT_ERROR_UNEXPECTED: + // Assert. + APP_ERROR_CHECK(p_evt->params.error_unexpected.error); + break;//PM_EVT_ERROR_UNEXPECTED + + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + break;//PM_EVT_PEER_DATA_UPDATE_SUCCEEDED + + case PM_EVT_PEER_DATA_UPDATE_FAILED: + // Assert. + APP_ERROR_CHECK_BOOL(false); + break;//PM_EVT_PEER_DATA_UPDATE_FAILED + + case PM_EVT_PEER_DELETE_SUCCEEDED: + break;//PM_EVT_PEER_DELETE_SUCCEEDED + + case PM_EVT_PEER_DELETE_FAILED: + // Assert. + APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error); + break;//PM_EVT_PEER_DELETE_FAILED + + case PM_EVT_PEERS_DELETE_SUCCEEDED: + advertising_start(); + break;//PM_EVT_PEERS_DELETE_SUCCEEDED + + case PM_EVT_PEERS_DELETE_FAILED: + // Assert. + APP_ERROR_CHECK(p_evt->params.peers_delete_failed_evt.error); + break;//PM_EVT_PEERS_DELETE_FAILED + + case PM_EVT_LOCAL_DB_CACHE_APPLIED: + break;//PM_EVT_LOCAL_DB_CACHE_APPLIED + + case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED: + // The local database has likely changed, send service changed indications. + pm_local_database_has_changed(); + break;//PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED + + case PM_EVT_SERVICE_CHANGED_IND_SENT: + break;//PM_EVT_SERVICE_CHANGED_IND_SENT + + case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED: + break;//PM_EVT_SERVICE_CHANGED_IND_CONFIRMED + + default: + // No implementation needed. + break; + } +} + +static void +peer_manager_init(bool erase_bonds) +{ + ble_gap_sec_params_t sec_param; + ret_code_t err_code; + + err_code = pm_init(); + APP_ERROR_CHECK(err_code); + + if (erase_bonds) + { + err_code = pm_peers_delete(); + APP_ERROR_CHECK(err_code); + } + + memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); + + // Security parameters to be used for all security procedures. + sec_param.bond = SEC_PARAM_BOND; + sec_param.mitm = SEC_PARAM_MITM; + sec_param.lesc = SEC_PARAM_LESC; + sec_param.keypress = SEC_PARAM_KEYPRESS; + sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; + sec_param.oob = SEC_PARAM_OOB; + sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; + sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; + sec_param.kdist_own.enc = 1; + sec_param.kdist_own.id = 1; + sec_param.kdist_peer.enc = 1; + sec_param.kdist_peer.id = 1; + + err_code = pm_sec_params_set(&sec_param); + APP_ERROR_CHECK(err_code); + + err_code = pm_register(pm_evt_handler); + APP_ERROR_CHECK(err_code); +} + +static void +timers_init() +{ + APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false); +} + +void +nrf52_ble_init(void) +{ + fds_init(); + fs_init(); + timers_init(); + ble_stack_init(); + ble_conn_state_init(); + peer_manager_init(false); + gap_params_init(); + services_init(); + advertising_init(); + conn_params_init(); + + (void)ble_advertising_start(BLE_ADV_MODE_FAST); + + +} + +static void +power_manage() +{ + uint32_t err_code = sd_app_evt_wait(); + APP_ERROR_CHECK(err_code); +} + +// ########################### MP IO functions ########################### + +void +mp_hal_stdout_tx_strn(const char *str, size_t len) +{ + uint32_t err_code; + uint8_t *buf = (uint8_t *)str; + size_t send_len; + + while (len > 0) { + if (len >= BLE_NUS_MAX_DATA_LEN) + send_len = BLE_NUS_MAX_DATA_LEN; + else + send_len = len; + err_code = ble_nus_string_send(&m_nus, buf, send_len); + if (err_code == NRF_SUCCESS) { + len -= send_len; + buf += send_len; + } else if (err_code != NRF_ERROR_INVALID_STATE) { + APP_ERROR_CHECK(err_code); + } + } +} + +int +mp_hal_stdin_rx_chr() +{ + uint8_t byte; + for (;;) { + if (app_fifo_get(&m_nus_rx_fifo, &byte) == NRF_SUCCESS) { + return byte; + } + power_manage(); + } +} diff --git a/nrf5/sdk/sdk_12.1.0/nrf52_ble.h b/nrf5/sdk/sdk_12.1.0/nrf52_ble.h new file mode 100644 index 0000000000..26f9d86400 --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/nrf52_ble.h @@ -0,0 +1,4 @@ +#pragma once + + +void nrf52_ble_init(void); diff --git a/nrf5/sdk/sdk_12.1.0/nrf52_board.h b/nrf5/sdk/sdk_12.1.0/nrf52_board.h new file mode 100644 index 0000000000..8d20b72844 --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/nrf52_board.h @@ -0,0 +1,9 @@ +#pragma once + +#include "nrf_sdm.h" + +// Low frequency clock source to be used by the SoftDevice +#define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ + .rc_ctiv = 0, \ + .rc_temp_ctiv = 0, \ + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} diff --git a/nrf5/sdk/sdk_12.1.0/sdk.mk b/nrf5/sdk/sdk_12.1.0/sdk.mk new file mode 100644 index 0000000000..2c744f013d --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/sdk.mk @@ -0,0 +1,19 @@ + +INC += -I./$(SDK_MODULES_PATH) + +include $(SDK_MODULES_PATH)build.mk + +INC += -I$(SDK_ROOT)components/softdevice/$(SD)/headers +INC += -I$(SDK_ROOT)components/softdevice/$(SD)/headers/$(MCU_VARIANT) +CFLAGS += -DBLUETOOTH_SD_DEBUG=1 + +# softdevice .hex file +ifeq ($(SD), s130) +CFLAGS += -DBLUETOOTH_SD=130 +SOFTDEV_HEX ?= $(lastword $(wildcard $(SDK_ROOT)/components/softdevice/s130/hex/s130_nrf51_2.0.1_softdevice.hex)) +else ifeq ($(SD), s132) +CFLAGS += -DBLUETOOTH_SD=132 +SOFTDEV_HEX ?= $(lastword $(wildcard $(SDK_ROOT)/components/softdevice/s132/hex/s132_nrf52_3.0.0_softdevice.hex)) +# Update to local linker file, special linking has to be done +LD_FILE := $(SDK_MODULES_PATH)nrf52832_aa_s132.ld +endif diff --git a/nrf5/sdk/sdk_12.1.0/sdk_config.h b/nrf5/sdk/sdk_12.1.0/sdk_config.h new file mode 100644 index 0000000000..fa78d17e3e --- /dev/null +++ b/nrf5/sdk/sdk_12.1.0/sdk_config.h @@ -0,0 +1,2299 @@ + + +#ifndef SDK_CONFIG_H +#define SDK_CONFIG_H +// <<< Use Configuration Wizard in Context Menu >>>\n +#ifdef USE_APP_CONFIG +#include "app_config.h" +#endif +// nRF_BLE + +//========================================================== +// BLE_ADVERTISING_ENABLED - ble_advertising - Advertising module + + +#ifndef BLE_ADVERTISING_ENABLED +#define BLE_ADVERTISING_ENABLED 1 +#endif + +// BLE_DTM_ENABLED - ble_dtm - Module for testing RF/PHY using DTM commands + + +#ifndef BLE_DTM_ENABLED +#define BLE_DTM_ENABLED 0 +#endif + +// BLE_RACP_ENABLED - ble_racp - Record Access Control Point library + + +#ifndef BLE_RACP_ENABLED +#define BLE_RACP_ENABLED 0 +#endif + +// NRF_BLE_QWR_ENABLED - nrf_ble_qwr - Queued writes support module (prepare/execute write) + + +#ifndef NRF_BLE_QWR_ENABLED +#define NRF_BLE_QWR_ENABLED 0 +#endif + +// PEER_MANAGER_ENABLED - peer_manager - Peer Manager + + +#ifndef PEER_MANAGER_ENABLED +#define PEER_MANAGER_ENABLED 1 +#endif + +// +//========================================================== + +// nRF_BLE_Services + +//========================================================== +// BLE_ANCS_C_ENABLED - ble_ancs_c - Apple Notification Service Client + + +#ifndef BLE_ANCS_C_ENABLED +#define BLE_ANCS_C_ENABLED 0 +#endif + +// BLE_ANS_C_ENABLED - ble_ans_c - Alert Notification Service Client + + +#ifndef BLE_ANS_C_ENABLED +#define BLE_ANS_C_ENABLED 0 +#endif + +// BLE_BAS_C_ENABLED - ble_bas_c - Battery Service Client + + +#ifndef BLE_BAS_C_ENABLED +#define BLE_BAS_C_ENABLED 0 +#endif + +// BLE_BAS_ENABLED - ble_bas - Battery Service + + +#ifndef BLE_BAS_ENABLED +#define BLE_BAS_ENABLED 0 +#endif + +// BLE_CSCS_ENABLED - ble_cscs - Cycling Speed and Cadence Service + + +#ifndef BLE_CSCS_ENABLED +#define BLE_CSCS_ENABLED 0 +#endif + +// BLE_CTS_C_ENABLED - ble_cts_c - Current Time Service Client + + +#ifndef BLE_CTS_C_ENABLED +#define BLE_CTS_C_ENABLED 0 +#endif + +// BLE_DIS_ENABLED - ble_dis - Device Information Service + + +#ifndef BLE_DIS_ENABLED +#define BLE_DIS_ENABLED 0 +#endif + +// BLE_GLS_ENABLED - ble_gls - Glucose Service + + +#ifndef BLE_GLS_ENABLED +#define BLE_GLS_ENABLED 0 +#endif + +// BLE_HIDS_ENABLED - ble_hids - Human Interface Device Service + + +#ifndef BLE_HIDS_ENABLED +#define BLE_HIDS_ENABLED 0 +#endif + +// BLE_HRS_C_ENABLED - ble_hrs_c - Heart Rate Service Client + + +#ifndef BLE_HRS_C_ENABLED +#define BLE_HRS_C_ENABLED 0 +#endif + +// BLE_HRS_ENABLED - ble_hrs - Heart Rate Service + + +#ifndef BLE_HRS_ENABLED +#define BLE_HRS_ENABLED 0 +#endif + +// BLE_HTS_ENABLED - ble_hts - Health Thermometer Service + + +#ifndef BLE_HTS_ENABLED +#define BLE_HTS_ENABLED 0 +#endif + +// BLE_IAS_C_ENABLED - ble_ias_c - Immediate Alert Service Client + + +#ifndef BLE_IAS_C_ENABLED +#define BLE_IAS_C_ENABLED 0 +#endif + +// BLE_IAS_ENABLED - ble_ias - Immediate Alert Service + + +#ifndef BLE_IAS_ENABLED +#define BLE_IAS_ENABLED 0 +#endif + +// BLE_LBS_C_ENABLED - ble_lbs_c - Nordic LED Button Service Client + + +#ifndef BLE_LBS_C_ENABLED +#define BLE_LBS_C_ENABLED 0 +#endif + +// BLE_LBS_ENABLED - ble_lbs - LED Button Service + + +#ifndef BLE_LBS_ENABLED +#define BLE_LBS_ENABLED 0 +#endif + +// BLE_LLS_ENABLED - ble_lls - Link Loss Service + + +#ifndef BLE_LLS_ENABLED +#define BLE_LLS_ENABLED 0 +#endif + +// BLE_NUS_C_ENABLED - ble_nus_c - Nordic UART Central Service + + +#ifndef BLE_NUS_C_ENABLED +#define BLE_NUS_C_ENABLED 0 +#endif + +// BLE_NUS_ENABLED - ble_nus - Nordic UART Service + + +#ifndef BLE_NUS_ENABLED +#define BLE_NUS_ENABLED 1 +#endif + +// BLE_RSCS_C_ENABLED - ble_rscs_c - Running Speed and Cadence Client + + +#ifndef BLE_RSCS_C_ENABLED +#define BLE_RSCS_C_ENABLED 0 +#endif + +// BLE_RSCS_ENABLED - ble_rscs - Running Speed and Cadence Service + + +#ifndef BLE_RSCS_ENABLED +#define BLE_RSCS_ENABLED 0 +#endif + +// BLE_TPS_ENABLED - ble_tps - TX Power Service + + +#ifndef BLE_TPS_ENABLED +#define BLE_TPS_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_Drivers + +//========================================================== +// ADC_ENABLED - nrf_drv_adc - Driver for ADC peripheral (nRF51) +//========================================================== +#ifndef ADC_ENABLED +#define ADC_ENABLED 0 +#endif +#if ADC_ENABLED +// ADC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef ADC_CONFIG_IRQ_PRIORITY +#define ADC_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //ADC_ENABLED +// + +// CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver +//========================================================== +#ifndef CLOCK_ENABLED +#define CLOCK_ENABLED 1 +#endif +#if CLOCK_ENABLED +// CLOCK_CONFIG_XTAL_FREQ - HF XTAL Frequency + +// <0=> Default (64 MHz) + +#ifndef CLOCK_CONFIG_XTAL_FREQ +#define CLOCK_CONFIG_XTAL_FREQ 0 +#endif + +// CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth + +#ifndef CLOCK_CONFIG_LF_SRC +#define CLOCK_CONFIG_LF_SRC 1 +#endif + +// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef CLOCK_CONFIG_IRQ_PRIORITY +#define CLOCK_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //CLOCK_ENABLED +// + +// COMP_ENABLED - nrf_drv_comp - COMP peripheral driver +//========================================================== +#ifndef COMP_ENABLED +#define COMP_ENABLED 0 +#endif +#if COMP_ENABLED +// COMP_CONFIG_REF - Reference voltage + +// <0=> Internal 1.2V +// <1=> Internal 1.8V +// <2=> Internal 2.4V +// <4=> VDD +// <7=> ARef + +#ifndef COMP_CONFIG_REF +#define COMP_CONFIG_REF 1 +#endif + +// COMP_CONFIG_MAIN_MODE - Main mode + +// <0=> Single ended +// <1=> Differential + +#ifndef COMP_CONFIG_MAIN_MODE +#define COMP_CONFIG_MAIN_MODE 0 +#endif + +// COMP_CONFIG_SPEED_MODE - Speed mode + +// <0=> Low power +// <1=> Normal +// <2=> High speed + +#ifndef COMP_CONFIG_SPEED_MODE +#define COMP_CONFIG_SPEED_MODE 2 +#endif + +// COMP_CONFIG_HYST - Hystheresis + +// <0=> No +// <1=> 50mV + +#ifndef COMP_CONFIG_HYST +#define COMP_CONFIG_HYST 0 +#endif + +// COMP_CONFIG_ISOURCE - Current Source + +// <0=> Off +// <1=> 2.5 uA +// <2=> 5 uA +// <3=> 10 uA + +#ifndef COMP_CONFIG_ISOURCE +#define COMP_CONFIG_ISOURCE 0 +#endif + +// COMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_INPUT +#define COMP_CONFIG_INPUT 0 +#endif + +// COMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_IRQ_PRIORITY +#define COMP_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //COMP_ENABLED +// + +// EGU_ENABLED - nrf_drv_swi - SWI(EGU) peripheral driver + + +#ifndef EGU_ENABLED +#define EGU_ENABLED 0 +#endif + +// GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver +//========================================================== +#ifndef GPIOTE_ENABLED +#define GPIOTE_ENABLED 1 +#endif +#if GPIOTE_ENABLED +// GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins +#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4 +#endif + +// GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef GPIOTE_CONFIG_IRQ_PRIORITY +#define GPIOTE_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //GPIOTE_ENABLED +// + +// I2S_ENABLED - nrf_drv_i2s - I2S peripheral driver +//========================================================== +#ifndef I2S_ENABLED +#define I2S_ENABLED 0 +#endif +#if I2S_ENABLED +// I2S_CONFIG_SCK_PIN - SCK pin <0-31> + + +#ifndef I2S_CONFIG_SCK_PIN +#define I2S_CONFIG_SCK_PIN 31 +#endif + +// I2S_CONFIG_LRCK_PIN - LRCK pin <1-31> + + +#ifndef I2S_CONFIG_LRCK_PIN +#define I2S_CONFIG_LRCK_PIN 30 +#endif + +// I2S_CONFIG_MCK_PIN - MCK pin +#ifndef I2S_CONFIG_MCK_PIN +#define I2S_CONFIG_MCK_PIN 255 +#endif + +// I2S_CONFIG_SDOUT_PIN - SDOUT pin <0-31> + + +#ifndef I2S_CONFIG_SDOUT_PIN +#define I2S_CONFIG_SDOUT_PIN 29 +#endif + +// I2S_CONFIG_SDIN_PIN - SDIN pin <0-31> + + +#ifndef I2S_CONFIG_SDIN_PIN +#define I2S_CONFIG_SDIN_PIN 28 +#endif + +// I2S_CONFIG_MASTER - Mode + +// <0=> Master +// <1=> Slave + +#ifndef I2S_CONFIG_MASTER +#define I2S_CONFIG_MASTER 0 +#endif + +// I2S_CONFIG_FORMAT - Format + +// <0=> I2S +// <1=> Aligned + +#ifndef I2S_CONFIG_FORMAT +#define I2S_CONFIG_FORMAT 0 +#endif + +// I2S_CONFIG_ALIGN - Alignment + +// <0=> Left +// <1=> Right + +#ifndef I2S_CONFIG_ALIGN +#define I2S_CONFIG_ALIGN 0 +#endif + +// I2S_CONFIG_SWIDTH - Sample width (bits) + +// <0=> 8 +// <1=> 16 +// <2=> 24 + +#ifndef I2S_CONFIG_SWIDTH +#define I2S_CONFIG_SWIDTH 1 +#endif + +// I2S_CONFIG_CHANNELS - Channels + +// <0=> Stereo +// <1=> Left +// <2=> Right + +#ifndef I2S_CONFIG_CHANNELS +#define I2S_CONFIG_CHANNELS 1 +#endif + +// I2S_CONFIG_MCK_SETUP - MCK behavior + +// <0=> Disabled +// <2147483648=> 32MHz/2 +// <1342177280=> 32MHz/3 +// <1073741824=> 32MHz/4 +// <805306368=> 32MHz/5 +// <671088640=> 32MHz/6 +// <536870912=> 32MHz/8 +// <402653184=> 32MHz/10 +// <369098752=> 32MHz/11 +// <285212672=> 32MHz/15 +// <268435456=> 32MHz/16 +// <201326592=> 32MHz/21 +// <184549376=> 32MHz/23 +// <142606336=> 32MHz/30 +// <138412032=> 32MHz/31 +// <134217728=> 32MHz/32 +// <100663296=> 32MHz/42 +// <68157440=> 32MHz/63 +// <34340864=> 32MHz/125 + +#ifndef I2S_CONFIG_MCK_SETUP +#define I2S_CONFIG_MCK_SETUP 536870912 +#endif + +// I2S_CONFIG_RATIO - MCK/LRCK ratio + +// <0=> 32x +// <1=> 48x +// <2=> 64x +// <3=> 96x +// <4=> 128x +// <5=> 192x +// <6=> 256x +// <7=> 384x +// <8=> 512x + +#ifndef I2S_CONFIG_RATIO +#define I2S_CONFIG_RATIO 2000 +#endif + +// I2S_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef I2S_CONFIG_IRQ_PRIORITY +#define I2S_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //I2S_ENABLED +// + +// LPCOMP_ENABLED - nrf_drv_lpcomp - LPCOMP peripheral driver +//========================================================== +#ifndef LPCOMP_ENABLED +#define LPCOMP_ENABLED 0 +#endif +#if LPCOMP_ENABLED +// LPCOMP_CONFIG_REFERENCE - Reference voltage + +// <0=> Supply 1/8 +// <1=> Supply 2/8 +// <2=> Supply 3/8 +// <3=> Supply 4/8 +// <4=> Supply 5/8 +// <5=> Supply 6/8 +// <6=> Supply 7/8 +// <8=> Supply 1/16 (nRF52) +// <9=> Supply 3/16 (nRF52) +// <10=> Supply 5/16 (nRF52) +// <11=> Supply 7/16 (nRF52) +// <12=> Supply 9/16 (nRF52) +// <13=> Supply 11/16 (nRF52) +// <14=> Supply 13/16 (nRF52) +// <15=> Supply 15/16 (nRF52) +// <7=> External Ref 0 +// <65543=> External Ref 1 + +#ifndef LPCOMP_CONFIG_REFERENCE +#define LPCOMP_CONFIG_REFERENCE 3 +#endif + +// LPCOMP_CONFIG_DETECTION - Detection + +// <0=> Crossing +// <1=> Up +// <2=> Down + +#ifndef LPCOMP_CONFIG_DETECTION +#define LPCOMP_CONFIG_DETECTION 2 +#endif + +// LPCOMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_INPUT +#define LPCOMP_CONFIG_INPUT 0 +#endif + +// LPCOMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_IRQ_PRIORITY +#define LPCOMP_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //LPCOMP_ENABLED +// + +// PDM_ENABLED - nrf_drv_pdm - PDM peripheral driver +//========================================================== +#ifndef PDM_ENABLED +#define PDM_ENABLED 0 +#endif +#if PDM_ENABLED +// PDM_CONFIG_MODE - Mode + +// <0=> Stereo +// <1=> Mono + +#ifndef PDM_CONFIG_MODE +#define PDM_CONFIG_MODE 1 +#endif + +// PDM_CONFIG_EDGE - Edge + +// <0=> Left falling +// <1=> Left rising + +#ifndef PDM_CONFIG_EDGE +#define PDM_CONFIG_EDGE 0 +#endif + +// PDM_CONFIG_CLOCK_FREQ - Clock frequency + +// <134217728=> 1000k +// <138412032=> 1032k (default) +// <142606336=> 1067k + +#ifndef PDM_CONFIG_CLOCK_FREQ +#define PDM_CONFIG_CLOCK_FREQ 138412032 +#endif + +// PDM_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PDM_CONFIG_IRQ_PRIORITY +#define PDM_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //PDM_ENABLED +// + +// PERIPHERAL_RESOURCE_SHARING_ENABLED - nrf_drv_common - Peripheral drivers common module + + +#ifndef PERIPHERAL_RESOURCE_SHARING_ENABLED +#define PERIPHERAL_RESOURCE_SHARING_ENABLED 0 +#endif + +// PPI_ENABLED - nrf_drv_ppi - PPI peripheral driver + + +#ifndef PPI_ENABLED +#define PPI_ENABLED 0 +#endif + +// PWM_ENABLED - nrf_drv_pwm - PWM peripheral driver +//========================================================== +#ifndef PWM_ENABLED +#define PWM_ENABLED 0 +#endif +#if PWM_ENABLED +// PWM_DEFAULT_CONFIG_OUT0_PIN - Out0 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT0_PIN +#define PWM_DEFAULT_CONFIG_OUT0_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT1_PIN - Out1 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT1_PIN +#define PWM_DEFAULT_CONFIG_OUT1_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT2_PIN - Out2 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT2_PIN +#define PWM_DEFAULT_CONFIG_OUT2_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT3_PIN - Out3 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT3_PIN +#define PWM_DEFAULT_CONFIG_OUT3_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_BASE_CLOCK - Base clock + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 MHz + +#ifndef PWM_DEFAULT_CONFIG_BASE_CLOCK +#define PWM_DEFAULT_CONFIG_BASE_CLOCK 4 +#endif + +// PWM_DEFAULT_CONFIG_COUNT_MODE - Count mode + +// <0=> Up +// <1=> Up and Down + +#ifndef PWM_DEFAULT_CONFIG_COUNT_MODE +#define PWM_DEFAULT_CONFIG_COUNT_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_TOP_VALUE - Top value +#ifndef PWM_DEFAULT_CONFIG_TOP_VALUE +#define PWM_DEFAULT_CONFIG_TOP_VALUE 1000 +#endif + +// PWM_DEFAULT_CONFIG_LOAD_MODE - Load mode + +// <0=> Common +// <1=> Grouped +// <2=> Individual +// <3=> Waveform + +#ifndef PWM_DEFAULT_CONFIG_LOAD_MODE +#define PWM_DEFAULT_CONFIG_LOAD_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_STEP_MODE - Step mode + +// <0=> Auto +// <1=> Triggered + +#ifndef PWM_DEFAULT_CONFIG_STEP_MODE +#define PWM_DEFAULT_CONFIG_STEP_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PWM_DEFAULT_CONFIG_IRQ_PRIORITY +#define PWM_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// PWM0_ENABLED - Enable PWM0 instance + + +#ifndef PWM0_ENABLED +#define PWM0_ENABLED 0 +#endif + +// PWM1_ENABLED - Enable PWM1 instance + + +#ifndef PWM1_ENABLED +#define PWM1_ENABLED 0 +#endif + +// PWM2_ENABLED - Enable PWM2 instance + + +#ifndef PWM2_ENABLED +#define PWM2_ENABLED 0 +#endif + +#endif //PWM_ENABLED +// + +// QDEC_ENABLED - nrf_drv_qdec - QDEC peripheral driver +//========================================================== +#ifndef QDEC_ENABLED +#define QDEC_ENABLED 0 +#endif +#if QDEC_ENABLED +// QDEC_CONFIG_REPORTPER - Report period + +// <0=> 10 Samples +// <1=> 40 Samples +// <2=> 80 Samples +// <3=> 120 Samples +// <4=> 160 Samples +// <5=> 200 Samples +// <6=> 240 Samples +// <7=> 280 Samples + +#ifndef QDEC_CONFIG_REPORTPER +#define QDEC_CONFIG_REPORTPER 0 +#endif + +// QDEC_CONFIG_SAMPLEPER - Sample period + +// <0=> 128 us +// <1=> 256 us +// <2=> 512 us +// <3=> 1024 us +// <4=> 2048 us +// <5=> 4096 us +// <6=> 8192 us +// <7=> 16384 us + +#ifndef QDEC_CONFIG_SAMPLEPER +#define QDEC_CONFIG_SAMPLEPER 7 +#endif + +// QDEC_CONFIG_PIO_A - A pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_A +#define QDEC_CONFIG_PIO_A 31 +#endif + +// QDEC_CONFIG_PIO_B - B pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_B +#define QDEC_CONFIG_PIO_B 31 +#endif + +// QDEC_CONFIG_PIO_LED - LED pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_LED +#define QDEC_CONFIG_PIO_LED 31 +#endif + +// QDEC_CONFIG_LEDPRE - LED pre +#ifndef QDEC_CONFIG_LEDPRE +#define QDEC_CONFIG_LEDPRE 511 +#endif + +// QDEC_CONFIG_LEDPOL - LED polarity + +// <0=> Active low +// <1=> Active high + +#ifndef QDEC_CONFIG_LEDPOL +#define QDEC_CONFIG_LEDPOL 1 +#endif + +// QDEC_CONFIG_DBFEN - Debouncing enable + + +#ifndef QDEC_CONFIG_DBFEN +#define QDEC_CONFIG_DBFEN 0 +#endif + +// QDEC_CONFIG_SAMPLE_INTEN - Sample ready interrupt enable + + +#ifndef QDEC_CONFIG_SAMPLE_INTEN +#define QDEC_CONFIG_SAMPLE_INTEN 0 +#endif + +// QDEC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef QDEC_CONFIG_IRQ_PRIORITY +#define QDEC_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //QDEC_ENABLED +// + +// RNG_ENABLED - nrf_drv_rng - RNG peripheral driver +//========================================================== +#ifndef RNG_ENABLED +#define RNG_ENABLED 0 +#endif +#if RNG_ENABLED +// RNG_CONFIG_ERROR_CORRECTION - Error correction + + +#ifndef RNG_CONFIG_ERROR_CORRECTION +#define RNG_CONFIG_ERROR_CORRECTION 0 +#endif + +// RNG_CONFIG_POOL_SIZE - Pool size +#ifndef RNG_CONFIG_POOL_SIZE +#define RNG_CONFIG_POOL_SIZE 8 +#endif + +// RNG_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RNG_CONFIG_IRQ_PRIORITY +#define RNG_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //RNG_ENABLED +// + +// RTC_ENABLED - nrf_drv_rtc - RTC peripheral driver +//========================================================== +#ifndef RTC_ENABLED +#define RTC_ENABLED 0 +#endif +#if RTC_ENABLED +// RTC_DEFAULT_CONFIG_FREQUENCY - Frequency <16-32768> + + +#ifndef RTC_DEFAULT_CONFIG_FREQUENCY +#define RTC_DEFAULT_CONFIG_FREQUENCY 32768 +#endif + +// RTC_DEFAULT_CONFIG_RELIABLE - Ensures safe compare event triggering + + +#ifndef RTC_DEFAULT_CONFIG_RELIABLE +#define RTC_DEFAULT_CONFIG_RELIABLE 0 +#endif + +// RTC_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RTC_DEFAULT_CONFIG_IRQ_PRIORITY +#define RTC_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// RTC0_ENABLED - Enable RTC0 instance + + +#ifndef RTC0_ENABLED +#define RTC0_ENABLED 0 +#endif + +// RTC1_ENABLED - Enable RTC1 instance + + +#ifndef RTC1_ENABLED +#define RTC1_ENABLED 0 +#endif + +// RTC2_ENABLED - Enable RTC2 instance + + +#ifndef RTC2_ENABLED +#define RTC2_ENABLED 0 +#endif + +// NRF_MAXIMUM_LATENCY_US - Maximum possible time[us] in highest priority interrupt +#ifndef NRF_MAXIMUM_LATENCY_US +#define NRF_MAXIMUM_LATENCY_US 2000 +#endif + +#endif //RTC_ENABLED +// + +// SAADC_ENABLED - nrf_drv_saadc - SAADC peripheral driver +//========================================================== +#ifndef SAADC_ENABLED +#define SAADC_ENABLED 0 +#endif +#if SAADC_ENABLED +// SAADC_CONFIG_RESOLUTION - Resolution + +// <0=> 8 bit +// <1=> 10 bit +// <2=> 12 bit +// <3=> 14 bit + +#ifndef SAADC_CONFIG_RESOLUTION +#define SAADC_CONFIG_RESOLUTION 1 +#endif + +// SAADC_CONFIG_OVERSAMPLE - Sample period + +// <0=> Disabled +// <1=> 2x +// <2=> 4x +// <3=> 8x +// <4=> 16x +// <5=> 32x +// <6=> 64x +// <7=> 128x +// <8=> 256x + +#ifndef SAADC_CONFIG_OVERSAMPLE +#define SAADC_CONFIG_OVERSAMPLE 0 +#endif + +// SAADC_CONFIG_LP_MODE - Enabling low power mode + + +#ifndef SAADC_CONFIG_LP_MODE +#define SAADC_CONFIG_LP_MODE 0 +#endif + +// SAADC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SAADC_CONFIG_IRQ_PRIORITY +#define SAADC_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //SAADC_ENABLED +// + +// SPIS_ENABLED - nrf_drv_spis - SPI Slave driver +//========================================================== +#ifndef SPIS_ENABLED +#define SPIS_ENABLED 0 +#endif +#if SPIS_ENABLED +// SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPIS_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// SPIS_DEFAULT_MODE - Mode + +// <0=> MODE_0 +// <1=> MODE_1 +// <2=> MODE_2 +// <3=> MODE_3 + +#ifndef SPIS_DEFAULT_MODE +#define SPIS_DEFAULT_MODE 0 +#endif + +// SPIS_DEFAULT_BIT_ORDER - SPIS default bit order + +// <0=> MSB first +// <1=> LSB first + +#ifndef SPIS_DEFAULT_BIT_ORDER +#define SPIS_DEFAULT_BIT_ORDER 0 +#endif + +// SPIS_DEFAULT_DEF - SPIS default DEF character <0-255> + + +#ifndef SPIS_DEFAULT_DEF +#define SPIS_DEFAULT_DEF 255 +#endif + +// SPIS_DEFAULT_ORC - SPIS default ORC character <0-255> + + +#ifndef SPIS_DEFAULT_ORC +#define SPIS_DEFAULT_ORC 255 +#endif + +// SPIS0_ENABLED - Enable SPIS0 instance + + +#ifndef SPIS0_ENABLED +#define SPIS0_ENABLED 0 +#endif + +// SPIS1_ENABLED - Enable SPIS1 instance + + +#ifndef SPIS1_ENABLED +#define SPIS1_ENABLED 0 +#endif + +// SPIS2_ENABLED - Enable SPIS2 instance + + +#ifndef SPIS2_ENABLED +#define SPIS2_ENABLED 0 +#endif + +#endif //SPIS_ENABLED +// + +// SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver +//========================================================== +#ifndef SPI_ENABLED +#define SPI_ENABLED 0 +#endif +#if SPI_ENABLED +// SPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPI_CONFIG_LOG_ENABLED +#define SPI_CONFIG_LOG_ENABLED 0 +#endif +#if SPI_CONFIG_LOG_ENABLED +// SPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPI_CONFIG_LOG_LEVEL +#define SPI_CONFIG_LOG_LEVEL 3 +#endif + +// SPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_INFO_COLOR +#define SPI_CONFIG_INFO_COLOR 0 +#endif + +// SPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_DEBUG_COLOR +#define SPI_CONFIG_DEBUG_COLOR 0 +#endif + +#endif //SPI_CONFIG_LOG_ENABLED +// + +// SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPI_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// SPI0_ENABLED - Enable SPI0 instance +//========================================================== +#ifndef SPI0_ENABLED +#define SPI0_ENABLED 0 +#endif +#if SPI0_ENABLED +// SPI0_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI0_USE_EASY_DMA +#define SPI0_USE_EASY_DMA 1 +#endif + +#endif //SPI0_ENABLED +// + +// SPI1_ENABLED - Enable SPI1 instance +//========================================================== +#ifndef SPI1_ENABLED +#define SPI1_ENABLED 0 +#endif +#if SPI1_ENABLED +// SPI1_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI1_USE_EASY_DMA +#define SPI1_USE_EASY_DMA 1 +#endif + +#endif //SPI1_ENABLED +// + +// SPI2_ENABLED - Enable SPI2 instance +//========================================================== +#ifndef SPI2_ENABLED +#define SPI2_ENABLED 0 +#endif +#if SPI2_ENABLED +// SPI2_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI2_USE_EASY_DMA +#define SPI2_USE_EASY_DMA 1 +#endif + +#endif //SPI2_ENABLED +// + +#endif //SPI_ENABLED +// + +// TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver +//========================================================== +#ifndef TIMER_ENABLED +#define TIMER_ENABLED 0 +#endif +#if TIMER_ENABLED +// TIMER_DEFAULT_CONFIG_FREQUENCY - Timer frequency if in Timer mode + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz +// <8=> 62.5 kHz +// <9=> 31.25 kHz + +#ifndef TIMER_DEFAULT_CONFIG_FREQUENCY +#define TIMER_DEFAULT_CONFIG_FREQUENCY 0 +#endif + +// TIMER_DEFAULT_CONFIG_MODE - Timer mode or operation + +// <0=> Timer +// <1=> Counter + +#ifndef TIMER_DEFAULT_CONFIG_MODE +#define TIMER_DEFAULT_CONFIG_MODE 0 +#endif + +// TIMER_DEFAULT_CONFIG_BIT_WIDTH - Timer counter bit width + +// <0=> 16 bit +// <1=> 8 bit +// <2=> 24 bit +// <3=> 32 bit + +#ifndef TIMER_DEFAULT_CONFIG_BIT_WIDTH +#define TIMER_DEFAULT_CONFIG_BIT_WIDTH 0 +#endif + +// TIMER_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#define TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// TIMER0_ENABLED - Enable TIMER0 instance + + +#ifndef TIMER0_ENABLED +#define TIMER0_ENABLED 0 +#endif + +// TIMER1_ENABLED - Enable TIMER1 instance + + +#ifndef TIMER1_ENABLED +#define TIMER1_ENABLED 0 +#endif + +// TIMER2_ENABLED - Enable TIMER2 instance + + +#ifndef TIMER2_ENABLED +#define TIMER2_ENABLED 0 +#endif + +// TIMER3_ENABLED - Enable TIMER3 instance + + +#ifndef TIMER3_ENABLED +#define TIMER3_ENABLED 0 +#endif + +// TIMER4_ENABLED - Enable TIMER4 instance + + +#ifndef TIMER4_ENABLED +#define TIMER4_ENABLED 0 +#endif + +#endif //TIMER_ENABLED +// + +// TWIS_ENABLED - nrf_drv_twis - TWIS peripheral driver +//========================================================== +#ifndef TWIS_ENABLED +#define TWIS_ENABLED 0 +#endif +#if TWIS_ENABLED +// TWIS_DEFAULT_CONFIG_ADDR0 - Address0 +#ifndef TWIS_DEFAULT_CONFIG_ADDR0 +#define TWIS_DEFAULT_CONFIG_ADDR0 0 +#endif + +// TWIS_DEFAULT_CONFIG_ADDR1 - Address1 +#ifndef TWIS_DEFAULT_CONFIG_ADDR1 +#define TWIS_DEFAULT_CONFIG_ADDR1 0 +#endif + +// TWIS_DEFAULT_CONFIG_SCL_PULL - SCL pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SCL_PULL +#define TWIS_DEFAULT_CONFIG_SCL_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_SDA_PULL - SDA pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SDA_PULL +#define TWIS_DEFAULT_CONFIG_SDA_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWIS_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// TWIS0_ENABLED - Enable TWIS0 instance + + +#ifndef TWIS0_ENABLED +#define TWIS0_ENABLED 0 +#endif + +// TWIS1_ENABLED - Enable TWIS1 instance + + +#ifndef TWIS1_ENABLED +#define TWIS1_ENABLED 0 +#endif + +// TWIS_ASSUME_INIT_AFTER_RESET_ONLY - Assume that any instance would be initialized only once + + +// Optimization flag. Registers used by TWIS are shared by other peripherals. Normally, during initialization driver tries to clear all registers to known state before doing the initialization itself. This gives initialization safe procedure, no matter when it would be called. If you activate TWIS only once and do never uninitialize it - set this flag to 1 what gives more optimal code. + +#ifndef TWIS_ASSUME_INIT_AFTER_RESET_ONLY +#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +#endif + +// TWIS_NO_SYNC_MODE - Remove support for synchronous mode + + +// Synchronous mode would be used in specific situations. And it uses some additional code and data memory to safely process state machine by polling it in status functions. If this functionality is not required it may be disabled to free some resources. + +#ifndef TWIS_NO_SYNC_MODE +#define TWIS_NO_SYNC_MODE 0 +#endif + +#endif //TWIS_ENABLED +// + +// TWI_ENABLED - nrf_drv_twi - TWI/TWIM peripheral driver +//========================================================== +#ifndef TWI_ENABLED +#define TWI_ENABLED 0 +#endif +#if TWI_ENABLED +// TWI_DEFAULT_CONFIG_FREQUENCY - Frequency + +// <26738688=> 100k +// <67108864=> 250k +// <104857600=> 400k + +#ifndef TWI_DEFAULT_CONFIG_FREQUENCY +#define TWI_DEFAULT_CONFIG_FREQUENCY 26738688 +#endif + +// TWI_DEFAULT_CONFIG_CLR_BUS_INIT - Enables bus clearing procedure during init + + +#ifndef TWI_DEFAULT_CONFIG_CLR_BUS_INIT +#define TWI_DEFAULT_CONFIG_CLR_BUS_INIT 0 +#endif + +// TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT - Enables bus holding after uninit + + +#ifndef TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 +#endif + +// TWI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWI_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// TWI0_ENABLED - Enable TWI0 instance +//========================================================== +#ifndef TWI0_ENABLED +#define TWI0_ENABLED 0 +#endif +#if TWI0_ENABLED +// TWI0_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI0_USE_EASY_DMA +#define TWI0_USE_EASY_DMA 0 +#endif + +#endif //TWI0_ENABLED +// + +// TWI1_ENABLED - Enable TWI1 instance +//========================================================== +#ifndef TWI1_ENABLED +#define TWI1_ENABLED 0 +#endif +#if TWI1_ENABLED +// TWI1_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI1_USE_EASY_DMA +#define TWI1_USE_EASY_DMA 0 +#endif + +#endif //TWI1_ENABLED +// + +#endif //TWI_ENABLED +// + +// UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver +//========================================================== +#ifndef UART_ENABLED +#define UART_ENABLED 1 +#endif +#if UART_ENABLED +// UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef UART_DEFAULT_CONFIG_HWFC +#define UART_DEFAULT_CONFIG_HWFC 0 +#endif + +// UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef UART_DEFAULT_CONFIG_PARITY +#define UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 57600 baud + +#ifndef UART_DEFAULT_CONFIG_BAUDRATE +#define UART_DEFAULT_CONFIG_BAUDRATE 30801920 +#endif + +// UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define UART_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// UART0_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART0_CONFIG_USE_EASY_DMA +#define UART0_CONFIG_USE_EASY_DMA 1 +#endif + +// UART_EASY_DMA_SUPPORT - Driver supporting EasyDMA + + +#ifndef UART_EASY_DMA_SUPPORT +#define UART_EASY_DMA_SUPPORT 1 +#endif + +// UART_LEGACY_SUPPORT - Driver supporting Legacy mode + + +#ifndef UART_LEGACY_SUPPORT +#define UART_LEGACY_SUPPORT 1 +#endif + +#endif //UART_ENABLED +// + +// WDT_ENABLED - nrf_drv_wdt - WDT peripheral driver +//========================================================== +#ifndef WDT_ENABLED +#define WDT_ENABLED 0 +#endif +#if WDT_ENABLED +// WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode + +// <1=> Run in SLEEP, Pause in HALT +// <8=> Pause in SLEEP, Run in HALT +// <9=> Run in SLEEP and HALT +// <0=> Pause in SLEEP and HALT + +#ifndef WDT_CONFIG_BEHAVIOUR +#define WDT_CONFIG_BEHAVIOUR 1 +#endif + +// WDT_CONFIG_RELOAD_VALUE - Reload value <15-4294967295> + + +#ifndef WDT_CONFIG_RELOAD_VALUE +#define WDT_CONFIG_RELOAD_VALUE 2000 +#endif + +// WDT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef WDT_CONFIG_IRQ_PRIORITY +#define WDT_CONFIG_IRQ_PRIORITY 6 +#endif + +#endif //WDT_ENABLED +// + +// +//========================================================== + +// nRF_Libraries + +//========================================================== +// APP_FIFO_ENABLED - app_fifo - Software FIFO implementation + + +#ifndef APP_FIFO_ENABLED +#define APP_FIFO_ENABLED 1 +#endif + +// APP_MAILBOX_ENABLED - app_mailbox - Thread safe mailbox + + +#ifndef APP_MAILBOX_ENABLED +#define APP_MAILBOX_ENABLED 0 +#endif + +// APP_PWM_ENABLED - app_pwm - PWM functionality + + +#ifndef APP_PWM_ENABLED +#define APP_PWM_ENABLED 0 +#endif + +// APP_SCHEDULER_ENABLED - app_scheduler - Events scheduler +//========================================================== +#ifndef APP_SCHEDULER_ENABLED +#define APP_SCHEDULER_ENABLED 0 +#endif +#if APP_SCHEDULER_ENABLED +// APP_SCHEDULER_WITH_PAUSE - Enabling pause feature + + +#ifndef APP_SCHEDULER_WITH_PAUSE +#define APP_SCHEDULER_WITH_PAUSE 0 +#endif + +// APP_SCHEDULER_WITH_PROFILER - Enabling scheduler profiling + + +#ifndef APP_SCHEDULER_WITH_PROFILER +#define APP_SCHEDULER_WITH_PROFILER 0 +#endif + +#endif //APP_SCHEDULER_ENABLED +// + +// APP_TIMER_ENABLED - app_timer - Application timer functionality +//========================================================== +#ifndef APP_TIMER_ENABLED +#define APP_TIMER_ENABLED 1 +#endif +#if APP_TIMER_ENABLED +// APP_TIMER_WITH_PROFILER - Enable app_timer profiling + + +#ifndef APP_TIMER_WITH_PROFILER +#define APP_TIMER_WITH_PROFILER 0 +#endif + +// APP_TIMER_KEEPS_RTC_ACTIVE - Enable RTC always on + + +// If option is enabled RTC is kept running even if there is no active timers. +// This option can be used when app_timer is used for timestamping. + +#ifndef APP_TIMER_KEEPS_RTC_ACTIVE +#define APP_TIMER_KEEPS_RTC_ACTIVE 0 +#endif + +#endif //APP_TIMER_ENABLED +// + +// APP_TWI_ENABLED - app_twi - TWI transaction manager + + +#ifndef APP_TWI_ENABLED +#define APP_TWI_ENABLED 0 +#endif + +// APP_UART_ENABLED - app_uart - UART driver +//========================================================== +#ifndef APP_UART_ENABLED +#define APP_UART_ENABLED 1 +#endif +#if APP_UART_ENABLED +// APP_UART_DRIVER_INSTANCE - UART instance used + +// <0=> 0 + +#ifndef APP_UART_DRIVER_INSTANCE +#define APP_UART_DRIVER_INSTANCE 0 +#endif + +#endif //APP_UART_ENABLED +// + +// BUTTON_ENABLED - app_button - buttons handling module + + +#ifndef BUTTON_ENABLED +#define BUTTON_ENABLED 1 +#endif + +// CRC16_ENABLED - crc16 - CRC16 calculation routines + + +#ifndef CRC16_ENABLED +#define CRC16_ENABLED 0 +#endif + +// CRC32_ENABLED - crc32 - CRC32 calculation routines + + +#ifndef CRC32_ENABLED +#define CRC32_ENABLED 0 +#endif + +// ECC_ENABLED - ecc - Elliptic Curve Cryptography Library + + +#ifndef ECC_ENABLED +#define ECC_ENABLED 0 +#endif + +// FDS_ENABLED - fds - Flash data storage module +//========================================================== +#ifndef FDS_ENABLED +#define FDS_ENABLED 1 +#endif +#if FDS_ENABLED +// FDS_OP_QUEUE_SIZE - Size of the internal queue. +#ifndef FDS_OP_QUEUE_SIZE +#define FDS_OP_QUEUE_SIZE 4 +#endif + +// FDS_CHUNK_QUEUE_SIZE - Determines how many @ref fds_record_chunk_t structures can be buffered at any time. +#ifndef FDS_CHUNK_QUEUE_SIZE +#define FDS_CHUNK_QUEUE_SIZE 8 +#endif + +// FDS_MAX_USERS - Maximum number of callbacks that can be registered. +#ifndef FDS_MAX_USERS +#define FDS_MAX_USERS 8 +#endif + +// FDS_VIRTUAL_PAGES - Number of virtual flash pages to use. +// One of the virtual pages is reserved by the system for garbage collection. +// Therefore, the minimum is two virtual pages: one page to store data and +// one page to be used by the system for garbage collection. The total amount +// of flash memory that is used by FDS amounts to @ref FDS_VIRTUAL_PAGES +// @ref FDS_VIRTUAL_PAGE_SIZE * 4 bytes. + +#ifndef FDS_VIRTUAL_PAGES +#define FDS_VIRTUAL_PAGES 3 +#endif + +// FDS_VIRTUAL_PAGE_SIZE - The size of a virtual page of flash memory, expressed in number of 4-byte words. + + +// By default, a virtual page is the same size as a physical page. +// The size of a virtual page must be a multiple of the size of a physical page. +// <1024=> 1024 +// <2048=> 2048 + +#ifndef FDS_VIRTUAL_PAGE_SIZE +#define FDS_VIRTUAL_PAGE_SIZE 1024 +#endif + +#endif //FDS_ENABLED +// + +// FSTORAGE_ENABLED - fstorage - Flash storage module +//========================================================== +#ifndef FSTORAGE_ENABLED +#define FSTORAGE_ENABLED 1 +#endif +#if FSTORAGE_ENABLED +// FS_QUEUE_SIZE - Configures the size of the internal queue. +// Increase this if there are many users, or if it is likely that many +// operation will be queued at once without waiting for the previous operations +// to complete. In general, increase the queue size if you frequently receive +// @ref FS_ERR_QUEUE_FULL errors when calling @ref fs_store or @ref fs_erase. + +#ifndef FS_QUEUE_SIZE +#define FS_QUEUE_SIZE 4 +#endif + +// FS_OP_MAX_RETRIES - Number attempts to execute an operation if the SoftDevice fails. +// Increase this value if events return the @ref FS_ERR_OPERATION_TIMEOUT +// error often. The SoftDevice may fail to schedule flash access due to high BLE activity. + +#ifndef FS_OP_MAX_RETRIES +#define FS_OP_MAX_RETRIES 3 +#endif + +// FS_MAX_WRITE_SIZE_WORDS - Maximum number of words to be written to flash in a single operation. +// Tweaking this value can increase the chances of the SoftDevice being +// able to fit flash operations in between radio activity. This value is bound by the +// maximum number of words which the SoftDevice can write to flash in a single call to +// @ref sd_flash_write, which is 256 words for nRF51 ICs and 1024 words for nRF52 ICs. + +#ifndef FS_MAX_WRITE_SIZE_WORDS +#define FS_MAX_WRITE_SIZE_WORDS 1024 +#endif + +#endif //FSTORAGE_ENABLED +// + +// HARDFAULT_HANDLER_ENABLED - hardfault_default - HardFault default handler for debugging and release + + +#ifndef HARDFAULT_HANDLER_ENABLED +#define HARDFAULT_HANDLER_ENABLED 0 +#endif + +// HCI_MEM_POOL_ENABLED - hci_mem_pool - memory pool implementation used by HCI +//========================================================== +#ifndef HCI_MEM_POOL_ENABLED +#define HCI_MEM_POOL_ENABLED 0 +#endif +#if HCI_MEM_POOL_ENABLED +// HCI_TX_BUF_SIZE - TX buffer size in bytes. +#ifndef HCI_TX_BUF_SIZE +#define HCI_TX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_SIZE - RX buffer size in bytes. +#ifndef HCI_RX_BUF_SIZE +#define HCI_RX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_QUEUE_SIZE - RX buffer queue size. +#ifndef HCI_RX_BUF_QUEUE_SIZE +#define HCI_RX_BUF_QUEUE_SIZE 4 +#endif + +#endif //HCI_MEM_POOL_ENABLED +// + +// HCI_SLIP_ENABLED - hci_slip - SLIP protocol implementation used by HCI +//========================================================== +#ifndef HCI_SLIP_ENABLED +#define HCI_SLIP_ENABLED 0 +#endif +#if HCI_SLIP_ENABLED +// HCI_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 57600 baud + +#ifndef HCI_UART_BAUDRATE +#define HCI_UART_BAUDRATE 30801920 +#endif + +// HCI_UART_FLOW_CONTROL - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef HCI_UART_FLOW_CONTROL +#define HCI_UART_FLOW_CONTROL 0 +#endif + +// HCI_UART_RX_PIN - UART RX pin +#ifndef HCI_UART_RX_PIN +#define HCI_UART_RX_PIN 8 +#endif + +// HCI_UART_TX_PIN - UART TX pin +#ifndef HCI_UART_TX_PIN +#define HCI_UART_TX_PIN 6 +#endif + +// HCI_UART_RTS_PIN - UART RTS pin +#ifndef HCI_UART_RTS_PIN +#define HCI_UART_RTS_PIN 5 +#endif + +// HCI_UART_CTS_PIN - UART CTS pin +#ifndef HCI_UART_CTS_PIN +#define HCI_UART_CTS_PIN 7 +#endif + +#endif //HCI_SLIP_ENABLED +// + +// HCI_TRANSPORT_ENABLED - hci_transport - HCI transport +//========================================================== +#ifndef HCI_TRANSPORT_ENABLED +#define HCI_TRANSPORT_ENABLED 0 +#endif +#if HCI_TRANSPORT_ENABLED +// HCI_MAX_PACKET_SIZE_IN_BITS - Maximum size of a single application packet in bits. +#ifndef HCI_MAX_PACKET_SIZE_IN_BITS +#define HCI_MAX_PACKET_SIZE_IN_BITS 8000 +#endif + +#endif //HCI_TRANSPORT_ENABLED +// + +// LED_SOFTBLINK_ENABLED - led_softblink - led_softblink module + + +#ifndef LED_SOFTBLINK_ENABLED +#define LED_SOFTBLINK_ENABLED 0 +#endif + +// LOW_POWER_PWM_ENABLED - low_power_pwm - low_power_pwm module + + +#ifndef LOW_POWER_PWM_ENABLED +#define LOW_POWER_PWM_ENABLED 0 +#endif + +// MEM_MANAGER_ENABLED - mem_manager - Dynamic memory allocator +//========================================================== +#ifndef MEM_MANAGER_ENABLED +#define MEM_MANAGER_ENABLED 0 +#endif +#if MEM_MANAGER_ENABLED +// MEMORY_MANAGER_SMALL_BLOCK_COUNT - Size of each memory blocks identified as 'small' block. <0-255> + + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT +#define MEMORY_MANAGER_SMALL_BLOCK_COUNT 1 +#endif + +// MEMORY_MANAGER_SMALL_BLOCK_SIZE - Size of each memory blocks identified as 'small' block. +// Size of each memory blocks identified as 'small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_SIZE +#define MEMORY_MANAGER_SMALL_BLOCK_SIZE 32 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_COUNT - Size of each memory blocks identified as 'medium' block. <0-255> + + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT +#define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_SIZE - Size of each memory blocks identified as 'medium' block. +// Size of each memory blocks identified as 'medium' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_SIZE +#define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_COUNT - Size of each memory blocks identified as 'large' block. <0-255> + + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT +#define MEMORY_MANAGER_LARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_SIZE - Size of each memory blocks identified as 'large' block. +// Size of each memory blocks identified as 'large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_SIZE +#define MEMORY_MANAGER_LARGE_BLOCK_SIZE 256 +#endif + +// MEM_MANAGER_ENABLE_LOGS - Enable debug trace in the module. + + +#ifndef MEM_MANAGER_ENABLE_LOGS +#define MEM_MANAGER_ENABLE_LOGS 0 +#endif + +// MEM_MANAGER_DISABLE_API_PARAM_CHECK - Disable API parameter checks in the module. + + +#ifndef MEM_MANAGER_DISABLE_API_PARAM_CHECK +#define MEM_MANAGER_DISABLE_API_PARAM_CHECK 0 +#endif + +#endif //MEM_MANAGER_ENABLED +// + +// NRF_CSENSE_ENABLED - nrf_csense - nrf_csense module +//========================================================== +#ifndef NRF_CSENSE_ENABLED +#define NRF_CSENSE_ENABLED 0 +#endif +#if NRF_CSENSE_ENABLED +// NRF_CSENSE_PAD_HYSTERESIS - Minimal value of change to decide that pad was touched. +#ifndef NRF_CSENSE_PAD_HYSTERESIS +#define NRF_CSENSE_PAD_HYSTERESIS 15 +#endif + +// NRF_CSENSE_PAD_DEVIATION - Minimal value measured on pad to take its value while calculating step. +#ifndef NRF_CSENSE_PAD_DEVIATION +#define NRF_CSENSE_PAD_DEVIATION 70 +#endif + +// NRF_CSENSE_MIN_PAD_VALUE - Minimum normalized value on pad to take its value into account. +#ifndef NRF_CSENSE_MIN_PAD_VALUE +#define NRF_CSENSE_MIN_PAD_VALUE 20 +#endif + +// NRF_CSENSE_MAX_PADS_NUMBER - Maximum number of pads used for one instance. +#ifndef NRF_CSENSE_MAX_PADS_NUMBER +#define NRF_CSENSE_MAX_PADS_NUMBER 20 +#endif + +// NRF_CSENSE_MAX_VALUE - Maximum normalized value got from measurement. +#ifndef NRF_CSENSE_MAX_VALUE +#define NRF_CSENSE_MAX_VALUE 1000 +#endif + +// NRF_CSENSE_OUTPUT_PIN - Output pin used by lower module. +// This is only used when running on NRF51. + +#ifndef NRF_CSENSE_OUTPUT_PIN +#define NRF_CSENSE_OUTPUT_PIN 30 +#endif + +#endif //NRF_CSENSE_ENABLED +// + +// NRF_DRV_CSENSE_ENABLED - nrf_drv_csense - Capacitive sensor module +//========================================================== +#ifndef NRF_DRV_CSENSE_ENABLED +#define NRF_DRV_CSENSE_ENABLED 0 +#endif +#if NRF_DRV_CSENSE_ENABLED +// TIMER0_FOR_CSENSE - First TIMER instance used by the driver (except nRF51) +#ifndef TIMER0_FOR_CSENSE +#define TIMER0_FOR_CSENSE 1 +#endif + +// TIMER1_FOR_CSENSE - Second TIMER instance used by the driver (except nRF51) +#ifndef TIMER1_FOR_CSENSE +#define TIMER1_FOR_CSENSE 2 +#endif + +// MEASUREMENT_PERIOD - Single measurement period. +// Time of single measurement can be calculated as T = (1/2)*MEASUREMENT_PERIOD*(1/f_OSC) where f_OSC = I_SOURCE / (2C*(VUP-VDOWN) ). I_SOURCE, VUP and VDOWN are values used to initialize COMP and C is capacitance of used pad. + +#ifndef MEASUREMENT_PERIOD +#define MEASUREMENT_PERIOD 20 +#endif + +#endif //NRF_DRV_CSENSE_ENABLED +// + +// RETARGET_ENABLED - retarget - Retargeting stdio functions + + +#ifndef RETARGET_ENABLED +#define RETARGET_ENABLED 1 +#endif + +// SLIP_ENABLED - slip - SLIP encoding decoding + + +#ifndef SLIP_ENABLED +#define SLIP_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_Log + +//========================================================== +// NRF_LOG_ENABLED - nrf_log - Logging +//========================================================== +#ifndef NRF_LOG_ENABLED +#define NRF_LOG_ENABLED 0 +#endif +#if NRF_LOG_ENABLED +// NRF_LOG_USES_COLORS - If enabled then ANSI escape code for colors is prefixed to every string +//========================================================== +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif +#if NRF_LOG_USES_COLORS +// NRF_LOG_COLOR_DEFAULT - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +// NRF_LOG_ERROR_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_ERROR_COLOR +#define NRF_LOG_ERROR_COLOR 0 +#endif + +// NRF_LOG_WARNING_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_WARNING_COLOR +#define NRF_LOG_WARNING_COLOR 0 +#endif + +#endif //NRF_LOG_USES_COLORS +// + +// NRF_LOG_DEFAULT_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 3 +#endif + +// NRF_LOG_DEFERRED - Enable deffered logger. + +// Log data is buffered and can be processed in idle. +//========================================================== +#ifndef NRF_LOG_DEFERRED +#define NRF_LOG_DEFERRED 1 +#endif +#if NRF_LOG_DEFERRED +// NRF_LOG_DEFERRED_BUFSIZE - Size of the buffer for logs in words. +// Must be power of 2 + +#ifndef NRF_LOG_DEFERRED_BUFSIZE +#define NRF_LOG_DEFERRED_BUFSIZE 256 +#endif + +#endif //NRF_LOG_DEFERRED +// + +// NRF_LOG_USES_TIMESTAMP - Enable timestamping + + +// Function for getting the timestamp is provided by the user + +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif + +#endif //NRF_LOG_ENABLED +// + +// +//========================================================== + +// <<< end of configuration section >>> +#endif //SDK_CONFIG_H + diff --git a/nrf5/sdk/sdk_common.mk b/nrf5/sdk/sdk_common.mk new file mode 100644 index 0000000000..cc75446b35 --- /dev/null +++ b/nrf5/sdk/sdk_common.mk @@ -0,0 +1,27 @@ + +SDK_MODULES ?= + +ifeq ($(SD), s1xx) + SDK_MODULES = iot_0.9.0 +else ifeq ($(SD), s110) + SDK_MODULES = sdk_10.0.0 +else ifeq ($(SD), s120) + SDK_MODULES = sdk_10.0.0 + $(error No supported BLE wrapper) +else ifeq ($(SD), s130) + SDK_MODULES = sdk_10.0.0 +else ifeq ($(SD), s132) + SDK_MODULES = sdk_12.1.0 +else + $(error No SDK configured for this SD) +endif + +SDK_MODULES_PATH = sdk/$(SDK_MODULES)/ + +include $(SDK_MODULES_PATH)sdk.mk + +INC += -I./sdk + +SRC_C += \ + sdk/modble.c \ + sdk/softdevice.c diff --git a/nrf5/sdk/softdevice.c b/nrf5/sdk/softdevice.c index 965bac4c6d..e59ddd66d1 100644 --- a/nrf5/sdk/softdevice.c +++ b/nrf5/sdk/softdevice.c @@ -52,7 +52,7 @@ void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { printf("ERROR: SoftDevice assert!!!"); } #endif -uint32_t softdevice_enable(void) { +uint32_t sd_enable(void) { #if (BLUETOOTH_SD != 100) && (BLUETOOTH_SD != 110) memset(&nrf_nvic_state, 0, sizeof(nrf_nvic_state_t)); #endif @@ -108,11 +108,11 @@ uint32_t softdevice_enable(void) { return err_code; } -void softdevice_disable(void) { +void sd_disable(void) { sd_softdevice_disable(); } -uint8_t softdevice_enabled(void) { +uint8_t sd_enabled(void) { uint8_t is_enabled; uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); @@ -123,7 +123,7 @@ uint8_t softdevice_enabled(void) { return is_enabled; } -void softdevice_address_get(void) { +void sd_address_get(void) { ble_gap_addr_t local_ble_addr; #if (BLUETOOTH_SD != 132) uint32_t err_code = sd_ble_gap_address_get(&local_ble_addr); @@ -157,7 +157,7 @@ void softdevice_address_get(void) { #define APP_CFG_NON_CONN_ADV_TIMEOUT 0 // Disable timeout. #define NON_CONNECTABLE_ADV_INTERVAL MSEC_TO_UNITS(100, UNIT_0_625_MS) -void softdevice_advertise(void) { +void sd_advertise(void) { ble_uuid_t adv_uuids[] = {{.uuid = EDDYSTONE_UUID, .type = BLE_UUID_TYPE_BLE}}; uint8_t encoded_size; uint8_t uuid_encoded[2]; diff --git a/nrf5/sdk/softdevice.h b/nrf5/sdk/softdevice.h index decc7e296f..78cb60a127 100644 --- a/nrf5/sdk/softdevice.h +++ b/nrf5/sdk/softdevice.h @@ -26,13 +26,13 @@ #include -uint32_t softdevice_enable(void); +uint32_t sd_enable(void); -void softdevice_disable(void); +void sd_disable(void); -uint8_t softdevice_enabled(void); +uint8_t sd_enabled(void); -void softdevice_address_get(void); +void sd_address_get(void); -void softdevice_advertise(void); +void sd_advertise(void); diff --git a/nrf5/spi.c b/nrf5/spi.c new file mode 100644 index 0000000000..60e1113f93 --- /dev/null +++ b/nrf5/spi.c @@ -0,0 +1,326 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 +#include + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "extmod/machine_spi.h" +#include "pin.h" +#include "genhdr/pins.h" +#include "spi.h" +#include "hal_spi.h" + +#if MICROPY_PY_MACHINE_SPI + +/// \moduleref pyb +/// \class SPI - a master-driven serial protocol +/// +/// SPI is a serial protocol that is driven by a master. At the physical level +/// there are 3 lines: SCK, MOSI, MISO. +/// +/// See usage model of I2C; SPI is very similar. Main difference is +/// parameters to init the SPI bus: +/// +/// from pyb import SPI +/// spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7) +/// +/// Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be +/// 0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1 +/// to sample data on the first or second clock edge respectively. Crc can be +/// None for no CRC, or a polynomial specifier. +/// +/// Additional method for SPI: +/// +/// data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes +/// buf = bytearray(4) +/// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf +/// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf + +typedef struct _pyb_spi_obj_t { + mp_obj_base_t base; + SPI_HandleTypeDef *spi; +} pyb_spi_obj_t; + +#if defined(MICROPY_HW_SPI0_SCK) +SPI_HandleTypeDef SPIHandle0 = {.instance = NULL}; +#endif + +STATIC const pyb_spi_obj_t machine_spi_obj[] = { + #if defined(MICROPY_HW_SPI0_SCK) + {{&machine_hard_spi_type}, &SPIHandle0}, + #else + {{&machine_hard_spi_type}, NULL}, + #endif +}; + +void spi_init0(void) { + // reset the SPI handles + #if defined(MICROPY_HW_SPI0_SCK) + memset(&SPIHandle0, 0, sizeof(SPI_HandleTypeDef)); + SPIHandle0.instance = SPI0; + #endif +} + +STATIC int spi_find(mp_obj_t id) { + if (MP_OBJ_IS_STR(id)) { + // given a string id + const char *port = mp_obj_str_get_str(id); + if (0) { + #ifdef MICROPY_HW_SPI0_NAME + } else if (strcmp(port, MICROPY_HW_SPI0_NAME) == 0) { + return 1; + #endif + } + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "SPI(%s) does not exist", port)); + } else { + // given an integer id + int spi_id = mp_obj_get_int(id); + if (spi_id >= 0 && spi_id <= MP_ARRAY_SIZE(machine_spi_obj) + && machine_spi_obj[spi_id].spi != NULL) { + return spi_id; + } + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "SPI(%d) does not exist", spi_id)); + } +} + +void spi_init(SPI_HandleTypeDef *spi, bool enable_nss_pin) { +} + +void spi_deinit(SPI_HandleTypeDef *spi) { +} + +STATIC void spi_transfer(const pyb_spi_obj_t * self, size_t len, const uint8_t * src, uint8_t * dest, uint32_t timeout) { + hal_spi_master_tx_rx(self->spi->instance, len, src, dest); +} + +STATIC void spi_print(const mp_print_t *print, SPI_HandleTypeDef *spi, bool legacy) { + uint spi_num = 0; // default to SPI1 + mp_printf(print, "SPI(%u)", spi_num); +} + +/******************************************************************************/ +/* MicroPython bindings for machine API */ + +// for make_new +enum { + ARG_NEW_id, + ARG_NEW_baudrate, + ARG_NEW_polarity, + ARG_NEW_phase, + ARG_NEW_bits, + ARG_NEW_firstbit, + ARG_NEW_sck, + ARG_NEW_mosi, + ARG_NEW_miso +}; + +// for init +enum { + ARG_INIT_baudrate, + ARG_INIT_polarity, + ARG_INIT_phase, + ARG_INIT_bits, + ARG_INIT_firstbit +}; + +STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args); +STATIC void machine_hard_spi_init(mp_obj_t self, mp_arg_val_t *args); +STATIC void machine_hard_spi_deinit(mp_obj_t self); + +/* common code for both soft and hard implementations *************************/ + +STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, + { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0 /* SPI_FIRSTBIT_MSB */} }, + { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_NEW_id].u_obj == MP_OBJ_NEW_SMALL_INT(-1)) { + // TODO: implement soft SPI + // return machine_soft_spi_make_new(args); + return mp_const_none; + } else { + // hardware peripheral id given + return machine_hard_spi_make_new(args); + } +} + +STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + // parse args + mp_obj_t self = pos_args[0]; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // dispatch to specific implementation + if (mp_obj_get_type(self) == &machine_hard_spi_type) { + machine_hard_spi_init(self, args); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init); + +STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) { + // dispatch to specific implementation + if (mp_obj_get_type(self) == &machine_hard_spi_type) { + machine_hard_spi_deinit(self); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit); + +STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_spi_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, + + { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(0) }, // SPI_FIRSTBIT_MSB + { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(1) }, // SPI_FIRSTBIT_LSB +}; + +STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_table); + +/* code for hard implementation ***********************************************/ + +typedef struct _machine_hard_spi_obj_t { + mp_obj_base_t base; + const pyb_spi_obj_t *pyb; +} machine_hard_spi_obj_t; + +STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = { + {{&machine_hard_spi_type}, &machine_spi_obj[0]}, +}; + +STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_hard_spi_obj_t *self = self_in; + spi_print(print, self->pyb->spi, false); +} + +STATIC mp_obj_t machine_hard_spi_make_new(mp_arg_val_t *args) { + // get static peripheral object + int spi_id = spi_find(args[ARG_NEW_id].u_obj); + const machine_hard_spi_obj_t *self = &machine_hard_spi_obj[spi_id]; + + hal_spi_init_t spi_init_conf; + + // here we would check the sck/mosi/miso pins and configure them + if (args[ARG_NEW_sck].u_obj != MP_OBJ_NULL + && args[ARG_NEW_mosi].u_obj != MP_OBJ_NULL + && args[ARG_NEW_miso].u_obj != MP_OBJ_NULL) { + + spi_init_conf.clk_pin = mp_obj_get_int(args[ARG_NEW_sck].u_obj); + spi_init_conf.mosi_pin = mp_obj_get_int(args[ARG_NEW_mosi].u_obj); + spi_init_conf.miso_pin = mp_obj_get_int(args[ARG_NEW_miso].u_obj); + spi_init_conf.enable_pin = MICROPY_HW_SPI0_NSS; + } else { + spi_init_conf.clk_pin = MICROPY_HW_SPI0_SCK; + spi_init_conf.mosi_pin = MICROPY_HW_SPI0_MOSI; + spi_init_conf.miso_pin = MICROPY_HW_SPI0_MISO; + spi_init_conf.enable_pin = MICROPY_HW_SPI0_NSS; + } + + int baudrate = args[ARG_NEW_baudrate].u_int; + + if (baudrate <= 125000) { + spi_init_conf.freq = HAL_FREQ_125_Kbps; + } else if (baudrate <= 250000) { + spi_init_conf.freq = HAL_FREQ_250_Kbps; + } else if (baudrate <= 500000) { + spi_init_conf.freq = HAL_FREQ_500_Kbps; + } else if (baudrate <= 1000000) { + spi_init_conf.freq = HAL_FREQ_1_Mbps; + } else if (baudrate <= 2000000) { + spi_init_conf.freq = HAL_FREQ_2_Mbps; + } else if (baudrate <= 4000000) { + spi_init_conf.freq = HAL_FREQ_4_Mbps; + } else { + spi_init_conf.freq = HAL_FREQ_8_Mbps; + } + + spi_init_conf.irq_priority = 4; + spi_init_conf.mode = HAL_SPI_MODE_CPOL0_CPHA0; + spi_init_conf.lsb_first = false; + hal_spi_master_init(self->pyb->spi->instance, &spi_init_conf); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC void machine_hard_spi_init(mp_obj_t self_in, mp_arg_val_t *args) { +} + +STATIC void machine_hard_spi_deinit(mp_obj_t self_in) { + machine_hard_spi_obj_t *self = self_in; + spi_deinit(self->pyb->spi); +} + +STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { + machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in; + spi_transfer(self->pyb, len, src, dest, 100); +} + +STATIC const mp_machine_spi_p_t machine_hard_spi_p = { + .transfer = machine_hard_spi_transfer, +}; + +const mp_obj_type_t machine_hard_spi_type = { + { &mp_type_type }, + .name = MP_QSTR_SPI, + .print = machine_hard_spi_print, + .make_new = machine_spi_make_new, + .protocol = &machine_hard_spi_p, + .locals_dict = (mp_obj_t)&machine_spi_locals_dict, +}; + +#endif // MICROPY_PY_MACHINE_SPI diff --git a/nrf5/spi.h b/nrf5/spi.h new file mode 100644 index 0000000000..dc8489d1e0 --- /dev/null +++ b/nrf5/spi.h @@ -0,0 +1,32 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2016 Glenn Ruben Bakke + * + * 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 "hal_spi.h" + +extern const mp_obj_type_t machine_hard_spi_type; + +void spi_init0(void); diff --git a/nrf5/uart.c b/nrf5/uart.c index 76fb4e8a47..1d6ca6fb01 100644 --- a/nrf5/uart.c +++ b/nrf5/uart.c @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,6 +24,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include #include #include diff --git a/nrf5/uart.h b/nrf5/uart.h index 6243bfe969..26b79c949f 100644 --- a/nrf5/uart.h +++ b/nrf5/uart.h @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy