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).

This commit is contained in:
Glenn Ruben Bakke 2016-12-13 20:27:26 +01:00
parent 227998f9cd
commit d7dc0b789d
103 changed files with 8409 additions and 314 deletions

View File

@ -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

View File

@ -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 :

398
nrf5/boards/make-pins.py Normal file
View File

@ -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()

View File

@ -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"

View File

@ -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;

View File

@ -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 */

View File

@ -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 */
}

View File

@ -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 */

View File

@ -0,0 +1,32 @@
// nrf51_prefix.c becomes the initial portion of the generated pins file.
#include <stdio.h>
#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, \
}

View File

@ -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 */

View File

@ -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"

View File

@ -0,0 +1,32 @@
// nrf52_prefix.c becomes the initial portion of the generated pins file.
#include <stdio.h>
#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, \
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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__

View File

@ -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
1 UART_RTS PA8
2 UART_TX PA9
3 UART_CTS PA10
4 UART_RX PA11
5 LED_RED PA21
6 LED_GREEN PA22
7 LED_BLUE PA23

View File

@ -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

View File

@ -0,0 +1,3 @@
MCU_SERIES = m0
MCU_VARIANT = nrf51
LD_FILE = boards/nrf51822_aa_s110.ld

View File

@ -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__

View File

@ -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
1 PA0 PA0
2 PA1 PA1
3 PA2 PA2
4 PA3 PA3
5 PA4 PA4
6 PA5 PA5
7 PA6 PA6
8 PA7 PA7
9 UART_RTS PA8
10 UART_TX PA9
11 UART_CTS PA10
12 UART_RX PA11
13 PA12 PA12
14 PA13 PA13
15 PA14 PA14
16 PA15 PA15
17 PA16 PA16
18 PA17 PA17
19 PA18 PA18
20 PA19 PA19
21 PA20 PA20
22 PA21 PA21
23 PA22 PA22
24 PA23 PA23
25 PA24 PA24
26 PA25 PA25
27 PA26 PA26
28 PA27 PA27
29 PA28 PA28
30 PA29 PA29
31 PA30 PA30
32 PA31 PA31

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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__

View File

@ -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
1 PA0 PA0
2 PA1 PA1
3 PA2 PA2
4 PA3 PA3
5 PA4 PA4
6 PA5 PA5
7 PA6 PA6
8 PA7 PA7
9 UART_RTS PA8
10 UART_TX PA9
11 UART_CTS PA10
12 UART_RX PA11
13 PA12 PA12
14 PA13 PA13
15 PA14 PA14
16 PA15 PA15
17 PA16 PA16
18 PA17 PA17
19 PA18 PA18
20 PA19 PA19
21 PA20 PA20
22 PA21 PA21
23 PA22 PA22
24 PA23 PA23
25 PA24 PA24
26 PA25 PA25
27 PA26 PA26
28 PA27 PA27
29 PA28 PA28
30 PA29 PA29
31 PA30 PA30
32 PA31 PA31

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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__

View File

@ -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
1 UART_RTS PA8
2 UART_TX PA9
3 UART_CTS PA10
4 UART_RX PA11
5 LED_RED PA21
6 LED_GREEN PA22
7 LED_BLUE PA23
8 PA15 PA15
9 PA16 PA16
10 PA17 PA17
11 PA18 PA18
12 PA19 PA19
13 PA20 PA20

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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__

View File

@ -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
1 PA2 PA2
2 PA3 PA3
3 PA4 PA4
4 PA5 PA5
5 PA6 PA6
6 PA7 PA7
7 PA8 PA8
8 PA9 PA9
9 PA10 PA10
10 PA11 PA11
11 PA12 PA12
12 PA13 PA13
13 PA14 PA14
14 PA15 PA15
15 PA16 PA16
16 PA17 PA17
17 PA18 PA18
18 PA19 PA19
19 PA20 PA20
20 PA21 PA21
21 PA22 PA22
22 PA23 PA23
23 PA24 PA24
24 PA25 PA25
25 PA26 PA26
26 PA27 PA27
27 PA28 PA28
28 PA29 PA29
29 PA30 PA30
30 PA31 PA31

30
nrf5/builtin_open.c Normal file
View File

@ -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);

View File

@ -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

46
nrf5/fatfs_port.c Normal file
View File

@ -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);
}

View File

@ -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

122
nrf5/hal/hal_spi.c Normal file
View File

@ -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 <stdint.h>
#include <stdio.h>
#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

105
nrf5/hal/hal_spi.h Normal file
View File

@ -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__

135
nrf5/hal/hal_spie.c Normal file
View File

@ -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 <stdint.h>
#include <stdio.h>
#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

116
nrf5/hal/hal_time.c Normal file
View File

@ -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

32
nrf5/hal/hal_time.h Normal file
View File

@ -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__

View File

@ -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

View File

@ -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

31
nrf5/hal/nrf51_hal.h Normal file
View File

@ -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 <nrf51.h>
#include <nrf51_bitfields.h>
// include config from board
#include "nrf51_hal_conf.h"

31
nrf5/hal/nrf52_hal.h Normal file
View File

@ -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 <nrf52.h>
#include <nrf52_bitfields.h>
// include config from board
#include "nrf52_hal_conf.h"

