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:
parent
227998f9cd
commit
d7dc0b789d
145
nrf5/Makefile
145
nrf5/Makefile
@ -5,66 +5,89 @@ ifeq ($(wildcard boards/$(BOARD)/.),)
|
||||
$(error Invalid BOARD specified)
|
||||
endif
|
||||
|
||||
check_defined = \
|
||||
$(strip $(foreach 1,$1, \
|
||||
$(call __check_defined,$1,$(strip $(value 2)))))
|
||||
__check_defined = \
|
||||
$(if $(value $1),, \
|
||||
$(error Undefined $1$(if $2, ($2))))
|
||||
|
||||
# If SoftDevice is selected, try to use that one.
|
||||
SD ?= none
|
||||
SD ?=
|
||||
SD_LOWER = $(shell echo $(SD) | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# TODO: Verify that it is a valid target.
|
||||
|
||||
|
||||
ifeq ($(SD), none)
|
||||
ifeq ($(SD), )
|
||||
# If the build directory is not given, make it reflect the board name.
|
||||
BUILD ?= build-$(BOARD)
|
||||
include ../py/mkenv.mk
|
||||
include boards/$(BOARD)/mpconfigboard.mk
|
||||
else
|
||||
$(call check_defined, SDK_ROOT, path to SDK containing softdevice)
|
||||
# If the build directory is not given, make it reflect the board name.
|
||||
BUILD ?= build-$(BOARD)-$(SD_LOWER)
|
||||
include ../py/mkenv.mk
|
||||
include boards/$(BOARD)/mpconfigboard_$(SD_LOWER).mk
|
||||
|
||||
include sdk/sdk_common.mk
|
||||
endif
|
||||
|
||||
# qstr definitions (must come before including py.mk)
|
||||
QSTR_DEFS = qstrdefsport.h
|
||||
QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
|
||||
|
||||
FROZEN_MPY_DIR = modules
|
||||
|
||||
# include py core make definitions
|
||||
include ../py/py.mk
|
||||
|
||||
|
||||
FATFS_DIR = lib/fatfs
|
||||
MPY_CROSS = ../mpy-cross/mpy-cross
|
||||
MPY_TOOL = ../tools/mpy-tool.py
|
||||
|
||||
CROSS_COMPILE = arm-none-eabi-
|
||||
|
||||
MCU_VARIANT_LOWER = $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]')
|
||||
MCU_VARIANT_UPPER = $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
INC = -I.
|
||||
INC += -I.
|
||||
INC += -I..
|
||||
INC += -I$(BUILD)
|
||||
INC += -I./device
|
||||
INC += -I./../lib/cmsis/inc
|
||||
INC += -I./device
|
||||
INC += -I./device/$(MCU_VARIANT_LOWER)
|
||||
INC += -I./device/$(MCU_VARIANT)
|
||||
INC += -I./hal
|
||||
INC += -I./hal/$(MCU_VARIANT_LOWER)
|
||||
INC += -I./hal/$(MCU_VARIANT)
|
||||
INC += -I./drivers
|
||||
INC += -I../lib/mp-readline
|
||||
|
||||
NRF_DEFINES = -D$(MCU_VARIANT)
|
||||
NRF_DEFINES = -D$(MCU_VARIANT_UPPER)
|
||||
NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET
|
||||
|
||||
CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion
|
||||
|
||||
CFLAGS_MCU_m4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
|
||||
CFLAGS_MCU_m4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections
|
||||
|
||||
CFLAGS_MCU_m0 = $(CFLAGS_CORTEX_M) --short-enums -mtune=cortex-m0 -mcpu=cortex-m0 -mfloat-abi=soft -fno-builtin
|
||||
|
||||
|
||||
CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES))
|
||||
CFLAGS += $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(COPT) $(NRF_DEFINES)
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -Iboards/$(BOARD)
|
||||
CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>'
|
||||
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
|
||||
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
|
||||
|
||||
LDFLAGS = $(CFLAGS)
|
||||
LDFLAGS += -Xlinker -Map=$(@:.elf=.map)
|
||||
LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE)
|
||||
LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE) -L boards/
|
||||
|
||||
#Debugging/Optimization
|
||||
ifeq ($(DEBUG), 1)
|
||||
#ASMFLAGS += -g -gtabs+
|
||||
CFLAGS += -O0 -ggdb
|
||||
LDFLAGS += -O0
|
||||
else
|
||||
@ -72,46 +95,132 @@ CFLAGS += -Os -DNDEBUG
|
||||
LDFLAGS += -Os
|
||||
endif
|
||||
|
||||
LIBS =
|
||||
LIBS += \
|
||||
|
||||
SRC_LIB = $(addprefix lib/,\
|
||||
libc/string0.c \
|
||||
mp-readline/readline.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/pyhelp.c \
|
||||
timeutils/timeutils.c \
|
||||
fatfs/ff.c \
|
||||
fatfs/option/ccsbcs.c \
|
||||
netutils/netutils.c \
|
||||
)
|
||||
|
||||
SRC_HAL = $(addprefix hal/,\
|
||||
hal_uart.c \
|
||||
hal_uarte.c \
|
||||
hal_spi.c \
|
||||
hal_spie.c \
|
||||
hal_time.c \
|
||||
)
|
||||
|
||||
SRC_C += \
|
||||
main.c \
|
||||
device/$(MCU_VARIANT_LOWER)/system_$(MCU_VARIANT_LOWER).c \
|
||||
modpyb.c \
|
||||
led.c \
|
||||
mphalport.c \
|
||||
uart.c \
|
||||
spi.c \
|
||||
help.c \
|
||||
gccollect.c \
|
||||
pin_named_pins.c \
|
||||
modmachine.c \
|
||||
pin.c \
|
||||
modutime.c \
|
||||
moduos.c \
|
||||
fatfs_port.c \
|
||||
builtin_open.c \
|
||||
lexerfatfs.c \
|
||||
modusocket.c \
|
||||
modnetwork.c \
|
||||
|
||||
#ifeq ($(SD), )
|
||||
|
||||
SRC_C += \
|
||||
device/$(MCU_VARIANT)/system_$(MCU_VARIANT).c \
|
||||
|
||||
SRC_S = \
|
||||
device/$(MCU_VARIANT_LOWER)/startup_$(MCU_VARIANT_LOWER).s \
|
||||
device/$(MCU_VARIANT)/startup_$(MCU_VARIANT).s \
|
||||
|
||||
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o))
|
||||
#endif
|
||||
|
||||
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
|
||||
OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o))
|
||||
OBJ += $(BUILD)/pins_gen.o
|
||||
OBJ += $(BUILD)/$(BUILD)/frozen_mpy.o
|
||||
|
||||
|
||||
.phony: all flash
|
||||
$(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os
|
||||
$(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os
|
||||
|
||||
.phony: all flash sd
|
||||
|
||||
all: $(BUILD)/firmware.elf binary hex
|
||||
|
||||
flash: $(BUILD)/firmware.elf
|
||||
nrfjprog --program $(BUILD)/firmware.hex --sectorerase -f $(MCU_VARIANT_LOWER)
|
||||
nrfjprog --pinreset -f $(MCU_VARIANT_LOWER)
|
||||
nrfjprog --program $(BUILD)/firmware.hex --sectorerase -f $(MCU_VARIANT)
|
||||
nrfjprog --pinreset -f $(MCU_VARIANT)
|
||||
|
||||
sd:
|
||||
nrfjprog --eraseall -f $(MCU_VARIANT)
|
||||
nrfjprog --program $(SOFTDEV_HEX) -f $(MCU_VARIANT)
|
||||
nrfjprog --program $(BUILD)/firmware.hex --sectorerase -f $(MCU_VARIANT)
|
||||
nrfjprog --pinreset -f $(MCU_VARIANT)
|
||||
|
||||
$(BUILD)/firmware.elf: $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
$(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(SRC_C) $(SRC_MOD) $(SRC_LIB)
|
||||
|
||||
# Append any auto-generated sources that are needed by sources listed in
|
||||
# SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
# Making OBJ use an order-only depenedency on the generated pins.h file
|
||||
# has the side effect of making the pins.h file before we actually compile
|
||||
# any of the objects. The normal dependency generation will deal with the
|
||||
# case when pins.h is modified. But when it doesn't exist, we don't know
|
||||
# which source files might need it.
|
||||
$(OBJ): | $(HEADER_BUILD)/pins.h
|
||||
|
||||
# Use a pattern rule here so that make will only call make-pins.py once to make
|
||||
# both pins_$(BOARD).c and pins.h
|
||||
$(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qstr.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD)
|
||||
$(ECHO) "Create $@"
|
||||
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC)
|
||||
|
||||
$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c
|
||||
$(call compile_c)
|
||||
|
||||
MAKE_PINS = boards/make-pins.py
|
||||
BOARD_PINS = boards/$(BOARD)/pins.csv
|
||||
AF_FILE = $(MCU_VARIANT)_af.csv
|
||||
PREFIX_FILE = boards/$(MCU_VARIANT)_prefix.c
|
||||
GEN_PINS_SRC = $(BUILD)/pins_gen.c
|
||||
GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
|
||||
GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
|
||||
GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
|
||||
GEN_PINS_AF_PY = $(BUILD)/pins_af.py
|
||||
|
||||
# to build .mpy files from .py files
|
||||
$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py
|
||||
@$(ECHO) "MPY $<"
|
||||
$(Q)$(MKDIR) -p $(dir $@)
|
||||
$(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
|
||||
|
||||
# to build frozen_mpy.c from all .mpy files
|
||||
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
|
||||
@$(ECHO) "Creating $@"
|
||||
$(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl mpz $(FROZEN_MPY_MPY_FILES) > $@
|
||||
|
||||
include ../py/mkrules.mk
|
||||
include mkrules.mk
|
||||
|
@ -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
398
nrf5/boards/make-pins.py
Normal 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()
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
32
nrf5/boards/nrf51_prefix.c
Normal file
32
nrf5/boards/nrf51_prefix.c
Normal 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, \
|
||||
}
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
32
nrf5/boards/nrf52_prefix.c
Normal file
32
nrf5/boards/nrf52_prefix.c
Normal 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, \
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
7
nrf5/boards/pca10000/nrf51_hal_conf.h
Normal file
7
nrf5/boards/pca10000/nrf51_hal_conf.h
Normal 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__
|
7
nrf5/boards/pca10000/pins.csv
Normal file
7
nrf5/boards/pca10000/pins.csv
Normal 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,6 +1,3 @@
|
||||
MCU_SERIES = m0
|
||||
MCU_VARIANT = NRF51
|
||||
MCU_VARIANT = nrf51
|
||||
LD_FILE = boards/nrf51822_aa.ld
|
||||
|
||||
SRC_C += \
|
||||
hal/hal_uart.c
|
||||
|
3
nrf5/boards/pca10001/mpconfigboard_s110.mk
Normal file
3
nrf5/boards/pca10001/mpconfigboard_s110.mk
Normal file
@ -0,0 +1,3 @@
|
||||
MCU_SERIES = m0
|
||||
MCU_VARIANT = nrf51
|
||||
LD_FILE = boards/nrf51822_aa_s110.ld
|
8
nrf5/boards/pca10001/nrf51_hal_conf.h
Normal file
8
nrf5/boards/pca10001/nrf51_hal_conf.h
Normal 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__
|
32
nrf5/boards/pca10001/pins.csv
Normal file
32
nrf5/boards/pca10001/pins.csv
Normal 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
|
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
8
nrf5/boards/pca10028/nrf51_hal_conf.h
Normal file
8
nrf5/boards/pca10028/nrf51_hal_conf.h
Normal 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__
|
32
nrf5/boards/pca10028/pins.csv
Normal file
32
nrf5/boards/pca10028/pins.csv
Normal 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
|
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
8
nrf5/boards/pca10031/nrf51_hal_conf.h
Normal file
8
nrf5/boards/pca10031/nrf51_hal_conf.h
Normal 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__
|
13
nrf5/boards/pca10031/pins.csv
Normal file
13
nrf5/boards/pca10031/pins.csv
Normal 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
|
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
10
nrf5/boards/pca10040/nrf52_hal_conf.h
Normal file
10
nrf5/boards/pca10040/nrf52_hal_conf.h
Normal 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__
|
30
nrf5/boards/pca10040/pins.csv
Normal file
30
nrf5/boards/pca10040/pins.csv
Normal 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
|
|
30
nrf5/builtin_open.c
Normal file
30
nrf5/builtin_open.c
Normal 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);
|
@ -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
46
nrf5/fatfs_port.c
Normal 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);
|
||||
}
|
@ -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
122
nrf5/hal/hal_spi.c
Normal 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
105
nrf5/hal/hal_spi.h
Normal 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
135
nrf5/hal/hal_spie.c
Normal 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
116
nrf5/hal/hal_time.c
Normal 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
32
nrf5/hal/hal_time.h
Normal 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__
|
@ -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
|
||||
|
@ -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
31
nrf5/hal/nrf51_hal.h
Normal 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
31
nrf5/hal/nrf52_hal.h
Normal 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"
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
35
nrf5/lexerfatfs.c
Normal 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);
|
||||
}
|
76
nrf5/main.c
76
nrf5/main.c
@ -3,6 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
* Copyright (c) 2015 Glenn Ruben Bakke
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -23,6 +24,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <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
185
nrf5/modmachine.c
Normal 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
42
nrf5/modmachine.h
Normal 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
97
nrf5/modnetwork.c
Normal 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
81
nrf5/modnetwork.h
Normal 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);
|
@ -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
9
nrf5/modules/mountsd.py
Normal 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
278
nrf5/modules/sdcard.py
Normal 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
411
nrf5/moduos.c
Normal 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
480
nrf5/modusocket.c
Normal 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
52
nrf5/modutime.c
Normal 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,
|
||||
};
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
32
nrf5/nrf51_af.csv
Normal 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
|
|
32
nrf5/nrf52_af.csv
Normal file
32
nrf5/nrf52_af.csv
Normal 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
|
|
611
nrf5/pin.c
Normal file
611
nrf5/pin.c
Normal 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
101
nrf5/pin.h
Normal 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
58
nrf5/pin_defs_nrf5.h
Normal 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
92
nrf5/pin_named_pins.c
Normal 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;
|
||||
}
|
||||
*/
|
@ -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
118
nrf5/sdk/iot_0.9.0/build.mk
Normal 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 \
|
||||
|
||||
|
217
nrf5/sdk/iot_0.9.0/modnwble6lowpan.c
Normal file
217
nrf5/sdk/iot_0.9.0/modnwble6lowpan.c
Normal 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
12
nrf5/sdk/iot_0.9.0/sdk.mk
Normal 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))
|
46
nrf5/sdk/iot_0.9.0/sdk_config.h
Normal file
46
nrf5/sdk/iot_0.9.0/sdk_config.h
Normal 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__
|
256
nrf5/sdk/iot_0.9.0/sdkhelp.c
Normal file
256
nrf5/sdk/iot_0.9.0/sdkhelp.c
Normal 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) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
27
nrf5/sdk/iot_0.9.0/sdkhelp.h
Normal file
27
nrf5/sdk/iot_0.9.0/sdkhelp.h
Normal 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);
|
@ -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
40
nrf5/sdk/nrf5_sdk_conf.h
Normal 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
|
17
nrf5/sdk/sdk_10.0.0/sdk.mk
Normal file
17
nrf5/sdk/sdk_10.0.0/sdk.mk
Normal 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
|
103
nrf5/sdk/sdk_12.1.0/build.mk
Normal file
103
nrf5/sdk/sdk_12.1.0/build.mk
Normal 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 \
|
||||
|
40
nrf5/sdk/sdk_12.1.0/nrf52832_aa_s132.ld
Normal file
40
nrf5/sdk/sdk_12.1.0/nrf52832_aa_s132.ld
Normal 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"
|
19
nrf5/sdk/sdk_12.1.0/nrf52_app_error.c
Normal file
19
nrf5/sdk/sdk_12.1.0/nrf52_app_error.c
Normal 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
|
||||
}
|
487
nrf5/sdk/sdk_12.1.0/nrf52_ble.c
Normal file
487
nrf5/sdk/sdk_12.1.0/nrf52_ble.c
Normal 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();
|
||||
}
|
||||
}
|
4
nrf5/sdk/sdk_12.1.0/nrf52_ble.h
Normal file
4
nrf5/sdk/sdk_12.1.0/nrf52_ble.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
void nrf52_ble_init(void);
|
9
nrf5/sdk/sdk_12.1.0/nrf52_board.h
Normal file
9
nrf5/sdk/sdk_12.1.0/nrf52_board.h
Normal 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}
|
19
nrf5/sdk/sdk_12.1.0/sdk.mk
Normal file
19
nrf5/sdk/sdk_12.1.0/sdk.mk
Normal 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
|
2299
nrf5/sdk/sdk_12.1.0/sdk_config.h
Normal file
2299
nrf5/sdk/sdk_12.1.0/sdk_config.h
Normal file
File diff suppressed because it is too large
Load Diff
27
nrf5/sdk/sdk_common.mk
Normal file
27
nrf5/sdk/sdk_common.mk
Normal 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
|
@ -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];
|
||||
|
@ -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
326
nrf5/spi.c
Normal 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
Loading…
x
Reference in New Issue
Block a user