mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Fixed comflicts with master.
This commit is contained in:
commit
cfa49a4dc7
@ -7,6 +7,15 @@
|
||||
Make sure execution stops for native functions if there's an error when parsing arguments
|
||||
NRF5x: remove setName and add functionality to setAdvertising, along with advertising interval
|
||||
NRF5x: allow raw advertising data in setAdvertising
|
||||
Add E.setPassword - allows Espruino console to be locked
|
||||
Fix pin header numbering for BBC micro:bit (it changed for the production version) (fix #896)
|
||||
Allow Magnetometer speed to be specified for Puck.js
|
||||
Fix out of memory when appending a string to itself
|
||||
Allow members of the same name as function arguments to be added to a function (fix #913)
|
||||
Fix STM32F4 RTC stopping if reset during first 1 sec of boot, also fix Espruino WiFi board clock startup
|
||||
Fix issue where native functions couldn't be replaced by non-native fns (fix #879)
|
||||
If statements now return values (fix #909)
|
||||
Fix >8 bit SPI when sending single elements with SPI.send (fix #897)
|
||||
|
||||
1v86 : Compile Telnet server into linux by default, Add '--telnet' command-line option to enable it
|
||||
Fix lock 'leak' in Telnet when Telnet is turned off
|
||||
|
||||
157
Makefile
157
Makefile
@ -75,6 +75,7 @@
|
||||
# # BLACKLIST=/home/mydir/myBlackList
|
||||
# VARIABLES=1700 # Sets number of variables for project defined firmware. This parameter can be dangerous, be careful before changing.
|
||||
# # used in build_platform_config.py
|
||||
# NO_COMPILE=1 # skips compiling and linking part, used to echo WRAPPERSOURCES only
|
||||
|
||||
ifndef GENDIR
|
||||
GENDIR=$(shell pwd)/gen
|
||||
@ -481,10 +482,11 @@ EMBEDDED=1
|
||||
BOARD=NRF52832DK
|
||||
OPTIMIZEFLAGS+=-O3
|
||||
USE_BLUETOOTH=1
|
||||
DEFINES += -DBOARD_PCA10040
|
||||
USE_NET=1
|
||||
USE_GRAPHICS=1
|
||||
DEFINES += -DBOARD_PCA10040 -DPCA10040
|
||||
|
||||
# Uncomment to build Espruino to be transferred over DFU instead of flashed to the device.
|
||||
#DFU_UPDATE_BUILD=1
|
||||
# DFU_UPDATE_BUILD=1 # Uncomment this to build Espruino for a device firmware update over the air.
|
||||
|
||||
else ifdef PUCKJS
|
||||
EMBEDDED=1
|
||||
@ -497,6 +499,8 @@ USE_GRAPHICS=1
|
||||
USE_FILESYSTEM=1
|
||||
USE_CRYPTO=1
|
||||
#USE_TLS=1
|
||||
USE_NFC=1
|
||||
USE_CUSTOM_BOOTLOADER=1
|
||||
|
||||
else ifdef LPC1768
|
||||
EMBEDDED=1
|
||||
@ -637,10 +641,10 @@ ifneq ("$(wildcard /usr/local/include/wiringPi.h)","")
|
||||
USE_WIRINGPI=1
|
||||
else
|
||||
DEFINES+=-DSYSFS_GPIO_DIR="\"/sys/class/gpio\""
|
||||
#$(info *************************************************************)
|
||||
#$(info * WIRINGPI NOT FOUND, and you probably want it *)
|
||||
#$(info * see http://wiringpi.com/download-and-install/ *)
|
||||
#$(info *************************************************************)
|
||||
$(info *************************************************************)
|
||||
$(info * WIRINGPI NOT FOUND, and you probably want it *)
|
||||
$(info * see http://wiringpi.com/download-and-install/ *)
|
||||
$(info *************************************************************)
|
||||
endif
|
||||
|
||||
else ifdef BEAGLEBONE
|
||||
@ -1047,6 +1051,11 @@ ifeq ($(BOARD),MICROBIT)
|
||||
WRAPPERSOURCES += libs/microbit/jswrap_microbit.c
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD),PUCKJS)
|
||||
INCLUDE += -I$(ROOT)/libs/puckjs
|
||||
WRAPPERSOURCES += libs/puckjs/jswrap_puck.c
|
||||
endif
|
||||
|
||||
ifdef USE_CRYPTO
|
||||
DEFINES += -DUSE_CRYPTO
|
||||
INCLUDE += -I$(ROOT)/libs/crypto
|
||||
@ -1306,13 +1315,17 @@ ifeq ($(FAMILY), NRF51)
|
||||
|
||||
SOFTDEVICE = $(NRF5X_SDK_PATH)/components/softdevice/s130/hex/s130_nrf51_2.0.0_softdevice.hex
|
||||
|
||||
LINKER_FILE = $(NRF5X_SDK_PATH)/../nrf5x_linkers/linker_nrf51_ble_espruino_$(LINKER_RAM).ld
|
||||
|
||||
ifdef USE_BOOTLOADER
|
||||
ifdef USE_CUSTOM_BOOTLOADER
|
||||
NRF_BOOTLOADER = $(BOOTLOADER_PROJ_NAME).hex
|
||||
else
|
||||
NRF_BOOTLOADER = $(ROOT)/targetlibs/nrf5x/nrf5_singlebank_bl_hex/nrf51_s130_singlebank_bl.hex
|
||||
NFR_BL_START_ADDR = 0x3C000
|
||||
endif
|
||||
NFR_BL_START_ADDR = 0x3C000# see dfu_gcc_nrf51.ld
|
||||
NRF_BOOTLOADER_SETTINGS = $(ROOT)/targetlibs/nrf5x/nrf5_singlebank_bl_hex/bootloader_settings_nrf51.hex # This file writes 0x3FC00 with 0x01 so we can flash the application with the bootloader.
|
||||
|
||||
LINKER_FILE = $(NRF5X_SDK_PATH)/../nrf5x_linkers/linker_nrf51_ble_espruino_$(LINKER_RAM).ld
|
||||
else
|
||||
LINKER_FILE = $(NRF5X_SDK_PATH)/../nrf5x_linkers/linker_nrf51_ble_espruino_$(LINKER_RAM).ld
|
||||
endif
|
||||
|
||||
endif # FAMILY == NRF51
|
||||
@ -1337,25 +1350,33 @@ ifeq ($(FAMILY), NRF52)
|
||||
|
||||
SOFTDEVICE = $(NRF5X_SDK_PATH)/components/softdevice/s132/hex/s132_nrf52_2.0.0_softdevice.hex
|
||||
|
||||
LINKER_FILE = $(NRF5X_SDK_PATH)/../nrf5x_linkers/linker_nrf52_ble_espruino.ld # TODO: Should have separate linkers like is done in nrf_bootloader branch.
|
||||
|
||||
ifdef USE_BOOTLOADER
|
||||
ifdef USE_CUSTOM_BOOTLOADER
|
||||
NRF_BOOTLOADER = $(BOOTLOADER_PROJ_NAME).hex
|
||||
else
|
||||
NRF_BOOTLOADER = $(ROOT)/targetlibs/nrf5x/nrf5_singlebank_bl_hex/nrf52_s132_singlebank_bl.hex
|
||||
NFR_BL_START_ADDR = 0x7A000
|
||||
endif
|
||||
NFR_BL_START_ADDR = 0x79000 # see Makefile, dfu_gcc_nrf52.ld, linker_nrf52_ble_espruino_bootloader.ld and dfu_types.h
|
||||
NRF_BOOTLOADER_SETTINGS = $(ROOT)/targetlibs/nrf5x/nrf5_singlebank_bl_hex/bootloader_settings_nrf52.hex # Writes address 0x7F000 with 0x01.
|
||||
ifdef BOOTLOADER
|
||||
# we're trying to compile the bootloader itself
|
||||
LINKER_FILE = $(NRF5X_SDK_PATH)/../nrf5x_linkers/dfu_gcc_nrf52.ld
|
||||
OPTIMIZEFLAGS=-Os # try to reduce bootloader size
|
||||
else
|
||||
LINKER_FILE = $(NRF5X_SDK_PATH)/../nrf5x_linkers/linker_nrf52_ble_espruino_bootloader.ld
|
||||
endif
|
||||
else
|
||||
LINKER_FILE = $(NRF5X_SDK_PATH)/../nrf5x_linkers/linker_nrf52_ble_espruino.ld
|
||||
endif
|
||||
endif #FAMILY == NRF52
|
||||
|
||||
|
||||
ifdef NFC
|
||||
ifdef USE_NFC
|
||||
DEFINES += -DUSE_NFC
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/clock
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/nfc/t2t_lib
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/nfc/ndef/uri
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/nfc/ndef/generic/message
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/nfc/ndef/generic/record
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/util/app_util_platform.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/drivers_nrf/clock/nrf_drv_clock.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/nfc/ndef/uri/nfc_uri_msg.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/nfc/ndef/uri/nfc_uri_rec.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/nfc/ndef/generic/message/nfc_ndef_msg.c
|
||||
@ -1441,7 +1462,6 @@ ifeq ($(FAMILY), EFM32GG)
|
||||
endif #FAMILY == EFM32
|
||||
|
||||
ifdef NRF5X
|
||||
|
||||
# Just try and get rid of the compile warnings.
|
||||
CFLAGS += -Wno-sign-conversion -Wno-conversion -Wno-unused-parameter -fomit-frame-pointer #this is for device manager in nordic sdk
|
||||
DEFINES += -DBLUETOOTH -D$(BOARD)
|
||||
@ -1455,10 +1475,19 @@ ifdef NRF5X
|
||||
|
||||
# These files are the Espruino HAL implementation.
|
||||
INCLUDE += -I$(ROOT)/targets/nrf5x
|
||||
SOURCES += \
|
||||
targets/nrf5x/main.c \
|
||||
targets/nrf5x/jshardware.c \
|
||||
targets/nrf5x/nrf5x_utils.c
|
||||
ifdef BOOTLOADER
|
||||
BUILD_LINKER_FLAGS+=--bootloader
|
||||
PROJ_NAME=$(BOOTLOADER_PROJ_NAME)
|
||||
WRAPPERSOURCES =
|
||||
SOURCES = \
|
||||
targets/nrf5x_dfu/main.c \
|
||||
targets/nrf5x_dfu/dfu_ble_svc.c
|
||||
else
|
||||
SOURCES += \
|
||||
targets/nrf5x/main.c \
|
||||
targets/nrf5x/jshardware.c \
|
||||
targets/nrf5x/nrf5x_utils.c
|
||||
endif
|
||||
|
||||
# Careful here.. All these includes and sources assume a SoftDevice. Not efficeint/clean if softdevice (ble) is not enabled...
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components
|
||||
@ -1486,7 +1515,9 @@ ifdef NRF5X
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/trace
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/softdevice/common/softdevice_handler
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/twi_master
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_pwm
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/ppi
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_pwm
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/drivers_nrf/clock
|
||||
|
||||
TARGETSOURCES += \
|
||||
$(NRF5X_SDK_PATH)/components/libraries/util/app_error.c \
|
||||
@ -1508,9 +1539,14 @@ ifdef NRF5X
|
||||
$(NRF5X_SDK_PATH)/components/softdevice/common/softdevice_handler/softdevice_handler.c \
|
||||
$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_nvmc.c \
|
||||
$(NRF5X_SDK_PATH)/components/drivers_nrf/twi_master/nrf_drv_twi.c \
|
||||
$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_adc.c
|
||||
$(NRF5X_SDK_PATH)/components/drivers_nrf/ppi/nrf_drv_ppi.c \
|
||||
$(NRF5X_SDK_PATH)/components/drivers_nrf/hal/nrf_adc.c \
|
||||
$(NRF5X_SDK_PATH)/components/drivers_nrf/clock/nrf_drv_clock.c
|
||||
|
||||
# $(NRF5X_SDK_PATH)/components/libraries/util/nrf_log.c
|
||||
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/util/app_util_platform.c
|
||||
|
||||
ifdef USE_BOOTLOADER
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/ble/device_manager
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/ble/ble_services/ble_dfu
|
||||
@ -1520,6 +1556,40 @@ ifdef NRF5X
|
||||
$(NRF5X_SDK_PATH)/components/ble/ble_services/ble_dfu/ble_dfu.c \
|
||||
$(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/bootloader_util.c \
|
||||
$(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/dfu_app_handler.c
|
||||
ifdef BOOTLOADER
|
||||
DEFINES += -DBOOTLOADER
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/crc16
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/scheduler
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/hci
|
||||
INCLUDE += -I$(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/ble_transport
|
||||
|
||||
TARGETSOURCES = # Make sure we don't include existing files (thanks to pstorage)
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/util/app_error.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/scheduler/app_scheduler.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/timer/app_timer.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/timer/app_timer_appsh.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/util/app_util_platform.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/bootloader.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/bootloader_settings.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/bootloader_util.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/crc16/crc16.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/dfu_single_bank.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/dfu_init_template.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/bootloader_dfu/dfu_transport_ble.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/hci/hci_mem_pool.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/libraries/util/nrf_assert.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/drivers_nrf/delay/nrf_delay.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/drivers_nrf/common/nrf_drv_common.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/drivers_nrf/pstorage/pstorage_raw.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/ble/common/ble_advdata.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/ble/common/ble_conn_params.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/ble/ble_services/ble_dfu/ble_dfu.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/ble/common/ble_srv_common.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/toolchain/system_nrf52.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/softdevice/common/softdevice_handler/softdevice_handler.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/softdevice/common/softdevice_handler/softdevice_handler_appsh.c
|
||||
TARGETSOURCES += $(NRF5X_SDK_PATH)/components/drivers_nrf/clock/nrf_drv_clock.c
|
||||
endif
|
||||
endif
|
||||
|
||||
endif #NRF5X
|
||||
@ -2004,14 +2074,20 @@ $(PROJ_NAME).hex: $(PROJ_NAME).elf
|
||||
ifdef SOFTDEVICE # Shouldn't do this when we want to be able to perform DFU OTA!
|
||||
ifdef USE_BOOTLOADER
|
||||
ifdef DFU_UPDATE_BUILD
|
||||
echo Not merging softdevice or bootloader with application
|
||||
@echo Not merging softdevice or bootloader with application
|
||||
scripts/nrfutil.exe dfu genpkg $(PROJ_NAME).zip --application $(PROJ_NAME).hex --application-version 0xff --dev-revision 1 --dev-type 1 --sd-req 0x81
|
||||
else
|
||||
echo Merging SoftDevice and Bootloader
|
||||
scripts/hexmerge.py $(SOFTDEVICE) $(NRF_BOOTLOADER):$(NFR_BL_START_ADDR): $(PROJ_NAME).hex $(NRF_BOOTLOADER_SETTINGS) -o tmp.hex
|
||||
ifdef BOOTLOADER
|
||||
@echo Not merging anything with bootloader
|
||||
else
|
||||
@echo Merging SoftDevice and Bootloader
|
||||
@echo FIXME - had to set --overlap=replace
|
||||
scripts/hexmerge.py --overlap=replace $(SOFTDEVICE) $(NRF_BOOTLOADER) $(PROJ_NAME).hex $(NRF_BOOTLOADER_SETTINGS) -o tmp.hex
|
||||
mv tmp.hex $(PROJ_NAME).hex
|
||||
endif
|
||||
endif
|
||||
else
|
||||
echo Merging SoftDevice
|
||||
@echo Merging SoftDevice
|
||||
scripts/hexmerge.py $(SOFTDEVICE) $(PROJ_NAME).hex -o tmp.hex
|
||||
mv tmp.hex $(PROJ_NAME).hex
|
||||
endif # USE_BOOTLOADER
|
||||
@ -2028,7 +2104,11 @@ ifndef TRAVIS
|
||||
bash scripts/check_size.sh $(PROJ_NAME).bin
|
||||
endif
|
||||
|
||||
ifdef NRF5X
|
||||
proj: $(PROJ_NAME).lst $(PROJ_NAME).hex
|
||||
else
|
||||
proj: $(PROJ_NAME).lst $(PROJ_NAME).bin $(PROJ_NAME).hex
|
||||
endif
|
||||
|
||||
#proj: $(PROJ_NAME).lst $(PROJ_NAME).hex $(PROJ_NAME).srec $(PROJ_NAME).bin
|
||||
|
||||
@ -2036,7 +2116,7 @@ flash: all
|
||||
ifdef USE_DFU
|
||||
sudo dfu-util -a 0 -s 0x08000000 -D $(PROJ_NAME).bin
|
||||
else ifdef OLIMEXINO_STM32_BOOTLOADER
|
||||
echo Olimexino Serial bootloader
|
||||
@echo Olimexino Serial bootloader
|
||||
dfu-util -a1 -d 0x1EAF:0x0003 -D $(PROJ_NAME).bin
|
||||
else ifdef NUCLEO
|
||||
if [ -d "/media/$(USER)/NUCLEO" ]; then cp $(PROJ_NAME).bin /media/$(USER)/NUCLEO;sync; fi
|
||||
@ -2048,21 +2128,21 @@ else ifdef NRF5X
|
||||
if [ -d "/media/$(USER)/JLINK" ]; then cp $(PROJ_NAME).hex /media/$(USER)/JLINK;sync; fi
|
||||
if [ -d "/media/JLINK" ]; then cp $(PROJ_NAME).hex /media/JLINK;sync; fi
|
||||
else
|
||||
echo ST-LINK flash
|
||||
@echo ST-LINK flash
|
||||
st-flash --reset write $(PROJ_NAME).bin $(BASEADDRESS)
|
||||
endif
|
||||
|
||||
serialflash: all
|
||||
echo STM32 inbuilt serial bootloader, set BOOT0=1, BOOT1=0
|
||||
@echo STM32 inbuilt serial bootloader, set BOOT0=1, BOOT1=0
|
||||
python scripts/stm32loader.py -b 460800 -a $(BASEADDRESS) -ew $(STM32LOADER_FLAGS) $(PROJ_NAME).bin
|
||||
# python scripts/stm32loader.py -b 460800 -a $(BASEADDRESS) -ewv $(STM32LOADER_FLAGS) $(PROJ_NAME).bin
|
||||
|
||||
gdb:
|
||||
echo "target extended-remote :4242" > gdbinit
|
||||
echo "file $(PROJ_NAME).elf" >> gdbinit
|
||||
@echo "target extended-remote :4242" > gdbinit
|
||||
@echo "file $(PROJ_NAME).elf" >> gdbinit
|
||||
#echo "load" >> gdbinit
|
||||
echo "break main" >> gdbinit
|
||||
echo "break HardFault_Handler" >> gdbinit
|
||||
@echo "break main" >> gdbinit
|
||||
@echo "break HardFault_Handler" >> gdbinit
|
||||
$(GDB) -x gdbinit
|
||||
rm gdbinit
|
||||
endif # ---------------------------------------------------
|
||||
@ -2082,3 +2162,8 @@ clean:
|
||||
$(Q)rm -f $(PROJ_NAME).bin
|
||||
$(Q)rm -f $(PROJ_NAME).srec
|
||||
$(Q)rm -f $(PROJ_NAME).lst
|
||||
|
||||
# start make like this "make varsonly" to get all variables created and used during make process without compiling
|
||||
# this helps to better understand linking, or to find oddities
|
||||
varsonly:
|
||||
$(foreach v, $(.VARIABLES), $(info $(v) = $($(v))))
|
||||
|
||||
@ -43,7 +43,7 @@ info = {
|
||||
chip = {
|
||||
'part' : "STM32F411CEU6",
|
||||
'family' : "STM32F4",
|
||||
'package' : "UQFN48",
|
||||
'package' : "UQFN48",
|
||||
'ram' : 96,
|
||||
'flash' : 512,
|
||||
'speed' : 100,
|
||||
@ -66,31 +66,35 @@ devices = {
|
||||
'pin_out' : 'H1' }, # checked
|
||||
'OSC_RTC' : { 'pin_in' : 'C14', # checked
|
||||
'pin_out' : 'C15' }, # checked
|
||||
'BTN1' : { 'pin' : 'C13', 'pinstate' : 'IN_PULLDOWN' },
|
||||
'LED1' : { 'pin' : 'B2' },
|
||||
'BTN1' : { 'pin' : 'C13', 'pinstate' : 'IN_PULLDOWN' },
|
||||
'LED1' : { 'pin' : 'B2' },
|
||||
'LED2' : { 'pin' : 'B12' },
|
||||
'USB' : { 'pin_vsense' : 'A9',
|
||||
'pin_dm' : 'A11', # checked
|
||||
'pin_dp' : 'A12' }, # checked
|
||||
'JTAG' : {
|
||||
'pin_MS' : 'A13',
|
||||
'pin_CK' : 'A14',
|
||||
# 'pin_DI' : 'A15'
|
||||
'pin_CK' : 'A14',
|
||||
# 'pin_DI' : 'A15'
|
||||
},
|
||||
'ESP8266' : { 'pin_rx' : 'A2',
|
||||
'pin_tx' : 'A3',
|
||||
'pin_tx' : 'A3',
|
||||
'pin_cts' : 'A15',
|
||||
'pin_ch_pd' : 'A14',
|
||||
'pin_gpio0' : 'A13',
|
||||
},
|
||||
};
|
||||
|
||||
def rev(x):
|
||||
x.reverse();
|
||||
return x;
|
||||
|
||||
# left-right, or top-bottom order
|
||||
board = {
|
||||
'top' : [ 'B15', 'B14', 'B13', 'B10', 'B1', 'A7', 'A6', 'A5', 'A4', 'A1', 'A0' ],
|
||||
'bottom' : [ 'GND', 'VBAT', '3.3', 'B3', 'B4', 'B5', 'B6', 'B7','B8', 'B9', 'B0'],
|
||||
'left' : rev([ 'B15', 'B14', 'B13', 'B10', 'B1', 'A7', 'A6', 'A5', 'A4', 'A1', 'A0' ]),
|
||||
'right' : rev([ 'GND', 'VBAT', '3.3', 'B3', 'B4', 'B5', 'B6', 'B7','B8', 'B9', 'B0']),
|
||||
|
||||
'right' : ['A10','A8'],
|
||||
'left2' : ['A10','A8'],
|
||||
'_notes' : {
|
||||
'A2' : 'ESP8266 RX',
|
||||
'A3' : 'ESP8266 TX',
|
||||
@ -101,32 +105,30 @@ board = {
|
||||
};
|
||||
board["_css"] = """
|
||||
#board {
|
||||
width: 550px;
|
||||
height: 272px;
|
||||
top: 300px;
|
||||
left : 100px;
|
||||
width: 371px;
|
||||
height: 450px;
|
||||
top: 25px;
|
||||
left : 200px;
|
||||
background-image: url(img/ESPRUINOWIFI.png);
|
||||
}
|
||||
#boardcontainer {
|
||||
height: 800px;
|
||||
height: 500px;
|
||||
}
|
||||
#top {
|
||||
bottom: 253px;
|
||||
left: 194px;
|
||||
#left {
|
||||
top: 10px;
|
||||
right: 370px;
|
||||
}
|
||||
#bottom {
|
||||
top: 255px;
|
||||
left: 192px;
|
||||
#right {
|
||||
top: 10px;
|
||||
left: 370px;
|
||||
}
|
||||
|
||||
#right {
|
||||
top: 60px;
|
||||
left: 540px;
|
||||
#left2 {
|
||||
top: 380px;
|
||||
left: 60px;
|
||||
}
|
||||
.toppin { width: 32px; }
|
||||
.bottompin { width: 32px; }
|
||||
|
||||
.rightpin { height: 17px; }
|
||||
.leftpin { height: 39px; }
|
||||
.rightpin { height: 39px; }
|
||||
.left2pin { height: 39px; }
|
||||
|
||||
""";
|
||||
|
||||
|
||||
@ -55,20 +55,8 @@ chip = {
|
||||
};
|
||||
|
||||
devices = {
|
||||
'BTN1' : { 'pin' : 'D4' }, # 'P0_17'
|
||||
'BTN1' : { 'pin' : 'D5' }, # 'P0_17'
|
||||
'BTN2' : { 'pin' : 'D11' }, # 'P0_26'
|
||||
'LED_COL1' : { 'pin': 'D4' },
|
||||
'LED_COL2' : { 'pin': 'D5' },
|
||||
'LED_COL3' : { 'pin': 'D6' },
|
||||
'LED_COL4' : { 'pin': 'D7' },
|
||||
'LED_COL5' : { 'pin': 'D8' },
|
||||
'LED_COL6' : { 'pin': 'D9' },
|
||||
'LED_COL7' : { 'pin': 'D10' },
|
||||
'LED_COL8' : { 'pin': 'D11' },
|
||||
'LED_COL9' : { 'pin': 'D12' },
|
||||
'LED_ROW1' : { 'pin': 'D13' },
|
||||
'LED_ROW2' : { 'pin': 'D14' },
|
||||
'LED_ROW3' : { 'pin': 'D15' },
|
||||
};
|
||||
|
||||
# left-right, or top-bottom order
|
||||
@ -77,18 +65,12 @@ board = {
|
||||
'D13','D14','D15','D16','3.3','','3.3','','3.3','D19','D20','GND','','GND','','GND' ],
|
||||
'_hide_not_on_connectors' : True,
|
||||
'_notes' : {
|
||||
'D4' : "LED Matrix Column 1",
|
||||
'D5' : "LED Matrix Column 2",
|
||||
'D6' : "LED Matrix Column 3",
|
||||
'D7' : "LED Matrix Column 4",
|
||||
'D8' : "LED Matrix Column 5",
|
||||
'D9' : "LED Matrix Column 6",
|
||||
'D10' : "LED Matrix Column 7",
|
||||
'D11' : "LED Matrix Column 8",
|
||||
'D12' : "LED Matrix Column 9",
|
||||
'D13' : "LED Matrix Row 1",
|
||||
'D14' : "LED Matrix Row 2",
|
||||
'D15' : "LED Matrix Row 3"
|
||||
'D3' : "LED Col 1",
|
||||
'D4' : "LED Col 2",
|
||||
'D6' : "LED Col 9",
|
||||
'D7' : "LED Col 8",
|
||||
'D9' : "LED Col 7",
|
||||
'D10' : "LED Col 3"
|
||||
}
|
||||
};
|
||||
board["_css"] = """
|
||||
@ -117,16 +99,16 @@ board["_css"] = """
|
||||
|
||||
def get_pins():
|
||||
pins = [
|
||||
{ "name":"PD0", "sortingname":"D00", "port":"D", "num":"3", "functions":{ "ADC1_IN4":0 }, "csv":{} },
|
||||
{ "name":"PD0", "sortingname":"D00", "port":"D", "num":"1", "functions":{ "ADC1_IN4":0 }, "csv":{} },
|
||||
{ "name":"PD1", "sortingname":"D01", "port":"D", "num":"2", "functions":{ "ADC1_IN3":0 }, "csv":{} },
|
||||
{ "name":"PD2", "sortingname":"D02", "port":"D", "num":"1", "functions":{ "ADC1_IN2":0 }, "csv":{} },
|
||||
{ "name":"PD3", "sortingname":"D03", "port":"D", "num":"4", "functions":{ "ADC1_IN5":0 }, "csv":{} }, # LED col 1
|
||||
{ "name":"PD4", "sortingname":"D04", "port":"D", "num":"17", "functions":{}, "csv":{} }, # BTNA
|
||||
{ "name":"PD5", "sortingname":"D05", "port":"D", "num":"5", "functions":{ "ADC1_IN6":0 }, "csv":{} }, # LED col 2
|
||||
{ "name":"PD6", "sortingname":"D06", "port":"D", "num":"14", "functions":{}, "csv":{} }, # LED row 2
|
||||
{ "name":"PD7", "sortingname":"D07", "port":"D", "num":"13", "functions":{}, "csv":{} }, # LED row 1
|
||||
{ "name":"PD8", "sortingname":"D08", "port":"D", "num":"18", "functions":{}, "csv":{} },
|
||||
{ "name":"PD9", "sortingname":"D09", "port":"D", "num":"15", "functions":{}, "csv":{} }, # LED row 3
|
||||
{ "name":"PD2", "sortingname":"D02", "port":"D", "num":"3", "functions":{ "ADC1_IN2":0 }, "csv":{} },
|
||||
{ "name":"PD3", "sortingname":"D03", "port":"D", "num":"4", "functions":{ "ADC1_IN5":0 }, "csv":{} }, # LED col 1
|
||||
{ "name":"PD4", "sortingname":"D04", "port":"D", "num":"5", "functions":{}, "csv":{} }, # BTNA
|
||||
{ "name":"PD5", "sortingname":"D05", "port":"D", "num":"17", "functions":{ "ADC1_IN6":0 }, "csv":{} }, # LED col 2
|
||||
{ "name":"PD6", "sortingname":"D06", "port":"D", "num":"12", "functions":{}, "csv":{} }, # LED row 2
|
||||
{ "name":"PD7", "sortingname":"D07", "port":"D", "num":"11", "functions":{}, "csv":{} }, # LED row 1
|
||||
{ "name":"PD8", "sortingname":"D08", "port":"D", "num":"18", "functions":{}, "csv":{} },
|
||||
{ "name":"PD9", "sortingname":"D09", "port":"D", "num":"10", "functions":{}, "csv":{} }, # LED row 3
|
||||
{ "name":"PD10", "sortingname":"D10", "port":"D", "num":"6", "functions":{ "ADC1_IN7":0 }, "csv":{} }, # LED col 3
|
||||
{ "name":"PD11", "sortingname":"D11", "port":"D", "num":"26", "functions":{}, "csv":{} }, # BTNB
|
||||
{ "name":"PD12", "sortingname":"D12", "port":"D", "num":"20", "functions":{}, "csv":{} },
|
||||
@ -134,8 +116,8 @@ def get_pins():
|
||||
{ "name":"PD14", "sortingname":"D14", "port":"D", "num":"22", "functions":{ "SPI1_MISO":0 }, "csv":{} },
|
||||
{ "name":"PD15", "sortingname":"D15", "port":"D", "num":"21", "functions":{ "SPI1_MOSI":0 }, "csv":{} },
|
||||
{ "name":"PD16", "sortingname":"D16", "port":"D", "num":"16", "functions":{}, "csv":{} },
|
||||
{ "name":"PD17", "sortingname":"D17", "port":"D", "num":"31", "functions":{}, "csv":{} }, # FIXME 3.3v
|
||||
{ "name":"PD18", "sortingname":"D18", "port":"D", "num":"31", "functions":{}, "csv":{} }, # FIXME 3.3v
|
||||
{ "name":"PD17", "sortingname":"D17", "port":"D", "num":"31", "functions":{}, "csv":{} }, # FIXME 3.3v
|
||||
{ "name":"PD18", "sortingname":"D18", "port":"D", "num":"31", "functions":{}, "csv":{} }, # FIXME 3.3v
|
||||
{ "name":"PD19", "sortingname":"D19", "port":"D", "num":"0", "functions":{ "I2C1_SCL":0, "ADC1_IN0":0 }, "csv":{} },
|
||||
{ "name":"PD20", "sortingname":"D20", "port":"D", "num":"30", "functions":{ "I2C1_SDA":0 }, "csv":{} },
|
||||
{ "name":"PH0", "sortingname":"H0", "port":"D", "num":"24", "functions":{}, "csv":{} },
|
||||
|
||||
@ -49,7 +49,7 @@ chip = {
|
||||
'saved_code' : {
|
||||
'address' : ((256 - 3) * 1024),
|
||||
'page_size' : 1024,
|
||||
'pages' : 0,
|
||||
'pages' : 3,
|
||||
'flash_available' : (256 - 108 - 16) # total flash pages - softdevice - bootloader
|
||||
}
|
||||
};
|
||||
|
||||
@ -48,7 +48,7 @@ chip = {
|
||||
'saved_code' : {
|
||||
'address' : ((256 - 3) * 1024),
|
||||
'page_size' : 1024,
|
||||
'pages' : 0,
|
||||
'pages' : 3,
|
||||
'flash_available' : (256 - 108 - 16) # total flash pages - softdevice - bootloader
|
||||
}
|
||||
};
|
||||
|
||||
@ -25,7 +25,7 @@ info = {
|
||||
'default_console_baudrate' : "9600",
|
||||
# Number of variables can be WAY higher on this board
|
||||
'variables' : 2040, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
|
||||
'bootloader' : 1,
|
||||
# 'bootloader' : 1,
|
||||
'binary_name' : 'espruino_%v_nrf52832.bin',
|
||||
'build' : {
|
||||
'defines' : [
|
||||
|
||||
@ -38,7 +38,7 @@ chip = {
|
||||
'ram' : 96, # 0x0001 8000 long, from 0x2000 0000 to 0x2001 7FFF
|
||||
'flash' : 512, # 0x0008 0000 long, from 0x0800 0000 to 0x0807 FFFF
|
||||
'speed' : 84,
|
||||
'usart' : 3,
|
||||
'usart' : 6,
|
||||
'spi' : 4,
|
||||
'i2c' : 3,
|
||||
'adc' : 1,
|
||||
|
||||
@ -38,7 +38,7 @@ chip = {
|
||||
'ram' : 128, # 0x0001 8000 long, from 0x2000 0000 to 0x2001 7FFF
|
||||
'flash' : 512, # 0x0008 0000 long, from 0x0800 0000 to 0x0807 FFFF
|
||||
'speed' : 100,
|
||||
'usart' : 3,
|
||||
'usart' : 6,
|
||||
'spi' : 4,
|
||||
'i2c' : 3,
|
||||
'adc' : 1,
|
||||
|
||||
@ -23,7 +23,8 @@ info = {
|
||||
'default_console_rx' : "D29",
|
||||
'default_console_baudrate' : "9600",
|
||||
# Number of variables can be WAY higher on this board
|
||||
'variables' : 1020, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
|
||||
'variables' : 2000, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
|
||||
'bootloader' : 1,
|
||||
'binary_name' : 'espruino_%v_puckjs.bin',
|
||||
'build' : {
|
||||
'defines' : [
|
||||
@ -39,16 +40,16 @@ chip = {
|
||||
'ram' : 64,
|
||||
'flash' : 512,
|
||||
'speed' : 64,
|
||||
'usart' : 1,
|
||||
'usart' : 1,
|
||||
'spi' : 3,
|
||||
'i2c' : 2,
|
||||
'adc' : 1,
|
||||
'dac' : 0,
|
||||
'saved_code' : {
|
||||
'address' : ((128 - 3) * 4096),
|
||||
'address' : ((121 - 3) * 4096), # Bootloader takes pages 121-127
|
||||
'page_size' : 4096,
|
||||
'pages' : 3,
|
||||
'flash_available' : (512 - 124 - 12) # Softdevice uses 31 plages of flash. Each page is 4 kb.
|
||||
'flash_available' : 512 - ((31 + 7 + 3)*4) # Softdevice uses 31 pages of flash, bootloader 7, code 3. Each page is 4 kb.
|
||||
},
|
||||
};
|
||||
|
||||
@ -56,15 +57,17 @@ devices = {
|
||||
'LED1' : { 'pin' : 'D5' },
|
||||
'LED2' : { 'pin' : 'D4' },
|
||||
'LED3' : { 'pin' : 'D3' },
|
||||
'LED4' : { 'pin' : 'D25', 'pin2' : 'D26' },
|
||||
'BTN1' : { 'pin' : 'D0', 'pinstate' : 'IN_PULLDOWN' }
|
||||
# CAPSENSE D8
|
||||
'IR' : { 'pin_anode' : 'D26', 'pin_cathode' : 'D25' },
|
||||
'BTN1' : { 'pin' : 'D0', 'pinstate' : 'IN_PULLDOWN' },
|
||||
'CAPSENSE' : { 'pin_rx' : 'D11', 'pin_tx' : 'D12' }
|
||||
# NFC D9/D10
|
||||
|
||||
};
|
||||
|
||||
# left-right, or top-bottom order
|
||||
board = {
|
||||
'left' : [ 'PD28', 'PD29', 'PD30', 'PD31'],
|
||||
'right' : [ 'GND', '3V', 'D4', 'D5' ],
|
||||
'right' : [ 'GND', '3V', 'D2', 'D1' ],
|
||||
};
|
||||
|
||||
def get_pins():
|
||||
|
||||
BIN
boards/img/ESPRUINOWIFI.png
Normal file
BIN
boards/img/ESPRUINOWIFI.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
@ -46,7 +46,14 @@ You can add more files here if you need. It's up to you!
|
||||
|
||||
## Modify the `Makefile`
|
||||
|
||||
Go to line [606](https://github.com/espruino/Espruino/blob/master/Makefile#L606) and append
|
||||
Find the text
|
||||
```
|
||||
# ---------------------------------------------------------------------------------
|
||||
# When adding stuff here, also remember build_pininfo, platform_config.h, jshardware.c
|
||||
# TODO: Load more of this out of the BOARDNAME.py files if at all possible (see next section)
|
||||
# ---------------------------------------------------------------------------------
|
||||
```
|
||||
and add those two lines just before it
|
||||
|
||||
```make
|
||||
INCLUDE += -I$(ROOT)/libs/hello
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "jswrap_bluetooth.h"
|
||||
#include "jsinteractive.h"
|
||||
#include "jsdevices.h"
|
||||
#include "nrf5x_utils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@ -33,6 +34,11 @@
|
||||
bool nfcEnabled = false;
|
||||
#endif
|
||||
|
||||
#undef USE_BOOTLOADER // FIXME - this now errors with 0x4001 - not sure why
|
||||
//... but then IMO we don't want to be able to enable DFU directly from BLE
|
||||
//... much better to
|
||||
|
||||
|
||||
#ifdef USE_BOOTLOADER
|
||||
#include "device_manager.h"
|
||||
#include "pstorage.h"
|
||||
@ -115,9 +121,10 @@ typedef enum {
|
||||
BLE_NONE = 0,
|
||||
BLE_IS_SENDING = 1,
|
||||
BLE_IS_SCANNING = 2,
|
||||
BLE_IS_ADVERTISING = 4,
|
||||
} BLEStatus;
|
||||
|
||||
static volatile BLEStatus bleStatus;
|
||||
static volatile BLEStatus bleStatus = 0;
|
||||
|
||||
#define BLE_SCAN_EVENT JS_EVENT_PREFIX"blescan"
|
||||
#define BLE_WRITE_EVENT JS_EVENT_PREFIX"blew"
|
||||
@ -134,7 +141,7 @@ bool jswrap_nrf_transmit_string();
|
||||
"generate" : "jswrap_nrf_idle"
|
||||
}*/
|
||||
bool jswrap_nrf_idle() {
|
||||
return jswrap_nrf_transmit_string()>0; // return true if we sent anything
|
||||
return false;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
@ -234,7 +241,7 @@ void ble_app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t
|
||||
*
|
||||
* @details This function will be called in case of an assert in the SoftDevice.
|
||||
*
|
||||
* @warning This handler is an example only and does not fit a final product. You need to analyse
|
||||
* @warning This handler is an example only and does not fit a final product. You need to analyse
|
||||
* how your product is supposed to react in case of Assert.
|
||||
* @warning On assert from the SoftDevice, the system can only recover on reset.
|
||||
*
|
||||
@ -246,11 +253,17 @@ void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) {
|
||||
}
|
||||
|
||||
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) {
|
||||
ble_app_error_handler(id, pc, 0);
|
||||
if (id == NRF_FAULT_ID_SDK_ERROR) {
|
||||
error_info_t *error_info = (error_info_t *)info;
|
||||
ble_app_error_handler(error_info->err_code, error_info->line_num, error_info->p_file_name);
|
||||
} else
|
||||
ble_app_error_handler(id, pc, 0);
|
||||
}
|
||||
|
||||
void advertising_start(void) {
|
||||
uint32_t err_code = 0;
|
||||
|
||||
if (bleStatus & BLE_IS_ADVERTISING) return;
|
||||
// Actually start advertising
|
||||
ble_gap_adv_params_t adv_params;
|
||||
memset(&adv_params, 0, sizeof(adv_params));
|
||||
@ -262,14 +275,17 @@ void advertising_start(void) {
|
||||
adv_params.interval = advertising_interval;
|
||||
|
||||
err_code = sd_ble_gap_adv_start(&adv_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
// APP_ERROR_CHECK(err_code); // don't bother checking
|
||||
bleStatus |= BLE_IS_ADVERTISING;
|
||||
}
|
||||
|
||||
static void advertising_stop(void) {
|
||||
uint32_t err_code;
|
||||
uint32_t err_code;
|
||||
|
||||
err_code = sd_ble_gap_adv_stop();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
if (!(bleStatus & BLE_IS_ADVERTISING)) return;
|
||||
err_code = sd_ble_gap_adv_stop();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
bleStatus &= ~BLE_IS_ADVERTISING;
|
||||
}
|
||||
|
||||
#ifdef USE_BOOTLOADER
|
||||
@ -359,7 +375,7 @@ static void reset_prepare(void)
|
||||
|
||||
/**@brief Function for the GAP initialization.
|
||||
*
|
||||
* @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
|
||||
* @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
|
||||
* the device. It also sets the permissions and appearance.
|
||||
*/
|
||||
static void gap_params_init(void)
|
||||
@ -439,7 +455,36 @@ bool jswrap_nrf_transmit_string() {
|
||||
}
|
||||
return idx>0;
|
||||
}
|
||||
/**@snippet [Handling the data received over BLE] */
|
||||
|
||||
uint32_t radio_notification_init(uint32_t irq_priority, uint8_t notification_type, uint8_t notification_distance)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// Configure the event
|
||||
return sd_radio_notification_cfg_set(notification_type, notification_distance);
|
||||
}
|
||||
|
||||
void SWI1_IRQHandler(bool radio_evt) {
|
||||
jswrap_nrf_transmit_string();
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for initializing services that will be used by the application.
|
||||
@ -448,11 +493,11 @@ static void services_init(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
ble_nus_init_t nus_init;
|
||||
|
||||
|
||||
memset(&nus_init, 0, sizeof(nus_init));
|
||||
|
||||
nus_init.data_handler = nus_data_handler;
|
||||
|
||||
|
||||
err_code = ble_nus_init(&m_nus, &nus_init);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
@ -489,7 +534,7 @@ static void services_init(void)
|
||||
*/
|
||||
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt) {
|
||||
uint32_t err_code;
|
||||
|
||||
|
||||
if(p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
|
||||
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
@ -511,7 +556,7 @@ static void conn_params_error_handler(uint32_t nrf_error) {
|
||||
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;
|
||||
@ -522,7 +567,7 @@ static void conn_params_init(void) {
|
||||
cp_init.disconnect_on_fail = false;
|
||||
cp_init.evt_handler = on_conn_params_evt;
|
||||
cp_init.error_handler = conn_params_error_handler;
|
||||
|
||||
|
||||
err_code = ble_conn_params_init(&cp_init);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
@ -559,20 +604,20 @@ JsVar *bleAddrToStr(ble_gap_addr_t addr) {
|
||||
addr.addr[0]);
|
||||
}
|
||||
|
||||
/* Convert a JsVar to a UUID - true if handled
|
||||
/* Convert a JsVar to a UUID - 0 if handled, a string showing the error if not
|
||||
* Converts:
|
||||
* Integers -> 16 bit BLE UUID
|
||||
* "0xABCD" -> 16 bit BLE UUID
|
||||
* "ABCDABCD-ABCD-ABCD-ABCD-ABCDABCDABCD" -> vendor specific BLE UUID
|
||||
*/
|
||||
bool bleVarToUUID(ble_uuid_t *uuid, JsVar *v) {
|
||||
const char *bleVarToUUID(ble_uuid_t *uuid, JsVar *v) {
|
||||
if (jsvIsInt(v)) {
|
||||
JsVarInt i = jsvGetInteger(v);
|
||||
if (i<0 || i>0xFFFF) return false;
|
||||
if (i<0 || i>0xFFFF) return "Integer out of range";
|
||||
BLE_UUID_BLE_ASSIGN((*uuid), i);
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
if (!jsvIsString(v)) return false;
|
||||
if (!jsvIsString(v)) return "Not a String or Integer";
|
||||
unsigned int expectedLength = 16;
|
||||
unsigned int startIdx = 0;
|
||||
if (jsvIsStringEqualOrStartsWith(v,"0x",true)) {
|
||||
@ -595,29 +640,33 @@ bool bleVarToUUID(ble_uuid_t *uuid, JsVar *v) {
|
||||
jsvStringIteratorNext(&it);
|
||||
if (hi<0 || lo<0) {
|
||||
jsvStringIteratorFree(&it);
|
||||
return false; // not hex chars
|
||||
return "String should only contain hex characters and dashes";
|
||||
}
|
||||
data[expectedLength - (dataLen+1)] = (unsigned)((hi<<4) | lo);
|
||||
dataLen++;
|
||||
}
|
||||
if (jsvStringIteratorHasChar(&it)) dataLen++; // make sure we fail is string too long
|
||||
jsvStringIteratorFree(&it);
|
||||
if (dataLen!=expectedLength) return false;
|
||||
if (dataLen!=expectedLength) {
|
||||
return "Not the right length (16)";
|
||||
}
|
||||
// now try and decode the UUID
|
||||
uint32_t err_code;
|
||||
err_code = sd_ble_uuid_decode(dataLen, data, uuid);
|
||||
// Not found - add it
|
||||
if (err_code == NRF_ERROR_NOT_FOUND) {
|
||||
uuid->uuid = ((data[12]<<8) | data[13]);
|
||||
uuid->uuid = ((data[13]<<8) | data[12]);
|
||||
data[12] = 0; // these 2 not needed, but let's zero them anyway
|
||||
data[13] = 0;
|
||||
err_code = sd_ble_uuid_vs_add((ble_uuid128_t*)data, &uuid->type);
|
||||
if (err_code == NRF_ERROR_NO_MEM)
|
||||
return "Too many custom UUIDs already";
|
||||
}
|
||||
return !err_code;
|
||||
return err_code ? "BLE device error" : 0;
|
||||
}
|
||||
|
||||
bool bleVarToUUIDAndUnLock(ble_uuid_t *uuid, JsVar *v) {
|
||||
bool r = bleVarToUUID(uuid, v);
|
||||
const char *bleVarToUUIDAndUnLock(ble_uuid_t *uuid, JsVar *v) {
|
||||
const char *r = bleVarToUUID(uuid, v);
|
||||
jsvUnLock(v);
|
||||
return r;
|
||||
}
|
||||
@ -645,7 +694,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
{
|
||||
uint32_t err_code;
|
||||
//jsiConsolePrintf("\n[%d]\n", p_ble_evt->header.evt_id);
|
||||
|
||||
|
||||
switch (p_ble_evt->header.evt_id) {
|
||||
case BLE_GAP_EVT_TIMEOUT:
|
||||
// the timeout for sd_ble_gap_adv_start expired - kick it off again
|
||||
@ -656,6 +705,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) {
|
||||
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
bleStatus &= ~BLE_IS_SENDING; // reset state - just in case
|
||||
bleStatus &= ~BLE_IS_ADVERTISING; // we're not advertising now we're connected
|
||||
if (!jsiIsConsoleDeviceForced()) jsiSetConsoleDevice(EV_BLUETOOTH, false);
|
||||
jshHadEvent();
|
||||
}
|
||||
@ -693,7 +743,6 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
case BLE_EVT_TX_COMPLETE:
|
||||
// UART Transmit finished - we can try and send more data
|
||||
bleStatus &= ~BLE_IS_SENDING;
|
||||
jswrap_nrf_transmit_string();
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_ADV_REPORT: {
|
||||
@ -808,10 +857,10 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for dispatching a SoftDevice event to all modules with a SoftDevice
|
||||
/**@brief Function for dispatching a SoftDevice event to all modules with a SoftDevice
|
||||
* event handler.
|
||||
*
|
||||
* @details This function is called from the SoftDevice event interrupt handler after a
|
||||
* @details This function is called from the SoftDevice event interrupt handler after a
|
||||
* SoftDevice event has been received.
|
||||
*
|
||||
* @param[in] p_ble_evt SoftDevice event.
|
||||
@ -848,7 +897,7 @@ static void sys_evt_dispatch(uint32_t sys_evt)
|
||||
#ifdef USE_NFC
|
||||
/// Sigh - NFC has lots of these, so we need to define it to build
|
||||
void log_uart_printf(const char * format_msg, ...) {
|
||||
jsiConsolePrintf("NFC: %s\n", format_msg);
|
||||
// jsiConsolePrintf("NFC: %s\n", format_msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -880,7 +929,7 @@ void nfc_callback(void *context, NfcEvent event, const char *data, size_t dataLe
|
||||
static void ble_stack_init(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
|
||||
// TODO: enable if we're on a device with 32kHz xtal
|
||||
/*nrf_clock_lf_cfg_t clock_lf_cfg = {
|
||||
.source = NRF_CLOCK_LF_SRC_XTAL,
|
||||
@ -895,15 +944,20 @@ static void ble_stack_init(void)
|
||||
|
||||
// Initialize SoftDevice.
|
||||
SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, false);
|
||||
|
||||
|
||||
ble_enable_params_t ble_enable_params;
|
||||
err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
|
||||
PERIPHERAL_LINK_COUNT,
|
||||
&ble_enable_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
|
||||
int softdevice_extra_ram_hack = 0;
|
||||
|
||||
ble_enable_params.common_enable_params.vs_uuid_count = 3;
|
||||
softdevice_extra_ram_hack += 256; // now we have more UUIDs, SD needs more RAM
|
||||
|
||||
|
||||
#ifdef USE_BOOTLOADER
|
||||
ble_enable_params.common_enable_params.vs_uuid_count = 2;
|
||||
ble_enable_params.gatts_enable_params.service_changed = 1;
|
||||
#endif
|
||||
|
||||
@ -911,15 +965,15 @@ static void ble_stack_init(void)
|
||||
CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT);
|
||||
|
||||
extern int __data_start__; // should be 'void', but 'int' avoids warnings
|
||||
if (IDEAL_RAM_START_ADDRESS(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT) != (uint32_t)&__data_start__) {
|
||||
jsiConsolePrintf("WARNING: BLE RAM start address not correct - is 0x%x, should be 0x%x\n\n", (uint32_t)&__data_start__, IDEAL_RAM_START_ADDRESS(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT));
|
||||
if (IDEAL_RAM_START_ADDRESS(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT)+softdevice_extra_ram_hack != (uint32_t)&__data_start__) {
|
||||
jsiConsolePrintf("WARNING: BLE RAM start address not correct - is 0x%x, should be 0x%x\n\n", (uint32_t)&__data_start__, IDEAL_RAM_START_ADDRESS(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT)+softdevice_extra_ram_hack);
|
||||
jshTransmitFlush();
|
||||
}
|
||||
|
||||
// Enable BLE stack.
|
||||
err_code = softdevice_enable(&ble_enable_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
|
||||
// Subscribe for BLE events.
|
||||
err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
@ -1035,7 +1089,7 @@ void jswrap_nrf_bluetooth_init(void) {
|
||||
// Initialize.
|
||||
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
|
||||
ble_stack_init();
|
||||
|
||||
|
||||
#ifdef USE_BOOTLOADER
|
||||
bool erase_bonds = false;
|
||||
device_manager_init(erase_bonds);
|
||||
@ -1047,6 +1101,15 @@ void jswrap_nrf_bluetooth_init(void) {
|
||||
conn_params_init();
|
||||
|
||||
jswrap_nrf_bluetooth_wake();
|
||||
|
||||
radio_notification_init(
|
||||
#ifdef NRF52
|
||||
6, /* IRQ Priority - Must be 6 on nRF52. 7 doesn't work */
|
||||
#else
|
||||
3, /* IRQ Priority - nRF51 has different IRQ structure */
|
||||
#endif
|
||||
NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE,
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_5500US);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
@ -1068,7 +1131,8 @@ void jswrap_nrf_bluetooth_sleep(void) {
|
||||
}
|
||||
|
||||
// Stop advertising
|
||||
err_code = sd_ble_gap_adv_stop();
|
||||
if (bleStatus & BLE_IS_ADVERTISING)
|
||||
advertising_stop();
|
||||
NRF_RADIO->TASKS_DISABLE = (1UL);
|
||||
}
|
||||
|
||||
@ -1150,7 +1214,7 @@ Or you could report the current temperature:
|
||||
```
|
||||
setInterval(function() {
|
||||
NRF.setAdvertising({
|
||||
0x1809 : [Math,round(E.getTemperature())]
|
||||
0x1809 : [Math.round(E.getTemperature())]
|
||||
});
|
||||
}, 30000);
|
||||
```
|
||||
@ -1189,7 +1253,8 @@ void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options) {
|
||||
uint32_t err_code;
|
||||
ble_advdata_t advdata;
|
||||
setup_advdata(&advdata);
|
||||
bool bleChanged;
|
||||
bool bleChanged = false;
|
||||
bool isAdvertising = bleStatus & BLE_IS_ADVERTISING;
|
||||
|
||||
if (jsvIsObject(options)) {
|
||||
JsVar *v;
|
||||
@ -1242,12 +1307,12 @@ void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bleChanged)
|
||||
if (bleChanged && isAdvertising)
|
||||
advertising_stop();
|
||||
err_code = sd_ble_gap_adv_data_set(dPtr, dLen, NULL, 0);
|
||||
if (err_code)
|
||||
jsExceptionHere(JSET_ERROR, "Got BLE error code %d", err_code);
|
||||
if (bleChanged)
|
||||
if (bleChanged && isAdvertising)
|
||||
advertising_start();
|
||||
return; // we're done here now
|
||||
} else if (jsvIsObject(data)) {
|
||||
@ -1274,12 +1339,12 @@ void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bleChanged)
|
||||
if (bleChanged && isAdvertising)
|
||||
advertising_stop();
|
||||
err_code = ble_advdata_set(&advdata, NULL);
|
||||
if (err_code)
|
||||
jsExceptionHere(JSET_ERROR, "Got BLE error code %d", err_code);
|
||||
if (bleChanged)
|
||||
if (bleChanged && isAdvertising)
|
||||
advertising_start();
|
||||
}
|
||||
|
||||
@ -1306,6 +1371,7 @@ NRF.setServices({
|
||||
broadcast : false, // optional, default is false
|
||||
readable : true, // optional, default is false
|
||||
writable : true, // optional, default is false
|
||||
notify : true, // optional, default is false
|
||||
onWrite : function(evt) { // optional
|
||||
console.log("Got ", evt.data);
|
||||
}
|
||||
@ -1322,7 +1388,8 @@ the form `"0xABCD"`, or strings of the form `""ABCDABCD-ABCD-ABCD-ABCD-ABCDABCDA
|
||||
void jswrap_nrf_bluetooth_setServices(JsVar *data) {
|
||||
uint32_t err_code;
|
||||
|
||||
// TODO: Reset services
|
||||
// TODO: Reset services (esp. removing Nordic UART if not needed)
|
||||
// TODO: Reset services on kill
|
||||
|
||||
if (jsvIsObject(data)) {
|
||||
JsvObjectIterator it;
|
||||
@ -1333,8 +1400,9 @@ void jswrap_nrf_bluetooth_setServices(JsVar *data) {
|
||||
|
||||
// Add the service
|
||||
|
||||
if (!bleVarToUUIDAndUnLock(&ble_uuid, jsvObjectIteratorGetKey(&it))) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid Service UUID");
|
||||
const char *errorStr;
|
||||
if ((errorStr=bleVarToUUIDAndUnLock(&ble_uuid, jsvObjectIteratorGetKey(&it)))) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid Service UUID: %s", errorStr);
|
||||
break;
|
||||
}
|
||||
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
|
||||
@ -1357,8 +1425,8 @@ void jswrap_nrf_bluetooth_setServices(JsVar *data) {
|
||||
ble_gatts_attr_md_t attr_md;
|
||||
ble_gatts_char_handles_t characteristic_handles;
|
||||
|
||||
if (!bleVarToUUIDAndUnLock(&char_uuid, jsvObjectIteratorGetKey(&serviceit))) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid Characteristic UUID");
|
||||
if ((errorStr=bleVarToUUIDAndUnLock(&char_uuid, jsvObjectIteratorGetKey(&serviceit)))) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid Characteristic UUID: %s", errorStr);
|
||||
break;
|
||||
}
|
||||
JsVar *charVar = jsvObjectIteratorGetValue(&serviceit);
|
||||
@ -1366,6 +1434,8 @@ void jswrap_nrf_bluetooth_setServices(JsVar *data) {
|
||||
memset(&char_md, 0, sizeof(char_md));
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "broadcast", 0)))
|
||||
char_md.char_props.broadcast = 1;
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "notify", 0)))
|
||||
char_md.char_props.notify = 1;
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "readable", 0)))
|
||||
char_md.char_props.read = 1;
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "writable", 0))) {
|
||||
@ -1796,7 +1866,6 @@ void jswrap_nrf_nfcURL(JsVar *url) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* TESTING
|
||||
* ---------------------------------------------------------------------
|
||||
@ -1847,5 +1916,3 @@ NRF.setServices({
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@ -37,6 +37,5 @@ void jswrap_nrf_blecharacteristic_write(JsVar *characteristic, JsVar *data);
|
||||
|
||||
void jswrap_nrf_nfcURL(JsVar *url);
|
||||
|
||||
|
||||
bool jswrap_nrf_idle();
|
||||
void jswrap_nrf_kill();
|
||||
|
||||
@ -201,6 +201,37 @@ void graphicsDrawRect(JsGraphics *gfx, short x1, short y1, short x2, short y2) {
|
||||
graphicsFillRectDevice(gfx,x1,y2,x1,y1);
|
||||
}
|
||||
|
||||
void graphicsDrawCircle(JsGraphics *gfx, short posX, short posY, short rad) {
|
||||
graphicsToDeviceCoordinates(gfx, &posX, &posY);
|
||||
|
||||
int radY = 0,
|
||||
radX = rad;
|
||||
// Decision criterion divided by 2 evaluated at radX=radX, radY=0
|
||||
int decisionOver2 = 1 - radX;
|
||||
|
||||
while (radX >= radY) {
|
||||
graphicsSetPixelDevice(gfx, radX + posX, radY + posY, gfx->data.fgColor);
|
||||
graphicsSetPixelDevice(gfx, radY + posX, radX + posY, gfx->data.fgColor);
|
||||
graphicsSetPixelDevice(gfx, -radX + posX, radY + posY, gfx->data.fgColor);
|
||||
graphicsSetPixelDevice(gfx, -radY + posX, radX + posY, gfx->data.fgColor);
|
||||
graphicsSetPixelDevice(gfx, -radX + posX, -radY + posY, gfx->data.fgColor);
|
||||
graphicsSetPixelDevice(gfx, -radY + posX, -radX + posY, gfx->data.fgColor);
|
||||
graphicsSetPixelDevice(gfx, radX + posX, -radY + posY, gfx->data.fgColor);
|
||||
graphicsSetPixelDevice(gfx, radY + posX, -radX + posY, gfx->data.fgColor);
|
||||
radY++;
|
||||
|
||||
if (decisionOver2 <= 0) {
|
||||
// Change in decision criterion for radY -> radY+1
|
||||
decisionOver2 += 2 * radY + 1;
|
||||
}
|
||||
else {
|
||||
radX--;
|
||||
// Change for radY -> radY+1, radX -> radX-1
|
||||
decisionOver2 += 2 * (radY - radX) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void graphicsFillCircle(JsGraphics *gfx, short x, short y, short rad) {
|
||||
graphicsToDeviceCoordinates(gfx, &x, &y);
|
||||
|
||||
|
||||
@ -99,6 +99,7 @@ void graphicsClear(JsGraphics *gfx);
|
||||
void graphicsFillRect(JsGraphics *gfx, short x1, short y1, short x2, short y2);
|
||||
void graphicsFallbackFillRect(JsGraphics *gfx, short x1, short y1, short x2, short y2); // Simple fillrect - doesn't call device-specific FR
|
||||
void graphicsDrawRect(JsGraphics *gfx, short x1, short y1, short x2, short y2);
|
||||
void graphicsDrawCircle(JsGraphics *gfx, short posX, short posY, short rad);
|
||||
void graphicsFillCircle(JsGraphics *gfx, short x, short y, short rad);
|
||||
void graphicsDrawString(JsGraphics *gfx, short x1, short y1, const char *str);
|
||||
void graphicsDrawLine(JsGraphics *gfx, short x1, short y1, short x2, short y2);
|
||||
|
||||
@ -351,6 +351,25 @@ void jswrap_graphics_drawRect(JsVar *parent, int x1, int y1, int x2, int y2) {
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
"name" : "drawCircle",
|
||||
"generate" : "jswrap_graphics_drawCircle",
|
||||
"params" : [
|
||||
["x","int32","The X axis"],
|
||||
["y","int32","The Y axis"],
|
||||
["rad","int32","The circle radius"]
|
||||
]
|
||||
}
|
||||
Draw an unfilled circle 1px wide in the Foreground Color
|
||||
*/
|
||||
void jswrap_graphics_drawCircle(JsVar *parent, int x, int y, int rad) {
|
||||
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return;
|
||||
graphicsDrawCircle(&gfx, (short)x,(short)y,(short)rad);
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
|
||||
@ -32,6 +32,7 @@ int jswrap_graphics_getWidthOrHeight(JsVar *parent, bool height);
|
||||
void jswrap_graphics_clear(JsVar *parent);
|
||||
void jswrap_graphics_fillRect(JsVar *parent, int x1, int y1, int x2, int y2);
|
||||
void jswrap_graphics_drawRect(JsVar *parent, int x1, int y1, int x2, int y2);
|
||||
void jswrap_graphics_drawCircle(JsVar *parent, int x, int y, int rad);
|
||||
void jswrap_graphics_fillCircle(JsVar *parent, int x, int y, int rad);
|
||||
int jswrap_graphics_getPixel(JsVar *parent, int x, int y);
|
||||
void jswrap_graphics_setPixel(JsVar *parent, int x, int y, JsVar *color);
|
||||
|
||||
@ -205,7 +205,8 @@ void jswrap_microbit_show(JsVar *image) {
|
||||
|
||||
if ((newState!=0) && (microbitLEDState==0)) {
|
||||
// we want to display something but we don't have an interval
|
||||
jstExecuteFn(jswrap_microbit_display_callback, jshGetTimeFromMilliseconds(5), true /* repeat */);
|
||||
JsSysTime period = jshGetTimeFromMilliseconds(5);
|
||||
jstExecuteFn(jswrap_microbit_display_callback, jshGetSystemTime()+period, (uint32_t)period);
|
||||
// and also set pins to outputs
|
||||
nrf_gpio_cfg_output(MB_LED_COL1);
|
||||
nrf_gpio_cfg_output(MB_LED_COL2);
|
||||
|
||||
@ -314,7 +314,7 @@ JsVar *jswrap_http_get(JsVar *options, JsVar *callback) {
|
||||
if (jsvIsObject(options)) {
|
||||
// if options is a string - it will be parsed, and GET will be set automatically
|
||||
JsVar *method = jsvNewFromString("GET");
|
||||
jsvUnLock2(jsvAddNamedChild(options, method, "method"), method);
|
||||
jsvUnLock2(jsvSetNamedChild(options, method, "method"), method);
|
||||
}
|
||||
JsVar *skippedCallback = jsvSkipName(callback);
|
||||
if (!jsvIsUndefined(skippedCallback) && !jsvIsFunction(skippedCallback)) {
|
||||
|
||||
426
libs/puckjs/jswrap_puck.c
Normal file
426
libs/puckjs/jswrap_puck.c
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* This file is designed to be parsed during the build process
|
||||
*
|
||||
* Contains JavaScript interface for Puck.js
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "jswrap_puck.h"
|
||||
#include "jsinteractive.h"
|
||||
#include "jsdevices.h"
|
||||
#include "jshardware.h"
|
||||
#include "jsdevices.h"
|
||||
#include "jspin.h"
|
||||
#include "jstimer.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf5x_utils.h"
|
||||
|
||||
#define MAG_PWR 18
|
||||
#define MAG_INT 17
|
||||
#define MAG_SDA 20
|
||||
#define MAG_SCL 19
|
||||
#define MAG3110_ADDR 0x0E
|
||||
#define I2C_TIMEOUT 100000
|
||||
|
||||
// Has the magnetometer been turned on?
|
||||
bool mag_enabled = false;
|
||||
|
||||
void wr(int pin, bool state) {
|
||||
if (state) {
|
||||
nrf_gpio_pin_set(pin); nrf_gpio_cfg_output(pin);
|
||||
nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_PULLUP);
|
||||
} else {
|
||||
nrf_gpio_pin_clear(pin);
|
||||
nrf_gpio_cfg_output(pin);
|
||||
}
|
||||
}
|
||||
|
||||
bool rd(int pin) {
|
||||
return nrf_gpio_pin_read(pin);
|
||||
}
|
||||
|
||||
void dly() {
|
||||
volatile int i;
|
||||
for (i=0;i<10;i++);
|
||||
}
|
||||
|
||||
void err(const char *s) {
|
||||
jsiConsolePrintf("I2C: %s\n", s);
|
||||
}
|
||||
|
||||
bool started = false;
|
||||
|
||||
void i2c_start() {
|
||||
if (started) {
|
||||
// reset
|
||||
wr(MAG_SDA, 1);
|
||||
dly();
|
||||
wr(MAG_SCL, 1);
|
||||
int timeout = I2C_TIMEOUT;
|
||||
while (!rd(MAG_SCL) && --timeout); // clock stretch
|
||||
if (!timeout) err("Timeout (start)");
|
||||
dly();
|
||||
}
|
||||
if (!rd(MAG_SDA)) err("Arbitration (start)");
|
||||
wr(MAG_SDA, 0);
|
||||
dly();
|
||||
wr(MAG_SCL, 0);
|
||||
dly();
|
||||
started = true;
|
||||
}
|
||||
|
||||
void i2c_stop() {
|
||||
wr(MAG_SDA, 0);
|
||||
dly();
|
||||
wr(MAG_SCL, 1);
|
||||
int timeout = I2C_TIMEOUT;
|
||||
while (!rd(MAG_SCL) && --timeout); // clock stretch
|
||||
if (!timeout) err("Timeout (stop)");
|
||||
dly();
|
||||
wr(MAG_SDA, 1);
|
||||
dly();
|
||||
if (!rd(MAG_SDA)) err("Arbitration (stop)");
|
||||
dly();
|
||||
started = false;
|
||||
}
|
||||
|
||||
void i2c_wr_bit(bool b) {
|
||||
wr(MAG_SDA, b);
|
||||
dly();
|
||||
wr(MAG_SCL, 1);
|
||||
dly();
|
||||
int timeout = I2C_TIMEOUT;
|
||||
while (!rd(MAG_SCL) && --timeout); // clock stretch
|
||||
if (!timeout) err("Timeout (wr)");
|
||||
wr(MAG_SCL, 0);
|
||||
wr(MAG_SDA, 1); // stop forcing SDA (needed?)
|
||||
}
|
||||
|
||||
bool i2c_rd_bit() {
|
||||
wr(MAG_SDA, 1); // stop forcing SDA
|
||||
dly();
|
||||
wr(MAG_SCL, 1); // stop forcing SDA
|
||||
int timeout = I2C_TIMEOUT;
|
||||
while (!rd(MAG_SCL) && --timeout); // clock stretch
|
||||
if (!timeout) err("Timeout (rd)");
|
||||
dly();
|
||||
bool b = rd(MAG_SDA);
|
||||
wr(MAG_SCL, 0);
|
||||
return b;
|
||||
}
|
||||
|
||||
// true on ack, false on nack
|
||||
bool i2c_wr(uint8_t data) {
|
||||
int i;
|
||||
for (i=0;i<8;i++) {
|
||||
i2c_wr_bit(data&128);
|
||||
data <<= 1;
|
||||
}
|
||||
return !i2c_rd_bit();
|
||||
}
|
||||
|
||||
uint8_t i2c_rd(bool nack) {
|
||||
int i;
|
||||
int data = 0;
|
||||
for (i=0;i<8;i++)
|
||||
data = (data<<1) | (i2c_rd_bit()?1:0);
|
||||
i2c_wr_bit(nack);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
// Turn magnetometer on and configure
|
||||
bool mag_on(int milliHz) {
|
||||
int reg1 = 0;
|
||||
if (milliHz == 80000) reg1 = (0x00)<<3; // 900uA
|
||||
else if (milliHz == 40000) reg1 = (0x04)<<3; // 550uA
|
||||
else if (milliHz == 20000) reg1 = (0x08)<<3; // 275uA
|
||||
else if (milliHz == 10000) reg1 = (0x0C)<<3; // 137uA
|
||||
else if (milliHz == 5000) reg1 = (0x10)<<3; // 69uA
|
||||
else if (milliHz == 2500) reg1 = (0x14)<<3; // 34uA
|
||||
else if (milliHz == 1250) reg1 = (0x18)<<3; // 17uA
|
||||
else if (milliHz == 630) reg1 = (0x1C)<<3; // 8uA
|
||||
else if (milliHz == 310) reg1 = (0x1D)<<3; // 8uA
|
||||
else if (milliHz == 160) reg1 = (0x1E)<<3; // 8uA
|
||||
else if (milliHz == 80) reg1 = (0x1F)<<3; // 8uA
|
||||
else return false;
|
||||
|
||||
nrf_gpio_pin_set(MAG_PWR);
|
||||
nrf_gpio_cfg_output(MAG_PWR);
|
||||
nrf_gpio_cfg_input(MAG_INT, NRF_GPIO_PIN_NOPULL);
|
||||
wr(MAG_SDA, 1);
|
||||
wr(MAG_SCL, 1);
|
||||
jshDelayMicroseconds(2000); // 1.7ms from power on to ok
|
||||
i2c_start();
|
||||
i2c_wr(MAG3110_ADDR<<1); // CTRL_REG2, AUTO_MRST_EN
|
||||
i2c_wr(0x11);
|
||||
i2c_wr(0x80/*AUTO_MRST_EN*/ + 0x20/*RAW*/);
|
||||
i2c_stop();
|
||||
i2c_start();
|
||||
i2c_wr(MAG3110_ADDR<<1); // CTRL_REG1, active mode 80 Hz ODR with OSR = 0
|
||||
i2c_wr(0x10);
|
||||
reg1 |= 1; // Active bit
|
||||
i2c_wr(reg1);
|
||||
i2c_stop();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wait for magnetometer IRQ line to be set
|
||||
void mag_wait() {
|
||||
int timeout = I2C_TIMEOUT*2;
|
||||
while (!nrf_gpio_pin_read(MAG_INT) && --timeout);
|
||||
if (!timeout) err("Timeout (wait reading)");
|
||||
}
|
||||
|
||||
// Read a value
|
||||
void mag_read(int16_t d[3]) {
|
||||
i2c_start();
|
||||
i2c_wr(MAG3110_ADDR<<1);
|
||||
i2c_wr(1);
|
||||
i2c_start();
|
||||
i2c_wr(1|(MAG3110_ADDR<<1));
|
||||
d[0] = i2c_rd(false)<<8;
|
||||
d[0] |= i2c_rd(false);
|
||||
d[1] = i2c_rd(false)<<8;
|
||||
d[1] |= i2c_rd(false);
|
||||
d[2] = i2c_rd(false)<<8;
|
||||
d[2] |= i2c_rd(true);
|
||||
i2c_stop();
|
||||
}
|
||||
|
||||
// Turn magnetometer off
|
||||
void mag_off() {
|
||||
nrf_gpio_cfg_input(MAG_SDA, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_cfg_input(MAG_SCL, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_cfg_input(MAG_PWR, NRF_GPIO_PIN_NOPULL);
|
||||
}
|
||||
|
||||
JsVar *mag_to_xyz(int16_t d[3]) {
|
||||
JsVar *obj = jsvNewObject();
|
||||
if (!obj) return 0;
|
||||
jsvObjectSetChildAndUnLock(obj,"x",jsvNewFromInteger(d[0]));
|
||||
jsvObjectSetChildAndUnLock(obj,"y",jsvNewFromInteger(d[1]));
|
||||
jsvObjectSetChildAndUnLock(obj,"z",jsvNewFromInteger(d[2]));
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type": "class",
|
||||
"class" : "NRF"
|
||||
}
|
||||
Class containing [Puck.js's](http://www.puck-js.com) utility functions.
|
||||
*/
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "Puck",
|
||||
"name" : "mag",
|
||||
"generate" : "jswrap_puck_mag",
|
||||
"return" : ["JsVar", "An Object `{x,y,z}` of magnetometer readings as integers" ]
|
||||
}
|
||||
Turn on the magnetometer, take a single reading, and then turn it off again.
|
||||
*/
|
||||
JsVar *jswrap_puck_mag() {
|
||||
if (!mag_enabled) mag_on(80000);
|
||||
mag_wait();
|
||||
int16_t d[3];
|
||||
mag_read(d);
|
||||
if (!mag_enabled) mag_off();
|
||||
return mag_to_xyz(d);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "event",
|
||||
"class" : "Puck",
|
||||
"name" : "mag"
|
||||
}
|
||||
Called after `Puck.magOn()` every time magnetometer data
|
||||
is discovered. There is one argument which is an object
|
||||
of the form `{x,y,z}' containing magnetometer readings
|
||||
as integers.
|
||||
*/
|
||||
|
||||
void _jswrap_mag_irq() {
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "Puck",
|
||||
"name" : "magOn",
|
||||
"generate" : "jswrap_puck_magOn",
|
||||
"params" : [
|
||||
["samplerate","float","The Samplerate in Hz, or undefined"]
|
||||
]
|
||||
}
|
||||
Turn the magnetometer on and configure it. Samples will then cause
|
||||
a 'mag' event on 'Puck':
|
||||
|
||||
```
|
||||
Puck.magOn();
|
||||
Puck.on('mag', function(xyz) {
|
||||
console.log(xyz);
|
||||
});
|
||||
// Turn events off with Puck.magOff();
|
||||
```
|
||||
|
||||
This call will be ignored if the magnetometer is already on.
|
||||
|
||||
If given an argument, the sample rate is set (if not, it's at 0.63Hz). The sample rate should be one of the following:
|
||||
|
||||
* 80 Hz - 900uA
|
||||
* 40 Hz - 550uA
|
||||
* 20 Hz - 275uA
|
||||
* 10 Hz - 137uA
|
||||
* 5 Hz - 69uA
|
||||
* 2.5 Hz - 34uA
|
||||
* 1.25 Hz - 17uA
|
||||
* 0.63 Hz - 8uA
|
||||
* 0.31 Hz - 8uA
|
||||
* 0.16 Hz - 8uA
|
||||
* 0.08 Hz - 8uA
|
||||
|
||||
*/
|
||||
void jswrap_puck_magOn(JsVarFloat hz) {
|
||||
if (!mag_enabled) {
|
||||
int milliHz = (int)((hz*1000)+0.5);
|
||||
if (milliHz==0) milliHz=630;
|
||||
if (!mag_on(milliHz)) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid sample rate %f - see docs for valid rates", hz);
|
||||
}
|
||||
jshPinWatch(MAG_INT, true);
|
||||
}
|
||||
mag_enabled = true;
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "Puck",
|
||||
"name" : "magOff",
|
||||
"generate" : "jswrap_puck_magOff"
|
||||
}
|
||||
Turn the magnetometer off
|
||||
*/
|
||||
void jswrap_puck_magOff() {
|
||||
if (mag_enabled) {
|
||||
jshPinWatch(MAG_INT, false);
|
||||
mag_off();
|
||||
}
|
||||
mag_enabled = false;
|
||||
}
|
||||
|
||||
|
||||
// Called when we're done with the IR transmission
|
||||
void _jswrap_puck_IR_done(JsSysTime t) {
|
||||
// set as input - so no signal
|
||||
jshPinSetState(IR_ANODE_PIN, JSHPINSTATE_GPIO_IN);
|
||||
// this one also stops the PWM
|
||||
jshPinSetState(IR_CATHODE_PIN, JSHPINSTATE_GPIO_IN);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "Puck",
|
||||
"name" : "IR",
|
||||
"generate" : "jswrap_puck_IR",
|
||||
"params" : [
|
||||
["data","JsVar","An array of pulse lengths, in milliseconds"]
|
||||
]
|
||||
}
|
||||
Transmit the given set of IR pulses - data should be an array of pulse times
|
||||
in milliseconds (as `[on, off, on, off, on, etc]`).
|
||||
*/
|
||||
void jswrap_puck_IR(JsVar *data) {
|
||||
if (!jsvIsIterable(data)) {
|
||||
jsExceptionHere(JSET_TYPEERROR, "Expecting an array, got %t", data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Pin pin = IR_ANODE_PIN;
|
||||
jshPinAnalogOutput(IR_CATHODE_PIN, 0.5, 38000, 0);
|
||||
|
||||
JsSysTime time = jshGetSystemTime();
|
||||
bool hasPulses = false;
|
||||
bool pulsePolarity = false;
|
||||
jshPinSetValue(IR_ANODE_PIN, pulsePolarity);
|
||||
|
||||
JsvIterator it;
|
||||
jsvIteratorNew(&it, data);
|
||||
while (jsvIteratorHasElement(&it)) {
|
||||
JsVarFloat pulseTime = jsvIteratorGetFloatValue(&it);
|
||||
if (hasPulses) jstPinOutputAtTime(time, &pin, 1, pulsePolarity);
|
||||
else jshPinSetState(IR_ANODE_PIN, JSHPINSTATE_GPIO_OUT);
|
||||
hasPulses = true;
|
||||
time += jshGetTimeFromMilliseconds(pulseTime);
|
||||
pulsePolarity = !pulsePolarity;
|
||||
jsvIteratorNext(&it);
|
||||
}
|
||||
jsvIteratorFree(&it);
|
||||
|
||||
if (hasPulses) {
|
||||
jstExecuteFn(_jswrap_puck_IR_done, time, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "Puck",
|
||||
"name" : "capSense",
|
||||
"#ifdef" : "NRF52",
|
||||
"generate" : "jswrap_puck_capSense",
|
||||
"params" : [
|
||||
["tx","pin",""],
|
||||
["rx","pin",""]
|
||||
],
|
||||
"return" : ["int", "Capacitive sense counter" ]
|
||||
}
|
||||
Capacitive sense. TX must be connected to RX pin and sense plate via 1MOhm resistor.
|
||||
|
||||
If no pins are supplied, the NFC ring is used for capacitive sense.
|
||||
*/
|
||||
int jswrap_puck_capSense(Pin tx, Pin rx) {
|
||||
if (jshIsPinValid(tx) && jshIsPinValid(rx)) {
|
||||
return (int)nrf_utils_cap_sense(tx, rx);
|
||||
}
|
||||
return (int)nrf_utils_cap_sense(CAPSENSE_TX_PIN, CAPSENSE_RX_PIN);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "kill",
|
||||
"generate" : "jswrap_puck_kill"
|
||||
}*/
|
||||
void jswrap_puck_kill() {
|
||||
if (mag_enabled) {
|
||||
mag_off();
|
||||
mag_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "idle",
|
||||
"generate" : "jswrap_puck_idle"
|
||||
}*/
|
||||
bool jswrap_puck_idle() {
|
||||
if (mag_enabled && nrf_gpio_pin_read(MAG_INT)) {
|
||||
int16_t d[3];
|
||||
mag_read(d);
|
||||
JsVar *xyz = mag_to_xyz(d);
|
||||
JsVar *puck = jsvObjectGetChild(execInfo.root, "Puck", 0);
|
||||
if (jsvHasChildren(puck))
|
||||
jsiQueueObjectCallbacks(puck, JS_EVENT_PREFIX"mag", &xyz, 1);
|
||||
jsvUnLock2(puck, xyz);
|
||||
return true; // don't sleep - handle this now
|
||||
}
|
||||
return false;
|
||||
}
|
||||
23
libs/puckjs/jswrap_puck.h
Normal file
23
libs/puckjs/jswrap_puck.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2016 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Contains JavaScript interface for Puck.js
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include "jspin.h"
|
||||
|
||||
void jswrap_puck_magOn();
|
||||
void jswrap_puck_magOff();
|
||||
JsVar *jswrap_puck_mag();
|
||||
void jswrap_puck_IR(JsVar *data);
|
||||
int jswrap_puck_capSense(Pin tx, Pin rx);
|
||||
|
||||
void jswrap_puck_kill();
|
||||
bool jswrap_puck_idle();
|
||||
10
scripts/build_js_hardware.js
Normal file → Executable file
10
scripts/build_js_hardware.js
Normal file → Executable file
@ -3,10 +3,10 @@
|
||||
the values of the bits in each register. Can be used for quickly building
|
||||
ways to access the underlying hardware from JS */
|
||||
|
||||
var INPUTFILE = "targetlibs/stm32f1/lib/stm32f10x.h";
|
||||
var definitions = {"STM32F10X_XL":true};
|
||||
//var INPUTFILE = "targetlibs/stm32f4/lib/stm32f4xx.h";
|
||||
//var definitions = {"STM32F401xx":true};
|
||||
//var INPUTFILE = "targetlibs/stm32f1/lib/stm32f10x.h";
|
||||
//var definitions = {"STM32F10X_XL":true};
|
||||
var INPUTFILE = "targetlibs/stm32f4/lib/stm32f411xe.h";
|
||||
var definitions = {"STM32F401xx":true};
|
||||
var fs = require('fs');
|
||||
|
||||
var structContents = undefined;
|
||||
@ -110,7 +110,7 @@ for (var def in definitions) {
|
||||
}
|
||||
}
|
||||
|
||||
var peripherals = ["RCC","DMA"];
|
||||
var peripherals = ["RCC","RTC","PWR"];
|
||||
|
||||
|
||||
function out(s) {
|
||||
|
||||
@ -176,6 +176,14 @@ def removeBlacklistForWrapper(blacklistfile,datas):
|
||||
if jsondata["class"] == black["class"]:
|
||||
if jsondata["name"] == black["name"]:
|
||||
toremove.append(idx)
|
||||
# extension by jumjum
|
||||
else:
|
||||
if "name" in jsondata:
|
||||
for black in blacklist:
|
||||
if black["class"] == "__":
|
||||
if jsondata["name"] == black["name"]:
|
||||
toremove.append(idx)
|
||||
# end extensioin by jumjum
|
||||
return delete_by_indices( datas, toremove)
|
||||
# ------------------------------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -380,8 +380,15 @@ if "SD" in board.devices:
|
||||
if spiNum==0: die("No SPI peripheral found for SD card's CLK pin")
|
||||
codeOut("#define SD_SPI EV_SPI"+str(spiNum))
|
||||
|
||||
if "IR" in board.devices:
|
||||
codeOutDevicePin("IR", "pin_anode", "IR_ANODE_PIN")
|
||||
codeOutDevicePin("IR", "pin_cathode", "IR_CATHODE_PIN")
|
||||
|
||||
for device in ["USB","SD","LCD","JTAG","ESP8266"]:
|
||||
if "CAPSENSE" in board.devices:
|
||||
codeOutDevicePin("CAPSENSE", "pin_rx", "CAPSENSE_RX_PIN")
|
||||
codeOutDevicePin("CAPSENSE", "pin_tx", "CAPSENSE_TX_PIN")
|
||||
|
||||
for device in ["USB","SD","LCD","JTAG","ESP8266","IR"]:
|
||||
if device in board.devices:
|
||||
for entry in board.devices[device]:
|
||||
if entry[:3]=="pin": usedPinChecks.append("(PIN)==" + toPinDef(board.devices[device][entry])+"/* "+device+" */")
|
||||
|
||||
@ -104,5 +104,5 @@ cp $DIR/dist_licences.txt $ZIPDIR/licences.txt
|
||||
|
||||
rm -f $ZIPFILE
|
||||
cd zipcontents
|
||||
echo zip $ZIPFILE *
|
||||
zip $ZIPFILE *
|
||||
echo zip -r $ZIPFILE *
|
||||
zip -r $ZIPFILE *
|
||||
|
||||
@ -846,7 +846,7 @@ class IntelHex(object):
|
||||
else: # conflict
|
||||
if overlap == 'error':
|
||||
raise AddressOverlapError(
|
||||
'Starting addresses are different')
|
||||
'Starting addresses are different - existing '+str(self.start_addr)+' vs new '+str(other.start_addr))
|
||||
elif overlap == 'replace':
|
||||
self.start_addr = other.start_addr
|
||||
#/IntelHex
|
||||
|
||||
@ -81,6 +81,7 @@ DEVICES = {
|
||||
"MEMS":"MEMS",
|
||||
"GYRO":"GYRO",
|
||||
"JTAG":"JTAG",
|
||||
"ESP8266":"ESP8266"
|
||||
};
|
||||
|
||||
for i in range(0,7):
|
||||
@ -116,12 +117,12 @@ def isvalidpin(pinname):
|
||||
pinnum = pinname[2:]
|
||||
return pinnum.isdigit()
|
||||
return False
|
||||
|
||||
|
||||
|
||||
# Find/populate a pin
|
||||
def haspin(pins, pinname):
|
||||
for pin in pins:
|
||||
if pin["name"]==pinname:
|
||||
if pin["name"]==pinname:
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -129,7 +130,7 @@ def haspin(pins, pinname):
|
||||
def findpin(pins, pinname, force):
|
||||
if pinname.find('-')!=-1: pinname = pinname[:pinname.find('-')]
|
||||
for pin in pins:
|
||||
if pin["name"]==pinname:
|
||||
if pin["name"]==pinname:
|
||||
return pin
|
||||
if force:
|
||||
print("ERROR: pin "+pinname+" not found")
|
||||
@ -154,8 +155,8 @@ def scan_pin_af_file(pins, filename, nameoffset, afoffset):
|
||||
pinname = pindata[nameoffset].strip()
|
||||
if pinname.find('(')>0: pinname = pinname[:pinname.find('(')]
|
||||
if not isvalidpin(pinname): continue
|
||||
pin = findpin(pins, pinname, False)
|
||||
#print(json.dumps(pin, sort_keys=True, indent=2))
|
||||
pin = findpin(pins, pinname, False)
|
||||
#print(json.dumps(pin, sort_keys=True, indent=2))
|
||||
for af in range(0, len(pindata)-afoffset):
|
||||
fnames = pindata[af+afoffset].split("/")
|
||||
for fname in fnames:
|
||||
@ -166,29 +167,29 @@ def scan_pin_af_file(pins, filename, nameoffset, afoffset):
|
||||
return pins
|
||||
|
||||
# Code for scanning normal file
|
||||
def scan_pin_file(pins, filename, nameoffset, functionoffset, altfunctionoffset):
|
||||
def scan_pin_file(pins, filename, nameoffset, functionoffset, altfunctionoffset):
|
||||
f = open(os.path.dirname(os.path.realpath(__file__))+'/../boards/pins/'+filename)
|
||||
lines = f.readlines()
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
headings = lines[0].split(",")
|
||||
for line in lines:
|
||||
pindata = line.split(",")
|
||||
pinname = pindata[nameoffset].strip()
|
||||
|
||||
extrafunction = ""
|
||||
if "BOOT1" in line: extrafunction="BOOT1"
|
||||
extrafunction = ""
|
||||
if "BOOT1" in line: extrafunction="BOOT1"
|
||||
if pinname.find('(')>0: pinname = pinname[:pinname.find('(')]
|
||||
if not isvalidpin(pinname): continue
|
||||
pin = findpin(pins, pinname, False)
|
||||
for i,head in enumerate(headings):
|
||||
pin["csv"][head] = pindata[i].strip()
|
||||
pin["csv"][head] = pindata[i].strip()
|
||||
if extrafunction!="":
|
||||
pin["functions"][extrafunction] = 0
|
||||
for fn in pindata[functionoffset].strip().split("/"):
|
||||
for fn in pindata[functionoffset].strip().split("/"):
|
||||
fname = fn.strip()
|
||||
pin["functions"][fname] = 0
|
||||
pin["functions"][fname] = 0
|
||||
if altfunctionoffset>=0:
|
||||
for fn in pindata[altfunctionoffset].strip().split("/"):
|
||||
for fn in pindata[altfunctionoffset].strip().split("/"):
|
||||
fname = fn.strip()
|
||||
pin["functions"][fname] = 1
|
||||
# print pin["name"]+" : "+', '.join(pin["functions"])
|
||||
@ -247,10 +248,9 @@ def get_device_pins(board):
|
||||
# If devices are used by a board, fill in their details for each pin
|
||||
def append_devices_to_pin_list(pins, board):
|
||||
devicepins = get_device_pins(board)
|
||||
|
||||
|
||||
for i,pin in enumerate(pins):
|
||||
if pin["name"] in devicepins:
|
||||
pins[i]["functions"][devicepins[pin["name"]]["device"]] = devicepins[pin["name"]]["function"]
|
||||
# print pins[i]["functions"][devicepins[pin["name"]]["device"]]
|
||||
# print pins[i]["functions"][devicepins[pin["name"]]["device"]]
|
||||
return pins
|
||||
|
||||
|
||||
@ -261,8 +261,7 @@ void jshPushIOCharEvent(
|
||||
) {
|
||||
// Check for a CTRL+C
|
||||
if (charData==3 && channel==jsiGetConsoleDevice()) {
|
||||
// Ctrl-C - force interrupt
|
||||
execInfo.execute |= EXEC_CTRL_C;
|
||||
jsiCtrlC(); // Ctrl-C - force interrupt of execution
|
||||
return;
|
||||
}
|
||||
// Check for existing buffer (we must have at least 2 in the queue to avoid dropping chars though!)
|
||||
|
||||
@ -101,8 +101,12 @@ NO_INLINE bool jsiEcho() {
|
||||
return ((jsiStatus&JSIS_ECHO_OFF_MASK)==0);
|
||||
}
|
||||
|
||||
NO_INLINE bool jsiPasswordProtected() {
|
||||
return ((jsiStatus&JSIS_PASSWORD_PROTECTED)!=0);
|
||||
}
|
||||
|
||||
static bool jsiShowInputLine() {
|
||||
return jsiEcho() && !inputLineRemoved;
|
||||
return jsiEcho() && !inputLineRemoved && !jsiPasswordProtected();
|
||||
}
|
||||
|
||||
/** Called when the input line/cursor is modified *and its iterator should be reset
|
||||
@ -371,6 +375,8 @@ void jsiConsoleReturnInputLine() {
|
||||
if (jsiStatus & JSIS_IN_DEBUGGER)
|
||||
jsiConsolePrint("debug");
|
||||
#endif
|
||||
if (jsiPasswordProtected())
|
||||
jsiConsolePrint("password");
|
||||
jsiConsolePrintChar('>'); // show the prompt
|
||||
jsiConsolePrintStringVarWithNewLineChar(inputLine, 0, ':');
|
||||
jsiMoveCursorChar(inputLine, jsvGetStringLength(inputLine), inputCursorPos);
|
||||
@ -379,14 +385,18 @@ void jsiConsoleReturnInputLine() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the input line of data.
|
||||
* Clear the input line of data. If updateConsole is set, it
|
||||
* sends VT100 characters to physically remove the line from
|
||||
* the user's terminal.
|
||||
*/
|
||||
void jsiClearInputLine() {
|
||||
jsiConsoleRemoveInputLine();
|
||||
void jsiClearInputLine(bool updateConsole) {
|
||||
if (updateConsole)
|
||||
jsiConsoleRemoveInputLine();
|
||||
// clear input line
|
||||
jsiInputLineCursorMoved();
|
||||
jsvUnLock(inputLine);
|
||||
inputLine = jsvNewFromEmptyString();
|
||||
inputCursorPos = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -723,7 +733,7 @@ void jsiSemiInit(bool autoLoad) {
|
||||
// Set state
|
||||
interruptedDuringEvent = false;
|
||||
// Set defaults
|
||||
jsiStatus = JSIS_NONE;
|
||||
jsiStatus &= ~JSIS_SOFTINIT_MASK;
|
||||
pinBusyIndicator = DEFAULT_BUSY_PIN_INDICATOR;
|
||||
|
||||
/* If flash contains any code, then we should
|
||||
@ -737,6 +747,12 @@ void jsiSemiInit(bool autoLoad) {
|
||||
jspSoftInit();
|
||||
}
|
||||
|
||||
// If a password was set, apply the lock
|
||||
JsVar *pwd = jsvObjectGetChild(execInfo.hiddenRoot, PASSWORD_VARIABLE_NAME, 0);
|
||||
if (pwd)
|
||||
jsiStatus |= JSIS_PASSWORD_PROTECTED;
|
||||
jsvUnLock(pwd);
|
||||
|
||||
// Softinit may run initialisation code that will overwrite defaults
|
||||
jsiSoftInit(!autoLoad);
|
||||
|
||||
@ -779,6 +795,8 @@ void jsiSemiInit(bool autoLoad) {
|
||||
|
||||
// The 'proper' init function - this should be called only once at bootup
|
||||
void jsiInit(bool autoLoad) {
|
||||
jsiStatus = JSIS_NONE;
|
||||
|
||||
#if defined(LINUX) || !defined(USB)
|
||||
consoleDevice = DEFAULT_CONSOLE_DEVICE;
|
||||
#else
|
||||
@ -1273,10 +1291,7 @@ void jsiHandleNewLine(bool execute) {
|
||||
|
||||
// Get line to execute, and reset inputLine
|
||||
JsVar *lineToExecute = jsvStringTrimRight(inputLine);
|
||||
jsiInputLineCursorMoved();
|
||||
jsvUnLock(inputLine);
|
||||
inputLine = jsvNewFromEmptyString();
|
||||
inputCursorPos = 0;
|
||||
jsiClearInputLine(false);
|
||||
#ifdef USE_DEBUGGER
|
||||
if (jsiStatus & JSIS_IN_DEBUGGER) {
|
||||
jsiDebuggerLine(lineToExecute);
|
||||
@ -1357,6 +1372,30 @@ void jsiHandleChar(char ch) {
|
||||
// 27 then 79 then 72 - end
|
||||
// 27 then 10 - alt enter
|
||||
|
||||
if (jsiPasswordProtected()) {
|
||||
if (ch=='\r' || ch==10) {
|
||||
JsVar *pwd = jsvObjectGetChild(execInfo.hiddenRoot, PASSWORD_VARIABLE_NAME, 0);
|
||||
// check password
|
||||
if (pwd && jsvCompareString(inputLine, pwd, 0, 0, false)==0)
|
||||
jsiStatus &= ~JSIS_PASSWORD_PROTECTED;
|
||||
jsvUnLock(pwd);
|
||||
jsiClearInputLine(false);
|
||||
if (jsiPasswordProtected()) {
|
||||
jsiConsolePrint("\n Invalid password\npassword>");
|
||||
} else {
|
||||
jsiConsolePrint("\n Logged in.\n");
|
||||
inputLineRemoved = true;
|
||||
jsiConsoleReturnInputLine();
|
||||
}
|
||||
} else {
|
||||
char str[2];
|
||||
str[0] = ch;
|
||||
str[1] = 0;
|
||||
if (jsvGetStringLength(inputLine)<20)
|
||||
jsiAppendToInputLine(str);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == 0) {
|
||||
inputState = IS_NONE; // ignore 0 - it's scary
|
||||
@ -1367,7 +1406,7 @@ void jsiHandleChar(char ch) {
|
||||
} else if (ch == 5) { // Ctrl-e
|
||||
jsiHandleEnd();
|
||||
} else if (ch == 21 || ch == 23) { // Ctrl-u or Ctrl-w
|
||||
jsiClearInputLine();
|
||||
jsiClearInputLine(true);
|
||||
} else if (ch == 27) {
|
||||
inputState = IS_HAD_27;
|
||||
} else if (inputState==IS_HAD_27) {
|
||||
@ -1425,7 +1464,7 @@ void jsiHandleChar(char ch) {
|
||||
} else {
|
||||
if (ch=='d') jsiLineNumberOffset = inputStateNumber;
|
||||
else if (ch=='H' /* 75 */) {
|
||||
if (inputStateNumber==2) jsiClearInputLine(); // Erase current line
|
||||
if (inputStateNumber==2) jsiClearInputLine(true); // Erase current line
|
||||
} else if (ch==126) {
|
||||
if (inputStateNumber==1) jsiHandleHome(); // Numpad Home
|
||||
else if (inputStateNumber==3) jsiHandleDelete(false/*not backspace*/); // Numpad (forwards) Delete
|
||||
@ -1607,6 +1646,14 @@ bool jsiIsWatchingPin(Pin pin) {
|
||||
return isWatched;
|
||||
}
|
||||
|
||||
void jsiCtrlC() {
|
||||
// If password protected, don't let Ctrl-C break out of running code!
|
||||
if (jsiPasswordProtected())
|
||||
return;
|
||||
// Force a break...
|
||||
execInfo.execute |= EXEC_CTRL_C;
|
||||
}
|
||||
|
||||
/** Take an event for a UART and handle the chareacters we're getting, potentially
|
||||
* grabbing more characters as well if it's easy. If more character events are
|
||||
* grabbed, the number of extra events (not characters) is returned */
|
||||
@ -2040,7 +2087,7 @@ bool jsiLoop() {
|
||||
#endif
|
||||
jsiTimeSinceCtrlC = 0;
|
||||
}
|
||||
jsiClearInputLine();
|
||||
jsiClearInputLine(true);
|
||||
}
|
||||
|
||||
// return console (if it was gone!)
|
||||
@ -2171,7 +2218,7 @@ void jsiDebuggerLoop() {
|
||||
EXEC_DEBUGGER_NEXT_LINE |
|
||||
EXEC_DEBUGGER_STEP_INTO |
|
||||
EXEC_DEBUGGER_FINISH_FUNCTION);
|
||||
jsiClearInputLine();
|
||||
jsiClearInputLine(true);
|
||||
jsiConsoleRemoveInputLine();
|
||||
jsiStatus = (jsiStatus & ~JSIS_ECHO_OFF_MASK) | JSIS_IN_DEBUGGER;
|
||||
|
||||
|
||||
@ -42,6 +42,8 @@ bool jsiFreeMoreMemory();
|
||||
bool jsiHasTimers(); // are there timers still left to run?
|
||||
bool jsiIsWatchingPin(Pin pin); // are there any watches for the given pin?
|
||||
|
||||
void jsiCtrlC(); // Ctrl-C - force interrupt of execution
|
||||
|
||||
/// Queue a function, string, or array (of funcs/strings) to be executed next time around the idle loop
|
||||
void jsiQueueEvents(JsVar *object, JsVar *callback, JsVar **args, int argCount);
|
||||
/// Return true if the object has callbacks...
|
||||
@ -122,6 +124,7 @@ void jsiSetSleep(JsiSleepType isSleep);
|
||||
#define USART_BAUDRATE_NAME "_baudrate"
|
||||
#define DEVICE_OPTIONS_NAME "_options"
|
||||
#define INIT_CALLBACK_NAME JS_EVENT_PREFIX"init" ///< Callback for `E.on('init'`
|
||||
#define PASSWORD_VARIABLE_NAME "pwd"
|
||||
|
||||
typedef enum {
|
||||
JSIS_NONE,
|
||||
@ -139,8 +142,10 @@ typedef enum {
|
||||
JSIS_TODO_MASK = JSIS_TODO_FLASH_SAVE|JSIS_TODO_FLASH_LOAD|JSIS_TODO_RESET,
|
||||
JSIS_CONSOLE_FORCED = 512, // see jsiSetConsoleDevice
|
||||
JSIS_WATCHDOG_AUTO = 1024, // Automatically kick the watchdog timer on idle
|
||||
JSIS_PASSWORD_PROTECTED = 2048, // Password protected
|
||||
|
||||
JSIS_ECHO_OFF_MASK = JSIS_ECHO_OFF|JSIS_ECHO_OFF_FOR_LINE
|
||||
JSIS_ECHO_OFF_MASK = JSIS_ECHO_OFF|JSIS_ECHO_OFF_FOR_LINE,
|
||||
JSIS_SOFTINIT_MASK = JSIS_PASSWORD_PROTECTED // stuff that DOESN'T get reset on softinit
|
||||
} PACKED_FLAGS JsiStatus;
|
||||
|
||||
extern JsiStatus jsiStatus;
|
||||
|
||||
@ -325,7 +325,10 @@ NO_INLINE bool jspeFunctionArguments(JsVar *funcVar) {
|
||||
JSP_MATCH('(');
|
||||
while (lex->tk!=')') {
|
||||
if (funcVar) {
|
||||
JsVar *param = jsvAddNamedChild(funcVar, 0, jslGetTokenValueAsString(lex));
|
||||
char buf[JSLEX_MAX_TOKEN_LENGTH+1];
|
||||
buf[0] = '\xFF';
|
||||
strcpy(&buf[1], jslGetTokenValueAsString(lex));
|
||||
JsVar *param = jsvAddNamedChild(funcVar, 0, buf);
|
||||
if (!param) { // out of memory
|
||||
jspSetError(false);
|
||||
return false;
|
||||
@ -614,7 +617,7 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
|
||||
JsVar *param = jsvObjectIteratorGetKey(&it);
|
||||
JsVar *value = jsvObjectIteratorGetValue(&it);
|
||||
while (jsvIsFunctionParameter(param) && value) {
|
||||
JsVar *paramName = jsvCopy(param);
|
||||
JsVar *paramName = jsvNewFromStringVar(param,1,JSVAPPENDSTRINGVAR_MAXLENGTH);
|
||||
if (paramName) { // could be out of memory
|
||||
jsvMakeFunctionParameter(paramName); // force this to be called a function parameter
|
||||
jsvSetValueOfName(paramName, value);
|
||||
@ -643,7 +646,7 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
|
||||
value = jspeAssignmentExpression();
|
||||
// and if execute, copy it over
|
||||
value = jsvSkipNameAndUnLock(value);
|
||||
JsVar *paramName = paramDefined ? jsvCopyNameOnly(param,false,true) : jsvNewFromEmptyString();
|
||||
JsVar *paramName = paramDefined ? jsvNewFromStringVar(param,1,JSVAPPENDSTRINGVAR_MAXLENGTH) : jsvNewFromEmptyString();
|
||||
if (paramName) { // could be out of memory
|
||||
jsvMakeFunctionParameter(paramName); // force this to be called a function parameter
|
||||
jsvSetValueOfName(paramName, value);
|
||||
@ -663,7 +666,7 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
|
||||
while (args<argCount) {
|
||||
JsVar *param = jsvObjectIteratorGetKey(&it);
|
||||
bool paramDefined = jsvIsFunctionParameter(param);
|
||||
JsVar *paramName = paramDefined ? jsvCopyNameOnly(param,false,true) : jsvNewFromEmptyString();
|
||||
JsVar *paramName = paramDefined ? jsvNewFromStringVar(param,1,JSVAPPENDSTRINGVAR_MAXLENGTH) : jsvNewFromEmptyString();
|
||||
if (paramName) {
|
||||
jsvMakeFunctionParameter(paramName); // force this to be called a function parameter
|
||||
jsvSetValueOfName(paramName, argPtr[args]);
|
||||
@ -688,9 +691,12 @@ NO_INLINE JsVar *jspeFunctionCall(JsVar *function, JsVar *functionName, JsVar *t
|
||||
thisVar = jsvSkipName(param);
|
||||
} else if (jsvIsStringEqual(param, JSPARSE_FUNCTION_LINENUMBER_NAME)) functionLineNumber = (uint16_t)jsvGetIntegerAndUnLock(jsvSkipName(param));
|
||||
else if (jsvIsFunctionParameter(param)) {
|
||||
JsVar *paramName = jsvCopy(param);
|
||||
JsVar *paramName = jsvNewFromStringVar(param,1,JSVAPPENDSTRINGVAR_MAXLENGTH);
|
||||
// paramName is already a name (it's a function parameter)
|
||||
if (paramName) {// could be out of memory - or maybe just not supplied!
|
||||
jsvMakeFunctionParameter(paramName);
|
||||
JsVar *defaultVal = jsvSkipName(param);
|
||||
if (defaultVal) jsvUnLock(jsvSetValueOfName(paramName, defaultVal));
|
||||
jsvAddName(functionRoot, paramName);
|
||||
jsvUnLock(paramName);
|
||||
}
|
||||
@ -1649,9 +1655,10 @@ NO_INLINE JsVar *__jspeAssignmentExpression(JsVar *lhs) {
|
||||
else if (op==LEX_RSHIFTUNSIGNEDEQUAL) op=LEX_RSHIFTUNSIGNED;
|
||||
if (op=='+' && jsvIsName(lhs)) {
|
||||
JsVar *currentValue = jsvSkipName(lhs);
|
||||
if (jsvIsString(currentValue) && !jsvIsFlatString(currentValue) && jsvGetRefs(currentValue)==1) {
|
||||
/* A special case for string += where this is the only use of the string,
|
||||
* as we may be able to do a simple append (rather than clone + append)*/
|
||||
if (jsvIsString(currentValue) && !jsvIsFlatString(currentValue) && jsvGetRefs(currentValue)==1 && rhs!=currentValue) {
|
||||
/* A special case for string += where this is the only use of the string
|
||||
* and we're not appending to ourselves. In this case we can do a
|
||||
* simple append (rather than clone + append)*/
|
||||
JsVar *str = jsvAsString(rhs, false);
|
||||
jsvAppendStringVarComplete(currentValue, str);
|
||||
jsvUnLock(str);
|
||||
@ -1796,7 +1803,7 @@ NO_INLINE JsVar *jspeStatementVar() {
|
||||
|
||||
NO_INLINE JsVar *jspeStatementIf() {
|
||||
bool cond;
|
||||
JsVar *var;
|
||||
JsVar *var, *result;
|
||||
JSP_ASSERT_MATCH(LEX_R_IF);
|
||||
JSP_MATCH('(');
|
||||
var = jspeExpression();
|
||||
@ -1807,16 +1814,26 @@ NO_INLINE JsVar *jspeStatementIf() {
|
||||
|
||||
JSP_SAVE_EXECUTE();
|
||||
if (!cond) jspSetNoExecute();
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
if (!cond) JSP_RESTORE_EXECUTE();
|
||||
JsVar *a = jspeBlockOrStatement();
|
||||
if (!cond) {
|
||||
jsvUnLock(a);
|
||||
JSP_RESTORE_EXECUTE();
|
||||
} else {
|
||||
result = a;
|
||||
}
|
||||
if (lex->tk==LEX_R_ELSE) {
|
||||
JSP_ASSERT_MATCH(LEX_R_ELSE);
|
||||
JSP_SAVE_EXECUTE();
|
||||
if (cond) jspSetNoExecute();
|
||||
jsvUnLock(jspeBlockOrStatement());
|
||||
if (cond) JSP_RESTORE_EXECUTE();
|
||||
JsVar *a = jspeBlockOrStatement();
|
||||
if (cond) {
|
||||
jsvUnLock(a);
|
||||
JSP_RESTORE_EXECUTE();
|
||||
} else {
|
||||
result = a;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
NO_INLINE JsVar *jspeStatementSwitch() {
|
||||
|
||||
@ -429,13 +429,14 @@ bool jstPinPWM(JsVarFloat freq, JsVarFloat dutyCycle, Pin pin) {
|
||||
}
|
||||
|
||||
/// Execute the given function repeatedly after the given time period
|
||||
bool jstExecuteFn(void (*fn)(JsSysTime), JsSysTime period, bool repeat) {
|
||||
bool jstExecuteFn(void (*fn)(JsSysTime), JsSysTime startTime, uint32_t period) {
|
||||
UtilTimerTask task;
|
||||
task.time = jshGetSystemTime() + period;
|
||||
task.repeatInterval = repeat ? (uint32_t)period : 0;
|
||||
task.time = startTime;
|
||||
task.repeatInterval = period;
|
||||
task.type = UET_EXECUTE;
|
||||
task.data.execute = fn;
|
||||
|
||||
WAIT_UNTIL(!utilTimerIsFull(), "Utility Timer");
|
||||
return utilTimerInsertTask(&task);
|
||||
}
|
||||
|
||||
|
||||
@ -108,8 +108,8 @@ bool jstPinOutputAtTime(JsSysTime time, Pin *pins, int pinCount, uint8_t value);
|
||||
// Do software PWM on the given pin, using the timer IRQs
|
||||
bool jstPinPWM(JsVarFloat freq, JsVarFloat dutyCycle, Pin pin);
|
||||
|
||||
/// Execute the given function repeatedly after the given time period
|
||||
bool jstExecuteFn(void (*fn)(JsSysTime), JsSysTime period, bool repeat);
|
||||
/// Execute the given function repeatedly after the given time period. If periof=0, don't repeat
|
||||
bool jstExecuteFn(void (*fn)(JsSysTime), JsSysTime startTime, uint32_t period);
|
||||
|
||||
/// Stop executing the given function
|
||||
bool jstStopExecuteFn(void (*fn)(JsSysTime));
|
||||
|
||||
@ -289,8 +289,8 @@ unsigned int jsvGetMemoryTotal() {
|
||||
void jsvSetMemoryTotal(unsigned int jsNewVarCount) {
|
||||
#ifdef RESIZABLE_JSVARS
|
||||
assert(!isMemoryBusy);
|
||||
isMemoryBusy = true;
|
||||
if (jsNewVarCount <= jsVarsSize) return; // never allow us to have less!
|
||||
isMemoryBusy = true;
|
||||
// When resizing, we just allocate a bunch more
|
||||
unsigned int oldSize = jsVarsSize;
|
||||
unsigned int oldBlockCount = jsVarsSize >> JSVAR_BLOCK_SHIFT;
|
||||
|
||||
@ -1117,6 +1117,34 @@ JsVarInt jswrap_espruino_HSBtoRGB(JsVarFloat hue, JsVarFloat sat, JsVarFloat bri
|
||||
}
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "E",
|
||||
"name" : "setPassword",
|
||||
"generate" : "jswrap_espruino_setPassword",
|
||||
"params" : [
|
||||
["opts","JsVar","The password - max 20 chars"]
|
||||
]
|
||||
}
|
||||
Set a password on the console (REPL). When powered on, Espruino will
|
||||
then demand a password before the console can be used.
|
||||
|
||||
To remove the password, call this function with no arguments.
|
||||
|
||||
**Note:** There is no protection against multiple password attempts, so someone
|
||||
could conceivably try every password in a dictionary.
|
||||
|
||||
**Note:** This password is stored in memory in plain text. If someone is able
|
||||
to execute arbitrary JavaScript code on the device (eg, you use `eval` on input
|
||||
from unknown sources) or read the device's firmware then they may be able to
|
||||
obtain it.
|
||||
*/
|
||||
void jswrap_espruino_setPassword(JsVar *pwd) {
|
||||
if (pwd)
|
||||
pwd = jsvAsString(pwd, false);
|
||||
jsvUnLock(jsvObjectSetChild(execInfo.hiddenRoot, PASSWORD_VARIABLE_NAME, pwd));
|
||||
}
|
||||
|
||||
// ----------------------------------------- USB Specific Stuff
|
||||
|
||||
#ifdef USE_USB_HID
|
||||
|
||||
@ -41,6 +41,7 @@ JsVar *jswrap_espruino_getSizeOf(JsVar *v, int depth);
|
||||
void jswrap_espruino_mapInPlace(JsVar *from, JsVar *to, JsVar *map, JsVarInt bits);
|
||||
JsVar *jswrap_e_dumpStr();
|
||||
JsVarInt jswrap_espruino_HSBtoRGB(JsVarFloat hue, JsVarFloat sat, JsVarFloat bri);
|
||||
void jswrap_espruino_setPassword(JsVar *pwd);
|
||||
|
||||
void jswrap_espruino_setUSBHID(JsVar *arr);
|
||||
bool jswrap_espruino_sendUSBHID(JsVar *arr);
|
||||
|
||||
@ -160,7 +160,7 @@ void jswrap_flash_write(JsVar *data, int addr) {
|
||||
"generate" : "jswrap_flash_read",
|
||||
"params" : [
|
||||
["length","int","The amount of data to read (in bytes)"],
|
||||
["addr","int","The address to start writing from"]
|
||||
["addr","int","The address to start reading from"]
|
||||
],
|
||||
"return" : ["JsVar","A Uint8Array of data"]
|
||||
}
|
||||
|
||||
@ -71,13 +71,14 @@ JsVar *jswrap_function_constructor(JsVar *args) {
|
||||
if (s) {
|
||||
// copy the string - if a string was supplied already we want to make
|
||||
// sure we have a new (unreferenced) string
|
||||
JsVar *paramName = jsvNewFromStringVar(s, 0, JSVAPPENDSTRINGVAR_MAXLENGTH);
|
||||
jsvUnLock(s);
|
||||
JsVar *paramName = jsvNewFromString("\xFF");
|
||||
if (paramName) {
|
||||
jsvAppendStringVarComplete(paramName, s);
|
||||
jsvMakeFunctionParameter(paramName); // force this to be called a function parameter
|
||||
jsvAddName(fn, paramName);
|
||||
jsvUnLock(paramName);
|
||||
}
|
||||
jsvUnLock(s);
|
||||
}
|
||||
|
||||
jsvUnLock(v);
|
||||
|
||||
@ -170,7 +170,9 @@ void jsfGetJSONForFunctionWithCallback(JsVar *var, JSONFlags flags, vcbprintf_ca
|
||||
firstParm=false;
|
||||
else
|
||||
cbprintf(user_callback, user_data, ",");
|
||||
cbprintf(user_callback, user_data, "%v", child);
|
||||
JsVar *name = jsvNewFromStringVar(child, 1, JSVAPPENDSTRINGVAR_MAXLENGTH);
|
||||
cbprintf(user_callback, user_data, "%v", name);
|
||||
jsvUnLock(name);
|
||||
} else if (jsvIsString(child) && jsvIsStringEqual(child, JSPARSE_FUNCTION_CODE_NAME)) {
|
||||
codeVar = jsvObjectIteratorGetValue(&it);
|
||||
}
|
||||
|
||||
@ -778,6 +778,14 @@ void jswrap_function_replaceWith(JsVar *oldFunc, JsVar *newFunc) {
|
||||
jsWarn("First argument of replaceWith should be a function - ignoring");
|
||||
return;
|
||||
}
|
||||
// If old was native or vice versa...
|
||||
if (jsvIsNativeFunction(oldFunc) != jsvIsNativeFunction(newFunc)) {
|
||||
if (jsvIsNativeFunction(newFunc))
|
||||
oldFunc->flags |= JSV_NATIVE;
|
||||
else
|
||||
oldFunc->flags &= ~JSV_NATIVE;
|
||||
}
|
||||
|
||||
// Grab scope - the one thing we want to keep
|
||||
JsVar *scope = jsvFindChildFromString(oldFunc, JSPARSE_FUNCTION_SCOPE_NAME, false);
|
||||
// so now remove all existing entries
|
||||
|
||||
@ -214,7 +214,9 @@ JsVar *jswrap_spi_send(
|
||||
|
||||
// Handle the data being a single byte value
|
||||
if (jsvIsNumeric(srcdata)) {
|
||||
int r = data.spiSend((unsigned char)jsvGetInteger(srcdata), &data.spiSendData);
|
||||
int d = jsvGetInteger(srcdata);
|
||||
if (d<0) d = 0; // protect against -1 as we use this in the jshardware SPI implementation
|
||||
int r = data.spiSend(d, &data.spiSendData);
|
||||
if (r<0) r = data.spiSend(-1, &data.spiSendData);
|
||||
dst = jsvNewFromInteger(r); // retrieve the byte (no send!)
|
||||
}
|
||||
@ -242,9 +244,8 @@ JsVar *jswrap_spi_send(
|
||||
unsigned char out = (unsigned char)data.spiSend(-1, &data.spiSendData);
|
||||
jsvAppendStringBuf(dst, (char*)&out, 1);
|
||||
}
|
||||
}
|
||||
// Handle the data being an iterable.
|
||||
else {
|
||||
} else {
|
||||
// Handle the data being an iterable.
|
||||
int nBytes = jsvIterateCallbackCount(srcdata);
|
||||
dst = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
|
||||
if (dst) {
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
#define PERIPHERAL_RESOURCE_SHARING_ENABLED 0
|
||||
|
||||
/* CLOCK */
|
||||
#define CLOCK_ENABLED 0
|
||||
#define CLOCK_ENABLED 1
|
||||
// CLOCK_ENABLED is for enabling the clock driver in the SDK
|
||||
// Seems not to be needed is using SoftDevice?
|
||||
// http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v11.0.0%2Fhardware_driver_clock.html&cp=4_0_0_2_1
|
||||
|
||||
@ -40,17 +40,30 @@ static __INLINE uint32_t pstorage_flash_page_end()
|
||||
|
||||
#define PSTORAGE_FLASH_PAGE_END pstorage_flash_page_end()
|
||||
|
||||
#define PSTORAGE_NUM_OF_PAGES 1 /**< Number of flash pages allocated for the pstorage module excluding the swap page, configurable based on system requirements. */
|
||||
/**< Number of flash pages allocated for the pstorage module excluding the swap page, configurable based on system requirements. */
|
||||
#ifdef BOOTLOADER
|
||||
#define PSTORAGE_NUM_OF_PAGES 3
|
||||
#else
|
||||
#define PSTORAGE_NUM_OF_PAGES 1
|
||||
#endif
|
||||
#define PSTORAGE_MIN_BLOCK_SIZE 0x0010 /**< Minimum size of block that can be registered with the module. Should be configured based on system requirements, recommendation is not have this value to be at least size of word. */
|
||||
|
||||
#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_NUM_OF_PAGES - 1) \
|
||||
#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_NUM_OF_PAGES) \
|
||||
* PSTORAGE_FLASH_PAGE_SIZE) /**< Start address for persistent data, configurable according to system requirements. */
|
||||
#define PSTORAGE_DATA_END_ADDR ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */
|
||||
#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR /**< Top-most page is used as swap area for clear and update. */
|
||||
#define PSTORAGE_DATA_END_ADDR (PSTORAGE_FLASH_PAGE_END * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */
|
||||
#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR
|
||||
|
||||
#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */
|
||||
#define PSTORAGE_CMD_QUEUE_SIZE 10 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */
|
||||
|
||||
#ifdef BOOTLOADER
|
||||
/**@breif Define this flag in case Raw access to persistent memory is to be enabled. Raw mode
|
||||
* unlike the data mode is for uses other than storing data from various mode. This mode is
|
||||
* employed when unpdating firmware or similar uses. Therefore, this mode shall be enabled
|
||||
* only for these special usecases and typically disabled.
|
||||
*/
|
||||
#define PSTORAGE_RAW_MODE_ENABLE
|
||||
#endif
|
||||
|
||||
/** Abstracts persistently memory block identifier. */
|
||||
typedef uint32_t pstorage_block_t;
|
||||
@ -61,7 +74,7 @@ typedef struct
|
||||
pstorage_block_t block_id; /**< Block ID.*/
|
||||
} pstorage_handle_t;
|
||||
|
||||
typedef uint16_t pstorage_size_t; /** Size of length and offset fields. */
|
||||
typedef uint32_t pstorage_size_t; /** Size of length and offset fields. */
|
||||
|
||||
/**@brief Handles Flash Access Result Events. To be called in the system event dispatcher of the application. */
|
||||
void pstorage_sys_event_handler (uint32_t sys_evt);
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @cond To make doxygen skip this file */
|
||||
|
||||
/** @file
|
||||
* This header contains defines with respect persistent storage that are specific to
|
||||
* persistent storage implementation and application use case.
|
||||
*/
|
||||
#ifndef PSTORAGE_PL_H__
|
||||
#define PSTORAGE_PL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf.h"
|
||||
|
||||
static __INLINE uint16_t pstorage_flash_page_size()
|
||||
{
|
||||
return (uint16_t)NRF_FICR->CODEPAGESIZE;
|
||||
}
|
||||
|
||||
#define PSTORAGE_FLASH_PAGE_SIZE pstorage_flash_page_size() /**< Size of one flash page. */
|
||||
#define PSTORAGE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */
|
||||
|
||||
static __INLINE uint32_t pstorage_flash_page_end()
|
||||
{
|
||||
uint32_t bootloader_addr = NRF_UICR->NRFFW[0];
|
||||
|
||||
return ((bootloader_addr != PSTORAGE_FLASH_EMPTY_MASK) ?
|
||||
(bootloader_addr/ PSTORAGE_FLASH_PAGE_SIZE) : NRF_FICR->CODESIZE);
|
||||
}
|
||||
|
||||
#define PSTORAGE_FLASH_PAGE_END pstorage_flash_page_end()
|
||||
|
||||
#define PSTORAGE_NUM_OF_PAGES 1 /**< Number of flash pages allocated for the pstorage module excluding the swap page, configurable based on system requirements. */
|
||||
#define PSTORAGE_MIN_BLOCK_SIZE 0x0010 /**< Minimum size of block that can be registered with the module. Should be configured based on system requirements, recommendation is not have this value to be at least size of word. */
|
||||
|
||||
#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_NUM_OF_PAGES - 1) \
|
||||
* PSTORAGE_FLASH_PAGE_SIZE) /**< Start address for persistent data, configurable according to system requirements. */
|
||||
#define PSTORAGE_DATA_END_ADDR ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */
|
||||
#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR /**< Top-most page is used as swap area for clear and update. */
|
||||
|
||||
#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */
|
||||
#define PSTORAGE_CMD_QUEUE_SIZE 10 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */
|
||||
|
||||
|
||||
/** Abstracts persistently memory block identifier. */
|
||||
typedef uint32_t pstorage_block_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t module_id; /**< Module ID.*/
|
||||
pstorage_block_t block_id; /**< Block ID.*/
|
||||
} pstorage_handle_t;
|
||||
|
||||
typedef uint16_t pstorage_size_t; /** Size of length and offset fields. */
|
||||
|
||||
/**@brief Handles Flash Access Result Events. To be called in the system event dispatcher of the application. */
|
||||
void pstorage_sys_event_handler (uint32_t sys_evt);
|
||||
|
||||
#endif // PSTORAGE_PL_H__
|
||||
|
||||
/** @} */
|
||||
/** @endcond */
|
||||
@ -14,7 +14,6 @@
|
||||
#include "dfu.h"
|
||||
#include <dfu_types.h>
|
||||
#include <stddef.h>
|
||||
#include "boards.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_sdm.h"
|
||||
#include "nrf_gpio.h"
|
||||
@ -36,11 +35,17 @@
|
||||
#include "nrf_delay.h"
|
||||
#include "sdk_common.h"
|
||||
|
||||
#include "platform_config.h"
|
||||
|
||||
#define ADVERTISING_LED_PIN_NO LED1_PININDEX /**< Is on when device is advertising. */
|
||||
#define ADVERTISING_LED_PIN_ON LED1_ONSTATE
|
||||
#define CONNECTED_LED_PIN_NO LED2_PININDEX /**< Is on when device has connected. */
|
||||
#define CONNECTED_LED_PIN_ON LED2_ONSTATE
|
||||
|
||||
|
||||
#define DFU_REV_MAJOR 0x00 /** DFU Major revision number to be exposed. */
|
||||
#define DFU_REV_MINOR 0x08 /** DFU Minor revision number to be exposed. */
|
||||
#define DFU_REVISION ((DFU_REV_MAJOR << 8) | DFU_REV_MINOR) /** DFU Revision number to be exposed. Combined of major and minor versions. */
|
||||
#define ADVERTISING_LED_PIN_NO BSP_LED_0 /**< Is on when device is advertising. */
|
||||
#define CONNECTED_LED_PIN_NO BSP_LED_1 /**< Is on when device has connected. */
|
||||
#define DFU_SERVICE_HANDLE 0x000C /**< Handle of DFU service when DFU service is first service initialized. */
|
||||
#define BLE_HANDLE_MAX 0xFFFF /**< Max handle value is BLE. */
|
||||
|
||||
@ -734,7 +739,7 @@ static void advertising_start(void)
|
||||
err_code = sd_ble_gap_adv_start(&m_adv_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);
|
||||
nrf_gpio_pin_write(ADVERTISING_LED_PIN_NO, ADVERTISING_LED_PIN_ON);
|
||||
|
||||
m_is_advertising = true;
|
||||
}
|
||||
@ -752,7 +757,7 @@ static void advertising_stop(void)
|
||||
err_code = sd_ble_gap_adv_stop();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
nrf_gpio_pin_set(ADVERTISING_LED_PIN_NO);
|
||||
nrf_gpio_pin_write(ADVERTISING_LED_PIN_NO, !ADVERTISING_LED_PIN_ON);
|
||||
|
||||
m_is_advertising = false;
|
||||
}
|
||||
@ -771,8 +776,8 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
nrf_gpio_pin_clear(CONNECTED_LED_PIN_NO);
|
||||
nrf_gpio_pin_set(ADVERTISING_LED_PIN_NO);
|
||||
nrf_gpio_pin_write(CONNECTED_LED_PIN_NO, CONNECTED_LED_PIN_ON);
|
||||
nrf_gpio_pin_write(ADVERTISING_LED_PIN_NO, !ADVERTISING_LED_PIN_ON);
|
||||
|
||||
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
m_is_advertising = false;
|
||||
@ -784,7 +789,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
|
||||
uint16_t sys_attr_len = 128;
|
||||
|
||||
m_direct_adv_cnt = APP_DIRECTED_ADV_TIMEOUT;
|
||||
nrf_gpio_pin_set(CONNECTED_LED_PIN_NO);
|
||||
nrf_gpio_pin_write(CONNECTED_LED_PIN_NO, !CONNECTED_LED_PIN_ON);
|
||||
|
||||
err_code = sd_ble_gatts_sys_attr_get(m_conn_handle,
|
||||
sys_attr,
|
||||
@ -946,8 +951,8 @@ static void leds_init(void)
|
||||
{
|
||||
nrf_gpio_cfg_output(ADVERTISING_LED_PIN_NO);
|
||||
nrf_gpio_cfg_output(CONNECTED_LED_PIN_NO);
|
||||
nrf_gpio_pin_set(ADVERTISING_LED_PIN_NO);
|
||||
nrf_gpio_pin_set(CONNECTED_LED_PIN_NO);
|
||||
nrf_gpio_pin_write(ADVERTISING_LED_PIN_NO, !ADVERTISING_LED_PIN_ON);
|
||||
nrf_gpio_pin_write(CONNECTED_LED_PIN_NO, !CONNECTED_LED_PIN_ON);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -57,8 +57,8 @@
|
||||
|
||||
|
||||
#elif NRF52
|
||||
|
||||
#define BOOTLOADER_REGION_START 0x0007A000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
|
||||
// see Makefile, dfu_gcc_nrf52.ld, linker_nrf52_ble_espruino_bootloader.ld and dfu_types.h
|
||||
#define BOOTLOADER_REGION_START 0x00079000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
|
||||
#define BOOTLOADER_SETTINGS_ADDRESS 0x0007F000 /**< The field specifies the page location of the bootloader settings address. */
|
||||
#define BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS 0x0007E000 /**< The field specifies the page location of the mbr params page address. */
|
||||
|
||||
|
||||
@ -155,19 +155,11 @@ static __INLINE void app_error_print(uint32_t id, uint32_t pc, uint32_t info)
|
||||
*
|
||||
* @param[in] ERR_CODE Error code supplied to the error handler.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define APP_ERROR_HANDLER(ERR_CODE) \
|
||||
do \
|
||||
{ \
|
||||
app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define APP_ERROR_HANDLER(ERR_CODE) \
|
||||
do \
|
||||
{ \
|
||||
app_error_handler_bare((ERR_CODE)); \
|
||||
} while (0)
|
||||
#endif
|
||||
/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS.
|
||||
*
|
||||
* @param[in] ERR_CODE Error code supplied to the error handler.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
59
targetlibs/nrf5x/nrf5x_linkers/dfu_gcc_nrf51.ld
Normal file
59
targetlibs/nrf5x/nrf5x_linkers/dfu_gcc_nrf51.ld
Normal file
@ -0,0 +1,59 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/** Flash start address for the bootloader. This setting will also be stored in UICR to allow the
|
||||
* MBR to init the bootloader when starting the system. This value must correspond to
|
||||
* BOOTLOADER_REGION_START found in dfu_types.h. The system is prevented from starting up if
|
||||
* those values do not match. The check is performed in main.c, see
|
||||
* APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
|
||||
*/
|
||||
FLASH (rx) : ORIGIN = 0x3C000, LENGTH = 0x3C00
|
||||
|
||||
/** RAM Region for bootloader. This setting is suitable when used with s110, s120, s130, s310. */
|
||||
RAM (rwx) : ORIGIN = 0x20002C00, LENGTH = 0x5380
|
||||
|
||||
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
|
||||
* from application to bootloader when using buttonluss DFU OTA.
|
||||
*/
|
||||
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
|
||||
|
||||
/** Location of bootloader setting in at the last flash page. */
|
||||
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0003FC00, LENGTH = 0x0400
|
||||
|
||||
/** Location in UICR where bootloader start address is stored. */
|
||||
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.fs_data_out ALIGN(4):
|
||||
{
|
||||
PROVIDE( __start_fs_data = .);
|
||||
KEEP(*(fs_data))
|
||||
PROVIDE( __stop_fs_data = .);
|
||||
} = 0
|
||||
/* Ensures the bootloader settings are placed at the last flash page. */
|
||||
.bootloaderSettings(NOLOAD) :
|
||||
{
|
||||
|
||||
} > BOOTLOADER_SETTINGS
|
||||
|
||||
/* Ensures the Bootloader start address in flash is written to UICR when flashing the image. */
|
||||
.uicrBootStartAddress :
|
||||
{
|
||||
KEEP(*(.uicrBootStartAddress))
|
||||
} > UICR_BOOTLOADER
|
||||
|
||||
/* No init RAM section in bootloader. Used for bond information exchange. */
|
||||
.noinit(NOLOAD) :
|
||||
{
|
||||
|
||||
} > NOINIT
|
||||
/* other placements follow here... */
|
||||
}
|
||||
|
||||
INCLUDE "gcc_nrf5x_espruino_common.ld"
|
||||
80
targetlibs/nrf5x/nrf5x_linkers/dfu_gcc_nrf52.ld
Normal file
80
targetlibs/nrf5x/nrf5x_linkers/dfu_gcc_nrf52.ld
Normal file
@ -0,0 +1,80 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/** Flash start address for the bootloader. This setting will also be stored in UICR to allow the
|
||||
* MBR to init the bootloader when starting the system. This value must correspond to
|
||||
* BOOTLOADER_REGION_START found in dfu_types.h. The system is prevented from starting up if
|
||||
* those values do not match. The check is performed in main.c, see
|
||||
* APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
|
||||
|
||||
* see Makefile, dfu_gcc_nrf52.ld, linker_nrf52_ble_espruino_bootloader.ld and dfu_types.h
|
||||
*/
|
||||
FLASH (rx) : ORIGIN = 0x79000, LENGTH = 0x5000
|
||||
|
||||
/** RAM Region for bootloader. This setting is suitable when used with s132. */
|
||||
RAM (rwx) : ORIGIN = 0x20002C00, LENGTH = 0x5380
|
||||
|
||||
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
|
||||
* from application to bootloader when using buttonluss DFU OTA.
|
||||
*/
|
||||
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
|
||||
|
||||
/** Location of bootloader setting in flash. */
|
||||
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0007F000, LENGTH = 0x1000
|
||||
|
||||
/** Location in UICR where bootloader start address is stored. */
|
||||
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
|
||||
|
||||
/** Location of mbr params page in flash. */
|
||||
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x0007E000, LENGTH = 0x1000
|
||||
|
||||
/** Location in UICR where mbr params page address is stored. */
|
||||
UICR_MBR_PARAM_PAGE(r) : ORIGIN = 0x10001018, LENGTH = 0x04
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.fs_data_out ALIGN(4):
|
||||
{
|
||||
PROVIDE( __start_fs_data = .);
|
||||
KEEP(*(fs_data))
|
||||
PROVIDE( __stop_fs_data = .);
|
||||
} = 0
|
||||
|
||||
/* Place the bootloader settings page in flash. */
|
||||
.bootloaderSettings(NOLOAD) :
|
||||
{
|
||||
|
||||
} > BOOTLOADER_SETTINGS
|
||||
|
||||
/* Write the bootloader address in UICR. */
|
||||
.uicrBootStartAddress :
|
||||
{
|
||||
KEEP(*(.uicrBootStartAddress))
|
||||
} > UICR_BOOTLOADER
|
||||
|
||||
/* Place the mbr params page in flash. */
|
||||
.mbrParamsPage(NOLOAD) :
|
||||
{
|
||||
|
||||
} > MBR_PARAMS_PAGE
|
||||
|
||||
/* Write the bootloader address in UICR. */
|
||||
.uicrMbrParamsPageAddress :
|
||||
{
|
||||
KEEP(*(.uicrMbrParamsPageAddress))
|
||||
} > UICR_MBR_PARAM_PAGE
|
||||
|
||||
/* No init RAM section in bootloader. Used for bond information exchange. */
|
||||
.noinit(NOLOAD) :
|
||||
{
|
||||
|
||||
} > NOINIT
|
||||
/* other placements follow here... */
|
||||
}
|
||||
|
||||
INCLUDE "gcc_nrf5x_espruino_common.ld"
|
||||
@ -6,7 +6,7 @@ GROUP(-lgcc -lc -lnosys)
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x1b000, LENGTH = 0x25000
|
||||
RAM (rwx) : ORIGIN = 0x20001fe8, LENGTH = 0x2018
|
||||
RAM (rwx) : ORIGIN = 0x20002008, LENGTH = 0x1FF8
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
|
||||
@ -6,7 +6,7 @@ GROUP(-lgcc -lc -lnosys)
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x1b000, LENGTH = 0x25000
|
||||
RAM (rwx) : ORIGIN = 0x20001fe8, LENGTH = 0x6018
|
||||
RAM (rwx) : ORIGIN = 0x20002008, LENGTH = 0x5FF8
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
|
||||
@ -5,8 +5,8 @@ GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x1c000, LENGTH = 0x5e000 /* 0x7a000 and above is reserved for the bootloader. */
|
||||
RAM (rwx) : ORIGIN = 0x200025e0, LENGTH = 0xda20
|
||||
FLASH (rx) : ORIGIN = 0x1c000, LENGTH = 0x64000
|
||||
RAM (rwx) : ORIGIN = 0x20002600, LENGTH = 0xda00
|
||||
/* FIXME - we seem to have to start with 256 bytes less RAM than the figures below */
|
||||
/* length is just 65536 - origin */
|
||||
/* PERIPH 1 CENTRAL 0 - RAM (rwx) : ORIGIN = 0x20001E00, LENGTH = 0xE200 */
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x1c000, LENGTH = 0x5d000 /* 0x79000 and above is reserved for the bootloader. see Makefile, dfu_gcc_nrf52.ld, linker_nrf52_ble_espruino_bootloader.ld and dfu_types.h */
|
||||
RAM (rwx) : ORIGIN = 0x20002600, LENGTH = 0xda00
|
||||
/* FIXME - we seem to have to start with 256 bytes less RAM than the figures below */
|
||||
/* length is just 65536 - origin */
|
||||
/* PERIPH 1 CENTRAL 0 - RAM (rwx) : ORIGIN = 0x20001E00, LENGTH = 0xE200 */
|
||||
/* PERIPH 1 CENTRAL 1 - RAM (rwx) : ORIGIN = 0x200023C8, LENGTH = 0xDC38 */
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.fs_data_out ALIGN(4):
|
||||
{
|
||||
PROVIDE( __start_fs_data = .);
|
||||
KEEP(*(fs_data))
|
||||
PROVIDE( __stop_fs_data = .);
|
||||
} = 0
|
||||
}
|
||||
|
||||
INCLUDE "gcc_nrf5x_espruino_common.ld"
|
||||
@ -31,14 +31,9 @@
|
||||
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_gpiote.h"
|
||||
#include "nrf_drv_twi.h"
|
||||
#include "nrf_drv_gpiote.h"
|
||||
#include "nrf_temp.h"
|
||||
#include "nrf_timer.h"
|
||||
#include "app_uart.h"
|
||||
#include "nrf_drv_uart.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
#ifdef NRF52
|
||||
#include "nrf_saadc.h"
|
||||
#include "nrf_pwm.h"
|
||||
@ -46,6 +41,13 @@
|
||||
#include "nrf_adc.h"
|
||||
#endif
|
||||
|
||||
#include "nrf_drv_uart.h"
|
||||
#include "nrf_drv_twi.h"
|
||||
#include "nrf_drv_gpiote.h"
|
||||
#include "nrf_drv_ppi.h"
|
||||
|
||||
#include "app_uart.h"
|
||||
|
||||
#include "nrf5x_utils.h"
|
||||
#include "softdevice_handler.h"
|
||||
|
||||
@ -70,6 +72,7 @@ volatile bool flashIsBusy = false;
|
||||
volatile bool hadEvent = false; // set if we've had an event we need to deal with
|
||||
bool uartIsSending = false;
|
||||
bool uartInitialised = false;
|
||||
unsigned int ticksSinceStart = 0;
|
||||
|
||||
JshPinFunction pinStates[JSH_PIN_COUNT];
|
||||
|
||||
@ -93,16 +96,48 @@ void sys_evt_handler(uint32_t sys_evt) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NRF52
|
||||
/* SysTick interrupt Handler. */
|
||||
void SysTick_Handler(void) {
|
||||
/* Handle the delayed Ctrl-C -> interrupt behaviour (see description by EXEC_CTRL_C's definition) */
|
||||
if (execInfo.execute & EXEC_CTRL_C_WAIT)
|
||||
execInfo.execute = (execInfo.execute & ~EXEC_CTRL_C_WAIT) | EXEC_INTERRUPTED;
|
||||
if (execInfo.execute & EXEC_CTRL_C)
|
||||
execInfo.execute = (execInfo.execute & ~EXEC_CTRL_C) | EXEC_CTRL_C_WAIT;
|
||||
|
||||
ticksSinceStart++;
|
||||
/* One second after start, call jsinteractive. This is used to swap
|
||||
* to USB (if connected), or the Serial port. */
|
||||
if (ticksSinceStart == 5) {
|
||||
jsiOneSecondAfterStartup();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NRF52
|
||||
NRF_PWM_Type *nrf_get_pwm(JshPinFunction func) {
|
||||
if ((func&JSH_MASK_TYPE) == JSH_TIMER1) return NRF_PWM0;
|
||||
else if ((func&JSH_MASK_TYPE) == JSH_TIMER2) return NRF_PWM1;
|
||||
else if ((func&JSH_MASK_TYPE) == JSH_TIMER3) return NRF_PWM2;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static NO_INLINE void jshPinSetFunction_int(JshPinFunction func, uint32_t pin) {
|
||||
JshPinFunction fType = func&JSH_MASK_TYPE;
|
||||
JshPinFunction fInfo = func&JSH_MASK_INFO;
|
||||
switch (fType) {
|
||||
case JSH_NOTHING: break;
|
||||
#ifdef NRF52
|
||||
case JSH_TIMER1: NRF_PWM0->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin; break;
|
||||
case JSH_TIMER2: NRF_PWM1->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin; break;
|
||||
case JSH_TIMER3: NRF_PWM2->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin; break;
|
||||
// FIXME: if no pins are active on the given PWM now, turn it off
|
||||
case JSH_TIMER1:
|
||||
case JSH_TIMER2:
|
||||
case JSH_TIMER3: {
|
||||
NRF_PWM_Type *pwm = nrf_get_pwm(fType);
|
||||
pwm->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin;
|
||||
// FIXME: Only disable if nothing else is using it!
|
||||
if (pin==0xFFFFFFFF) nrf_pwm_disable(pwm);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case JSH_USART1: if (fInfo==JSH_USART_RX) NRF_UART0->PSELRXD = pin;
|
||||
else NRF_UART0->PSELTXD = pin; break;
|
||||
@ -179,9 +214,16 @@ void jshInit() {
|
||||
wakeup_handler);
|
||||
if (err_code) jsiConsolePrintf("app_timer_create error %d\n", err_code);
|
||||
#endif
|
||||
|
||||
|
||||
// Softdevice is initialised now
|
||||
softdevice_sys_evt_handler_set(sys_evt_handler);
|
||||
// Enable PPI driver
|
||||
err_code = nrf_drv_ppi_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
#ifdef NRF52
|
||||
// Turn on SYSTICK - used for handling Ctrl-C behaviour
|
||||
SysTick_Config(0xFFFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
// When 'reset' is called - we try and put peripherals back to their power-on state
|
||||
@ -196,10 +238,12 @@ void jshKill() {
|
||||
|
||||
// stuff to do on idle
|
||||
void jshIdle() {
|
||||
#ifndef NRF52
|
||||
if (init == 1) {
|
||||
jsiOneSecondAfterStartup(); // Do this the first time we enter jshIdle() after we have called jshInit() and never again.
|
||||
init = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Get this IC's serial number. Passed max # of chars and a pointer to write to. Returns # of chars
|
||||
@ -288,6 +332,7 @@ void jshPinSetState(Pin pin, JshPinState state) {
|
||||
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
break;
|
||||
case JSHPINSTATE_GPIO_IN :
|
||||
case JSHPINSTATE_ADC_IN :
|
||||
nrf_gpio_cfg_input(ipin, NRF_GPIO_PIN_NOPULL);
|
||||
break;
|
||||
case JSHPINSTATE_GPIO_IN_PULLUP :
|
||||
@ -296,9 +341,7 @@ void jshPinSetState(Pin pin, JshPinState state) {
|
||||
case JSHPINSTATE_GPIO_IN_PULLDOWN :
|
||||
nrf_gpio_cfg_input(ipin, NRF_GPIO_PIN_PULLDOWN);
|
||||
break;
|
||||
/*case JSHPINSTATE_ADC_IN :
|
||||
break;
|
||||
case JSHPINSTATE_AF_OUT :
|
||||
/*case JSHPINSTATE_AF_OUT :
|
||||
break;
|
||||
case JSHPINSTATE_AF_OUT_OPENDRAIN :
|
||||
break;
|
||||
@ -354,6 +397,7 @@ nrf_saadc_value_t nrf_analog_read() {
|
||||
// Returns an analog value between 0 and 1
|
||||
JsVarFloat jshPinAnalog(Pin pin) {
|
||||
if (pinInfo[pin].analog == JSH_ANALOG_NONE) return NAN;
|
||||
jshPinSetState(pin, JSHPINSTATE_ADC_IN);
|
||||
#ifdef NRF52
|
||||
// sanity checks for channel
|
||||
assert(NRF_SAADC_INPUT_AIN0 == 1);
|
||||
@ -376,7 +420,10 @@ JsVarFloat jshPinAnalog(Pin pin) {
|
||||
nrf_saadc_resolution_set(NRF_SAADC_RESOLUTION_14BIT);
|
||||
nrf_saadc_channel_init(0, &config);
|
||||
|
||||
return nrf_analog_read() / 16384.0;
|
||||
JsVarFloat f = nrf_analog_read() / 16384.0;
|
||||
nrf_saadc_channel_input_set(0, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); // give us back our pin!
|
||||
nrf_saadc_disable();
|
||||
return f;
|
||||
#else
|
||||
const nrf_adc_config_t nrf_adc_config = {
|
||||
NRF_ADC_CONFIG_RES_10BIT,
|
||||
@ -453,11 +500,8 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, Js
|
||||
JshPinFunction func = JSH_TIMER1 | JSH_TIMER_CH1;
|
||||
// FIXME: Search for free timers to use (based on freq as well)
|
||||
|
||||
NRF_PWM_Type *pwm;
|
||||
if ((func&JSH_MASK_TYPE) == JSH_TIMER1) pwm = NRF_PWM0;
|
||||
else if ((func&JSH_MASK_TYPE) == JSH_TIMER2) pwm = NRF_PWM1;
|
||||
else if ((func&JSH_MASK_TYPE) == JSH_TIMER3) pwm = NRF_PWM2;
|
||||
else { assert(0); return 0; };
|
||||
NRF_PWM_Type *pwm = nrf_get_pwm(func);
|
||||
if (!pwm) { assert(0); return 0; };
|
||||
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
|
||||
jshPinSetFunction(pin, func);
|
||||
nrf_pwm_enable(pwm);
|
||||
@ -562,6 +606,7 @@ static void jsvPinWatchHandler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t a
|
||||
lastHandledPinState = (bool)nrf_gpio_pin_read(pin);
|
||||
IOEventFlags evt = jshGetEventFlagsForWatchedPin(pin);
|
||||
jshPushIOWatchEvent(evt);
|
||||
jshHadEvent();
|
||||
}
|
||||
|
||||
|
||||
@ -574,7 +619,7 @@ IOEventFlags jshPinWatch(Pin pin, bool shouldWatch) {
|
||||
if (!jshIsPinValid(pin)) return EV_NONE;
|
||||
uint32_t p = (uint32_t)pinInfo[pin].pin;
|
||||
if (shouldWatch) {
|
||||
nrf_drv_gpiote_in_config_t cls_1_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
|
||||
nrf_drv_gpiote_in_config_t cls_1_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); // FIXME: Maybe we want low accuracy? Otherwise this will
|
||||
nrf_drv_gpiote_in_init(p, &cls_1_config, jsvPinWatchHandler);
|
||||
nrf_drv_gpiote_in_event_enable(p, true);
|
||||
return jshGetEventFlagsForWatchedPin(p);
|
||||
@ -643,6 +688,11 @@ void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
|
||||
if (!jshIsPinValid(inf->pinRX) || !jshIsPinValid(inf->pinTX))
|
||||
return jsError("Invalid RX or TX pins");
|
||||
|
||||
if (uartInitialised) {
|
||||
uartInitialised = false;
|
||||
app_uart_close();
|
||||
}
|
||||
|
||||
uint32_t err_code;
|
||||
const app_uart_comm_params_t comm_params = {
|
||||
pinInfo[inf->pinRX].pin,
|
||||
@ -661,21 +711,13 @@ void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
|
||||
uart0_event_handle,
|
||||
APP_IRQ_PRIORITY_HIGH,
|
||||
err_code);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
if (err_code)
|
||||
jsExceptionHere(JSET_INTERNALERROR, "app_uart_init failed, error %d", err_code);
|
||||
uartInitialised = true;
|
||||
}
|
||||
|
||||
/** Kick a device into action (if required). For instance we may need to set up interrupts */
|
||||
void jshUSARTKick(IOEventFlags device) {
|
||||
|
||||
if (device == EV_BLUETOOTH) {
|
||||
/* For bluetooth, start transmit after one character.
|
||||
The BLE_EVT_TX_COMPLETE event will get triggered and
|
||||
will auto-reload whatever needs sending. */
|
||||
bool jswrap_nrf_transmit_string();
|
||||
jswrap_nrf_transmit_string();
|
||||
}
|
||||
|
||||
if (device == EV_SERIAL1) {
|
||||
if (uartInitialised) {
|
||||
if (!uartIsSending) {
|
||||
|
||||
@ -19,8 +19,13 @@
|
||||
int main() {
|
||||
|
||||
jshInit();
|
||||
|
||||
bool buttonState = false;
|
||||
#ifdef BTN1_PININDEX
|
||||
buttonState = jshPinInput(BTN1_PININDEX) == BTN1_ONSTATE;
|
||||
#endif
|
||||
jsvInit();
|
||||
jsiInit(true /* load from flash by default */);
|
||||
jsiInit(!buttonState /* load from flash by default */); // pressing USER button skips autoload
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
@ -18,9 +18,16 @@
|
||||
|
||||
#include "nrf.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_gpiote.h"
|
||||
#include "app_uart.h"
|
||||
#include "nrf_error.h"
|
||||
#include "nrf_nvmc.h"
|
||||
#include "nrf_timer.h"
|
||||
|
||||
#include "nrf_drv_gpiote.h"
|
||||
#include "nrf_drv_ppi.h"
|
||||
|
||||
#include "jsparse.h"
|
||||
|
||||
unsigned int nrf_utils_get_baud_enum(int baud) {
|
||||
switch (baud) {
|
||||
@ -56,8 +63,8 @@ void nrf_utils_lfclk_config_and_start()
|
||||
NRF_CLOCK->TASKS_LFCLKSTART = 1;
|
||||
while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);
|
||||
|
||||
/*
|
||||
// wait until the clock is running - Xtal only?
|
||||
/*
|
||||
// wait until the clock is running - Xtal only?
|
||||
while (((NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_STATE_Msk) != ((CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos) & CLOCK_LFCLKSTAT_STATE_Msk)))
|
||||
{
|
||||
// Do nothing...
|
||||
@ -86,7 +93,7 @@ int nrf_utils_get_device_id(uint8_t * device_id, int maxChars)
|
||||
|
||||
uint8_t nrf_utils_get_random_number()
|
||||
{
|
||||
|
||||
|
||||
NRF_RNG->CONFIG = 0x00000001; // Use the bias generator.
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
|
||||
@ -104,3 +111,119 @@ uint8_t nrf_utils_get_random_number()
|
||||
return rand_num;
|
||||
|
||||
}
|
||||
|
||||
unsigned int nrf_utils_cap_sense(int capSenseTxPin, int capSenseRxPin) {
|
||||
#ifdef NRF5DDD
|
||||
uint32_t err_code;
|
||||
|
||||
nrf_drv_gpiote_in_config_t rxconfig = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
|
||||
nrf_drv_gpiote_in_init(capSenseRxPin, &rxconfig, 0);
|
||||
nrf_drv_gpiote_in_event_enable(capSenseRxPin, false /* no interrupt */);
|
||||
//
|
||||
|
||||
nrf_drv_gpiote_out_config_t txconfig = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
|
||||
nrf_drv_gpiote_out_init(capSenseTxPin, &txconfig);
|
||||
nrf_drv_gpiote_out_task_enable(capSenseTxPin);
|
||||
//;
|
||||
|
||||
nrf_timer_mode_set(NRF_TIMER2, TIMER_MODE_MODE_Timer);
|
||||
nrf_timer_bit_width_set(NRF_TIMER2, NRF_TIMER_BIT_WIDTH_16);
|
||||
nrf_timer_frequency_set(NRF_TIMER2, NRF_TIMER_FREQ_16MHz);
|
||||
nrf_timer_cc_write(NRF_TIMER2, 0, 0);
|
||||
nrf_timer_cc_write(NRF_TIMER2, 1, 2047);
|
||||
nrf_timer_cc_write(NRF_TIMER2, 3, 4095);
|
||||
nrf_timer_shorts_enable(NRF_TIMER2, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK);
|
||||
|
||||
nrf_ppi_channel_t ppi_channel1, ppi_channel2, ppi_channel3;
|
||||
|
||||
// 1: When RX pin goes low->high, capture it in the timer
|
||||
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
err_code = nrf_drv_ppi_channel_assign(ppi_channel1,
|
||||
nrf_drv_gpiote_in_event_addr_get(capSenseRxPin),
|
||||
nrf_timer_task_address_get(NRF_TIMER2, NRF_TIMER_TASK_CAPTURE2));
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// 2: When timer is at Compare0, toggle
|
||||
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel2);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
err_code = nrf_drv_ppi_channel_assign(ppi_channel2,
|
||||
nrf_timer_event_address_get(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE0),
|
||||
nrf_drv_gpiote_out_task_addr_get(capSenseTxPin));
|
||||
APP_ERROR_CHECK(err_code);
|
||||
// 3: When timer is at Compare1, toggle
|
||||
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel3);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
err_code = nrf_drv_ppi_channel_assign(ppi_channel3,
|
||||
nrf_timer_event_address_get(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE1),
|
||||
nrf_drv_gpiote_out_task_addr_get(capSenseTxPin));
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// Enable both configured PPI channels
|
||||
err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
err_code = nrf_drv_ppi_channel_enable(ppi_channel3);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// start timer
|
||||
|
||||
NRF_TIMER2->CC[2] = 0;
|
||||
nrf_timer_task_trigger(NRF_TIMER2, NRF_TIMER_TASK_START);
|
||||
nrf_gpio_cfg_input(capSenseRxPin, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_cfg_output(capSenseTxPin);
|
||||
|
||||
//
|
||||
unsigned int sum = 0;
|
||||
NRF_TIMER2->EVENTS_COMPARE[1] = 0;
|
||||
int i;
|
||||
for (i=0;i<50;i++) {
|
||||
unsigned int timeout = 100000;
|
||||
while (!NRF_TIMER2->EVENTS_COMPARE[1] && --timeout);
|
||||
NRF_TIMER2->EVENTS_COMPARE[1] = 0;
|
||||
sum += NRF_TIMER2->CC[2];
|
||||
if (jspIsInterrupted()) break;
|
||||
}
|
||||
|
||||
nrf_gpio_cfg_input(capSenseTxPin, NRF_GPIO_PIN_NOPULL);
|
||||
|
||||
nrf_timer_task_trigger(NRF_TIMER2, NRF_TIMER_TASK_STOP);
|
||||
nrf_timer_shorts_disable(NRF_TIMER2, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK);
|
||||
nrf_drv_ppi_channel_disable(ppi_channel3);
|
||||
nrf_drv_ppi_channel_disable(ppi_channel2);
|
||||
nrf_drv_ppi_channel_disable(ppi_channel1);
|
||||
nrf_drv_ppi_channel_free(ppi_channel3);
|
||||
nrf_drv_ppi_channel_free(ppi_channel2);
|
||||
nrf_drv_ppi_channel_free(ppi_channel1);
|
||||
|
||||
nrf_drv_gpiote_in_uninit(capSenseTxPin);
|
||||
nrf_drv_gpiote_in_uninit(capSenseRxPin);
|
||||
|
||||
return sum;
|
||||
#else
|
||||
unsigned int sum = 0;
|
||||
|
||||
int i;
|
||||
unsigned int mask = 1<<capSenseRxPin;
|
||||
|
||||
nrf_gpio_cfg_input(capSenseRxPin, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_pin_clear(capSenseTxPin);
|
||||
nrf_gpio_cfg_output(capSenseTxPin);
|
||||
|
||||
for (i=0;i<100;i++) {
|
||||
const unsigned int CTR_MAX = 100000;
|
||||
unsigned int ctr = CTR_MAX;
|
||||
nrf_gpio_pin_set(capSenseTxPin);
|
||||
while (!(NRF_GPIO->IN & mask) && ctr--);
|
||||
sum += CTR_MAX-ctr;
|
||||
nrf_gpio_pin_clear(capSenseTxPin);
|
||||
while (NRF_GPIO->IN & mask && ctr--);
|
||||
sum += CTR_MAX-ctr;
|
||||
if (jspIsInterrupted()) break;
|
||||
}
|
||||
nrf_gpio_cfg_input(capSenseTxPin, NRF_GPIO_PIN_NOPULL);
|
||||
|
||||
return sum;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -28,6 +28,8 @@ void nrf_utils_lfclk_config_and_start(void);
|
||||
int nrf_utils_get_device_id(uint8_t * device_id, int maxChars);
|
||||
uint8_t nrf_utils_get_random_number(void);
|
||||
|
||||
unsigned int nrf_utils_cap_sense(int capSenseTxPin, int capSenseRxPin);
|
||||
|
||||
#endif // NRF5X_UTILS_H__
|
||||
|
||||
/** @} */
|
||||
|
||||
205
targets/nrf5x_dfu/dfu_ble_svc.c
Normal file
205
targets/nrf5x_dfu/dfu_ble_svc.c
Normal file
@ -0,0 +1,205 @@
|
||||
/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dfu_ble_svc.h"
|
||||
#include <string.h>
|
||||
#include "nrf_error.h"
|
||||
#include "crc16.h"
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
static dfu_ble_peer_data_t m_peer_data __attribute__((section("NoInit"), zero_init)); /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
|
||||
static uint16_t m_peer_data_crc __attribute__((section("NoInit"), zero_init)); /**< CRC variable to ensure the integrity of the peer data provided. */
|
||||
#elif defined ( __GNUC__ )
|
||||
__attribute__((section(".noinit"))) static dfu_ble_peer_data_t m_peer_data; /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
|
||||
__attribute__((section(".noinit"))) static uint16_t m_peer_data_crc; /**< CRC variable to ensure the integrity of the peer data provided. */
|
||||
#elif defined ( __ICCARM__ )
|
||||
__no_init static dfu_ble_peer_data_t m_peer_data @ 0x20003F80; /**< This variable should be placed in a non initialized RAM section in order to be valid upon soft reset from application into bootloader. */
|
||||
__no_init static uint16_t m_peer_data_crc @ 0x20003F80 + sizeof(dfu_ble_peer_data_t); /**< CRC variable to ensure the integrity of the peer data provided. */
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief Function for setting the peer data from application in bootloader before reset.
|
||||
*
|
||||
* @param[in] p_peer_data Pointer to the peer data containing keys for the connection.
|
||||
*
|
||||
* @retval NRF_SUCCES The data was set succesfully.
|
||||
* @retval NRF_ERROR_NULL If a null pointer was passed as argument.
|
||||
*/
|
||||
static uint32_t dfu_ble_peer_data_set(dfu_ble_peer_data_t * p_peer_data)
|
||||
{
|
||||
if (p_peer_data == NULL)
|
||||
{
|
||||
return NRF_ERROR_NULL;
|
||||
}
|
||||
|
||||
uint32_t src = (uint32_t)p_peer_data;
|
||||
uint32_t dst = (uint32_t)&m_peer_data;
|
||||
// Calculating length in order to check if destination is residing inside source.
|
||||
// Source inside the the destination (calculation underflow) is safe a source is read before
|
||||
// written to destination so that when destination grows into source, the source data is no
|
||||
// longer needed.
|
||||
uint32_t len = dst - src;
|
||||
|
||||
if (src == dst)
|
||||
{
|
||||
// Do nothing as source and destination are identical, just calculate crc below.
|
||||
}
|
||||
else if (len < sizeof(dfu_ble_peer_data_t))
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
dst += sizeof(dfu_ble_peer_data_t);
|
||||
src += sizeof(dfu_ble_peer_data_t);
|
||||
|
||||
// Copy byte wise backwards when facing overlapping structures.
|
||||
while (i++ <= sizeof(dfu_ble_peer_data_t))
|
||||
{
|
||||
*((uint8_t *)dst--) = *((uint8_t *)src--);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((void *)dst, (void *)src, sizeof(dfu_ble_peer_data_t));
|
||||
}
|
||||
|
||||
m_peer_data_crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling second stage of SuperVisor Calls (SVC).
|
||||
*
|
||||
* @details The function will use svc_num to call the corresponding SVC function.
|
||||
*
|
||||
* @param[in] svc_num SVC number for function to be executed
|
||||
* @param[in] p_svc_args Argument list for the SVC.
|
||||
*
|
||||
* @return This function returns the error value of the SVC return. For further details, please
|
||||
* refer to the details of the SVC implementation itself.
|
||||
* @ref NRF_ERROR_SVC_HANDLER_MISSING is returned if no SVC handler is implemented for the
|
||||
* provided svc_num.
|
||||
*/
|
||||
void C_SVC_Handler(uint8_t svc_num, uint32_t * p_svc_args)
|
||||
{
|
||||
switch (svc_num)
|
||||
{
|
||||
case DFU_BLE_SVC_PEER_DATA_SET:
|
||||
p_svc_args[0] = dfu_ble_peer_data_set((dfu_ble_peer_data_t *)p_svc_args[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
p_svc_args[0] = NRF_ERROR_SVC_HANDLER_MISSING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the first stage of SuperVisor Calls (SVC) in assembly.
|
||||
*
|
||||
* @details The function will use the link register (LR) to determine the stack (PSP or MSP) to be
|
||||
* used and then decode the SVC number afterwards. After decoding the SVC number then
|
||||
* @ref C_SVC_Handler is called for further processing of the SVC.
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
__asm void SVC_Handler(void)
|
||||
{
|
||||
EXC_RETURN_CMD_PSP EQU 0xFFFFFFFD ; EXC_RETURN using PSP for ARM Cortex. If Link register contains this value it indicates the PSP was used before the SVC, otherwise the MSP was used.
|
||||
|
||||
IMPORT C_SVC_Handler
|
||||
LDR R0, =EXC_RETURN_CMD_PSP ; Load the EXC_RETURN into R0 to be able to compare against LR to determine stack pointer used.
|
||||
CMP R0, LR ; Compare the link register with R0. If equal then PSP was used, otherwise MSP was used before SVC.
|
||||
BNE UseMSP ; Branch to code fetching SVC arguments using MSP.
|
||||
MRS R1, PSP ; Move PSP into R1.
|
||||
B Call_C_SVC_Handler ; Branch to Call_C_SVC_Handler below.
|
||||
UseMSP
|
||||
MRS R1, MSP ; MSP was used, therefore Move MSP into R1.
|
||||
Call_C_SVC_Handler
|
||||
LDR R0, [R1, #24] ; The arguments for the SVC was stacked. R1 contains Stack Pointer, the values stacked before SVC are R0, R1, R2, R3, R12, LR, PC (Return address), xPSR.
|
||||
; R1 contains current SP so the PC of the stacked frame is at SP + 6 words (24 bytes). We load the PC into R0.
|
||||
SUBS R0, #2 ; The PC before the SVC is in R0. We subtract 2 to get the address prior to the instruction executed where the SVC number is located.
|
||||
LDRB R0, [R0] ; SVC instruction low octet: Load the byte at the address before the PC to fetch the SVC number.
|
||||
LDR R2, =C_SVC_Handler ; Load address of C implementation of SVC handler.
|
||||
BX R2 ; Branch to C implementation of SVC handler. R0 is now the SVC number, R1 is the StackPointer where the arguments (R0-R3) of the original SVC are located.
|
||||
ALIGN
|
||||
}
|
||||
#elif defined ( __GNUC__ )
|
||||
void __attribute__ (( naked )) SVC_Handler(void)
|
||||
{
|
||||
const uint32_t exc_return = 0xFFFFFFFD; // EXC_RETURN using PSP for ARM Cortex. If Link register contains this value it indicates the PSP was used before the SVC, otherwise the MSP was used.
|
||||
|
||||
__asm volatile(
|
||||
"cmp lr, %0\t\n" // Compare the link register with argument 0 (%0), which is exc_return. If equal then PSP was used, otherwise MSP was used before SVC.
|
||||
"bne UseMSP\t\n" // Branch to code fetching SVC arguments using MSP.
|
||||
"mrs r1, psp\t\n" // Move PSP into R1.
|
||||
"b Call_C_SVC_Handler\t\n" // Branch to Call_C_SVC_Handler below.
|
||||
"UseMSP: \t\n" //
|
||||
"mrs r1, msp\t\n" // MSP was used, therefore Move MSP into R1.
|
||||
"Call_C_SVC_Handler: \t\n" //
|
||||
"ldr r0, [r1, #24]\t\n" // The arguments for the SVC was stacked. R1 contains Stack Pointer, the values stacked before SVC are R0, R1, R2, R3, R12, LR, PC (Return address), xPSR.
|
||||
// R1 contains current SP so the PC of the stacked frame is at SP + 6 words (24 bytes). We load the PC into R0.
|
||||
"sub r0, r0, #2\t\n" // The PC before the SVC is in R0. We subtract 2 to get the address prior to the instruction executed where the SVC number is located.
|
||||
"ldrb r0, [r0]\t\n" // SVC instruction low octet: Load the byte at the address before the PC to fetch the SVC number.
|
||||
"bx %1\t\n" // Branch to C implementation of SVC handler, argument 1 (%1). R0 is now the SVC number, R1 is the StackPointer where the arguments (R0-R3) of the original SVC are located.
|
||||
".align\t\n"
|
||||
:: "r" (exc_return), "r" (C_SVC_Handler) // Argument list for the gcc assembly. exc_return is %0, C_SVC_Handler is %1.
|
||||
: "r0", "r1" // List of register maintained manually.
|
||||
);
|
||||
}
|
||||
#elif defined ( __ICCARM__ )
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
asm("movs r0, #0x02\n" // Load 0x02 into R6 to prepare for exec return test.
|
||||
"mvns r0, r0\n" // Invert R0 to obtain exec return code using PSP for ARM Cortex.
|
||||
"cmp lr, r0\n" // Compare the link register with argument 0 (%0), which is exc_return. If equal then PSP was used, otherwise MSP was used before SVC.
|
||||
"bne.n UseMSP\n" // Branch to code fetching SVC arguments using MSP.
|
||||
"mrs r1, psp\n" // Move PSP into R1.
|
||||
"b.n Call_C_SVC_Handler\t\n" // Branch to Call_C_SVC_Handler below.
|
||||
"UseMSP: \n" //
|
||||
"mrs r1, msp\n" // MSP was used, therefore Move MSP into R1.
|
||||
"Call_C_SVC_Handler: \n" //
|
||||
"ldr r0, [r1, #24]\n" // The arguments for the SVC was stacked. R1 contains Stack Pointer, the values stacked before SVC are R0, R1, R2, R3, R12, LR, PC (Return address), xPSR.
|
||||
// R1 contains current SP so the PC of the stacked frame is at SP + 6 words (24 bytes). We load the PC into R0.
|
||||
"subs r0, #0x02\n" // The PC before the SVC is in R0. We subtract 2 to get the address prior to the instruction executed where the SVC number is located.
|
||||
"ldrb r0, [r0]\n" // SVC instruction low octet: Load the byte at the address before the PC to fetch the SVC number.
|
||||
"bx %0\n" // Branch to C implementation of SVC handler, argument 1 (%1). R0 is now the SVC number, R1 is the StackPointer where the arguments (R0-R3) of the original SVC are located.
|
||||
:: "r" (C_SVC_Handler) // Argument list for the gcc assembly. C_SVC_Handler is %0.
|
||||
: "r0", "r1" // List of register maintained manually.
|
||||
);
|
||||
}
|
||||
#else
|
||||
#error Compiler not supported.
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t dfu_ble_peer_data_get(dfu_ble_peer_data_t * p_peer_data)
|
||||
{
|
||||
uint16_t crc;
|
||||
|
||||
if (p_peer_data == NULL)
|
||||
{
|
||||
return NRF_ERROR_NULL;
|
||||
}
|
||||
|
||||
crc = crc16_compute((uint8_t *)&m_peer_data, sizeof(m_peer_data), NULL);
|
||||
if (crc != m_peer_data_crc)
|
||||
{
|
||||
return NRF_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
*p_peer_data = m_peer_data;
|
||||
|
||||
// corrupt CRC to invalidate shared information.
|
||||
m_peer_data_crc++;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
279
targets/nrf5x_dfu/main.c
Normal file
279
targets/nrf5x_dfu/main.c
Normal file
@ -0,0 +1,279 @@
|
||||
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup ble_sdk_app_bootloader_main main.c
|
||||
* @{
|
||||
* @ingroup dfu_bootloader_api
|
||||
* @brief Bootloader project main file.
|
||||
*
|
||||
* -# Receive start data packet.
|
||||
* -# Based on start packet, prepare NVM area to store received data.
|
||||
* -# Receive data packet.
|
||||
* -# Validate data packet.
|
||||
* -# Write Data packet to NVM.
|
||||
* -# If not finished - Wait for next packet.
|
||||
* -# Receive stop data packet.
|
||||
* -# Activate Image, boot application.
|
||||
*
|
||||
*/
|
||||
#include "dfu_transport.h"
|
||||
#include "bootloader.h"
|
||||
#include "bootloader_util.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "nordic_common.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "app_error.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "ble.h"
|
||||
#include "nrf.h"
|
||||
#include "ble_hci.h"
|
||||
#include "app_scheduler.h"
|
||||
#include "app_timer_appsh.h"
|
||||
#include "nrf_error.h"
|
||||
#include "softdevice_handler_appsh.h"
|
||||
#include "pstorage_platform.h"
|
||||
#include "nrf_mbr.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "platform_config.h"
|
||||
|
||||
|
||||
#define BOOTLOADER_BUTTON BTN1_PININDEX /**< Button used to enter SW update mode. */
|
||||
#define BOOTLOADER_BUTTON_ONSTATE BTN1_ONSTATE /**< Button used to enter SW update mode. */
|
||||
#define UPDATE_IN_PROGRESS_LED LED3_PININDEX /**< Led used to indicate that DFU is active. */
|
||||
#define UPDATE_IN_PROGRESS_LED_ONSTATE LED3_ONSTATE /**< Led used to indicate that DFU is active. */
|
||||
#define BOOTLOADER_BUTTON_PRESS_LED LED2_PININDEX /**< Led used to indicate that DFU is active. */
|
||||
#define BOOTLOADER_BUTTON_PRESS_LED_ONSTATE LED2_ONSTATE /**< Led used to indicate that DFU is active. */
|
||||
// Other LED is set in targetlibs/nrf5x/nrf5_sdk/components/libraries/bootloader_dfu/dfu_transport_ble.c (currently LED1)
|
||||
|
||||
|
||||
#define IS_SRVC_CHANGED_CHARACT_PRESENT 1 /**< Include the service_changed characteristic. For DFU this should normally be the case. */
|
||||
|
||||
|
||||
#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
|
||||
#define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */
|
||||
|
||||
#define SCHED_MAX_EVENT_DATA_SIZE MAX(APP_TIMER_SCHED_EVT_SIZE, 0) /**< Maximum size of scheduler events. */
|
||||
|
||||
#define SCHED_QUEUE_SIZE 20 /**< Maximum number of events in the scheduler queue. */
|
||||
|
||||
|
||||
/**@brief Callback function for asserts in the SoftDevice.
|
||||
*
|
||||
* @details This function will be called in case of an assert in the SoftDevice.
|
||||
*
|
||||
* @warning This handler is an example only and does not fit a final product. You need to analyze
|
||||
* how your product is supposed to react in case of Assert.
|
||||
* @warning On assert from the SoftDevice, the system can only recover on reset.
|
||||
*
|
||||
* @param[in] line_num Line number of the failing ASSERT call.
|
||||
* @param[in] file_name File name of the failing ASSERT call.
|
||||
*/
|
||||
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
|
||||
{
|
||||
app_error_handler(0xDEADBEEF, line_num, p_file_name);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for initialization of LEDs.
|
||||
*/
|
||||
static void leds_init(void)
|
||||
{
|
||||
nrf_gpio_cfg_output(UPDATE_IN_PROGRESS_LED);
|
||||
nrf_gpio_pin_write(UPDATE_IN_PROGRESS_LED, !UPDATE_IN_PROGRESS_LED_ONSTATE);
|
||||
nrf_gpio_cfg_output(BOOTLOADER_BUTTON_PRESS_LED);
|
||||
nrf_gpio_pin_write(BOOTLOADER_BUTTON_PRESS_LED, !BOOTLOADER_BUTTON_PRESS_LED_ONSTATE);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for initializing the timer handler module (app_timer).
|
||||
*/
|
||||
static void timers_init(void)
|
||||
{
|
||||
// Initialize timer module, making it use the scheduler.
|
||||
APP_TIMER_APPSH_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, true);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for initializing the button module.
|
||||
*/
|
||||
static void buttons_init(void)
|
||||
{
|
||||
nrf_gpio_cfg_sense_input(BOOTLOADER_BUTTON,
|
||||
BOOTLOADER_BUTTON_ONSTATE ? NRF_GPIO_PIN_PULLDOWN : NRF_GPIO_PIN_PULLUP,
|
||||
BOOTLOADER_BUTTON_ONSTATE ? NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler.
|
||||
*
|
||||
* @details This function is called from the scheduler in the main loop after a BLE stack
|
||||
* event has been received.
|
||||
*
|
||||
* @param[in] p_ble_evt Bluetooth stack event.
|
||||
*/
|
||||
static void sys_evt_dispatch(uint32_t event)
|
||||
{
|
||||
pstorage_sys_event_handler(event);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for initializing the BLE stack.
|
||||
*
|
||||
* @details Initializes the SoftDevice and the BLE event interrupt.
|
||||
*
|
||||
* @param[in] init_softdevice true if SoftDeviceshould be initialized. The SoftDevice must only
|
||||
* be initialized if a chip reset has occured. Soft reset from
|
||||
* application must not reinitialize the SoftDevice.
|
||||
*/
|
||||
static void ble_stack_init(bool init_softdevice)
|
||||
{
|
||||
uint32_t err_code;
|
||||
sd_mbr_command_t com = {SD_MBR_COMMAND_INIT_SD, };
|
||||
|
||||
if (init_softdevice)
|
||||
{
|
||||
err_code = sd_mbr_command(&com);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_REGION_START);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
// TODO: enable if we're on a device with 32kHz xtal
|
||||
/*nrf_clock_lf_cfg_t clock_lf_cfg = {
|
||||
.source = NRF_CLOCK_LF_SRC_XTAL,
|
||||
.rc_ctiv = 0,
|
||||
.rc_temp_ctiv = 0,
|
||||
.xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM};*/
|
||||
nrf_clock_lf_cfg_t clock_lf_cfg = {
|
||||
.source = NRF_CLOCK_LF_SRC_RC,
|
||||
.rc_ctiv = 16, // recommended for nRF52
|
||||
.rc_temp_ctiv = 2, // recommended for nRF52
|
||||
.xtal_accuracy = 0};
|
||||
|
||||
SOFTDEVICE_HANDLER_APPSH_INIT(&clock_lf_cfg, true);
|
||||
|
||||
// Enable BLE stack.
|
||||
ble_enable_params_t ble_enable_params;
|
||||
// Only one connection as a central is used when performing dfu.
|
||||
err_code = softdevice_enable_get_default_config(1, 1, &ble_enable_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
|
||||
err_code = softdevice_enable(&ble_enable_params);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for event scheduler initialization.
|
||||
*/
|
||||
static void scheduler_init(void)
|
||||
{
|
||||
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for bootloader main entry.
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
bool dfu_start = false;
|
||||
bool app_reset = (NRF_POWER->GPREGRET == BOOTLOADER_DFU_START);
|
||||
|
||||
if (app_reset)
|
||||
{
|
||||
NRF_POWER->GPREGRET = 0;
|
||||
}
|
||||
|
||||
leds_init();
|
||||
|
||||
// This check ensures that the defined fields in the bootloader corresponds with actual
|
||||
// setting in the chip.
|
||||
APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
|
||||
APP_ERROR_CHECK_BOOL(NRF_FICR->CODEPAGESIZE == CODE_PAGE_SIZE);
|
||||
|
||||
// Initialize.
|
||||
timers_init();
|
||||
buttons_init();
|
||||
|
||||
(void)bootloader_init();
|
||||
|
||||
if (bootloader_dfu_sd_in_progress())
|
||||
{
|
||||
nrf_gpio_pin_write(UPDATE_IN_PROGRESS_LED, UPDATE_IN_PROGRESS_LED_ONSTATE);
|
||||
|
||||
err_code = bootloader_dfu_sd_update_continue();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
ble_stack_init(!app_reset);
|
||||
scheduler_init();
|
||||
|
||||
err_code = bootloader_dfu_sd_update_finalize();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
nrf_gpio_pin_write(UPDATE_IN_PROGRESS_LED, !UPDATE_IN_PROGRESS_LED_ONSTATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If stack is present then continue initialization of bootloader.
|
||||
ble_stack_init(!app_reset);
|
||||
scheduler_init();
|
||||
}
|
||||
|
||||
dfu_start = app_reset;
|
||||
dfu_start |= ((nrf_gpio_pin_read(BOOTLOADER_BUTTON) == BOOTLOADER_BUTTON_ONSTATE) ? true: false);
|
||||
|
||||
// If button is held down for 3 seconds, don't start bootloader.
|
||||
// This means that we go straight to Espruino, where the button is still
|
||||
// pressed and can be used to stop execution of the sent code.
|
||||
if (dfu_start) {
|
||||
nrf_gpio_pin_write(BOOTLOADER_BUTTON_PRESS_LED, BOOTLOADER_BUTTON_PRESS_LED_ONSTATE);
|
||||
int count = 3000;
|
||||
while (nrf_gpio_pin_read(BOOTLOADER_BUTTON) == BOOTLOADER_BUTTON_ONSTATE && count) {
|
||||
nrf_delay_us(999);
|
||||
count--;
|
||||
}
|
||||
if (!count)
|
||||
dfu_start = false;
|
||||
nrf_gpio_pin_write(BOOTLOADER_BUTTON_PRESS_LED, !BOOTLOADER_BUTTON_PRESS_LED_ONSTATE);
|
||||
}
|
||||
|
||||
if (dfu_start || (!bootloader_app_is_valid(DFU_BANK_0_REGION_START))) {
|
||||
nrf_gpio_pin_write(UPDATE_IN_PROGRESS_LED, UPDATE_IN_PROGRESS_LED_ONSTATE);
|
||||
|
||||
// Initiate an update of the firmware.
|
||||
err_code = bootloader_dfu_start();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
nrf_gpio_pin_write(UPDATE_IN_PROGRESS_LED, !UPDATE_IN_PROGRESS_LED_ONSTATE);
|
||||
}
|
||||
|
||||
if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress())
|
||||
{
|
||||
// Select a bank region to use as application region.
|
||||
// @note: Only applications running from DFU_BANK_0_REGION_START is supported.
|
||||
bootloader_app_start(DFU_BANK_0_REGION_START);
|
||||
}
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
@ -707,6 +707,7 @@ void jshSetupRTC(bool isUsingLSI) {
|
||||
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
|
||||
RTC_Init(&RTC_InitStructure);
|
||||
#endif
|
||||
RTC_WaitForSynchro();
|
||||
}
|
||||
|
||||
void jshResetRTCTimer() {
|
||||
@ -729,9 +730,10 @@ void jshDoSysTick() {
|
||||
if (ticksSinceStart==RTC_INITIALISE_TICKS) {
|
||||
// Use LSI if the LSE hasn't stabilised
|
||||
bool isUsingLSI = RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET;
|
||||
bool wasUsingLSI = !jshIsRTCUsingLSE();
|
||||
|
||||
// If the RTC is already doing the right thing, do nothing
|
||||
if (isUsingLSI == jshIsRTCUsingLSE()) {
|
||||
if (isUsingLSI != wasUsingLSI) {
|
||||
// We just set the RTC up, so we have to reset the
|
||||
// backup domain again to change sources :(
|
||||
#ifdef STM32F1
|
||||
@ -744,14 +746,15 @@ void jshDoSysTick() {
|
||||
#endif
|
||||
RCC_BackupResetCmd(ENABLE);
|
||||
RCC_BackupResetCmd(DISABLE);
|
||||
RCC_LSEConfig(RCC_LSE_ON); // reset would have turned LSE off
|
||||
if (!isUsingLSI) RCC_LSEConfig(RCC_LSE_ON); // reset would have turned LSE off
|
||||
jshSetupRTC(isUsingLSI);
|
||||
#ifdef STM32F1
|
||||
RTC_SetCounter(time);
|
||||
#else
|
||||
RTC_SetDate(RTC_Format_BIN, &date);
|
||||
RTC_SetTime(RTC_Format_BIN, &time);
|
||||
RTC_WaitForSynchro();
|
||||
#endif
|
||||
jshSetupRTC(isUsingLSI);
|
||||
}
|
||||
|
||||
// Disable RTC clocks depending on what we decided...
|
||||
@ -760,7 +763,6 @@ void jshDoSysTick() {
|
||||
RCC_LSEConfig(RCC_LSE_OFF); // disable low speed external oscillator
|
||||
} else {
|
||||
// LSE working! Yay! turn LSI off now
|
||||
RCC_LSEConfig(RCC_LSE_ON);
|
||||
RCC_LSICmd(DISABLE); // disable low speed internal oscillator
|
||||
}
|
||||
}
|
||||
@ -1096,6 +1098,16 @@ void jshInit() {
|
||||
jshPinOutput(LED1_PININDEX, 1);
|
||||
#endif
|
||||
#ifdef USE_RTC
|
||||
/* RTC setup works like this:
|
||||
|
||||
* Turn LSI on (it always defaults to off)
|
||||
* If RTC is set up already, awesome. Job done.
|
||||
* If not, set up the RTC with the LSI, but turn the LSE on
|
||||
* Around 1 sec later, in jshDoSysTick, check if the LSE is working
|
||||
* If it isn't, turn it off
|
||||
* If it is, switch over to it and disable LSI
|
||||
|
||||
*/
|
||||
// allow access to backup domain
|
||||
PWR_BackupAccessCmd(ENABLE);
|
||||
// enable low speed internal oscillator (reset always kills this, and we might need it)
|
||||
|
||||
5
tests/test_string_append_same.js
Normal file
5
tests/test_string_append_same.js
Normal file
@ -0,0 +1,5 @@
|
||||
// http://forum.espruino.com/conversations/292461
|
||||
a = "1234567890123456789012345678901234567890";
|
||||
a+=a
|
||||
result = a.length==80;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user