View File

@ -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

View File

@ -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

View File

@ -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

35
nrf5/lexerfatfs.c Normal file
View File

@ -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);
}

View File

@ -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 <stdint.h>
#include <stdio.h>
#include <string.h>
@ -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) {
}

185
nrf5/modmachine.c Normal file
View File

@ -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 <stdio.h>
#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,
};

42
nrf5/modmachine.h Normal file
View File

@ -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__

97
nrf5/modnetwork.c Normal file
View File

@ -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 <stdio.h>
#include <stdint.h>
#include <string.h>
#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

81
nrf5/modnetwork.h Normal file
View File

@ -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);

View File

@ -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 }*/
};

9
nrf5/modules/mountsd.py Normal file
View File

@ -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, '/')

278
nrf5/modules/sdcard.py Normal file
View File

@ -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

411
nrf5/moduos.c Normal file
View File

@ -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 <stdint.h>
#include <string.h>
#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,
};

480
nrf5/modusocket.c Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#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 <nrf.h>
// 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

52
nrf5/modutime.c Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#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,
};

View File

@ -27,7 +27,7 @@
#ifndef NRF5_MPCONFIGPORT_H__
#define NRF5_MPCONFIGPORT_H__
#include <stdint.h>
#include <mpconfigboard.h>
// 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 <alloca.h>
#include "mpconfigboard.h"
#define MICROPY_PIN_DEFS_PORT_H "pin_defs_nrf5.h"
#endif

View File

@ -23,6 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <errno.h>
#include <string.h>
@ -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) {

View File

@ -27,10 +27,9 @@
#ifndef __NRF52_HAL
#define __NRF52_HAL
#include <stdbool.h>
#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

32
nrf5/nrf51_af.csv Normal file
View File

@ -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
1 PA0 PA0
2 PA1 PA1
3 PA2 PA2
4 PA3 PA3
5 PA4 PA4
6 PA5 PA5
7 PA6 PA6
8 PA7 PA7
9 PA8 PA8
10 PA9 PA9
11 PA10 PA10
12 PA11 PA11
13 PA12 PA12
14 PA13 PA13
15 PA14 PA14
16 PA15 PA15
17 PA16 PA16
18 PA17 PA17
19 PA18 PA18
20 PA19 PA19
21 PA20 PA20
22 PA21 PA21
23 PA22 PA22
24 PA23 PA23
25 PA24 PA24
26 PA25 PA25
27 PA26 PA26
28 PA27 PA27
29 PA28 PA28
30 PA29 PA29
31 PA30 PA30
32 PA31 PA31

32
nrf5/nrf52_af.csv Normal file
View File

@ -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
1 PA0 PA0
2 PA1 PA1
3 PA2 PA2
4 PA3 PA3
5 PA4 PA4
6 PA5 PA5
7 PA6 PA6
8 PA7 PA7
9 PA8 PA8
10 PA9 PA9
11 PA10 PA10
12 PA11 PA11
13 PA12 PA12
14 PA13 PA13
15 PA14 PA14
16 PA15 PA15
17 PA16 PA16
18 PA17 PA17
19 PA18 PA18
20 PA19 PA19
21 PA20 PA20
22 PA21 PA21
23 PA22 PA22
24 PA23 PA23
25 PA24 PA24
26 PA25 PA25
27 PA26 PA26
28 PA27 PA27
29 PA28 PA28
30 PA29 PA29
31 PA30 PA30
32 PA31 PA31

611
nrf5/pin.c Normal file
View File

@ -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 <stdio.h>
#include <stdint.h>
#include <string.h>
#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,
};

101
nrf5/pin.h Normal file
View File

@ -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__

58
nrf5/pin_defs_nrf5.h Normal file
View File

@ -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;

92
nrf5/pin_named_pins.c Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#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, "<Pin.%q>", 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;
}
*/

View File

@ -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=<softdevice> 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

118
nrf5/sdk/iot_0.9.0/build.mk Normal file
View File

@ -0,0 +1,118 @@
# this file's folder
SDK_DIR := $(SDK_ROOT)
# -D<define> 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 \

View File

@ -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 <stdio.h>
#include <stdint.h>
#include <string.h>
#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

12
nrf5/sdk/iot_0.9.0/sdk.mk Normal file
View File

@ -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))

View File

@ -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__

View File

@ -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 <stdbool.h>
#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) {
;
}
}

View File

@ -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);

View File

@ -28,6 +28,8 @@
#include <stdint.h>
#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

40
nrf5/sdk/nrf5_sdk_conf.h Normal file
View File

@ -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

View File

@ -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

View File

@ -0,0 +1,103 @@
# this file's folder
SDK_DIR := $(SDK_ROOT)
# -D<define> 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 \

View File

@ -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"

View File

@ -0,0 +1,19 @@
#include <stdint.h>
#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
}

View File

@ -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();
}
}

View File

@ -0,0 +1,4 @@
#pragma once
void nrf52_ble_init(void);

View File

@ -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}

View File

@ -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

File diff suppressed because it is too large Load Diff

27
nrf5/sdk/sdk_common.mk Normal file
View File

@ -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

View File

@ -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];

View File

@ -26,13 +26,13 @@
#include <stdint.h>
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);

326
nrf5/spi.c Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#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

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